redis设计与实现第三版 pdf_轻量级分布式锁的设计原理分析与实现

本文探讨了分布式锁的设计原因和面临的问题,详细分析了基于Redis的五种加锁与三种释放锁的实现方式及其存在的问题。还介绍了利用Zookeeper实现分布式锁的基本思路,比较了Redis和Zookeeper在分布式锁上的优劣。
摘要由CSDN通过智能技术生成
7c7d4d7efdbd3bef92bddecc19f58d45.png

为什么要设计分布式锁

在简单的单机系统中,当存在多个线程同时要修改某个共享变量时,为了数据的操作安全,往往需要通过加锁的方法,在同一时刻同一代码块只能有一个进程执行操作,存在很多加锁的方式,比如在java中有synchronize或Lock子类等。 但是在分布式中,会存在多个主机,即会存在多个jvm, 在jvm之间数据是不能共享的,上面的方法只能在一个jvm中执行有效,在多个jvm中同一变量可能会有不同的值。所以我们要设计一种跨jvm的共享互斥机制来控制共享变量资源的访问,这也是提出分布式锁的初衷。

需要解决的问题

为了将分布式锁实现较好的性能,我们需要解决下面几个重要的问题:

  • 一个方法或代码片段在同一时刻只能被一个进程所执行。
  • 高可用的获取锁与释放锁功能。
  • 避免死锁
  • 锁只能被持有该锁的客户端删除或者释放。
  • 容错,在服务器宕机时,锁依然能得到释放或者其他服务器可以进行加锁。

下面分别利用redis和zookeeper来实现加锁和解锁机制。

基于Redis的加锁第一版

本版本通过变量sign设置锁的唯一标识,确保只有拥有该锁的客户端才能删除它,其他客户端不能删除。利用阻塞锁的思想, 通过while(System.currentTimeMillis() < endTime)和Thread.sleep()相结合,在设置的规定时间内进行多次尝试。但是setnx操作和expire分割开了,不具有原子性,可能会出现问题。比如说,在执行到jedis.expire时,可能系统发生了崩溃,导致锁没有设置过期时间,导致发生死锁。

 public String addLockVersion1(String key, int blockTime, int expireTime) {        if (blockTime <=0 || expireTime <= 0)            return null;        Jedis jedis = null;        try {            jedis = jedisPool.getResource();            String sign = UUID.randomUUID().toString();            String token = null;            //设置阻塞尝试时间            long endTime = System.currentTimeMillis() + blockTime;            while (System.currentTimeMillis() 

基于Redis的加锁第二版

通过设置key对应的value值为锁的过期时间,当遇到系统崩溃,致使利用expire设置锁过期时间失败时,通过获取value值,来判断当前锁是否过期,如果该锁已经过期了,则进行重新获取。

但是它也存在一些问题。当锁过期时,如果多个进程同时执行jedis.getSet方法,虽然只有一个进程可以获得该锁,但是这个进程的锁的过期时间可能被其他进程的锁所覆盖。该锁没有设置唯一标识,也会被其他客户端锁释放,不满足只能被锁的拥有者锁释放的条件。

public boolean addLockVersion2(String key, int blockTime, int expireTime) {        if (blockTime <=0 || expireTime <= 0)            return false;        Jedis jedis = null;        try {            jedis = jedisPool.getResource();  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值