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. Rabbitmq 与springboot 结合

    <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring- ...

  2. django 数据库查询 ORM

    实用的logging模块: zaisetting配置中加入下列配置,将sql语句打印到屏幕上,可以进行查看. LOGGING = { 'version': 1, 'disable_existing_l ...

  3. 编织织物的knit course direction and knit wale direction

    来自:http://www.definetextile.com/2013/04/course-wale.html

  4. 数据库设计,表与表的关系,一对多。One-To-Many(2)

    一对多:主键数据表中只能包含一个记录,而在其关系记录表中这条记录可以与一个或多个记录相关,也可以没有记录与之相关. 关联映射:一对多/多对一存在最普遍的映射关系,简单来讲就如球员与球队的关系:一对多: ...

  5. faster rcnn源码阅读笔记2

  6. R语言-箱型图&热力图

    1.箱型图 boxplot()函数 > metals<-read.csv("metals.csv",header=TRUE) #读取文件和列名 > boxplot ...

  7. Java学习笔记(十九):Object类

  8. Pandas数据的去重,替换和离散化,异常值的检测

    数据转换 移除重复数据 import pandas as pd import numpy as np from pandas import Series data = pd.DataFrame( {' ...

  9. Linux 禁止普通用户su到root

    Linux账户权限管理上为了防止普通用户通过su切换到root用户,需要修改/etc/pam.d/su和/etc/login.defs两个配置文件. Step1:修改 /etc/pam.d/su文件 ...

  10. 36 【kubernetes】coredns

    CoreDNS是k8s中,master节点和从节点及其pods之间通信的接口. 但是上个博客中遇到一个问题dns一直处于crush的状态. https://www.cnblogs.com/helww/ ...