前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Redisson初级原理 & Redisson主从一致性的原理

Redisson初级原理 & Redisson主从一致性的原理

作者头像
收心
发布2022-08-23 17:21:49
4080
发布2022-08-23 17:21:49
举报
文章被收录于专栏:Java实战博客

参考于:https://www.bilibili.com/video/BV1cr4y1671t?p=67&share_source=copy_web&vd_source=164fe0eebbe1de2dc8ea1db9b173c783

这是常规Redisson使用代码

代码语言:javascript
复制
    @Autowired
    Redisson redisson;

    @Test
    public void Redisson入门Demo() {
        String lockKey = "自定义一个key(一般是用户Id锁自己的操作)";
        RLock redissonLock = redisson.getLock(lockKey);
        boolean doLockRes = redissonLock.tryLock();
        if (doLockRes) {
            try {
                // TODO 执行业务操作
            } finally {
                if (doLockRes) {
                    redissonLock.unlock();
                }
            }
        } else {
            System.out.println("加锁失败!");
        }
    }

idea查看trylock方法 其是一个接口,我们去找具体实现RedisonLock类的发现其调用

代码语言:javascript
复制
    @Override
    public boolean tryLock() {
        return get(tryLockAsync());
    }

    <T> RFuture<T> tryLockInnerAsync(long waitTime, long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand<T> command) {
        return evalWriteAsync(getRawName(), LongCodec.INSTANCE, command,
                "if (redis.call('exists', KEYS[1]) == 0) then " +
                        "redis.call('hincrby', KEYS[1], ARGV[2], 1); " +
                        "redis.call('pexpire', KEYS[1], ARGV[1]); " +
                        "return nil; " +
                        "end; " +
                        "if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +
                        "redis.call('hincrby', KEYS[1], ARGV[2], 1); " +
                        "redis.call('pexpire', KEYS[1], ARGV[1]); " +
                        "return nil; " +
                        "end; " +
                        "return redis.call('pttl', KEYS[1]);",
                Collections.singletonList(getRawName()), unit.toMillis(leaseTime), getLockName(threadId));
    }

原码讲解:

  • KEYS[1]:Collections.singletonList(getRawName()) 是Redis中存的键名,不是key名。来自于redisson.getLock(lockKey)时指定的名字
  • ARGV[1]:unit.toMillis(leaseTime) 锁的持有时间
  • ARGV[2]:getLockName(threadId) key的名字
  • hincrby Redis的Hash的键自增
  • pexpire 设定过期时间

整体讲解

  • 首先判断键不存在,直接指定为1,并加入过期时间,加锁成功,返回空
  • 如果键存在且key等于1时,加锁成功,返回空
  • 上述条件不满足,直接返回键的过期时间

上述就是lua的加锁脚本。再去看看释放锁的源码(也再RedisonLock类中):

代码语言:javascript
复制
    protected RFuture<Boolean> unlockInnerAsync(long threadId) {
        return evalWriteAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
                "if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then " +
                        "return nil;" +
                        "end; " +
                        "local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1); " +
                        "if (counter > 0) then " +
                        "redis.call('pexpire', KEYS[1], ARGV[2]); " +
                        "return 0; " +
                        "else " +
                        "redis.call('del', KEYS[1]); " +
                        "redis.call('publish', KEYS[2], ARGV[1]); " +
                        "return 1; " +
                        "end; " +
                        "return nil;",
                Arrays.asList(getRawName(), getChannelName()), LockPubSub.UNLOCK_MESSAGE, internalLockLeaseTime, getLockName(threadId));
    }

大致原理太多太复杂了,不搞了!

反正整体来看的原理就是

  • 重入性:记录线程id与重入次数
  • 重试性:利用Redis的Pub/Sub 实现等待、唤醒、获取锁失败的重试机制

Redisson的解决Redis集群的主从一致性原理

Redis主从在切换时,会导致数据不一致。如果在切换异常期间就会导致解锁失败等情况。

Redisson解决办法时MuiltLock。就是向所有节点加锁,当所有节点锁加成功后,才算加锁成功!避免了数据不一致性!

特殊说明: 以上文章,均是我实际操作,写出来的笔记资料,不会盗用别人文章!烦请各位,请勿直接盗用!转载记得标注来源!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 反正整体来看的原理就是
  • Redisson的解决Redis集群的主从一致性原理
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档