分布式锁的这三种实现90%的人都不知道
一、为什么要使用分布式锁我们在开发应用的时候 , 如果需要对某一个共享变量进行多线程同步访问的时候 , 可以使用我们学到的Java多线程的18般武艺进行处理 , 并且可以完美的运行 , 毫无Bug!
注意这是单机应用 , 也就是所有的请求都会分配到当前服务器的JVM内部 , 然后映射为操作系统的线程进行处理!而这个共享变量只是在这个JVM内部的一块内存空间!
后来业务发展 , 需要做集群 , 一个应用需要部署到几台机器上然后做负载均衡 , 大致如下图:
文章插图
上图可以看到 , 变量A存在JVM1、JVM2、JVM3三个JVM内存中(这个变量A主要体现是在一个类中的一个成员变量 , 是一个有状态的对象 , 例如:UserController控制器中的一个整形类型的成员变量) , 如果不加任何控制的话 , 变量A同时都会在JVM分配一块内存 , 三个请求发过来同时对这个变量操作 , 显然结果是不对的!即使不是同时发过来 , 三个请求分别操作三个不同JVM内存区域的数据 , 变量A之间不存在共享 , 也不具有可见性 , 处理的结果也是不对的!
如果我们业务中确实存在这个场景的话 , 我们就需要一种方法解决这个问题!
为了保证一个方法或属性在高并发情况下的同一时间只能被同一个线程执行 , 在传统单体应用单机部署的情况下 , 可以使用Java并发处理相关的API(如ReentrantLock或Synchronized)进行互斥控制 。 在单机环境中 , Java中提供了很多并发处理相关的API 。 但是 , 随着业务发展的需要 , 原单体单机部署的系统被演化成分布式集群系统后 , 由于分布式系统多线程、多进程并且分布在不同机器上 , 这将使原单机部署情况下的并发控制锁策略失效 , 单纯的Java API并不能提供分布式锁的能力 。 为了解决这个问题就需要一种跨JVM的互斥机制来控制共享资源的访问 , 这就是分布式锁要解决的问题!
二、分布式锁应该具备哪些条件在分析分布式锁的三种实现方式之前 , 先了解一下分布式锁应该具备哪些条件:
1、在分布式系统环境下 , 一个方法在同一时间只能被一个机器的一个线程执行;
2、高可用的获取锁与释放锁;
3、高性能的获取锁与释放锁;
4、具备可重入特性;
5、具备锁失效机制 , 防止死锁;
6、具备非阻塞锁特性 , 即没有获取到锁将直接返回获取锁失败 。
三、分布式锁的三种实现方式 目前几乎很多大型网站及应用都是分布式部署的 , 分布式场景中的数据一致性问题一直是一个比较重要的话题 。 分布式的CAP理论告诉我们“任何一个分布式系统都无法同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance) , 最多只能同时满足两项 。 ”所以 , 很多系统在设计之初就要对这三者做出取舍 。 在互联网领域的绝大多数的场景中 , 都需要牺牲强一致性来换取系统的高可用性 , 系统往往只需要保证“最终一致性” , 只要这个最终时间是在用户可以接受的范围内即可 。
在很多场景中 , 我们为了保证数据的最终一致性 , 需要很多的技术方案来支持 , 比如分布式事务、分布式锁等 。 有的时候 , 我们需要保证一个方法在同一时间内只能被同一个线程执行 。
基于数据库实现分布式锁;
基于缓存(Redis等)实现分布式锁;
基于Zookeeper实现分布式锁;
1.基于数据库实现排他锁【分布式锁的这三种实现90%的人都不知道】方案1
表结构
文章插图
获取锁
INSERT INTO method_lock (method_name, desc) VALUES ('methodName', 'methodName');
对method_name做了唯一性约束 , 这里如果有多个请求同时提交到数据库的话 , 数据库会保证只有一个操作可以成功 。
方案2
表结构
DROP TABLE IF EXISTS `method_lock`;
CREATE TABLE `method_lock` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`method_name` varchar(64) NOT NULL COMMENT '锁定的方法名',
`state` tinyint NOT NULL COMMENT '1:未分配;2:已分配',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`version` int NOT NULL COMMENT '版本号',
`PRIMARY KEY (`id`),
UNIQUE KEY `uidx_method_name` (`method_name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='锁定中的方法';
先获取锁的信息
select id, method_name, state,version from method_lock where state=1 and method_name='methodName';
- 智能手机市场|华为再拿第一!27%的份额领跑全行业,苹果8%排在第四名!
- 会员|美容院使用会员管理软件给顾客更好的消费体验!
- 行业|现在行业内客服托管费用是怎么算的
- 人民币|天猫国际新增“服务大类”,知舟集团提醒入驻这些类目的要注意
- 国外|坐拥77件专利,打破国外的垄断,造出中国最先进的家电芯片
- 技术|做“视频”绿厂是专业的,这项技术获人民日报评论点赞
- 面临|“熟悉的陌生人”不该被边缘化
- 中国|浅谈5G移动通信技术的前世和今生
- 页面|如何简单、快速制作流程图?上班族的画图技巧get
- 桌面|日常使用的软件及网站分享 篇一:几个动态壁纸软件和静态壁纸网站:助你美化你的桌面