基于Mysql实现分布式锁
一.分布式锁要解决的问题
可以保证在分布式部署的应用集群中,同一个方法在同一时间只能被一台机器上的一个线程执行。
这把锁要是一把可重入锁(避免死锁)
这把锁最好是一把阻塞锁(根据业务需求考虑要不要这条)
这把锁最好是一把公平锁(根据业务需求考虑要不要这条)
有高可用的获取锁和释放锁功能
获取锁和释放锁的性能要好
二.基于数据库实现原理
1.新建锁表记录
CREATE TABLE `methodLock` ( |
2.第一种实现
当想要锁住某个方法时执行insert方法,插入一条数据,method_name有唯一约束,可以保证多次提交只有一次成功,而成功的这次就可以认为其获得了锁,而执行完成后执行delete语句释放锁
缺点:
这把锁强依赖数据库的可用性,数据库是一个单点,一旦数据库挂掉,会导致业务系统不可用。
这把锁没有失效时间,一旦解锁操作失败,就会导致锁记录一直在数据库中,其他线程无法再获得到锁。
这把锁只能是非阻塞的,因为数据的insert操作,一旦插入失败就会直接报错。没有获得锁的线程并不会进入排队队列,要想再次获得锁就要再次触发获得锁操作。
这把锁是非重入的,同一个线程在没有释放锁之前无法再次获得该锁。因为数据中数据已经存在了。
这把锁是非公平锁,所有等待锁的线程凭运气去争夺锁。
3.第二种实现
还是使用上方的表结构,可以通过数据库的排他锁来实现分布式锁
在查询语句后面增加for update,数据库会在查询过程中给数据库表增加排他锁。当某条记录被加上排他锁之后,其他线程无法再在该行记录上增加排他锁。
我们可以认为获得排它锁的线程即可获得分布式锁,当获取到锁之后,可以执行方法的业务逻辑,执行完方法之后,再通过connection.commit();操作来释放锁
代码:
public boolean lock(){
connection.setAutoCommit(false)
while(true){
try{
result = select * from methodLock where method_name=xxx for update;
if(result==null){
return true;
}
}catch(Exception e){
}
sleep(1000);
}
return false;
}public void unlock(){
connection.commit();
}
4.乐观锁实现
一般是通过为数据库表添加一个 “version”字段来实现读取出数据时,将此版本号一同读出,之后更新时,对此版本号加1,在更新过程中,会对版本号进行比较,如果是一致的,没有发生改变,则会成功执行本次操作;如果版本号不一致,则会更新失败,实际就是个diff过程
缺点:
(1). 这种操作方式,使原本一次的update操作,必须变为2次操作: select版本号一次;update一次。增加了数据库操作的次数。
(2). 如果业务场景中的一次业务流程中,多个资源都需要用保证数据一致性,那么如果全部使用基于数据库资源表的乐观锁,就要让每个资源都有一张资源表,这个在实际使用场景中肯定是无法满足的。而且这些都基于数据库操作,在高并发的要求下,对数据库连接的开销一定是无法忍受的。
(3). 乐观锁机制往往基于系统中的数据存储逻辑,因此可能会造成脏数据被更新到数据库中。
总结
数据库锁现在使用较多的就上面说的3种方式,排他锁(悲观锁),版本号(乐观锁),记录锁,各有优缺点
数据库锁的优点就是 直接借助DB简单易懂
缺点也很明显:
会有各种各样的问题,在解决问题的过程中会使整个方案变得越来越复杂。
操作数据库需要一定的开销,性能问题需要考虑
基于Mysql实现分布式锁的更多相关文章
- 基于 redis 的分布式锁实现 Distributed locks with Redis debug 排查错误
小结: 1. 锁的实现方式,按照应用的实现架构,可能会有以下几种类型: 如果处理程序是单进程多线程的,在 python下,就可以使用 threading 模块的 Lock 对象来限制对共享变量的同步访 ...
- Java基于redis实现分布式锁(SpringBoot)
前言 分布式锁,其实原理是就是多台机器,去争抢一个资源,谁争抢成功,那么谁就持有了这把锁,然后去执行后续的业务逻辑,执行完毕后,把锁释放掉. 可以通过多种途径实现分布式锁,例如利用数据库(mysql等 ...
- 基于 Redis 实现分布式锁
1.主流分布式锁实现方案 基于数据库实现分布式锁 基于缓存(redis 等) 基于 Zookeeper 2.根据实现方式分类 类 CAS 自旋式分布式锁:询问的方式,类似 java 并发编程中的线程获 ...
- 一次基于etcd的分布式锁自动延时失败问题的排查
今天在测试基于etcd的分布式锁过程中,在测试获取锁后,释放之前超出TTL时长的情况下自动延长TTL这部分功能,在延长指定key的TTL时总是返回404错误信息,在对目标KEY更新TTL时目标KEY已 ...
- 基于redis 实现分布式锁的方案
在电商项目中,经常有秒杀这样的活动促销,在并发访问下,很容易出现上述问题.如果在库存操作上,加锁就可以避免库存卖超的问题.分布式锁使分布式系统之间同步访问共享资源的一种方式 基于redis实现分布式锁 ...
- 基于redis的分布式锁
<?php /** * 基于redis的分布式锁 * * 参考开源代码: * http://nleach.com/post/31299575840/redis-mutex-in-php * * ...
- 基于Redis的分布式锁真的安全吗?
说明: 我前段时间写了一篇用consul实现分布式锁,感觉理解的也不是很好,直到我看到了这2篇写分布式锁的讨论,真的是很佩服作者严谨的态度, 把这种分布式锁研究的这么透彻,作者这种技术态度真的值得我好 ...
- 基于 Redis 的分布式锁
前言 分布式锁在分布式应用中应用广泛,想要搞懂一个新事物首先得了解它的由来,这样才能更加的理解甚至可以举一反三. 首先谈到分布式锁自然也就联想到分布式应用. 在我们将应用拆分为分布式应用之前的单机系统 ...
- 基于 Zookeeper 的分布式锁实现
1. 背景 最近在学习 Zookeeper,在刚开始接触 Zookeeper 的时候,完全不知道 Zookeeper 有什么用.且很多资料都是将 Zookeeper 描述成一个“类 Unix/Linu ...
随机推荐
- python基础--字符编码以及文件操作
字符编码: 1.运行程序的三个核心硬件:cpu.内存.硬盘 任何一个程序要是想要运算,肯定是先从硬盘加载到当前的内存中,然后cpu根据指定的指令去执行操作 2.python解释器运行一个py文件的步骤 ...
- Session学习小结
前言: 1.我们在学习一项技术的时候,首先应该是什么时候会用到这项技术.这次学习session也是如此,一般的web项目中都有用户的存在,有用户那么就有了用户的管理,而用户往往是存在于session中 ...
- vue移动端项目
用vue mint-ui jquery-weui写了一个移动端demo 技术栈 vue2.0 vue-router axios mint-ui jquery-weui webpack 页面截图 最后 ...
- 【水滴石穿】react-native-ble-demo
项目的话,是想打开蓝牙,然后连接设备 点击已经连接的设备,我们会看到一些设备 不过我这边在开启蓝牙的时候报错了 先放作者的项目地址: https://github.com/hezhii/react-n ...
- 【转载】遗传算法及matlab实现
摘自https://www.cnblogs.com/LoganChen/p/7509702.html 1.遗传算法介绍 遗传算法,模拟达尔文进化论的自然选择和遗产学机理的生物进化构成的计算模型,一种不 ...
- 洛谷2050 BZOJ2897美食节题解
放个链接 BZ链接 其实这题就是修车的加强版,做法差不多,还是对于每个厨师进行拆点 可是这样强行建图跑网络流会T飞 我们发现,如果一个厨师没有做倒数第x到菜,他一定不会做倒数第x+1到菜 我们的每次增 ...
- Inno Setup 设置开机启动
案1: 将快捷方式添加到“启动”文件夹 [Tasks] Name: "startupicon"; Description: "{cm:CreateQuickLaunchI ...
- Java转iOS-第一个项目总结(2):遇到问题和解决方案
目录1.UITableView滑动卡顿的优化 2.右滑手势返回 3.添加页面统计 4.debug版和release版 5.关于页面刷新 6.关于页面布局 7.推荐博客 遇到问题和解决方案 本文是Jav ...
- Python 3.x版本中的字符串
- el标签 2016-06-05 21:39 477人阅读 评论(15) 收藏
JSP EL语言定义 E L(Expression Language) 目的:为了使JSP写起来更加简单. 表达式语言的灵感来自于 ECMAScript 和 XPath 表达式语言,它提供了在 JSP ...