读读Redis的官网,学第一手的资料:Redid官方文档地址
Redis中国-文档网址:Redis中国-文档地址
或者看看书《Redis 深度历险: 核心原理和应用实践》
1、Redis 的并发竞争问题是什么?
看到这个标题,有人可能会有疑问了,redis不是单线程的吗,怎么还会有并发竞争问题?
其实是这样的,redis并发竞争是多个客户端并发写一个key,本来应该是先到的请求先写key,但可能由于网络环境差异,先发起的请求后到了,导致value最终被后发起的请求修改,最终数据错乱了。或者是多个客户端同时获取一个key,修改值后再写回去,只要顺序错了,数据纠错了。
图1 redis并发问题
现象:
客户端1修改库存为999,客户端2修改库存为998;客户端3修改库存为997。
我们期望的更新库存顺序树set inventory 1000 -> 999 -> 998 -> 997,但由于网络环境差异,影响了更新库存请求达到顺序。可能变成set inventory 1000 -> 999 -> 997 -> 998。期望的库存最终是997,但实际是998,导致数据最终出错。
2、解决方案:
解决这种问题的方案也很简单,就是用分布式锁。
当然了如果你系统缓存并发量很低,你的业务场景中不会出现并发竞争问题,就不要用分布式锁。
分布式锁是一个很重的解决方案,锁的本质是使并发的请求串行化执行,会大大的降低系统性能和吞吐量,所以在生成环境中,能不用就不用。
2.1 分布式锁常用的解决方案有两种:
1)基于redis,可以使用redisson框架使用;
2)基于zookeeper,可以使用curator框架使用;
两种解决方案怎么选型后面会专门讲解,这里就不细说了。
图2 基于分布式锁解决缓存并发更新问题
写入缓存的时候,同时把更新时间写到缓存里,同时每次要写缓存之前,先判断一下当前这个库存的时间戳是否比缓存里的时间戳要新。如果是的话,那么可以写,否则,就不能用旧的数据覆盖新的数据。
比如当前更新缓存库存时间是:10:00:02,现在三个客户端发起更新缓存,它们执行请求的时间分别是:
客户端1:10:00:01
客户端2:10:00:03
客户端3:10:00:04
客户端1的时间 < 缓存更新时间,所以就不更新,客户端2和客户端端3的时间大于10:00:02,可以更新。
假如客户端3先更新,缓存时间就变成了:10:00:04,客户端2再来更新,由于它的时间10:00:03 < 10:00:04,就是用旧数据覆盖新数据,是不被允许了,所以就不执行更新。
这样就不会有数据错了的问题了。
3、Redis事务的CAS方案
看官网哈
Transactions
How transactions work in Redis
Redis Transactions allow the execution of a group of commands in a single step,
they are centered around the commands MULTI, EXEC, DISCARD and WATCH.
Redis Transactions make two important guarantees:
All the commands in a transaction are serialized and executed sequentially.
A request sent by another client will never be served in the middle of the execution of
a Redis Transaction. This guarantees that the commands are executed as
a single isolated operation.
The EXEC command triggers the execution of all the commands in the transaction,
so if a client loses the connection to the server in the context of a transaction
before calling the EXEC command none of the operations are performed,
instead if the EXEC command is called, all the operations are performed.
When using the append-only file Redis makes sure to use a single write(2) syscall to
write the transaction on disk. However if the Redis server crashes or is killed by
the system administrator in some hard way it is possible that only a partial number of
operations are registered. Redis will detect this condition at restart,
and will exit with an error. Using the redis-check-aof tool it is possible to
fix the append only file that will remove the partial transaction so that
the server can start again.
Starting with version 2.2, Redis allows for an extra guarantee to the above two,
in the form of optimistic locking in a way very similar to a check-and-set (CAS) operation.
This is documented later on this page.
再看看官网中下面的表述: