标签:redis des 引入 原子性操作 mysq 就是 varchar 服务 ber
上图分析:
(1)变量A存在JVM1、JVM2、JVM3三个JVM内存中(这个变量A主要体现是在一个类中的一个成员变量,是一个有状态的对象),如果不加任何控制的话,变量A同时都会在JVM1、JVM2、JVM3中分配一块内存;
(2)三个请求发过来同时对这个变量进行操作,显然结果是不同的。
(3)即使不是同时发过来,三个请求分别操作三个不同JVM内存区域的数据,变量A之间不存在共享,也不具有可见性,处理的结果也是不对的。
(4)如果我们业务中存在这种场景的话,我们就需要一种方法解决这个问题。
创建一个表:
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 ‘锁定的方法名‘,
`desc` varchar(255) NOT NULL COMMENT ‘备注信息‘,
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uidx_method_name` (`method_name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT=‘锁定中的方法‘;
想要执行某个方法,就使用这个方法名向表中插入数据:
INSERT INTO method_lock (method_name, desc) VALUES (‘methodName‘, ‘测试的methodName‘);
成功插入则获取锁,执行完成后删除对应的行数据释放锁:
delete from method_lock where method_name =‘methodName‘;
使用基于数据库的这种实现方式很简单,但是对于分布式锁应该具备的条件来说,它有一些问题需要解决及优化:
(1)因为是基于数据库实现的,数据库的可用性和性能将直接影响分布式锁的可用性及性能,所以,数据库需要双机部署、数据同步、主备切换。
(2)不具备可重入的特性,因为同一个线程在释放锁之前,行数据一直存在,无法再次成功插入数据,所以,需要在表中新增一列,用于记录当前获取到锁的机器和线程信息,在再次获取锁的时候,先查询表中机器和线程信息是否和当前机器和线程信息相同,若相同则直接获取锁;
(3)没有锁失效机制,因为有可能出现成功插入数据后,服务器宕机了,对应的数据没有被删除,当服务恢复后一直获取不到锁,所以,需要在锁中新增一列,用于记录失效时间,并且需要有定时任务清除这些失效的数据;
(4)不具备阻塞锁特性,获取不到锁直接返回失败,所以需要优化获取逻辑,循环多次去获取。
选择redis分布式锁的原因:
(1)redis有很高的性能;
(2)redis对此支持的命令较好,实现起来比较方便
使用分布式锁的时候主要用到的命令介绍:
(1)SETNX
SETNX key val:当且仅当key不存在时,set一个key为val的字符串,返回1;若key存在,则什么都不做,返回0。
(2)expire
expire key timeout:当key设置一个超时时间,单位为second,超过这个时间锁会自动释放,避免死锁。
(3)delete
delete key:删除key
实现思想:
(1)获取锁的时候,使用setnx加锁,并使用expire命令给锁加一个超时时间,超过该时间则自动释放锁,锁的value值为一个随机生成的UUID,通过此在释放锁的时候进行判断。
(2)获取锁的时候还设置一个获取的超时时间,若超过这个时间则放弃获取锁。
(3)释放锁的时候,通过UUID判断是不是该锁,若是该锁,则执行delete进行锁释放。
基于ZooKeeper实现分布式锁的步骤如下:
(1)创建一个目录mylock;
(2)线程A想获取锁就在mylock目录下创建临时顺序节点;
(3)获取mylock目录下所有的子节点,然后获取比自己小的兄弟节点,如果不存在,则说明当前线程顺序号最小,获得锁;
(4)线程B获取所有节点,判断自己不是最小节点,设置监听比自己小的节点;
(5)线程A处理完,删除自己的节点,线程B监听到变更事件,判断自己是不是最小节点,如果是则获得锁。
标签:redis des 引入 原子性操作 mysq 就是 varchar 服务 ber
原文地址:https://www.cnblogs.com/justuntil/p/10538825.html