挑灯夜读——Redis实现分布式锁:含解决分布式问题思路

本次参考自redis的官方文档,主要作为自己学习的一个记录,并能够整理和精化其内容,希望大家指正。

分布式锁

分布式锁在很多高并发的场景中使用,比如电商中的秒杀活动、限量的优惠券的抢购等等,这样的一个场景特点就是访问量极具增长。尽管系统使用了限流、异步、排队的方式优化,但是整体还是没有达到效果,为了避免逻辑错误,这些系统往往都会使用到锁,比如一共有九十九张百元优惠券,但是抢券的人数达到了五万多人,这样的场景显然使用到分布式锁,每当有一个进入券系统并拿到了锁,那么其他人就只能等待系统将券减一,并释放掉锁。

因此一般一个安全的分布式锁应该具备以下特征:

  • 互斥性。互斥是锁的基本特征,同一时刻只能被一个线程持有,执行临界区操作。
  • 超时释放。通过超时释放,避免死锁
  • 可重入性。一个线程在持有锁的情况下可以再次请求加锁。防止锁没操作完就提前释放。
  • 高性能和高可用。加锁和释放锁的过程尽量开销低。

其中实现的方式有很多,一般为:

分布式锁类型特征
Memecached分布式锁利用其add命令,该命令是原子操作,只有在key不存在的情况下,才能add成功,也就意味线程得到了锁
Zookeeper分布式锁利用其顺序临时节点,来实现分布式锁和等待队列。该框架专门为分布式应用提供方案
Chubby锁Google实现的粗粒度分布式锁服务,通过sequencer机制解决了请求延迟造成的锁失效问题
Redis分布式锁基于Redis单机实现的分布式锁,其方式和memecached很像,利用redis的SERNX命令,实现了原子操作,只有在key不存在的情况下,才能set成功。

Redis分布式锁演变

上面我们也看到了通过redis实现的分布式锁,具体的实现细节可以通过Redsync.go或者Redisson查看。

其实实现redis分布式锁很简单,就是在redis创建一个key,这个key设置一个失效时间(TTL),以保证锁最后能释放,确保不会产生死锁。当客户端释放资源的时候,就会删除掉这个key。

虽然表面上看效果不错,但是还是有个问题:这个架构中存在一个严重的单点失败问题,如果redis挂掉了,在增加slave作为主节点的过程中,有其他线程来获取slave节点的锁,就会出现安全失效的情况。

因此,在尝试克服上述单实例设置的限制之前,让我们使用原子锁的命令

SET resource_name my_random_value NX PX 30000

这个命令仅在不存在key的时候才能被执行成功(NX选项),并且这个key有一个30秒的自动失效时间(PX属性)。这个key有个随机值“my_random_value“,这个值在所有的客户端必须是唯一的,所有同一个key的获取者这个值都不能一样。

value值必须是随机的主要原因是为了更安全的释放锁,释放锁的时候使用脚本告诉redis:只有key存在并且存储的值和我指定的一样才能删除成功。使用这个方式释放锁主要是为了避免别的客户端获取成功的锁

Redlock算法

在redis的分布式环境中,我们假设有N个Redis master。这些节点完全互相独立,不存在主从复制或者其他集群协调机制。我们在五台机器或者五台虚拟机上运行这些实例,这样就能保证他们不会同时宕机。

为了取得锁,客户端应该执行以下操作:

  1. 获取当前的Unix时间,以毫秒为单位
  2. 依次尝试从N个实例,使用相同的key和随机值来获取锁。其中redis设置锁的时候,超时时间应该小于锁的失效时间。这样就避免了服务器端挂掉了,客户端不会死死的等待结果。如果服务器没有响应,客户端会尝试其他redis实例。
  3. 客户端使用当前时间剪去第一步获取到的时间就是锁使用的时间。当且仅当大多数的redis节点都取得锁,并且使用的时间小于锁失效时间,锁才算获取成功。
  4. 如果取得了锁,key的真正有效时间=有效时间-获取锁使用的时间
  5. 如果获取锁失败了,没有在至少N/2+1个redis实例取得锁或者取锁时间已经超过有效时间。则客户端应该在所有的redis实例上进行解锁。

总结

本次的文章编写,主要是在梳理系统的内容中,查看到了redis锁的使用,便展开进行了了解,这也算大致对其原理有了些了解,下面就准备去看源码了。奥力给!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

米店不卖你

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值