目录
2.setindex()和get()以及getset()实现的锁
一:事务和锁的关联
1.事务和锁的联系
在上一章谈到过数据库事物的实现思路(单库单表事物到分布式事物一键解读),我们这里跳出事物实来谈,事物保证了了单
个(或者说某一个瞬间)用户在数据库一系列顺序的操作的一致性。如下:可以理解为垂直层面的一系列操作。
而锁视为保证在某一个瞬间只能有一个用户操作,而其他用户只能等待,而这种情况产生的前提就是,有一张表关联了其他许
多张表,且其他表的操作都会影响该表。如图
2.什么是锁
(1)锁产生的背景:在高并发的情况,当一个线程或者方法被同时调用时,我们需要方法或者线程的调用有个顺序性,否则会
导致结果或者数据不一一对应。
(2)锁的特性:当一个线程或者方法的调用需要一个顺序性,且在某一个时刻只能有一个执行。锁是为了实现同步。
3.分布式锁的特性
(1)可重入锁:锁不能产生死锁
(2)竞争锁:锁执行等级的是否一致
(3)阻塞锁:锁的竞争机制
(4)高可用的获取/释放锁的方法:锁是个很消耗资源的,所以在锁的获取/释放性能要好
4.分布式锁解决的问题
简而言之:保证数据的强一致性。在上章中(参照上诉地址)提到在分布式中大多数场景中CAP理论都是满足AP(即一致性
和容错性,至于原因也讨论过)而达到结果的强一致性,那么势必会牺牲一部分一致性,这时候锁会在很大程度上保证一致性。
但是,在大多数的互联网场景中,AP能满足结果的强一致性而且锁真的是一个很耗资源的东西,因此,我们对于锁的使用一定要
多加考虑。
二:基于数据库锁的实现方式之一:唯一主键乐观锁
准确来说这是一种设计思路而不是一种实现方法。基于数据库锁的思路都是基于数据库的事物的隔离级别。
1.实现思路或者原理
基于主键唯一的特性。当多个用户提交到数据库,使用一张主键表中的主键来判断能否执行,执行完成后,删除主键表的
主键数据,如图:
2.不足点:
(1)依赖主键表,会出现单点故障。
(2)容易造成死锁,如果某一个操作毁掉,删除主键表出错,导致主键表中的值未删除
(3)锁无失效时间
(3)非公平锁:抢夺靠时间实现。
(4)大并发的情况下,容易因为主键冲突导致锁表
3.解决不足的方案
(1)建立主键表备份,灵活切换
(2),(3)写个定时任务,定时清理主键表
(4) 通过记录版本号来控制公平性
三:基于表字段版本号
1.思路
为每一个表设置一个版本号字段,然后写一条sql语句进行每一次判断。
2.优缺点
基于mvcc机制,但是表入侵过大
四:基于排它锁
思路
在查询语句后添加一个for update来添加添加所,并且这把锁不会死锁。
五:基于Redis的锁
1.setindex()和expire()实现的锁
主要基于redis 的setindex()和expire()。setindex()方法是一个原子性的操作,当key不存在则key设置成功返回1,否则
返回0。expire()设置失效时间。最后执行成功删除该key。
2.setindex()和get()以及getset()实现的锁
此法同于法1,只不过在死锁方面做了一些优化这个命令主要有两个参数 getset(key,newValue)。该方法是原子的,对 key 设置 newValue 这个值,并且返回 key 原来的旧值。
3.其他方案
基于 REDLOCK 做分布式锁等。