网站首页 > java教程 正文
目前大多数单体应用系统中,微服务应用系统中以及分布式系统中,Redis作为缓存中间件被广泛使用。Redis被公认的是基于内存的,高效的,支持多种数据结构的缓存框架,Redis官方网站有这样一段话,对其进行了清晰的描述:
Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache, and message broker. Redis provides data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes, and streams.
从Redis的官方文档描述,Redis不仅仅可以用来作为高效的数据缓存;基于Redis的高级特性,我们可以基于Redis实现消息队列,分布式锁等功能。
在单体应用系统中,所有的业务和功能都在一个应用系统中,也相当所有业务和功能都在一个线程中运行,如果需要对某一资源或者某一变量进行加锁操作,我们完全可以基于程序本身使用的语言的锁机制来实现,比如Java我们可以采用synchronized和Lock的实现类。
在分布式和微服务系统中,不同功能或者不同业务被拆分成独立的应用,并且完成独立的功能。在部署方式上独立的应用分别被部署到不同的机器上,以及采用集群化部署,一个独立的应用被部署为多个副本。相比于单体应用最直观的区别是:不同的功能或者不同的业务是跨进程运行。
那么,在分布式应用系统中,我们如何对某一竞争资源进行加锁操作呢?
答案:当然是我们需要一种分布式锁机制。
实现分布式锁有多种解决方案,常用的解决方案整理如下:
- 基于Redis对字符串操作命令SETNX实现;
- 基于Zookeeper的临时有序节点实现;
由于Redis是单线程的,基于命令SETNX(set if not exists)可以实现锁的机制;
当一个key在Redis中不存在时;返回1(成功);
当一个key在Redis中存在时;返回0(失败);
127.0.0.1:6379> SETNX abc 1
(integer) 1
127.0.0.1:6379> SETNX abc 1
(integer) 0
在Redis的帮助文档中,对该SETNX命令是这样描述的:
127.0.0.1:6379> help @string
........................................
SETNX key value
summary: Set the value of a key, only if the key does not exist
since: 1.0.0
下面我们通过一个简单的demo来演示下,基于Redis如何实现分布式锁机制。
新建一个Java工程redis-distributed-lock,maven依赖如下:
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
</dependency>
redisson封装了对Redis的大多数操作命令,相当于Redis的Java客户端。我们只需要做简单的配置,就可以像redis-cli那样操作Redis。当然,这里也可以选择其他的Redis Java客户端,例如Jedis,RedisTemplate等。
定义一个main函数
public class RedisLockDemo {
public static void main(String[] args) throws IOException {
Config config = new Config();
config.useSingleServer().setAddress("redis://localhost:6379");
config.useSingleServer().setPassword("123456");
RedissonClient redissonClient = Redisson.create(config);
RLock rLock = redissonClient.getLock("lock");
for (int i = 0; i < 20; i++) {
//开启自线程
new Thread(() -> {
//加锁
rLock.lock();
System.out.println(Thread.currentThread().getName() + " 获取锁");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//释放锁
rLock.unlock();
}
}).start();
}
}
}
在这里我们采用多线程来模拟一个分布式系统,每一个线程代表一个独立的应用系统。我们在同一时间开启20个线程,这20个线程同时去抢占锁,如果某一线程抢占到锁,则打印“获取到锁”,没有抢占到锁的线程则处于等待状态。当某一线程抢占到锁后,完成操作后释放掉锁,则其他未抢占到锁的线程被唤醒,并且同时再一次去抢占锁。
运行mian函数执行结果如下:
从代码层面和运行结果层面,我们可以看到基于Redis实现了分布式锁的机制。redisson这个Java版的Redis客户端封装了对锁的实现细节,具体封装了如下:
- 所有线程同时抢占锁,以及抢占到锁的线程释放锁;
- 未抢占到锁的线程阻塞等待;
- 抢占到锁的线程释放锁后,唤醒未抢占到锁的线程,并且同时再次抢占锁;
参考:
https://redis.io/
demo源码:
https://github.com/bq-xiao/distributed-lock-demo.git
不积跬步,无以至千里;不积小流,无以成江海!
- 上一篇: 一篇文章带你解读redis分布式锁的发展史和正确实现方式
- 下一篇: 浅谈分布式锁
猜你喜欢
- 2024-11-22 redis分布式锁
- 2024-11-22 4K字深度剖析redisson分布式锁原理
- 2024-11-22 java都为我们提供了各种锁,为什么还需要分布式锁?
- 2024-11-22 一文带你了解Java手写分布式锁的实现
- 2024-11-22 如何用Redisson框架实现分布式锁?
- 2024-11-22 基于 Redis 实现的分布式锁
- 2024-11-22 京东秒杀系统模块的Redis分布式锁深度剖析,没给你讲明白你打我
- 2024-11-22 面试官:Redis分布式锁超时了,任务还没执行完怎么办?
- 2024-11-22 聊聊Redis分布式锁
- 2024-11-22 浅谈分布式锁
你 发表评论:
欢迎- 最近发表
-
- 五,网络安全IDA Pro反汇编工具初识及逆向工程解密实战
- 「JAVA8」- Lambda 表达式(java lambda表达式原理)
- 深入探讨Java代码保护:虚拟机保护技术的新时代
- Nginx反向代理原理详解(图文全面总结)
- 逆向拆解日本IT,哪些Java技术栈薪资溢价高
- mybatis 逆向工程使用姿势不对,把表清空了,心里慌的一比
- Spring Boot集成ProGuard轻松实现Java 代码混淆, Java 应用固若金汤
- 从 Java 代码逆向工程生成 UML 类图和序列图
- 人与人相处:尊重是标配,靠谱是高配,厚道是顶配
- Windows系统安装日期如何修改(windows10怎么修改安装日期)
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)