分布式锁

为什么要用分布式锁?

分布式锁是悲观锁的实现;

如果采用乐观锁的方案就用不着分布式锁了。

能用乐观锁的地方尽量用乐观锁, 添加version字段,每次更新version++;

CAP理论: 分布式系统中的不可能三角

1、一致性

2、 可用性

3、 分区容错性

1、 锁的要素: 一致性; 为了一致性可以牺牲掉完全的高可用性

Zookeeper集群: 保证了一致性和分区容错性; 牺牲了完全的高可用

单点Redis: 保证了一致性;不存在网络分布问题;但是牺牲了高可用性

单点MySQL: 保证了一致性;不存在网络分布问题;但是牺牲了高可用性

单点MySQL优缺点:

1、 借助事务行锁实现;
在事务执行期间可以一直锁住,其他连接等待行锁释放;
嵌套事务,在获取锁的事务中嵌套一个执行业务的事务;
缺点是: 占用了一个连接; 牺牲了高可用性;
优点是: 强一致性保证; 客户端挂了会释放锁,事务回滚。

2、 插入一行记录:
缺点:加锁的客户端挂了, 不能及时释放锁;解决方案: 定时任务检测, 移除超时的锁;
问题聚焦于超时时间的选定, 如果超时时间短了, 则同样会导致客户端未挂,但是锁被释放了; 如果超时时间长了, 则客户端挂了, 其他连接等待时间较长;问题又回归到了Zookeeper和Redis实现的分布式锁一样的问题上了;只不过Zookeeper确定是session超时, 而Redis确定锁过期的时间的问题;

优点: 因为客户端改动的就是数据库, 如果客户端挂了, 则改动必将是失败的, 也不会导致数据不一致的问题。

3、 MySQL的优势

简化了参与方:
加锁服务-MySQL,如果加锁服务挂了, 则服务开启的事务也将回滚; 保证了数据一致性;

其他中间件:
加锁服务- 中间件 - MySQL
引入了中间件角色就引入了复杂度;客户端到底是因为挂了导致session会话超时, 还是因为网络抖动导致会话超时, 如果是后者就会导致数据不一致;

chubby的开源实现Zookeeper

分布式锁
image.png

分布式锁服务关键技术和常见解决方案 ( 下)