java分布式并发唯一键冲突解决总结

        在单台web服务器情况下,我们处理并发的时候,可以用到关键字sychronized或相关并发类库即可方便处理。

        一旦遇到多台web服务器情况下,也就是分布式并发下,采用上述处理方式是不行的,因为存在多个jvm,以上方法就失效了。

       下面让我们考虑一个这样一个场景:

  • 业务背景:举办一场讲座,采取网上抢票分号码的行,号码不能重复,及讲座id与号码形成一个唯一键,如course表:id,seatNum,其他字段等等
  • 环境:多台web服务器提供服务
         要保证上述业务正常运行,可能会碰到并发情况,多个人抢到的号码一样,这样存入db时候,会抛出异常,因为设置了唯一键,不允许号码重复。那有什么方法能很好解决呢?
  1. 可以采用对表加锁方式,采用悲观锁能很好解决这个问题,但是效率不高,还可能出现死锁。采用乐观锁,也就是用程序实现时候发现抛出异常,就继续处理,这种方式较暴力,也没很好解决这个问题。
  2. 额外加一张表course_extra,seatNum作为自增主键,course_id等,每次分号码,直接往这个插入一条数据,这样保证每次seatNum自增,不会出现重复。
        要是有多场讲座,并且每场讲座的号码都从1开始呢?采用额外表的时候,是不是每场讲座都需要额外建一张表呢?这也太浪费数据库空间了吧。
  1. 这样的话,可以建另外一张表course_sequence:id, current_val, increment,每次取的时候,都获取current_val的值,并且采用自建函数如next_val或存储过程,每次获取当前值的时候,自动获取下一个值更新当前值,类似事务处理方式,不能拆开执行。否则,也有并发情况存在,导致重复。
  2. 采用分布式缓存memcache,采用自带的原子递增方式,能很好解决这个问题。为了防止缓存失效等问题,需要定时读、写数据库,保证号码是最大的,否则缓存一旦失效,也会面临类似并发问题。注意:原子递增时候,都需要采用string类型,int也需要转string才行。
        总结,最后在实际应用中,考虑到各种问题的存在,采用了memcache来解决。

你可能感兴趣的:(java常见问题总结,java分布式)