Redis的并发竞争问题,主要是发生在并发写竞争。考虑到redis没有像db中的sql语句,update val = val + 10 where ...,没法使用这种方式进行对数据的更新。html
假若有某个key(mileage), value(10),如今想把value值进行+10操做。正常逻辑下,就是先把数据key为mileage的值读回来,加上10,再把值给设置回去。java
若是只有一个链接的状况下,这种方式没有问题,能够工做得很好,但若是有两个链接时,两个链接同时想对还mileage进行+10操做,就可能会出现问题了。redis
例如:两个链接同时对mileage进行写操做,同时加10,最终结果咱们知道,应该为30才是正确。sql
考虑到一种状况:并发
T1时刻,链接1将mileage读出,目标设置的数据为10+10 = 20。post
T2时刻,链接2也将数据读出,也是为10,目标设置为20。性能
T3时刻,链接1将mileage设置为20。url
T4时刻,链接2也将mileage设置为20,则最终结果是一个错误值20。spa
另外假设有个A线程正在写mileage,B线程正在读写mileage,当A,B同时执行的时候也可能发生并发竞争问题:操作系统
即B将mileage值读出来的时候,A正好更新了mileage值,而后B又更新回mileage值,此时照成A的更新无效。
利用redis自带的incr命令,具体用法看这里http://doc.redisfans.com/string/incr.html。
利用redis的setnx实现内置的锁。
使用乐观锁的方式进行解决(成本较低,非阻塞,性能较高)。如何用乐观锁方式进行解决?本质上是假设不会进行冲突,使用redis的命令watch进行构造条件。伪代码以下:
watch mileage get mileage $mileage $mileage = $mileage + 10 multi set mileage $mileage exec
解释一下:
watch这里表示监控该key值,后面的事务是有条件的执行,若是从watch的exec语句执行时,watch的key对应的value值被修改了,则事务不会执行。
具体看Redis的事务功能详解这篇文章里的watch命令介绍。
这个是针对同一个服务的客户端来的,在代码里要对redis操做的时候,针对同一key的资源,就先进行加锁(java里的synchronized或lock)。
能够使用独占锁的方式,相似操做系统的mutex机制。(网上有例子,http://blog.csdn.net/black_ox/article/details/48972085 不过实现相对复杂,成本较高)