- 1、本文档共5页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
【黑马程序员】关于分布式锁
并发编程的锁机制: synchronized 和 lock 。在单进程的系统中,当存在多个线程可以
同时改变某个变量时,就需要对变量或代码块做同步,使其在修改这种变量时能够线性执
行消除并发修改变量。而同步的本质是通过锁来实现的。为了实现多个线程在一个时刻同
一个代码块只能有一个线程可执行,那么需要在某个地方做个标记,这个标记必须每个线
程都能看到,当标记不存在时可以设置该标记,其余后续线程发现已经有标记了则等待拥
有标记的线程结束同步代码块取消标记后再去尝试设置标记。
分布式环境下,数据一致性问题一直是一个比较重要的话题,而又不同于单进程的
情况。分布式与单机情况下最大的不同在于其不是多线程而是多进程。多线程由于可以共
享堆内存,因此可以简单的采取内存作为标记存储位置。而进程之间甚至可能都不在同一
台物理机上,因此需要将标记存储在一个所有进程都能看到的地方。
常见的是秒杀场景,订单服务部署了多个实例。如秒杀商品有 4 个,第一个用户购
买 3 个,第二个用户购买 2 个,理想状态下第一个用户能购买成功,第二个用户提示购买
失败,反之亦可。而实际可能出现的情况是,两个用户都得到库存为 4 ,第一个用户买到
了 3 个,更新库存之前,第二个用户下了 2 个商品的订单,更新库存为 2 ,导致出错。
在上面的场景中, 商品的库存是共享变量, 面对高并发情形, 需要保证对资源的访问互斥。
在单机环境中, Java 中其实提供了很多并发处理相关的 API ,但是这些 API 在分布式场景
中就无能为力了。也就是说单纯的 Java Api 并不能提供分布式锁的能力。分布式系统中,
由于分布式系统的分布性,即多线程和多进程并且分布在不同机器中, synchronized 和
lock 这两种锁将失去原有锁的效果,需要我们自己实现分布式锁。
常见的锁方案如下:
·基于数据库实现分布式锁
黑马程序员成都中心 编著
·基于缓存,实现分布式锁,如 redis
·基于 Zookeeper 实现分布式锁
下面我们简单介绍下这几种锁的实现。
基于数据库
基于数据库的锁实现也有两种方式,一是基于数据库表,另一种是基于数据库排他
锁。
基于数据库表的增删
基于数据库表增删是最简单的方式,首先创建一张锁的表主要包含下列字段:方法
名,时间戳等字段。
具体使用的方法,当需要锁住某个方法时,往该表中插入一条相关的记录。这边需
要注意,方法名是有唯一性约束的,如果有多个请求同时提交到数据库的话,数据库会保
证只有一个操作可以成功,那么我们就可以认为操作成功的那个线程获得了该方法的锁,
可以执行方法体内容。
执行完毕,需要 delete 该记录。
当然,对于上述方案可以进行优化,如应用主从数据库,数据之间双向同步。一旦
挂掉快速切换到备库上; 做一个定时任务, 每隔一定时间把数据库中的超时数据清理一遍;
使用 while 循环,直到 insert 成功再返回成功,虽然并不推荐这样做;还可以记录当前获
得锁的机器的主机信息和线程信息,那么下次再获取锁的时候先查询数据库,如果当前机
器的主机信息和线程信息在数据库可以查到的话,直接把锁分配给他就可以了,实现可重
入锁。
基于数据库排他锁
我们还可以通过数据库的排他锁来实现分布式锁。 基于 MySql 的 InnoDB 引擎, 可
黑马程序员成都中心 编著
以使用以下方法来实现加锁操作: 在查询语句后面增加 for update ,数据库会在查询过程
中给数据库表增加排他锁。当某条记录被加上排他锁之
文档评论(0)