Redis—并发访问控制

Redis—并发访问控制

假如有这么一个场景,redis缓存了一个购物网站的商品库存,同时有两个用户对A商品下单购买了,分别都从redis读取了库存量,然后减一,又分别存回了数据库,此时商品库存应该减2,但是只减少了 1。

对此,多个客户端并发访问redis时,需要进行一定的访问控制

不需要加锁实现并发访问控制

1:像是简单的数值加减操作,可以调用redis提供的一些原子操作INCR/DECR进行增值减值操作

2:将多个不是原子操作的的操作合并在一起中写入LUA脚本执行,redis能保证lua脚本执行时是原子性的

基于Redis实现的分布式锁

由于分布式系统无法像运行在单个JVM的应用程序那样共用共享内存中的变量实现加锁操作

所以分布式锁需要用到一个共享的存储系统

同时由于高并发的分布式系统中 并发访问量大 对此获取锁与释放锁都需要性能比较高

且次共享存储系统必须是高可靠的 防止单台机器发生故障 分布式系统便无法利用锁来实现并发控制

redis便可以很好的实现这些特性

1:redis可以支持多个客户端的连接,是一个共享的key value数据库

2:redis支持高性能的读写 且redis多于多个客户端的请求是顺序执行命令的

3:redis也可以进行集群部署 部署主节点的备库 实现高可用

一般通过

SET key value EX/PX NX 命令进行加锁操作

NX能够保证key不存在则创建 返回OK(加锁成功) key存在则返回nil(获取锁失败)

EX/PX是设置过期时间 防止某个客户端加锁之后 执行业务逻辑时发生异常退出 不进行释放锁操作

使得其它客户端一直获取不到锁

每个客户端加锁时 value都设置成一个客户端唯一标识

防止客户端A加锁成功之后 客户端C执行DEL命令 将锁释放

所以每次释放锁之前 先比对一下value是否为本客户端唯一标识 是代表自己获取到了锁 可以释放

释放锁操作同样要保证原子性,因为设计三个步骤

1:读取key的value

2:比对value和自己的唯一标识

3:删除key

所以释放锁操作可以写入LUA脚本执行保证原子性

基于多个Redis实例的高可靠分布式锁

分布式锁算法RedLock

每次加锁时 向多个Redis实例依次发生加锁命令,满足下列两个条件加锁成功

1:超过半数的实例加锁成功

2:执行加锁的总耗时没有超过锁的有效时间

LUA脚本

优势

1:减少网络开销 一次向redis服务器发送多个请求

2:保证脚本多个操作整体的原子性

3:复用,其它客户端可以复用服务器执行过的lua脚本


版权声明:本文为qq_23850095原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>