解读Google分布式锁服务

背景介绍

在2010年4月,Google的网页索引更新实现了实时更新,在今年的OSDI大会上,Google首次公布了有关这一技术的论文。

在此之前,Google的索引更新,采用的的批处理的方式(map/reduce),也就是当增量数据达到一定规模之后,把增量数据和全量索引库Join,得到最新的索引数据。采用新的索引更新系统之后,数据的生命周期缩短了50%,所谓的数据生命周期是指,数据从网页上爬下来,到展现在搜索结果中这段时间间隔,但是正如Google所强调的,这一系统仅仅是为增量更新所建立的,并没有取代map/reduce的批量作业处理模式。

架构Overview

Google的新一代增量索引更新 – Percolator,是建立在Bigtable之上,提供的API也尽量接近Bigtable的方式,所以整个架构大致是如下的样子:

事务(Transaction)和锁(Lock)有区别吗?

在关系数据库领域,二者还是有很大区别的,但是对Percolator而言,Transaction = Lock,所以我们这里讨论的分布式锁,也可以说是分布式事务,所以下面提到的锁或者事务,指的都是同一件事。

Percolator利用Bigtable原有的行锁,再加上自己的一些巧妙的做法,实现了分布式锁服务,这就意味着,Google可以实时的更新PB级别的索引库。最近我们发现Google的搜索结果时效性很好,刚写好的文章,几分钟之后,Google就可以检索到,原因就在Google的Crawler在抓到新的网页之后,不用再等待一定的时间批量更新索引,而是实时的更新,数据生命周期大大缩短。

Percolator支持跨行,跨表的事务,充分利用了Bigtable本身已经有的行事务、备份机制。

简单的示例

在分析Percolator的细节之前,先看一个简单的例子,对Percolator有一个大概的认识,有利于后面的理解。

下面的这个例子是把UserA的人气分减掉10,加到UserB的人气分上,key表示每一行的key,data,lock,write是列名字,data存储数据,lock存储锁状态,write表示事务提交后的数据位置引用.

初始状态:UserA有100个人气分,UserB有50个人气分

最终状态:UserA有90个人气分,UserB有60个人气分

Step0(初始状态)

Key Data Lock Write
UserA 100:t1    
UserB 50:t2    

Step1(从UserA中拿出10个人气分)

Key Data Lock Write
UserA 90:t2100:t1 Primary Lock:t2 t2
UserB 50:t2    

Step2(把UserB的人气分加10)

Key Data Lock Write
UserA 90:t2100:t1 primary_lock:t2 t2
UserB 60:t350:t2 Primary_lock:UserA@data t3

Step3(事务提交)

A:先提交primary(移除锁,写入新的timestamp,在write列写入新数据的位置引用)

Key Data Lock Write
UserA t390:t2

100:t1

  t3:data:t2t2
UserB 60:t350:t2 [email protected] t3

B:再提交非primary(步骤同上)

Key Data Lock Write
UserA t390:t2

100:t1

  t3:data:t2t2
UserB t460:t3

50:t2

  t4:data:t3t3

事务结束了,UserA有90个人气分,timestamp是t3,Userb有60个人气分,timestamp是t4。(至于锁的写法和write列为什么那样写,后面再详细解释)

事务的执行过程

Percolator锁分为两种,primary和non-primary,在事务提交的过程中,先提交primary锁,无论是跨行还是跨表,primary锁都是没有区别的。

事务的提交

事务的提交的过程分两步,以UserA为例:

首先,在write列写入新数据的位置引用,注意不是数据,是引用(理解成指针会更形象),上面step3A 中t3:data:t2表示在t3时刻提交的数据,最新的数据在data列的t2 timestamp

然后,移除lock列的内容。

因为Bigtable支持行锁定,所以上述两步都是在一个Bigtable事务内完成的。

读操作

当一个client在发起读操作之后,首先会向oracle server申请time stamp,接下来Percolator会检查lock列,如果lock列不空,那么读操作试图移除(修复)这个lock或者等待,在后续锁冲突处理详细介绍如何修复。

补充:oracle发放time stamp是严格递增的,而且不是一次发放一个,而是采取批量的方式。

写操作

当一个client发起写操作之后,首先会向oracle server申请time stamp,Percolator会检查write列,如果write列的timestamp大于当前client的timestamp,那么写失败(不能覆盖新的数据 write-write conflict);如果lock列有锁存在,说明当前行正在被另外的client锁定,client要么写失败,要么试图修复(lock conflict)!

Notify机制

Percolator定义了一系列的Observer(类似于数据库的trigger),位于Bigtable的tablet server上,Observer会监视某一列或者某几列,当数据发生变化就会触发Observer,Observer执行完之后,又会创建或者通知后续的Observer,从而形成一个通知的传递。

锁冲突的处理

当一个client在事务提交阶段,crash掉了,那么锁还保留,这样后续的client访问就会被阻止,这种情况叫做锁冲突,Percolator提供了一种简单的机制来解决这个问题。

每个client定期向Chubby Server写入token,表明自己还活着,当某个client发现锁冲突,那么会检查持有锁的client是否还活着,如果client是working状态,那么client等待锁释放。否则client要清除掉当前锁。

Roll  forward & roll  back:

Client先检查primary lock是否存在,因为事务提交先从primary开始,如果primary不存在,那么说明前面的client已经提交了数据,所以client执行roll forward操作:把non-primary对应的数据提交,并且清除non-primary lock;如果primary存在,说明前面的client还没有提交数据就crash了,此时client执行roll back操作:把primary和non-primary的数据清除掉,并且清除lock。

小结

Google的分布式锁服务很好了支持了增量索引的实时更新,缩短了数据的生命周期。本文对notify机制介绍的比较简单,感兴趣的请参考论文原文

摘自:http://my.oschina.net/u/593721/blog/100389

0
时间: 2024-10-10 07:30:29

解读Google分布式锁服务的相关文章

分布式锁服务Chubby之paxos算法

分布式锁服务Chubby之paxos算法 在分布式系统设计领域,Paxos可谓是最重要一致性的算法.Google的大牛们称 All working protocols for asynchronous consensus we have so far encountered have Paxos at their core. 可见此算法的地位.网络上讨论此算法的文章多如牛毛,但大多数让人看了之后仍然是一头雾水,就连维基百科中,对此算法的描述亦有含糊和错误之处.但实际上,此算法的核心思想还是比较简

[转载] zookeeper 分布式锁服务

转载自http://www.cnblogs.com/shanyou/archive/2012/09/22/2697818.html 分布式锁服务在大家的项目中或许用的不多,因为大家都把排他放在数据库那一层来挡.当大量的行锁.表锁.事务充斥着数据库的时候.一般web应用很多的瓶颈都在数据库上,这里给大家介绍的是减轻数据库锁负担的一种方案,使用zookeeper分布式锁服务. zookeeper是hadoop下面的一个子项目, 用来协调跟hadoop相关的一些分布式的框架, 如hadoop, hiv

Redis分布式锁服务(转)

原文:http://www.cnblogs.com/mushroom/p/4752499.html 概述 在多线程环境下,通常会使用锁来保证有且只有一个线程来操作共享资源.比如: object obj = new object(); lock (obj) { //操作共享资源 } 利用操作系统提供的锁机制,可以确保多线程或多进程下的并发唯一操作.但如果在多机环境下就不能满足了,当A,B两台机器同时操作C机器的共享资源时,就需要第三方的锁机制来保证在分布式环境下的资源协调,也称分布式锁. Redi

Redis分布式锁服务(八)

阅读目录: 概述 分布式锁 多实例分布式锁 总结 概述 在多线程环境下,通常会使用锁来保证有且只有一个线程来操作共享资源.比如: object obj = new object(); lock (obj) { //操作共享资源 } 利用操作系统提供的锁机制,可以确保多线程或多进程下的并发唯一操作.但如果在多机环境下就不能满足了,当A,B两台机器同时操作C机器的共享资源时,就需要第三方的锁机制来保证在分布式环境下的资源协调,也称分布式锁. Redis有三个最基本属性来保证分布式锁的有效实现: 安全

Zookeeper实现分布式锁服务(Chubby)

在分布式系统中,如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰,来保证一致性,在这种情况下,便需要使用到分布式锁 例如有N台服务器同时要对某个文件进行修改,如何才能保证文本不会被写乱,这就是一个简单的分布式锁应用场景 使用zookeeper就可以轻松实现分布式锁 思路 前期准备 在zookeeper中创建一个根节点(Locks),用于后续各个客户端的锁操作 获取锁的过程 想要获取锁的client都在Locks中创建一个自增序的子

分布式锁服务ZooKeeper

zookeeper概述 针对分布式应用的分布式协作服务,zookeeper的开发动机就是为了减轻分布式应用从头开发协作服务的负担. 设计目标 简单. 允许多个分布的进程基于一个共享的,类似标准文件系统的树状名称空间进行协作.每个节点称作一个znode. ZooKeeper is replicated 几个zookeeper集群包含多个zookeeper server, 称作一个ensemble. 这些server彼此都知道对方的存在. 需要维护的数据: 内存中的状态的镜像, 持久化存储中的事务日

【6】分布式锁

1.为什么要使用分布式锁? ? 如下图所示,成员变量A存在JVM1.JVM2.JVM3三个JVM内存中.由于成员变量A同时都会在三个JVM上分配一块内存: 若三个请求同时对这个变量操作时,显然结果是不对的: 若三个请求依次分别请求三个不同的JVM内存区域的数据时,由于各JVM之间的变量A不存在共享,也不具有可见性,处理结果也不对. 这就是分布式锁要解决的问题. 2.分布式锁概念 ? 用于实现在分布式系统中多个进程对临界资源的互斥访问,保证分布式系统数据的一致性. ? 分布式协调技术的核心就是实现

Zookeep 分布式锁

什么是分布式锁 概述 为了防止分布式系统中的多个进程之间相互干扰,我们需要一种分布式协调技术来对这些进程进行调度.而这个分布式协调技术的核心就是来实现这个分布式锁. 分布式锁应具备的条件 在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行 高可用的获取锁与释放锁 高性能的获取锁与释放锁 具备可重入特性 具备锁失效机制 具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败 分布式锁有哪些实现 Memcached:利用 Memcached 的 add 命令.此命令是原子性操作,只有在

聊一聊分布式锁的设计

起因 前段时间,看到redis作者发布的一篇文章<Is Redlock safe?>,Redlock是redis作者基于redis设计的分布式锁的算法.文章起因是有一位分布式的专家写了一篇文章<How to do distributed locking>,质疑Redlock的正确性.redis作者则在<Is Redlock safe?>文章中给予回应,一来一回甚是精彩.文本就为读者一一解析两位专家的争论. 在了解两位专家的争论前,让我先从我了解的分布式锁一一道来.文章中