分布式锁
简述: 分布式锁主要解决在不同服务器上访问临界资源导致的错乱, 在目前手上业务中主要解决对于mysql的读写问题。
首先第一种方案:
Mysql的悲观锁,带来的负面影响是并发性不高,可能会导致数据库宕机
第二种方案:
Mysql的乐观锁,如果两个服务要修改一条数据,首先访问这条数据,并记录其版本号,然后在修改的时候where条件里加上版本号的筛选,如果修改成功则会连带版本号一起修改,而修改不成功则说明,修改前版本号已经被修改过了,即被其他服务拿到锁并修改了。
第三种方案:
使用redis来实现分布式锁,这里存在一些问题:
首先是上锁与取消锁在同一个服务,且同一时间对于一个资源只能一个服务上锁
其次是过期时间问题,一个服务不可能始终占用一个锁
然后是过期时间续约的问题
解决方案:
首先,在服务开始访问临界资源的时候,在redis里加一个这个资源id的key,修改完成后在删除这个key。
这里存在一个问题,首先是去判断key是否在redis中,如果不在再去set,这里可能会有多个服务都判断到不在,且同时去set,所以这两步需要一步完成,这里我们使用到redis 的set中的nx=True, 如果在返回空,如果不在就set。
在这里为了避免在别的服务里删除key,可以将value设置为一个uuid,并保存下,需要释放锁的时候比对一下value值,则解决上锁与释放锁是同一个服务。
其次是如果持有锁的服务异常,锁子需要自己释放掉,在这里解决情况是在上锁的时候加一个过期时间,但是如果服务处理时间确实大于设定时间需要再起一个线程去自动增加时间,一般再这个锁的时间到2/3时自动序时间,这里的话是对redis处理使用lura语言。
最后还有在锁子释放的时候也要保持原子性,当删除并没有nx之类的参数,则需要写lura去实现。
redis分布式锁,维护成本低,由于内存库等特点比mysql并发性高。 可以借鉴 python-redis-lock去实现redis锁。
第四种方案:
zookeepper, 维护成本高一点,后期用到的话更上来。
1097

被折叠的 条评论
为什么被折叠?



