网站首页 > java教程 正文
在很多场景中,我们为了保证数据的一致性,需要很多的技术方案来支持,比如:之前谈过的分布式事务、本篇继续谈谈分布式锁的实现与应用@mikechen
01 什么是分布式锁
分布式锁是一种用于在分布式系统中实现协作和同步的机制。
在分布式系统中,由于存在多个节点和进程,为了确保数据的一致性和正确性,需要对共享资源进行协调和同步。
常见的分布式锁实现包括:基于ZooKeeper、Redis等的实现。
02 为什么需要分布式锁
首先在传统单机部署的情况下,在Java多线程并发竞争资源场景,可以使用ReentrantLcok 、Synchronized进行互斥控制,用于解决单机并发共享资源问题。
如下图所示:
当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段,线程锁只在同一JVM中有效果。
但是在分布式系统后,由于分布式系统是分布在不同机器上,这将使原单机并发控制锁策略失效。
为了解决这个问题就需要一种跨JVM的互斥机制来控制共享资源的访问,这就是分布式锁的来源。
分布式锁的应用场景
在传统单体应用单机部署的情况下,可以使用Java并发处理相关,比如:ReentrantLcok、或者synchronized进行互斥控制。
分布式锁应用场景大都是用在高并发,大流量场景。
当多个进程不在同一个系统中,就需要用分布式锁控制多个进程对资源的访问。
分布式锁的实现
分布式锁一般有三种实现方式,如下图所示:
主要就是:Redis的分布式锁、ZooKeeper的分布式锁、以及数据库乐观锁。
Redis使用比较多,这里我就主要结合Redis来谈分布式锁的实现。
分布式锁的实现原理可以归纳为以下几个步骤:
1.获取锁
当一个节点或进程需要访问共享资源时,它首先向分布式锁服务请求获取锁。
在这个过程中,分布式锁服务会检查当前是否已经有其他节点或进程持有该锁,如果没有,则会将锁授予当前请求的节点或进程,并返回获取锁成功的消息。
public class RedisTool {
private static final String LOCK_SUCCESS = "OK";
private static final String SET_IF_NOT_EXIST = "NX";
private static final String SET_WITH_EXPIRE_TIME = "PX";
/**
* 尝试获取分布式锁
* @param jedis Redis客户端
* @param lockKey 锁
* @param requestId 请求标识
* @param expireTime 超期时间
* @return 是否获取成功
*/
public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
if (LOCK_SUCCESS.equals(result)) {
return true;}return false;}
}
2.访问共享资源
当一个节点或进程获得了分布式锁后,它可以访问共享资源。
在这个过程中,其他节点或进程无法访问该共享资源,因为它们没有获得分布式锁。
3.释放锁
当一个节点或进程完成对共享资源的访问后,它会向分布式锁服务请求释放锁。
在这个过程中,分布式锁服务会将该锁授予其他等待获取锁的节点或进程。
public class RedisTool {
private static final Long RELEASE_SUCCESS = 1L;
/**
* 释放分布式锁
* @param jedis Redis客户端
* @param lockKey 锁
* @param requestId 请求标识
* @return 是否释放成功
*/
public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
if (RELEASE_SUCCESS.equals(result)) {return true;}return false;}
}
那么这段Redis释放锁的Lua代码的功能是什么呢?其实很简单,首先获取锁对应的value值,检查是否与requestId相等,如果相等则删除锁(解锁)。
那么为什么要使用Lua语言来实现呢,留给大家讨论探索。
以上
更多分布式架构系列、阿里架构师进阶系列,请查看以下文章:
- 上一篇: 深入浅出Redis:分布式锁实现
- 下一篇: Java中如何实现分布式锁
猜你喜欢
- 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)
本文暂时没有评论,来添加一个吧(●'◡'●)