沃趣科技技术社区
行业前沿信息一网打尽
技术社区 > 技术实践|技术实践|分布式时间锁

技术实践|技术实践|分布式时间锁

2023年06月13日

前言

K8s client-go中,源生自带了一个leader库,便于实现分布式时间锁。



分布式时间锁使用场景

以K8s原生的controller-manager组件为例,当有三台master机器时,默认会运行三个controller-manager实例,但只有一个在干活,另外两个处于备用状态。而这个功能的实现,就依赖于分布式时间锁。



时间锁配置说明


 所有相关配置如下图所示:


1.png

锁的持有者,会每隔retryPeriod更新锁的有效期,表示它一直在持有这把锁。


特别说明下两个参数:

一. leaseTimeout 

  1. 举个例子:现在有个房间,我要求当有人进入房间时,下一个人至少等待1小时才可进入房间。这时,我们可以将leaseTimeout设置为1小时,每当有人进入房间,则将房门上的时候改为当前时间。下一个人准备进入时,必须检查房门上的时间距离当前时间超过leaseTimeout。


  2. 之所以要这样设计,是因为在分布式情况下,只有程序活着的时候才可以要求它干什么,而一旦它异常了,它就失控了。而为了防止在它异常时,其它活着的程序可以正常接替它,所以就约定了leaseTimeout,一旦超过这个时间,则直接认定它异常,可以接管。


二. renewDeadline 

  1. 上面的约定,无法防止脑裂。因为锁持有者在leaseTimeout中未更新锁,并不代表它已经挂了,它可能只是因为其它原因无法更新锁,或者程序夯住了,之后它可能再恢复。而如果它在别人接替它后,原持有者再恢复运行,则会导致脑裂,为了防止这种情况发生,针对锁持有者就设置了renewDeadline

  2. 如果锁持有者如果无法在renewDeadline时间内完成锁的更新,则要求锁持有者强制释放锁,程序退出。


  3. 所以renewDeadline必须比leaseTimeout



leader运行流程


2.png




上面流程很清晰,下面单独详细讲下:

尝试获取锁并更新锁




3.png




选举时序图


从上面获取锁流程,除了第一次创建锁之外,选举的关键就是观察时间: observedTime


4.png



  • id1异常情况


5.png



  • id1网络异常无法更新锁

6.png


从时序图中可看出来,监听时间的必要性。所有的flower(待接替者)都必须更新本地监听时间,必需保证在renewDeadline时间中,锁未发生任何变化,否则就需要再重新选举。


当然,还有一种极端情况:两个flower同时发现锁未发生任何变化,同时尝试去获取锁,这个时候就需要用到etcd的resourceVersion机制:在update时需要上送查询时的resourceVersion,表示在这过程中该资源未发生过其它更新。


原理就类似sql的select for update –> 查询时锁定记录。在这种情况下,etcd会保证先更新的能更新成功,后更新的会失败。这样就保证这种极端情况不会脑裂。

让数据库基础设施更简单
加速企业数字化转型建设及落地
立即咨询

沃趣科技

中立的企业级数据库云
十年磨一剑十年来始终如一的专注数据库生态领域
夯实技术底蕴打造最适合时代的数据库基础设施
业绩持续领先目前已累计服务超3000家企业客户

留言咨询

完善信息,我们第一时间跟您联系
姓名
手机
公司
所在地区
咨询问题