3.2.6 手把手实现分布式锁

手把手实现分布式锁
进程中的锁

1.互斥锁
2.自旋锁
3.读写锁
4.信号量
5.条件变量
6.原子变量以及内存屏障

进程间通信

1.pipe
2.FIFO
3.信号量
4.信号
5.消息队列
6.共享内存
7.socket

1.条件变量为什么与互斥锁协同
条件的判断是一个临界资源,需要互斥锁保护
2.哪些锁是自己加锁自己释放锁?哪些是自己加锁,可能由别的线程释放锁?
互斥锁,自旋锁;信号量和条件变量可能由别的线程释放锁;

pthread_mutex_lock(&mtx);

while (condition) //解决了虚假唤醒的问题
  pthread_cond_wait(&cond, &mtx);
pthread_mutex_unlock(&mtx);

pthread_mutex_lock(&mtx);
pthread_mutex_unlock(&mtx);
pthread_cond_signal(&cond);

pthread_cond_broadcast(&cond);

为什么会产生虚假唤醒(pthread_cond_wait会返回,但其实条件并不满足)问题:

1.条件变量有可能会被信号打断
信号 -1 = read errno = EINTR
2.信号劫持
3.多处理实现过程中出现的bug:signal可能会唤醒多个

分布式锁是什么类型的锁?
在分布式场景中实现互斥类型的锁
分布式:运行的节点可能在不同机器或不同网段当中,节点间通信通过socket
互斥类型:同一时刻只允许一个执行体进入临界资源
解决了什么问题?
在分布式场景中,同时只允许一个节点执行某类任务
什么场景下
分布式场景中
行为:加锁,解锁-》网络交互-》锁超时功能,由锁存储的所在节点来实现
加锁对象和解锁对象必须为同一个 -》除了因为网络异常而造成锁超时情况
分布式锁特性
1.互斥性:
锁打上标记:加锁
锁取消标记:解锁
标记:执行体的唯一标识
2.锁超时
3.可用性
3.1合理时间内得到合理的回复
3.2实现
3.2.1计算型(网关)-> 开多个备份点
3.2.2存储型 ->多个备份点/主从切换
4.容错性 一致性来解决(半数以上)
4.1 raft一致性算法
4.2 redlock

分布式锁类型
重入锁和非重入锁:允许同一个线程多次持有锁
公平锁和非公平锁
公平锁:排队
非公平锁:轮询

公平锁   互斥锁
非公平锁  自旋锁

实现重点
锁是一种资源,需要存储;同时要保证可用性,避免锁失效 ->一个进程多线程中的锁资源存储在进程中
互斥语义:将锁打标记
1.加锁对象和解锁对象必须为同一个
2.解锁时需要判断当前持有锁的对象是否是自己
加锁解锁行为是网络通信,需要锁超时->进程是资源的容器,线程是执行的单元
怎么获知持有锁对象的释放锁行为?
主动探寻->非公平锁
被动通知
是否允许同一持锁对象多次加锁?重入锁,非重入锁

MySQL中

特征:关系型数据库、表
实现:锁的存储->表
获取锁和释放锁->字段
互斥语义:
唯一性约束->unique key primary key
利用innodb中的S锁和X锁互斥
锁超时:
另起进程
表增加一个字段:加锁时间戳
定时检测是否超时
delete from lock where lock type = "act_lock"
其他进程怎么获取锁:
实现定时器
主动探寻

总结:
可用性依赖数据库;若数据库是单点,挂掉将导致业务系统不可用;
还需额外实现锁失效的问题;解锁失败,其他线程将无法获得锁;

Redis中

分布式锁流程
尝试获取锁:
获取锁成功,操作临界资源,操作结束尝试释放锁
获取锁失败,订阅解锁信息

尝试释放锁:
释放锁成功,广播解锁信息;
释放锁失败(说明此时持有锁对象不是自己),获得锁失效时间;
特性:内存数据库,数据结构数据库
实现:锁存储
锁存储:set lock uuid nx ex 30
获取和释放锁:
set lock uuid nx ex 30
需要通过lua脚本先要确定是否是持锁对象,然后del lock
互斥语义 nx
锁超时 ex expire pexpire
其他进程怎么获取锁 可以通过广播的方式 sub/pub
递归锁 

动态库
1.runtime path
2.ld.so.conf动态库缓存查找
3.系统路径 PATH
总结:
可用性依赖redis的可用性
容错性很差,redis采用的异步复制,数据可能丢失
效率最高的一种分布式锁
最安全的redis分布式锁

etcd实现公平锁

性能出发:redis>etcd>mysql
完备性:etcd>redis>mysql
选择:都有选择etcd,如果只有mysql不会为了实现分布式锁加入redis或etcd,有etcd选择etcd。

文章参考于<零声教育>的C/C++linux服务期高级架构系统教程学习:https://ke.qq.com/course/417774?flowToken=1020253

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高二的笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值