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. IDEA使用SpringBoot 、maven创建微服务的简单过程

    使用IDEA新建一个简单的微服务 1. 打开IDEA,File -> New  -> project 打开如下图1-1所示的对话框 图 1-1 2.点击"Next"按钮 ...

  2. ReactiveX 学习笔记(21)使用 Rx.NET + ReactiveUI 进行 GUI 编程

    课题 程序界面由3个文本编辑框和1个文本标签组成. 要求文本标签实时显示3个文本编辑框所输入的数字之和. 文本编辑框输入的不是合法数字时,将其值视为0. 3个文本编辑框的初值分别为1,2,3. 创建工 ...

  3. mysql数据库中指定值在所有表中所有字段中的替换

    MySQL数据库: 指定值在数据库中所有表所有字段值的替换(存储过程): 1.写一个存储过程,查指定数据库中所有的表名: CREATE PROCEDURE init_replace(in orig_s ...

  4. vue 未完待续

    1. v-text:主要用来更新textContent,可以等同于JS的text属性. <span v-text="msg"></span> 这两者等价: ...

  5. vivo手机,自带世界之窗浏览器,sessionStorage设置的值为null

    最近遇到一个小问题 用vivo手机自带浏览器,每次跳转到一个新页面都是重新打开一个webpage,导致sessionStorage设置的值都没了. 所以开发移动端网页时,谨慎使用sessionStor ...

  6. BlockTrain网络

    [BlockTrain网络] 1.每个节点都参与全⽹络的路由功能,同时也可能包含其他功能.每个节点都参与验证并传播交易及区块信息,发现并维持与对等节点的连接.在图6-1所⽰的全节点⽤例中,名为“⽹络路 ...

  7. socket failed: EACCES

    参考 https://blog.csdn.net/ct_ts/article/details/80010208 <uses-permission android:name=“android.pe ...

  8. Cocos2dx开发之屏幕适配

    由于各种智能手机的屏幕大小都不一致,会出现同一张图片资源在不同的设备分辨率下显示不一样的问题.为避免这样的情况,需要Cocos引擎能提供多分辨率的支持,也就是说要求实现这样的效果 — 开发者不需要考虑 ...

  9. OOm是否可以try catch ?

    只有在一种情况下,这样做是可行的: 在try语句中声明了很大的对象,导致OOM,并且可以确认OOM是由try语句中的对象声明导致的,那么在catch语句中,可以释放掉这些对象,解决OOM的问题,继续执 ...

  10. jquery 表单校验

    <link type="text/css" href="<%=basepath%>css/form/validate.css" rel=&qu ...