大数据量下高并发同步

来源:互联网 发布:淘宝店 虎扑识货认证 编辑:程序博客网 时间:2024/06/08 10:07

大数据量下高并发同步

转自:http://www.cnblogs.com/bababao/p/5474121.html

同步和异步

   1、同步和异步的区别和联系

         所谓同步,可以理解为在执行完一个函数或方法之后,一直等待系统返回值或消息,这时程序是出于阻塞的,只有接收到

        返回的值或消息后才往下执行其它的命令。

        异步,执行完函数或方法后,不必阻塞性地等待返回值或消息,只需要向系统委托一个异步过程,那么当系统接收到返回

        值或消息时,系统会自动触发委托的异步过程,从而完成一个完整的流程。

         同步在一定程度上可以看做是单线程,这个线程请求一个方法后就待这个方法给他回复,否则他不往下执行(死心眼)。

        异步在一定程度上可以看做是多线程的(废话,一个线程怎么叫异步),请求一个方法后,就不管了,继续执行其他的方法。

        

        同步就是一件事,一件事情一件事的做。
        异步就是,做一件事情,不引响做其他事情。

        例如:吃饭和说话,只能一件事一件事的来,因为只有一张嘴。
                但吃饭和听音乐是异步的,因为,听音乐并不引响我们吃饭。

 

        对于Java程序员而言,我们会经常听到同步关键字synchronized,假如这个同步的监视对象是类的话,那么如果当一个对象

        访问类里面的同步方法的话,那么其它的对象如果想要继续访问类里面的这个同步方法的话,就会进入阻塞,只有等前一个对象

        执行完该同步方法后当前对象才能够继续执行该方法。这就是同步。相反,如果方法前没有同步关键字修饰的话,那么不同的对象

        可以在同一时间访问同一个方法,这就是异步。

      

        在补充一下(脏数据和不可重复读的相关概念):

       脏数据

  脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这
个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是脏数据(Dirty Data),依据脏数据所做的操作可能是不正确的。

     不可重复读

  不可重复读是指在一个事务内,多次 读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次 读到的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读

 

         

 

   2、如何处理并发和同步

另外一种是数据库层次上的,比较典型的就是悲观锁和乐观锁。这里我们重点讲解的就是悲观锁(传统的物理锁)和乐观锁。

       悲观锁(Pessimistic Locking):       

       悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自 外部系统的事务处理)修改持保守态度,因此,

       在整个数据处理过程中,将数据处于锁定状态。

       悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能 真正保证数据访问的排他性,否则,即使在本系统

       中实现了加锁机制,也无法保证外部系 统不会修改数据)

 乐观锁(Optimistic Locking):        
         相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。悲观锁大多数情况下依 靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之

而来的就是数据库 性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。 如一个金融系统,当某个操作员读取用户的数据,并在读出的用户数

据的基础上进 行修改时(如更改用户帐户余额),如果采用悲观锁机制,也就意味着整个操作过 程中(从操作员读出数据、开始修改直至提交修改结果的全

过程,甚至还包括操作 员中途去煮咖啡的时间),数据库记录始终处于加锁状态,可以想见,如果面对几 百上千个并发,这样的情况将导致怎样的后果。 乐

观锁机制在一定程度上解决了这个问题。

         乐观锁,大多是基于数据版本   Version )记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通

过为数据库表增加一个 “version” 字段来 实现。

所以,大数量的系统,必须考虑表拆分-(表名字不一样,但是结构完全一样),通用的几种方式:(视情况而定)

1)按业务分,比如 手机号的表,我们可以考虑 130开头的作为一个表,131开头的另外一张表 以此类推

2)利用oracle的表拆分机制做分表

3)如果是交易系统,我们可以考虑按时间轴拆分,当日数据一个表,历史数据弄到其它表。这里历史数据的报表和查询不会影响当日交易。

当然,表拆分后我们的应用得做相应的适配。单纯的or-mapping也许就得改动了。比如部分业务得通过存储过程等

此外,我们还得考虑缓存

这里的缓存,指的不仅仅是hibernate,hibernate本身提供了一级二级缓存。这里的缓存独立于应用,依然是内存的读取,假如我们能减少数据库频繁的访

问,那对系统肯定大大有利的。比如一个电子商务系统的商品搜索,如果某个关键字的商品经常被搜,那就可以考虑这部分商品列表存放到缓存(内存中

去),这样不用每次访问数据库,性能大大增加。

简单的缓存大家可以理解为自己做一个hashmap,把常访问的数据做一个key,value是第一次从数据库搜索出来的值,下次访问就可以从map里读取,而不

读数据库;专业些的目前有独立的缓存框架比如memcached 等,可独立部署成一个缓存服务器。

 

4、常见的提高高并发下访问的效率的手段

      首先要了解高并发的的瓶颈在哪里?

     1、可能是服务器网络带宽不够

     2.可能web线程连接数不够

     3.可能数据库连接查询上不去。

     根据不同的情况,解决思路也不同。

  1. 像第一种情况可以增加网络带宽,DNS域名解析分发多台服务器。

  2. 负载均衡,前置代理服务器nginx、apache等等

  3. 数据库查询优化,读写分离,分表等等

   最后复制一些在高并发下面需要常常需要处理的内容:

  • 尽量使用缓存,包括用户缓存,信息缓存等,多花点内存来做缓存,可以大量减少与数据库的交互,提高性能。

  • 用jprofiler等工具找出性能瓶颈,减少额外的开销。

  • 优化数据库查询语句,减少直接使用hibernate等工具的直接生成语句(仅耗时较长的查询做优化)。

  • 优化数据库结构,多做索引,提高查询效率。

  • 统计的功能尽量做缓存,或按每天一统计或定时统计相关报表,避免需要时进行统计的功能。

  • 能使用静态页面的地方尽量使用,减少容器的解析(尽量将动态内容生成静态html来显示)。

  • 解决以上问题后,使用服务器集群来解决单台的瓶颈问题。


0 0
原创粉丝点击