zoukankan      html  css  js  c++  java
  • redis 分布式读写锁

    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

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

  • 相关阅读:
    WSS页面定制系列(1)如何启用表单页面的编辑模式
    [转载]Customizing the Context Menu of Document Library Items
    MOSS publishing功能:创建页面到子文件夹
    CodeArt.SharePoint.CamlQuery_0.9发布(源码)
    WSS页面定制系列(2)定制单个列表的表单页面
    WSS页面定制系列(3)重写表单的保存逻辑
    MOSS字段编辑权限控制方案(3)重写表单字段呈现逻辑
    WSS(MOSS)如何修改Rich文本编辑器的宽度
    web录音的实现
    WSS 扩展文件夹的属性如何给文件夹添加扩展字段
  • 原文地址:https://www.cnblogs.com/hangj/p/8013202.html
Copyright © 2011-2022 走看看