您的位置:首页 > 其它

多服务分布式并发问题的理解

2014-12-17 09:51 225 查看
最近在研究一些并发的问题,我们知道java中控制并发有很多种方式,但是由于现在项目中一般都不可能把服务器布置成单点,都是以多台服务器集群的方式,所以在java中去加锁已经无法完全控制并发问题了。在我碰到的项目中,数据库的写入基本可以用单点这个词来形容,所以在数据库中我们可以做到并发的控制。

关于UPDATE的并发控制

update数据库的时候,数据库控制并发的方式,基本分为2种:

1.锁更新的那条记录。

锁记录我们一般的操作就是SELECT ... FOR UPDATE,行级锁。这个SQL在读取完数据后,就能把这行数据锁住,防止其它SESSION对行数据进行修改。这就是我们所说的悲观锁。为什么叫悲观锁呢,因为它会让其它SESSION阻塞,等待锁定行记录的那条SESSION将修改COMMIT掉后才能获得对行数据的操作资源。

我们通常不提倡用悲观锁,为什么呢?因为我们通常公司里的服务都是访问量挺高的,所以占用数据池资源是挺大的,如果用悲观锁,就会导致很多的资源阻塞而无法使用,这样我们的系统便会变得很慢,老是在等资源。

个人觉得悲观锁的使用场景得看业务和实际情况,如果这个模块本身访问量就很低,那就可以用悲观锁。

2.在表中加入版本号字段,更新时将版本号同时更新。

在表中加入字段,每次UPDATE前会先去读取该版本号(可以是一个整数),更新的时候将之前读取版本号加1再和实际那行的版本号比较,如果大于实际版本号便更新,其他则失败。举个例子,比如表中的字段LOCK_ST = 0。2个SEESION同时去更新它,a SESSION和b SESSION同时会读取0这个值,然后a比较快,更新了这条数据,并把版本字段LOCK_ST更新成1,这个时候b再去更新,b会把读到的LOCK_ST加1,也就是0+1,然后提交更新的时候比较版本号,发现1=1,所以更新不了,于是b就失败了。这就是我们所说的乐观锁。不锁定资源,任由所有SESSION都去更新,但是更新会失败。

通常我们的系统中比较提倡乐观锁,原因和悲观锁正好相反。

关于INSERT的并发控制

刚才我们谈到了乐观锁和悲观锁可以用来控制多服务的并发,那么INSERT数据的时候怎么控制呢?它根本没有行数据的概念,所以就不存在之前那2种做法。最近我想了一些办法,可能不是最好的办法,如果大家有更好的办法可以留言告诉我如何控制。

首先看插入的数据,如果每条数据有区分它们的唯一字段,那可以给那个字段加入UNIQUE唯一键属性,这样2条有共同字段的数据不能插入。比如一个身份证只能建立一条用户信息,当2个用户用同一个身份证注册插入数据时,我们只要设置身份证为UNIQUE唯一键,那么第二条便插入不了。这个其实并不只是在控制并发,其实串行的事务也能控制。所以它不能称为针对并发的控制,只能说可以避免并发。

那么还有一个问题,如果插入的这条数据身份证号系统要拿去公安局校验,而校验的结果是异步的。如果校验失败,用户还能再插入一次数据,那么这样的场景就是身份证号不能作为唯一键来使用了。对于这个问题,我已经想出一种办法了,就是建立临时表加身份证临时字段。但不一定最好,所以大家如果有好的方法可以留言告诉我。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐