并发的常见问题和对应的解决方案

1、 最简单的,页面的《提交》按钮,在点击后(校验通过后)Disabled ,这样用户就不会重复点击《提交》按钮;

2、 数据库表增加唯一性索引(比如memberId ),这个只能解决一般(为什么一般,继续看)并发插入的问题;

如果两条一样的数据插入,只有一条会成功,另外一次插入失败;

3、 使用乐观锁,在Table 里增加一个version int 字段,这个可以保证更新操作的并发问题;

Select version, .. from table1 where id=?

//do biz

Update set version=version+1 where id=? And version=?

在代码里,需要判断update 返回的更新条数(count ==1?true:false )来判断本次更新是否成功

4、 使用悲观锁,一般使用数据库提供的功能(不建议);

select for update (悲观锁)

//do biz

Update ( 事物提交,锁释放)

5、 有时候,数据库不能加唯一性索引(比如由memberId,status 两个字段,业务要求memberId,status=approved 的数据唯一,其他状态的数据不做限制);

这个时候,需要寻求新的协调中心(之前是数据库光荣的承担这一角色),我们现在使用的Memcached 可以完成这个任务,利用memcached 协议规定add 的原子性,详细请点击这里

我们在信联项目里使用了这个方案,有一个缺点,就是需要侵入到业务代码里来控制并发,参考代码:     

方式1- 回调(推荐):

 try {

     concurrentTemplate.execute(key, new ConcurrentCallback() {

         public Object doInConcurrent() {

             // do your biz

             return null;

         }

     });

} catch (ConcurrentException e) {

     // catch this exception

     // return value;

}

方式二:自助获取和释放锁

 ConcurrentLock lock = null;

try {

     lock = concurrentTemplate.acquireLock(key);

     // do your biz

} catch (ConcurrentException e) {

     // catch this exception

     // return value;

} finally {

     concurrentTemplate.releaseLock(lock);

}

更多实现,请参考

http://svn.alibaba-inc.com/repos/ali_cn/olps/credit_shared/trunk/common/concurrent

6、 上面的故障4 案例,以上方案都解决不了,这个需要从设计入手来解决此问题,此方案敬请期待宝委会最近的案例分享;

 

写在最后

      随着我们现在系统的复杂性上升,在我们的设计上,必须要考虑并发问题 ,接下来我们会在《设计文档模板》上,增加并发这一章节的hit ,以提醒大家;

      同时,测试同学也需要提高并发方面的测试意识。

      同理,下次再出并发引起的故障,那就需要新的解释理由了。

猜你喜欢

转载自san-yun.iteye.com/blog/1602738