Google的锁,才是分布式锁?
早年Google的四大基础设施,分别是GFS, MapReduce, BigTable, Chubby, 前三个比较有名,今天来说说后一个,Chubby。
Chubby是什么?
Chubby是早年Google四大基础设施之一,提供粗粒度的分布式锁服务。
Chubby的使用者不需要关注复杂的同步协议,而是通过已经封装好的客户端直接调用锁服务,通过分布式锁,满足各种分布式场景下的一致性需求。
Chubby有什么典型的业务场景?
Chubby具有广泛的应用场景,例如:
(1)GFS选主;
(2)BigTable中的表锁;
Chubby的内核本质是什么?
Chubby本质上是一个分布式文件系统,存储大量小文件。每个文件就代表一个锁,并且可以保存一些应用层面的小规模数据。
用户通过打开、关闭、读取文件来获取共享锁或者独占锁;并通过反向通知机制,向用户发送更新信息。
Chubby系统设计目标是什么?
Chubby系统设计之初,主要想满足以下几点:
(1)粗粒度的锁服务;
(2)高可用、高可靠;
(3)可直接存储服务信息,而无需另建服务;
(4)高扩展性;
Chubby的整体架构是怎么样的?
Chubby架构并不复杂,如上图所示,其核心是这两个重要组件:
(1)Chubby客户端:以库的方式提供,可以通过相应API接口,申请锁服务,获取数据信息,同时保持与服务端的连接;
(2)Chubby服务端:服务端集群,一般由5个节点组成(至少3个节点),其中一台主节点(master),维护与客户端的所有通信;其他节点不断和主节点通信,获取用户操作;
在系统实现时,还使用了以下特性:
(1)客户端缓存,以减少对主节点的访问;
(2)反向通知机制,锁变化时,会反向通知客户端;
Chubby的实现关键点有哪些?
其一,文件系统。
Chubby文件系统类似于简单的unix文件系统。
文件系统由许多Node组成,每个Node代表一个文件,或者一个目录。文件系统使用Berkeley DB来保存每个Node的数据。文件系统提供的API很少:创建文件系统、文件操作、目录操作等简易操作。
其二,基于ICE的通信机制。
Chubby基于ICE的通信机制,核心就是异步,部分组件负责发送,部分组件负责接收。
其三,客户端与主节点通信。
(1)使用长连接,连接有效期内,锁服务、客户端缓存数据均一直有效;
(2)定时双向keepalive;
(3)出错回调;
下面将说明正常、客户端租约过期、主节点租约过期、主节点出错等情况。
(1)正常情况
keepalive会周期性发送,它有两方面功能:
一来,延长租约有效期,携带事件信息告诉客户端更新。
二来,执行回调,例如文件内容修改、子节点增删改、主节点出错等。
(2)客户端租约过期
客户端没有收到主节点的keepalive,租约随之过期,将会进入一个“危险状态”。由于此时不能确定主节点是否已经终止,客户端必须主动让本地缓存失效,同时,进入一个寻找新的主节点的阶段。
这个阶段中,客户端会轮询服务集群,访问非主节点的其他节点,当客户端收到一个肯定的答复时,他会向新的主节点发送keepalive信息,告之自己处于“危险状态”,并和新的主节点建立会话,然后把本地缓存中的信息刷新。
(3)主节点租约过期
主节点一段时间没有收到客户端的keepalive,会进入一段等待期,此期间内客户端仍没有响应,则主节点认为客户端失效。失效后,主节点会把客户端获得的锁,打开的临时文件清理掉,并通知各副本节点,以保持一致性。
(4)主服务器出错
主节点出错,需要内部进行重新选举,各副本节点只响应客户端的读取命令,而忽略写命令。
其四,服务器集群间的一致性操作。
这里需要解决的问题是,当主节点收到客户端请求时(主要是写),如何将操作同步到其他服务器节点,以保证数据的一致性。
(1)节点数目
一般来说,节点数为5,至少要是3。
(2)关于复制
收到客户端请求时,主节点会将请求复制到所有成员,并在消息中添加新被提交的请求序号。副本节点收到这个请求后,获取主节点处被提交的请求序号,然后执行这个序列之前的所有请求,并把其记录到内存的日志里。
各副本节点会向主节点回复消息,主节点收到半数以上的消息(集群包含5个节点时,至少要收到3个节点),才能够进行确认,执行请求,并返回客户端。
画外音:半数以上确认,才认为成功。
如果某个副本节点出现暂时的故障,没有收到部分消息也没关系,副本节点重新启动后,主动从主节点处获得已执行的,自己却还没有完成的日志,并进行执行。
画外音:像不像MySQL的binlog。
终,所有成员都会获得一致性的数据,正常情况下,至少有3个节点包含一致,且新的数据。
后,举几个Chubby使用场景的例子。
例子一,集群选主
(1)集群中每个节点都试图创建/打开同一个文件,并在该文件中记录自己的服务信息,任何时刻,肯定只有一个服务器能够获得该文件的控制权;
(2)首先创建该文件的节点成为主,并写入自己的信息;
(3)后续打开该文件的节点成为从,并读取主的信息;
画外音:是不是很巧妙?
例子二,进程监控
(1)各个进程都把自己的状态写入指定目录下的临时文件里;
(2)监控进程通过阅读该目录下的文件信息来获得进程状态;
(3)各个进程随时有可能死亡,因此指定目录的数据状态会发生变化;
(4)通过事件机制通知监控进程,读取相关内容,获取新状态,达到监控目的;
总结
Google Chubby提供粗粒度锁服务,它的本质是一个松耦合分布式文件系统。开发者不需要关注复杂的同步协议,直接调用库来取得锁服务,并保证了数据的一致性。
后要说明的是,终Chubby系统代码共13700多行,其中ICE自动生成6400行,手动编写约8000行。
这就是Google牛逼的地方:强大的工程能力,快速稳定的实现,快速解决各种业务问题。
相关文章