http://zhangtielei.com/posts/blog-redlock-reasoning.html

链接里这篇 blog 讨论了 redis 分布式锁的实现以及安全性

我要参考 基于单Redis节点的分布式锁,实现一个 基于单Redis节点的分布式读写锁

先是想到一个不是很好的方案

read lock

eval "if not redis.call('GET', KEYS[1]) then return redis.call('SET', KEYS[2] .. '.' .. ARGV[1], ARGV[1], 'NX', 'PX', ARGV[2]) end" 2 rwlock.write rwlock.read unique_value 300000

write lock 分两步,第一步 SET 成功且第二步返回空,则写锁成功。第二步等待所有的读都解锁,只是这个 KEYS 命令效率太低,所以说这不是一个好方案

SET rwlock.write unique_value NX PX 300000
KEYS rwlock.read.*

read unlock

DEL rwlock.read.unique_value

write unlock

eval "if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('DEL', KEYS[1]) end" 1 rwlock.write unique_value

这个读写锁有个好处,当有人等待可写状态时,不会再有新的人增加读状态的人数,所以不会有等到死也等不来可写状态的事情发生

好一点的读写锁

参考 https://github.com/redisson/redisson/blob/master/redisson/src/main/java/org/redisson/RedissonReadLock.java

额外弄一个 hash table 存取读的信息,避免用 KEYS 命令。大致步骤如下

read lock

eval
"if not redis.call('GET', KEYS[1]) then
redis.call('HSET', KEYS[2], ARGV[1], ARGV[2])
redis.call('SET', ARGV[1], ARGV[2], 'PX', ARGV[2])
local t = redis.call('PTTL', KEYS[2])
redis.call('PEXPIRE', KEYS[2], math.max(t, ARGV[2]))
end" 2 rwlock.write rwlock.read unique_value 300000

write lock

SET rwlock.write unique_value NX PX 300000
EXISTS rwlock.read  // 这里等待的时候应该不断地更新 rwlock.write 的过期时间

read unlock

"if redis.call('HEXISTS', KEYS[1], KEYS[2]) == 0 then return end
redis.call('HDEL', KEYS[1], KEYS[2]);
local t1 = redis.call('PTTL', KEYS[1]);
local t2 = redis.call('PTTL', KEYS[2]);
redis.call('DEL', KEYS[2])
if t1 > t2 then return end
local maxRemainTime = -2
local keys = redis.call('HKEYS', KEYS[1]);
for k,v in pairs(keys) do
local remainTime = redis.call('PTTL', v)
maxRemainTime = math.max(maxRemainTime, remainTime)
end
if maxRemainTime > 0 then
redis.call('PEXPIRE', KEYS[1], maxRemainTime)
end" 2 rwlock.read unique_value

write unlock

eval "if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('DEL', KEYS[1]) end" 1 rwlock.write unique_value

第二种如果要支持重复加锁,只需稍微再改改

redis 分布式读写锁的更多相关文章

  1. Java之——redis并发读写锁,使用Redisson实现分布式锁

    原文:http://blog.csdn.net/l1028386804/article/details/73523810 1. 可重入锁(Reentrant Lock) Redisson的分布式可重入 ...

  2. Redis实现分布式读写锁(Java基于Lua实现)

    https://blog.csdn.net/grandachn/article/details/89032815 https://blog.csdn.net/xingsilong/article/de ...

  3. 使用ZooKeeper实现Java跨JVM的分布式锁(读写锁)

    一.使用ZooKeeper实现Java跨JVM的分布式锁 二.使用ZooKeeper实现Java跨JVM的分布式锁(优化构思) 三.使用ZooKeeper实现Java跨JVM的分布式锁(读写锁) 读写 ...

  4. 【分布式锁】07-Zookeeper实现分布式锁:Semaphore、读写锁实现原理

    前言 前面已经讲解了Zookeeper可重入锁的实现原理,自己对分布式锁也有了更深的认知. 我在公众号中发了一个疑问,相比于Redis来说,Zookeeper的实现方式要更好一些,即便Redis作者实 ...

  5. redis 读写锁实现

    一 先搞清楚读写锁要做什么. 基本就是 读读不互斥,读写互斥,写写互斥.可重入. 关于redis读写锁,我写了一次之后,总觉得很怪,然后就上网看到大神的redisson了,果断借鉴一番. 二 读行为 ...

  6. 一文读懂 Redis 分布式部署方案

    为什么要分布式 Redis是一款开源的基于内存的K-V型数据库,因为内存访问速度快,一般被用来做系统的缓存. Redis作为单机部署能够支持业务简单,数据量不大的系统需求,但在实际应用中,一旦系统规模 ...

  7. Redis专题(3):锁的基本概念到Redis分布式锁实现

    拓展阅读:Redis闲谈(1):构建知识图谱 Redis专题(2):Redis数据结构底层探秘 近来,分布式的问题被广泛提及,比如分布式事务.分布式框架.ZooKeeper.SpringCloud等等 ...

  8. 死磕 java同步系列之redis分布式锁进化史

    问题 (1)redis如何实现分布式锁? (2)redis分布式锁有哪些优点? (3)redis分布式锁有哪些缺点? (4)redis实现分布式锁有没有现成的轮子可以使用? 简介 Redis(全称:R ...

  9. 乐观、悲观锁、redis分布式锁

    悲观锁总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给 ...

随机推荐

  1. Python入门:Anaconda和Pycharm的安装和配置

    Python入门:Anaconda和Pycharm的安装和配置  转自:https://www.cnblogs.com/yuxuefeng/articles/9235431.html 子曰:“工欲善其 ...

  2. 【395】yield 和 yield from

    yield:生成器 yield from:将生成器 yield 的内容相当于逐一在 yield 一般 参考:Python 3: Using "yield from" in Gene ...

  3. 百度分享不支持Https的解决方案--本地化

    站点自从开启 https 之后 ,百度分享就不能用了!但是又寻找不到类似百度分享的替代品.. 怎么办呢?要如何解决 百度分享不支持https的问题呢, 跟着博主动动手,让你百度分享仍然能在https下 ...

  4. java应用健康检查

    本文主要针对自己手写shell监控应用状态,有可系统解决方案的,比如K8S,可以略过 #!/bin/sh#health_check.sh count=`ps -ef | grep test.jar | ...

  5. 编程语言的分类及其优缺点,Python标准输入与输出

    一. 编程语言分类 1.机器语言 以0,1的组合作为指令集,用二进制指令来编写程序: 优点:执行效率高 缺点:开发效率低 2.汇编语言 用英文标签代替二进制指令集来编写程序,比机器语言稍微高级,但本质 ...

  6. 联想电脑t450,t460p,t470等安装好ubuntu后启动找不到系统

    其实我是这样解决的: 进入bios: 关quick start 关security 然后reboot就可以了

  7. 新建jsp项目

    选择 下面类型

  8. 整数中1出现的次数(从1到n整数中1出现的次数)(python)

    题目描述 求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1.10.11.12.13因此共出现6次,但是对于后面问题他就没辙了. ...

  9. 用归并排序或树状数组求逆序对数量 poj2299

    题目链接:https://vjudge.net/problem/POJ-2299 推荐讲解树状数组的博客:https://blog.csdn.net/int64ago/article/details/ ...

  10. Android Studio修改项目中整体包名

    莫名的需求,要把之前的apk分成三个不同的apk,还要在应用市场能够上线,麻麻滴这样一听那还不要各个apk包的包名不同以及apk签名文件也不同嘛(签名文件一般也用不同,为防止上线冲突嘛).所以就亲自尝 ...