Kubernetes并发控制与数据一致性的实现原理

  

在大型分布式系统中,定会存在大量并发写入的场景。在这种场景下如何进行更好的并发控制,即在多个任务同时存取数据时保证数据的一致性,成为分布式系统必须解决的问题。
悲观并发控制和乐观并发控制是并发控制中采用的主要技术手段,对于不同的业务场景,应该选择不同的控制方法。
悲观锁
悲观并发控制(又名“悲观锁”,悲观并发控制,缩写“PCC”)是一种并发控制的方法,它可以阻止一个事务以影响其他用户的方式来修改数据。如果一个事务执行的操作读某行数据应用了锁,那只有当这个事务把锁释放,其他事务才能够执行与该锁冲突的操作。
在悲观锁的场景下,假设用A和B户要修改同一个文件,一个在锁定文件并且修改的过程中,B是无法修改这个文件的,只有等到一个修改完成,并且释放锁以后,乙方才可以获取锁,然后修改文件。由此可以看的出,悲观锁对并发的控制持悲观态度,它在进行任何修改前,首先会为其加锁,确保整个修改过程中不会出现冲突,从而有效的保证数据一致性。但这样的机制同时降低了系统的并发性,尤其是两个同时修改的对象本身不存在冲突的情况,同时也可能在竞争锁的时候出现死锁,所以现在很多的系统例如Kubernetes采用了乐观并发的控制方法。
乐观锁
乐观并发控制(又名“乐观锁”,乐观并发控制,缩写“OCC”)是一种并发控制的方法。它假设多用户并发的事务在处理时不会彼此影响,各事务能够在不请求锁的情况下处理各自的数据。在提交数据更新之前,每个事务会先检查在该事务读取数据后,有没有其他事务又修改了该数据。如果其他事务有更新的话,正在提交的事务会进行回滚。
相对于悲观锁对锁的提前控制,乐观锁相信请求之间出现冲突的概率是比较小的,在读取及更改的过程中都是不加锁的,只有在最后提交更新时才会检测冲突,因此在高并发量的系统中占有绝对优势。同样假设用A和B户要修改同一个文件,A和B会先将文件获取到本地,然后进行修改。如果一个已经修改好并且将数据提交,此B时再提交,服务器端会告知乙文件已经被修改,返回冲突错误。此时冲突必须由B来解决,可以将文件重新获取回来,再一次修改后提交。
乐观锁通常通过增加一个资源版本字段,来判断请求是否冲突。初始化时指定一个版本值,每次读取数据时将版本号一同读出,每次更新数据,同时也对版本号进行更新。当服务器端收到数据时,将数据中的版本号与服务器端的做对比,如果不一致,则说明数据已经被修改,返回冲突错误。
Kubernetes中的并发控制
在Kubernetes集群中,外部用户及内部组件频繁的数据更新操作,导致系统的数据并发读写量非常大。假设采用悲观并行的控制方法,将严重损耗集群性能,因此Kubernetes采用乐观并行的控制方法.Kubernetes通过定义资源版本字段实现了乐观并发控制,资源版本(ResourceVersion)字段包含在Kubernetes对象的元数据(元数据)中。这个字符串格式的字段标识了对象的内部版本号,其取值来自etcd的modifiedindex,且当对象被修改时,该字段将随之被修改。值得注意的是该字段由服务端维护,不建议在客户端进行修改。
类型ObjectMeta struct {
……
//不透明值表示该对象的内部版本
//可以使用由客户来决定当对象已经发生了变化。可以用于乐观
//并发、资源上的变化检测,观察操作或一组资源。
//客户端必须将这些值作为不透明,通过修改的回服务器。
//他们只能适用于一个特定的资源或一组资源。
//
//填充系统。
//只读的。
//值必须在客户端和被视为不透明。
//更多信息:https://git.k8s.io/community/contributors/devel/api-conventions。md # concurrency-control-and-consistency
//+可选
ResourceVersion字符串
,
}
Kube-Apiserver可以通过该字段判断对象是否已经被修改。当包含ResourceVersion的更新请求到达Apiserver,服务器端将对比请求数据与服务器中数据的资源版本号,如果不一致,则表明在本次更新提交时,服务端对象已被修改,此时Apiserver将返回冲突错误(409),客户端需重新获取服务端数据,重新修改后再次提交到服务器端。上述并行控制方法可防止如下的数据竞赛:
客户# 1:获得Foo
客户端# 2:获得Foo
客户# 1:Foo。酒吧=叭?br/>客户# 1:把Foo
客户端# 2:Foo。巴兹=皌wo"
客户端# 2:把Foo
当未采用并发控制时,假设发生如上请求序列,两个客户端同时从服务端获取同一对象Foo(含有酒吧,巴兹两个字段),客户# 1先将酒吧字段置成一个,其后端# 2对巴兹字段赋值的更新请求到服务端时,将覆盖客户# 1对酒吧的修改。反之在对象中添加资源版本字段,同样的请求序列将如下:

Kubernetes并发控制与数据一致性的实现原理