Redis与分布式-分布式锁

接上文 Redis与分布式-集群搭建

1.分布式锁


为了解决上述问题,可以利用分布式锁来实现。

重新复制一份redis,配置文件都是刚下载时候的不用更改,然后启动redis服务和redis客户。

redis存在这样的命令:和set命令差不多,但是它有一个机制,当指定的key不存在的时候,才能进行插入,实际上就是 set if not exists的缩写,当key被删除后可以进行插入。

c 复制代码
setnx key value

利用这种特性,可以再不同的服务中实现分布式锁。但是若某个服务加了锁并且卡顿了,或者崩溃,那么这把锁永远无法释放了,因此可以加过期时间:set a666 EX 5 NX



如果学习过JUC并发编程,会发现若在超时之前那一刻进入到释放锁的阶段,获取到的值肯定还是自己,但是在即将执行删除之前,由于超时机制导致被删除并且其他任务也加锁了,那么这时候在删除,仍会导致删除其他任务加的锁

导入Redisson依赖

c 复制代码
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.17.0</version>
</dependency>

<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.1.75.Final</version>
</dependency>

不加锁的情况

c 复制代码
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try(Jedis jedis = new Jedis("192.168.0.10", 6379)){
                    for (int j = 0; j < 100; j++) {   //每个客户端获取a然后增加a的值再写回去,如果不加锁那么肯定会出问题
                        int a = Integer.parseInt(jedis.get("a")) + 1;
                        jedis.set("a", a+"");
                    }
                }
            }).start();
        }
    }

在redis中设置a=0,然后测试不加锁

取出a,得出结果不对

测试加锁

c 复制代码
public static void main(String[] args) {
    Config config = new Config();
    config.useSingleServer().setAddress("redis://192.168.0.10:6379");   //配置连接的Redis服务器,也可以指定集群
    RedissonClient client =  Redisson.create(config);   //创建RedissonClient客户端
    for (int i = 0; i < 10; i++) {
        new Thread(() -> {
            try(Jedis jedis = new Jedis("192.168.0.10", 6379)){
                RLock lock = client.getLock("testLock");    //指定锁的名称,拿到锁对象
                for (int j = 0; j < 100; j++) {
                    lock.lock();    //加锁
                    int a = Integer.parseInt(jedis.get("a")) + 1;
                    jedis.set("a", a+"");
                    lock.unlock();   //解锁
                }
            }
            System.out.println("结束!");
        }).start();
    }
}

执行完a的值加了1000,此时写入为正常

此时若用于存放锁的redis服务挂了,那么肯定会出问题的,这个时候可以用RedLock,它的思路是在多个redis服务器上保持锁,只需要超过半数的redis服务获取到锁,那么就真的获取到锁了,这样挂掉一部分节点,也能保证正常运行。

相关推荐
Elastic 中国社区官方博客15 分钟前
Elasticsearch:使用 Agent Builder 的 A2A 实现 - 开发者的圣诞颂歌
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
2301_8166602117 分钟前
PHP怎么处理Eloquent Attribute Inference属性推断_Laravel从数据自动推导类型【操作】
jvm·数据库·python
qq_372154231 小时前
Go 中自定义类型与基础类型的显式转换规则详解
jvm·数据库·python
_下雨天.2 小时前
NoSQL之Redis配置与优化
数据库·redis·nosql
LiAo_1996_Y2 小时前
CSS如何实现文字渐变效果_通过background-clip实现艺术字
jvm·数据库·python
2401_887724502 小时前
CSS如何让表单在手机端友好展示_利用Flexbox实现堆叠排版
jvm·数据库·python
数据库小组2 小时前
MySQL 删库后怎么恢复?binlog2sql 之外,NineData 还能做什么
数据库·sql·mysql·安全·数据·ninedata·删库
zhangchaoxies2 小时前
Layui轮播图(carousel)怎么设置自动播放间隔
jvm·数据库·python
切糕师学AI3 小时前
HBase:一文搞懂分布式宽列数据库(原理 + 架构 + 实战)
数据库·分布式·nosql·hbase·分布式宽列数据库·wide column db
competes3 小时前
慈善基金投资底层逻辑应用 顶层代码低代码配置平台开发结构方式数据存储模块
java·开发语言·数据库·windows·sql