基于Redis的分布式锁(不公平锁)

[TOC]

基于Redis的分布式锁(不公平锁)

锁的应用场景

Redis其实是有事务功能的,但是Redis的事务不能回滚,具体原因就忘了,有兴趣可以看下<Redis设计与实现(第二版)>这本书.

分布式事务不会应用在MySQL等数据库中,因为这种数据库已经有完美的事务和锁机制了.

主要用在, 比如在集群机器抢购时,你没有使用Redis队列,而是在Redis的string定义一个数字作为商品总量.比如set phone_count 10000台手机.

这时候如果出现并发修改(肯定会有并发),比如10个用户同时修改该字段decr phone_count可能是不准确的,因为可能会很多人都在修改.

这时候就需要我们自己来实现一套基于Redis锁机制,悲观锁.

锁的实现介绍

Redis的所有命令都是具有原子性的,之所以说要用锁,是因为可能有多个用户同时修改,那么我们的得到的数据就会是不准确的.

  • Ggetset: 字段存在时同时返回字段的内容
  • Setnx: 字段存在时,set会失败
  • Decr: 会出现小于0的负数情况

假定,超时时间为2秒.

假定商品数量为1000台 set phone_count 1000

  • get phone_count如果返回值小于等于零,直接提示已抢完.
  • 直接声明$time=time()尝试进行加锁,Setnx Lock $time
  • 如果setnx失败,说明已有锁,执行while循环get Lock和while中的$time=time()对比,如果差大于2秒则为超时, 直接del Lock,然后Setnx Lock $time
  • 如果setnx成功,则为加锁成功,开始执行逻辑decr phone_count,如果这个过程执行超过了2秒,必然会被后面来的del Lock
  • 所以在逻辑执行完毕之后, 此时我们再次get Lock查看Redis的时间戳是否是$time,如果不相等则回滚事物.
  • 如果相等, 再对比当前时间戳和get Lock内容,如果差小于2秒,判断decr的返回值如果大于等于0则提示success同时del Lock.
  • 如果当前时间戳和Lock的内容差大于2或者和之前保存的时间戳不是同一个.则提示抢购失败.或者decr的结果小于等于0,则提示抢购完毕.

如果要做公平锁的话就需要用到zset的zadd等有序队列的命令

可以使用Redis命令中混合lua的形式

这篇博文是真的不错, 一直关注博主, 跟随博主学习好多年了.

飞鸿影的博客-Redis使用lua脚本

看完上面的博客之后,结合上面说的分布式锁的思路, 一套基于redis的lua脚本的形式的完成的分布式锁的代码就出现了. 这里就不累述了

转载于:https://my.oschina.net/chinaliuhan/blog/3084455

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值