codecamp

从Paxos到Zookeeper分布式一致性原理与实践(博文视点出品)

从Paxos到Zookeeper分布式一致性原理与实践(博文视点出品)

倪超 著

  • 出版社: 电子工业出版社
  • ISBN:9787121249679
  • 版次:1
  • 商品编码:11622772
  • 品牌:博文视点
  • 包装:平装
  • 开本:16开
  • 出版时间:2015-02-01
  • 用纸:胶版纸
  • 页数:420
  • 字数:548000
  • 正文语种:中文

点此购买


编辑推荐

适读人群 :大型网站和分布式系统的开发人员,对分布式一致性和ZooKeeper感兴趣的IT从业人员。

国内罕见系统讲解ZooKeeper这一应用广泛、成熟的分布式协调框架之技术书。

 原理深入,阐述清晰,覆盖ACID、CAP、BASE,二阶段/三阶段提交,Paxos、ZAB协议等热门话题。

 彻底剖析分布式一致性问题,并给出相应系统思路,以及完整解决方案及实战参考。

 无论开发人员,还是运维人士,都可通过书中ZooKeeper使用方法、内部实现及运维技巧来全面提升。

内容简介

  《Paxos到Zookeeper 分布式一致性原理与实践》从分布式一致性的理论出发,向读者简要介绍几种典型的分布式一致性协议,以及解决分布式一致性问题的思路,其中重点讲解了Paxos和ZAB协议。同时,本书深入介绍了分布式一致性问题的工业解决方案——ZooKeeper,并着重向读者展示这一分布式协调框架的使用方法、内部实现及运维技巧,旨在帮助读者全面了解ZooKeeper,并更好地使用和运维ZooKeeper。全书共8章,分为五部分:前一部分(第1章)主要介绍了计算机系统从集中式向分布式系统演变过程中面临的挑战,并简要介绍了ACID、CAP和BASE等经典分布式理论;第二部分(第2~4章)介绍了2PC、3PC和Paxos三种分布式一致性协议,并着重讲解了ZooKeeper中使用的一致性协议——ZAB协议;第三部分(第5~6章)介绍了ZooKeeper的使用方法,包括客户端API的使用以及对ZooKeeper服务的部署与运行,并结合真实的分布式应用场景,总结了ZooKeeper使用实践;第四部分(第7章)对ZooKeeper的架构设计和实现原理进行了深入分析,包含系统模型、Leader选举、客户端与服务端的工作原理、请求处理,以及服务器角色的工作流程和数据存储等;第五部分(第8章)介绍了ZooKeeper的运维实践,包括配置详解和监控管理等,重点讲解了如何构建一个高可用的ZooKeeper服务。


作者简介

  倪超,阿里巴巴集团高级研发工程师,国家认证系统分析师,毕业于杭州电子科技大学计算机系。2010年加入阿里巴巴中间件团队担任研发实习岗位,一直从事ZooKeeper的开发与运维工作,从中学习与总结了不少分布式一致性相关的理论与实践经验,尤其对ZooKeeper及其相关技术有非常深入的研究。目前在中间件团队专家组任职产品经理,负责分布式产品的产品化和云计算化改造工作。


精彩书评

  ★感谢软件开源和知识开源,新浪爱彩利用各开源软件和算法,构建了核心交易系统和分布式中间件系统:利用ZooKeeper 构建了分布式 ID 生成器、分布式单例控制器、Dubbo RPC 框架,以及基于 Hadoop/JStorm/Spark 体系的业务系统,等等。ZooKeeper 的稳定性和对一致性的保证一直为业界所称道,在大量的分布式系统和开源组件中得到应用。本书是作者在长期使用 ZooKeeper 后深入研究其算法原理和源代码的总结,将对读者在分布式一致性的理论学习与实践上有启发意义。

  ——新浪爱彩首席架构师 周锋

    ★分布式一致性是中国银联风控系统架构与设计的重要目标,新一代的银联反洗钱交易实时分析系统采用 Storm 进行大数据的实时计算,ZooKeeper 作为 Storm 的重要组成部分,为数据一致性提供了关键保障。本书深入浅出地描述了分布式一致性这一问题的由来,并对 ZooKeeper 在 Storm、Hadoop 和 HBase 等大型分布式系统中的应用场景进行了详尽介绍,针对 ZooKeeper在分布式系统中的业务实践与运维保障提供了重要参考。

  ——中国银联反洗钱系统核心负责人 罗科勤

    ★分布式地理信息系统的研发挑战主要在于它的地理信息共享和分布式协调操作,ZooKeeper 作为一个针对大型分布式系统的高可靠协调系统,提供的功能包括:配置维护、名字服务、分布式同步和组服务等,正好能够解决地信系统中的诸多分布式一致性问题。该书兼顾分布式一致性的理论和实践,并重点讲解了 ZooKeeper,适合不同层次的读者阅读。

  ——浙江省测绘局地信系统设计师 王浩烽

  ★腾讯在 2010 年启动建设开放云平台时,面临着海量第三方虚拟机之间访问限制规则以及内网透明负载均衡配置的管理等问题。引入 ZooKeeper 之后,一直稳定运行至今,利用其发布订阅特性很好地保证了规则数据和配置信息的一致性,确保了服务的可用性。本书从分布式一致性理论出发,再以ZooKeeper 系统为例详尽地介绍了这个开源系统的架构与实现,并结合实际的应用场景和运维经验为在实战中面临分布式问题的读者提供了重要参考。

  ——腾讯企业级产品中心架构师 陈盛龙

    ★一致性是计算机学科中“硬”和重要的问题之一,可见写这样一个主题挑战之大。阿里巴巴业务庞大,倪超之前维护的为整个集团提供一致性方案的 ZooKeeper 集群,场景之复杂、规模之大在国内甚至世界上都可能是罕见的。本人由于工作需要对 Paxos 和 ZooKeeper 进行了粗浅的学习,所以有机会和倪超有过这方面的交流,乐自不言,获益彼多。本书兼顾理论与实践,希望让读者读完之后有所提升:使用上知其所以然,架构上能选择出合适又低成本的方案。

  ——阿里巴巴 Dubbo 框架、PaaS 平台资深架构师 & 核心开发 李鼎

    ★在我的工作经历中,有多次与分布式系统的配置管理中心打过交道,比如之前在老东家阿里巴巴负责 HSF 服务框架,以及最近在陌陌负责的 MOA 服务框架的工作。基于简单可用的原则,这些场景都没有选择使用 ZooKeeper,而是自己实现了配置管理系统。但最近在参与分布式缓存服务建设的过程中,我们发现已经无法再绕开分布式协调问题,这时,ZooKeeper作为行业的成熟实践就成了我们的优选。这本书的作者倪超是我在阿里的同事,一直从事着与 ZooKeeper 相关的工作 在这个领域积累了丰富的经验。本书从理论、设计实现和应用场景等多个方面对 ZooKeeper 进行了深入介绍,非常值得一读。

  ——陌陌基础平台部主管 宓学强

    ★搜狐从 2009 年微博时代初期就利用 ZooKeeper 的发布与订阅模型实现了对 CDN URL 和一些基本管理配置的动态加载。至今 ZooKeeper 已经被运用在了搜狐各大业务线上,完成了许多分布式高可用服务的构建,范围涉及分布式缓存、服务化框架和前端业务系统等等,帮助团队解决了分布式方面的主要技术障碍,大大提高了业务稳定性和运维效率。本书全面详尽地介绍了分布式环境中各个典型场景下的 ZooKeeper 应用实例,为读者构建自己的分布式高可用服务提供了参考。

  ——搜狐移动事业部高级运维主管 刘鹏


目录


第1章 分布式架构
1.1 从集中式到分布式
1.1.1 集中式的特点
1.1.2 分布式的特点
1.1.3 分布式环境的各种问题
1.2 从ACID到CAP/BASE
1.2.1 ACID
1.2.2 分布式事务
1.2.3 CAP和BASE理论
小结

第2章 一致性协议
2.1 2PC与3PC
2.1.1 2PC
2.1.2 3PC
2.2 Paxos算法
2.2.1 追本溯源
2.2.2 Paxos理论的诞生
2.2.3 Paxos算法详解
小结

第3章 Paxos的工程实践
3.1 Chubby
3.1.1 概述
3.1.2 应用场景
3.1.3 设计目标
3.1.4 Chubby技术架构
3.1.5 Paxos协议实现
3.2 Hypertable
3.2.1 概述
3.2.2 算法实现
小结

第4章 ZooKeeper与Paxos
4.1 初识ZooKeeper
4.1.1 ZooKeeper介绍
4.1.2 ZooKeeper从何而来
4.1.3 ZooKeeper的基本概念
4.1.4 为什么选择ZooKeeper
4.2 ZooKeeper的ZAB协议
4.2.1 ZAB协议
4.2.2 协议介绍
4.2.3 深入ZAB协议
4.2.4 ZAB与Paxos算法的联系与区别
小结

第5章 使用ZooKeeper
5.1 部署与运行
5.1.1 系统环境
5.1.2 集群与单机
5.1.3 运行服务
5.2 客户端脚本
5.2.1 创建
5.2.2 读取
5.2.3 更新
5.2.4 删除
5.3 Java客户端API使用
5.3.1 创建会话
5.3.2 创建节点
5.3.3 删除节点
5.3.4 读取数据
5.3.5 更新数据
5.3.6 检测节点是否存在
5.3.7 权限控制
5.4 开源客户端
5.4.1 ZkClient
5.4.2 Curator
小结

第6章 ZooKeeper的典型应用场景
6.1 典型应用场景及实现注
6.1.1 数据发布/订阅
6.1.2 负载均衡
6.1.3 命名服务
6.1.4 分布式协调/通知
6.1.5 集群管理
6.1.6 Master选举
6.1.7 分布式锁
6.1.8 分布式队列
小结
6.2 ZooKeeper在大型分布式系统中的应用
6.2.1 Hadoop
6.2.2 HBase
6.2.3 Kafka
6.3 ZooKeeper在阿里巴巴的实践与应用
6.3.1 案例一 消息中间件:Metamorphosis
6.3.2 案例二 RPC服务框架:Dubbo
6.3.3 案例三 基于MySQL Binlog的增量订阅和消费组件:Canal
6.3.4 案例四 分布式数据库同步系统:Otter
6.3.5 案例五 轻量级分布式通用搜索平台:终搜
6.3.6 案例六 实时计算引擎:JStorm
小结

第7章 ZooKeeper技术内幕
7.1 系统模型
7.1.1 数据模型
7.1.2 节点特性
7.1.3 版本――保证分布式数据原子性操作
7.1.4 Watcher――数据变更的通知
7.1.5 ACL――保障数据的安全
7.2 序列化与协议
7.2.1 Jute介绍
7.2.2 使用Jute进行序列化
7.2.3 深入Jute
7.2.4 通信协议
7.3 客户端
7.3.1 一次会话的创建过程
7.3.2 服务器地址列表
7.3.3 ClientCnxn:网络I/O
7.4 会话
7.4.1 会话状态
7.4.2 会话创建
7.4.3 会话管理
7.4.4 会话清理
7.4.5 重连
7.5 服务器启动
7.5.1 单机版服务器启动
7.5.2 集群版服务器启动
7.6 Leader选举
7.6.1 Leader选举概述
7.6.2 Leader选举的算法分析
7.6.3 Leader选举的实现细节
7.7 各服务器角色介绍
7.7.1 Leader
7.7.2 Follower
7.7.3 Observer
7.7.4 集群间消息通信
7.8 请求处理
7.8.1 会话创建请求
7.8.2 SetData请求
7.8.3 事务请求转发
7.8.4 GetData请求
7.9 数据与存储
7.9.1 内存数据
7.9.2 事务日志
7.9.3 snapshot――数据快照
7.9.4 初始化
7.9.5 数据同步
小结

第8章 ZooKeeper运维
8.1 配置详解
8.1.1 基本配置
8.1.2 高级配置
8.2 四字命令
8.3 JMX
8.3.1 开启远程JMX
8.3.2 通过JConsole连接ZooKeeper
8.4 监控
8.4.1 实时监控
8.4.2 数据统计
8.5 构建一个高可用的集群
8.5.1 集群组成
8.5.2 容灾
8.5.3 扩容与缩容
8.6 日常运维
8.6.1 数据与日志管理
8.6.2 Too many connections
8.6.3 磁盘管理
小结
附录A Windows平台上部署ZooKeeper
附录B 从源代码开始构建
附录C 各发行版本重大更新记录
附录D ZooKeeper源代码阅读指引


精彩书摘

  第1章

  分布式架构

  随着计算机系统规模变得越来越大,将所有的业务单元集中部署在一个或若干个大型机上的体系结构,已经越来越不能满足当今计算机系统,尤其是大型互联网系统的快速发展,各种灵活多变的系统架构模型层出不穷。同时,随着微型计算机的出现,越来越多廉价的PC机成为了各大企业IT架构的首选,分布式的处理方式越来越受到业界的青睐——计算机系统正在经历一场前所未有的从集中式向分布式架构的变革。

  1.1 从集中式到分布式

  自20世纪60年代大型主机被发明出来以后,凭借其超强的计算和I/O处理能力以及在稳定性和安全性方面的卓越表现,在很长一段时间内,大型主机引领了计算机行业以及商业计算领域的发展。在大型主机的研发上最知名的当属IBM,其主导研发的革命性产品System/360系列大型主机,是计算机发展史上的一个里程碑,与波音707和福特T型车齐名,被誉为20世纪最重要的三大商业成就,并一度成为了大型主机的代名词。从那时起,IT界进入了大型主机时代。

  伴随着大型主机时代的到来,集中式的计算机系统架构也成为了主流。在那个时候,由于大型主机卓越的性能和良好的稳定性,其在单机处理能力方面的优势非常明显,使得IT系统快速进入了集中式处理阶段,其对应的计算机系统称为集中式系统。但从20世纪80年代以来,计算机系统向网络化和微型化的发展日趋明显,传统的集中式处理模式越来越不能适应人们的需求。

  首先,大型主机的人才培养成本非常之高。通常一台大型主机汇集了大量精密的计算机组件,操作非常复杂,这对一个运维人员掌握其技术细节提出了非常高的要求。

  其次,大型主机也是非常昂贵的。通常一台配置较好的IBM大型主机,其售价可能在上百万美元甚至更高,因此也只有像政府、金融和电信等企业才有能力采购大型主机。

  另外,集中式系统具有明显的单点问题。大型主机虽然在性能和稳定性方面表现卓越,但这并不代表其永远不会出现故障。一旦一台大型主机出现了故障,那么整个系统将处于不可用状态,其后果相当严重。最后,随着业务的不断发展,用户访问量迅速提高,计算机系统的规模也在不断扩大,在单一大型主机上进行系统的扩容往往比较困难。

  而另一方面,随着PC机性能的不断提升和网络技术的快速普及,大型主机的市场份额变得越来越小,很多企业开始放弃原来的大型主机,而改用小型机和普通PC服务器来搭建分布式的计算机系统。

  其中最为典型的就是阿里巴巴集团的“去IOE”运动。从2008年开始,阿里巴巴的各项业务都进入了井喷式的发展阶段,这对于后台IT系统的计算与存储能力提出了非常高的要求,一味地针对小型机和高端存储进行不断扩容,无疑会产生巨大的成本。同时,集中式的系统架构体系也存在诸多单点问题,完全无法满足互联网应用爆炸式的发展需求。因此,为了解决业务快速发展给IT系统带来的巨大挑战,从2009年开始,阿里集团启动了“去IOE”计划,其电商系统开始正式迈入分布式系统时代。

  1.1.1 集中式的特点

  所谓的集中式系统就是指由一台或多台主计算机组成中心节点,数据集中存储于这个中心节点中,并且整个系统的所有业务单元都集中部署在这个中心节点上,系统的所有功能均由其集中处理。也就是说,在集中式系统中,每个终端或客户端机器仅仅负责数据的录入和输出,而数据的存储与控制处理完全交由主机来完成。

  集中式系统最大的特点就是部署结构简单。由于集中式系统往往基于底层性能卓越的大型主机,因此无须考虑如何对服务进行多个节点的部署,也就不用考虑多个节点之间的分布式协作问题。

  1.1.2 分布式的特点

  在《分布式系统概念与设计》注 一书中,对分布式系统做了如下定义:

  分布式系统是一个硬件或软件组件分布在不同的网络计算机上,彼此之间仅仅通过消息传递进行通信和协调的系统。

  上面这个简单的定义涵盖了几乎所有有效地部署了网络化计算机的系统。严格地讲,同一个分布式系统中的计算机在空间部署上是可以随意分布的,这些计算机可能被放在不同的机柜上,也可能在不同的机房中,甚至分布在不同的城市。无论如何,一个标准的分布式系统在没有任何特定业务逻辑约束的情况下,都会有如下几个特征。

  分布性

  分布式系统中的多台计算机都会在空间上随意分布,同时,机器的分布情况也会随时变动。

  对等性

  分布式系统中的计算机没有主/从之分,既没有控制整个系统的主机,也没有被控制的从机,组成分布式系统的所有计算机节点都是对等的。副本(Replica)是分布式系统最常见的概念之一,指的是分布式系统对数据和服务提供的一种冗余方式。在常见的分布式系统中,为了对外提供高可用的服务,我们往往会对数据和服务进行副本处理。数据副本是指在不同的节点上持久化同一份数据,当某一个节点上存储的数据丢失时,可以从副本上读取到该数据,这是解决分布式系统数据丢失问题最为有效的手段。另一类副本是服务副本,指多个节点提供同样的服务,每个节点都有能力接收来自外部的请求并进行相应的处理。

  并发性

  在“问题的提出”部分,我们已经提到过与“更新的并发性”相关的内容。在一个计算机网络中,程序运行过程中的并发性操作是非常常见的行为,例如同一个分布式系统中的多个节点,可能会并发地操作一些共享的资源,诸如数据库或分布式存储等,如何准确并高效地协调分布式并发操作也成为了分布式系统架构与设计中最大的挑战之一。  缺乏全局时钟  在上面的讲解中,我们已经了解到,一个典型的分布式系统是由一系列在空间上随意分布的多个进程组成的,具有明显的分布性,这些进程之间通过交换消息来进行相互通信。因此,在分布式系统中,很难定义两个事件究竟谁先谁后,原因就是因为分布式系统缺乏一个全局的时钟序列控制。关于分布式系统的时钟和事件顺序,在Leslie Lamport注 的经典论文Time, Clocks, and the Ordering of Events in a Distributed System注 中已经做了非常深刻的讲解。

  故障总是会发生

  组成分布式系统的所有计算机,都有可能发生任何形式的故障。一个被大量工程实践所检验过的黄金定理是:任何在设计阶段考虑到的异常情况,一定会在系统实际运行中发生,并且,在系统实际运行过程中还会遇到很多在设计时未能考虑到的异常故障。所以,除非需求指标允许,在系统设计时不能放过任何异常情况。

  1.1.3 分布式环境的各种问题

  分布式系统体系结构从其出现之初就伴随着诸多的难题和挑战,本节将向读者简要的介绍分布式环境中一些典型的问题。

  通信异常

  从集中式向分布式演变的过程中,必然引入了网络因素,而由于网络本身的不可靠性,因此也引入了额外的问题。分布式系统需要在各个节点之间进行网络通信,因此每次网络通信都会伴随着网络不可用的风险,网络光纤、路由器或是DNS等硬件设备或是系统不可用都会导致最终分布式系统无法顺利完成一次网络通信。另外,即使分布式系统各节点之间的网络通信能够正常进行,其延时也会远大于单机操作。通常我们认为在现代计算机体系结构中,单机内存访问的延时在纳秒数量级(通常是10ns左右),而正常的一次网络通信的延迟在0.1~1ms左右(相当于内存访问延时的105~106倍),如此巨大的延时差别,也会影响消息的收发的过程,因此消息丢失和消息延迟变得非常普遍。  网络分区  当网络由于发生异常情况,导致分布式系统中部分节点之间的网络延时不断增大,最终导致组成分布式系统的所有节点中,只有部分节点之间能够进行正常通信,而另一些节点则不能——我们将这个现象称为网络分区,就是俗称的“脑裂”。当网络分区出现时,分布式系统会出现局部小集群,在极端情况下,这些局部小集群会独立完成原本需要整个分布式系统才能完成的功能,包括对数据的事务处理,这就对分布式一致性提出了非常大的挑战。

  三态

  从上面的介绍中,我们已经了解到了在分布式环境下,网络可能会出现各式各样的问题,因此分布式系统的每一次请求与响应,存在特有的“三态”概念,即成功、失败与超时。在传统的单机系统中,应用程序在调用一个函数之后,能够得到一个非常明确的响应:成功或失败。而在分布式系统中,由于网络是不可靠的,虽然在绝大部分情况下,网络通信也能够接收到成功或失败的响应,但是当网络出现异常的情况下,就可能会出现超时现象,通常有以下两种情况:  由于网络原因,该请求(消息)并没有被成功地发送到接收方,而是在发送过程就发生了消息丢失现象。

  该请求(消息)成功的被接收方接收后,并进行了处理,但是在将响应反馈给发送方的过程中,发生了消息丢失现象。  当出现这样的超时现象时,网络通信的发起方是无法确定当前请求是否被成功处理的。

  节点故障

  节点故障则是分布式环境下另一个比较常见的问题,指的是组成分布式系统的服务器节点出现的宕机或“僵死”现象。通常根据经验来说,每个节点都有可能会出现故障,并且每天都在发生。

  1.2 从ACID到CAP/BASE

  在上文中,我们讲解了集中式系统和分布式系统各自的特点,同时也看到了在从集中式系统架构向分布式系统架构变迁的过程中会碰到的一系列问题。接下来,我们再重点看看在分布式系统事务处理与数据一致性上遇到的种种挑战。

  1.2.1 ACID

  事务(Transaction)是由一系列对系统中数据进行访问与更新的操作所组成的一个程序执行逻辑单元(Unit),狭义上的事务特指数据库事务。一方面,当多个应用程序并发访问数据库时,事务可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。另一方面,事务为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持数据一致性的方法。

  事务具有四个特征,分别是原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability),简称为事务的ACID特性。  原子性  事务的原子性是指事务必须是一个原子的操作序列单元。事务中包含的各项操作在一次执行过程中,只允许出现以下两种状态之一。

  全部成功执行。

  全部不执行。

  任何一项操作失败都将导致整个事务失败,同时其他已经被执行的操作都将被撤销并回滚,只有所有的操作全部成功,整个事务才算是成功完成。

  一致性

  事务的一致性是指事务的执行不能破坏数据库数据的完整性和一致性,一个事务在执行之前和执行之后,数据库都必须处于一致性状态。也就是说,事务执行的结果必须是使数据库从一个一致性状态转变到另一个一致性状态,因此当数据库只包含成功事务提交的结果时,就能说数据库处于一致性状态。而如果数据库系统在运行过程中发生故障,有些事务尚未完成就被迫中断,这些未完成的事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不正确的状态,或者说是不一致的状态。

  隔离性

  事务的隔离性是指在并发环境中,并发的事务是相互隔离的,一个事务的执行不能被其他事务干扰。也就是说,不同的事务并发操纵相同的数据时,每个事务都有各自完整的数据空间,即一个事务内部的操作及使用的数据对其他并发事务是隔离的,并发执行的各个事务之间不能互相干扰。

  在标准SQL规范中,定义了4个事务隔离级别,不同的隔离级别对事务的处理不同,如未授权读取、授权读取、可重复读取和串行化注 。

  未授权读取

  未授权读取也被称为读未提交(Read Uncommitted),该隔离级别允许脏读取,其隔离级别最低。换句话说,如果一个事务正在处理某一数据,并对其进行了更新,但同时尚未完成事务,因此还没有进行事务提交;而与此同时,允许另一个事务也能够访问该数据。举个例子来说,事务A和事务B同时进行,事务A在整个执行阶段,会将某数据项的值从1开始,做一系列加法操作(比如说加1操作)直到变成10之后进行事务提交,此时,事务B能够看到这个数据项在事务A操作过程中的所有中间值(如1变成2、2变成3等),而对这一系列的中间值的读取就是未授权读取。

  授权读取

  授权读取也被称为读已提交(Read Committed),它和未授权读取非常相近,唯一的区别就是授权读取只允许获取已经被提交的数据。同样以上面的例子来说,事务A和事务B同时进行,事务A进行与上述同样的操作,此时,事务B无法看到这个数据项在事务A操作过程中的所有中间值,只能看到最终的10。另外,如果说有一个事务C,和事务A进行非常类似的操作,只是事务C是将数据项从10加到20,此时事务B也同样可以读取到20,即授权读取允许不可重复读取。

  可重复读取

  可重复读取(Repeatable Read),简单地说,就是保证在事务处理过程中,多次读取同一个数据时,其值都和事务开始时刻是一致的。因此该事务级别禁止了不可重复读取和脏读取,但是有可能出现幻影数据。所谓幻影数据,就是指同样的事务操作,在前后两个时间段内执行对同一个数据项的读取,可能出现不一致的结果。在上面的例子,可重复读取隔离级别能够保证事务B在第一次事务操作过程中,始终对数据项读取到1,但是在下一次事务操作中,即使事务B(注意,事务名字虽然相同,但是指的是另一次事务操作)采用同样的查询方式,就可能会读取到10或20。

  串行化

  串行化(Serializable)是最严格的事务隔离级别。它要求所有事务都被串行执行,即事务只能一个接一个地进行处理,不能并发执行。

  图1-1展示了不同隔离级别下事务访问数据的差异。

  图1-1.4种隔离级别示意图

  以上4个隔离级别的隔离性依次增强,分别解决不同的问题,表1-1对这4个隔离级别进行了一个简单的对比。

  表1-1.隔离级别对比  隔离级别 脏读 可重复读 幻读  未授权读取 存在 不可以 存在

  授权读取 不存在 不可以 存在

  可重复读取 不存在 可以 存在

  串行化 不存在 可以 不存在

  事务隔离级别越高,就越能保证数据的完整性和一致性,但同时对并发性能的影响也越大。通常,对于绝大多数的应用程序来说,可以优先考虑将数据库系统的隔离级别设置为授权读取,这能够在避免脏读取的同时保证较好的并发性能。尽管这种事务隔离级别会导致不可重复读、虚读和第二类丢失更新等并发问题,但较为科学的做法是在可能出现这类问题的个别场合中,由应用程序主动采用悲观锁或乐观锁来进行事务控制。

  持久性

  事务的持久性也被称为永久性,是指一个事务一旦提交,它对数据库中对应数据的状态变更就应该是永久性的。换句话说,一旦某个事务成功结束,那么它对数据库所做的更新就必须被永久保存下来——即使发生系统崩溃或机器宕机等故障,只要数据库能够重新启动,那么一定能够将其恢复到事务成功结束时的状态。

  1.2.2 分布式事务

  随着分布式计算的发展,事务在分布式计算领域中也得到了广泛的应用。在单机数据库中,我们很容易能够实现一套满足ACID特性的事务处理系统,但在分布式数据库中,数据分散在各台不同的机器上,如何对这些数据进行分布式的事务处理具有非常大的挑战。在1.1.3节中,我们已经讲解了分布式环境中会碰到的种种问题,其中就包括机器宕机和各种网络异常等。尽管存在这种种分布式问题,但是在分布式计算领域,为了保证分布式应用程序的可靠性,分布式事务是无法回避的。

  分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于分布式系统的不同节点之上。通常一个分布式事务中会涉及对多个数据源或业务系统的操作。

  我们可以设想一个最典型的分布式事务场景:一个跨银行的转账操作涉及调用两个异地的银行服务,其中一个是本地银行提供的取款服务,另一个则是目标银行提供的存款服务,这两个服务本身是无状态并且是互相独立的,共同构成了一个完整的分布式事务。如果从本地银行取款成功,但是因为某种原因存款服务失败了,那么就必须回滚到取款前的状态,否则用户可能会发现自己的钱不翼而飞了。

  从上面这个例子中,我们可以看到,一个分布式事务可以看作是由多个分布式的操作序列组成的,例如上面例子中的取款服务和存款服务,通常可以把这一系列分布式的操作序列称为子事务。因此,分布式事务也可以被定义为一种嵌套型的事务,同时也就具有了ACID事务特性。但由于在分布式事务中,各个子事务的执行是分布式的,因此要实现一种能够保证ACID特性的分布式事务处理系统就显得格外复杂。

  1.2.3 CAP和BASE理论

  对于本地事务处理或者是集中式的事务处理系统,很显然我们可以采用已经被实践证明很成熟的ACID模型来保证数据的严格一致性。而在1.2.2节中,我们也已经看到,随着分布式事务的出现,传统的单机事务模型已经无法胜任。尤其是对于一个高访问量、高并发的互联网分布式系统来说,如果我们期望实现一套严格满足ACID特性的分布式事务,很可能出现的情况就是在系统的可用性和严格一致性之间出现冲突——因为当我们要求分布式系统具有严格一致性时,很可能就需要牺牲掉系统的可用性。但毋庸置疑的一点是,可用性又是一个所有消费者不允许我们讨价还价的系统属性,比如说像淘宝网这样的在线购物网站,就要求它能够7?24小时不间断地对外提供服务,而对于一致性,则更加是所有消费者对于一个软件系统的刚需。因此,在可用性和一致性之间永远无法存在一个两全其美的方案,于是如何构建一个兼顾可用性和一致性的分布式系统成为了无数工程师探讨的难题,出现了诸如CAP和BASE这样的分布式系统经典理论。

  CAP定理

  2000年7月,来自加州大学伯克利分校的Eric Brewer教授注 在ACM PODC(Principles of Distributed Computing)会议上,首次提出了著名的CAP猜想注 。2年后,来自麻省理工学院的Seth Gilbert和Nancy Lynch从理论上证明了Brewer教授CAP猜想的可行性注 ,从此,CAP理论正式在学术上成为了分布式计算领域的公认定理,并深深地影响了分布式计算的发展。

  CAP理论告诉我们,一个分布式系统不可能同时满足一致性(C:Consistency)、可用性(A:Availability)和分区容错性(P:Partition tolerance)这三个基本需求,最多只能同时满足其中的两项。

  一致性  在分布式环境中,一致性是指数据在多个副本之间是否能够保持一致的特性。在一致性的需求下,当一个系统在数据一致的状态下执行更新操作后,应该保证系统的数据仍然处于一致的状态。

  对于一个将数据副本分布在不同分布式节点上的系统来说,如果对第一个节点的数据进行了更新操作并且更新成功后,却没有使得第二个节点上的数据得到相应的更新,于是在对第二个节点的数据进行读取操作时,获取的依然是老数据(或称为脏数据),这就是典型的分布式数据不一致情况。在分布式系统中,如果能够做到针对一个数据项的更新操作执行成功后,所有的用户都可以读取到其最新的值,那么这样的系统就被认为具有强一致性(或严格的一致性)。

  可用性

  可用性是指系统提供的服务必须一直处于可用的状态,对于用户的每一个操作请求总是能够在有限的时间内返回结果。这里我们重点看下“有限的时间内”和“返回结果”。

  “有限的时间内”是指,对于用户的一个操作请求,系统必须能够在指定的时间(即响应时间)内返回对应的处理结果,如果超过了这个时间范围,那么系统就被认为是不可用的。另外,“有限的时间内”是一个在系统设计之初就设定好的系统运行指标,通常不同的系统之间会有很大的不同。比如说,对于一个在线搜索引擎来说,通常在0.5秒内需要给出用户搜索关键词对应的检索结果。以Google为例,搜索“分布式”这一关键词,Google能够在0.3秒左右的时间,返回大约上千万条检索结果。而对于一个面向HIVE的海量数据查询平台来说,正常的一次数据检索时间可能在20秒到30秒之间,而如果是一个时间跨度较大的数据内容查询,“有限的时间”有时候甚至会长达几分钟。

  从上面的例子中,我们可以看出,用户对于一个系统的请求响应时间的期望值不尽相同。但是,无论系统之间的差异有多大,唯一相同的一点就是对于用户请求,系统必须存在一个合理的响应时间,否则用户便会对系统感到失望。

  “返回结果”是可用性的另一个非常重要的指标,它要求系统在完成对用户请求的处理后,返回一个正常的响应结果。正常的响应结果通常能够明确地反映出对请求的处理结果,即成功或失败,而不是一个让用户感到困惑的返回结果。

  让我们再来看看上面提到的在线搜索引擎的例子,如果用户输入指定的搜索关键词后,返回的结果是一个系统错误,通常类似于“OutOfMemoryError”或“System Has Crashed”等提示语,那么我们认为此时系统是不可用的。

  分区容错性

  分区容错性约束了一个分布式系统需要具有如下特性:分布式系统在遇到任何网络分区故障的时候,仍然需要能够保证对外提供满足一致性和可用性的服务,除非是整个网络环境都发生了故障。

  网络分区是指在分布式系统中,不同的节点分布在不同的子网络(机房或异地网络等)中,由于一些特殊的原因导致这些子网络之间出现网络不连通的状况,但各个子网络的内部网络是正常的,从而导致整个系统的网络环境被切分成了若干个孤立的区域。需要注意的是,组成一个分布式系统的每个节点的加入与退出都可以看作是一个特殊的网络分区。

  以上就是对CAP定理中一致性、可用性和分区容错性的讲解,通常使用图1-2所示的示意图来表示CAP定理。

  既然在上文中我们提到,一个分布式系统无法同时满足上述三个需求,而只能满足其中的两项,因此在进行对CAP定理的应用时,我们就需要抛弃其中的一项,表1-2所示是抛弃CAP定理中任意一项特性的场景说明。

  图1-2.CAP定理示意图

  表1-2.CAP定理应用

  放弃CAP定理 说明

  放弃P 如果希望能够避免系统出现分区容错性问题,一种较为简单的做法是将所有的数据(或者仅仅是那些与事务相关的数据)都放在一个分布式节点上。这样的做法虽然无法100%地保证系统不会出错,但至少不会碰到由于网络分区带来的负面影响。但同时需要注意的是,放弃P的同时也就意味着放弃了系统的可扩展性

  放弃A 相对于放弃“分区容错性”来说,放弃可用性则正好相反,其做法是一旦系统遇到网络分区或其他故障时,那么受到影响的服务需要等待一定的时间,因此在等待期间系统无法对外提供正常的服务,即不可用

  放弃C 这里所说的放弃一致性,并不是完全不需要数据一致性,如果真是这样的话,那么系统的数据都是没有意义的,整个系统也是没有价值的。

  事实上,放弃一致性指的是放弃数据的强一致性,而保留数据的最终一致性。这样的系统无法保证数据保持实时的一致性,但是能够承诺的是,数据最终会达到一个一致的状态。这就引入了一个时间窗口的概念,具体多久能够达到数据一致取决于系统的设计,主要包括数据副本在不同节点之间的复制时间长短

  从CAP定理中我们可以看出,一个分布式系统不可能同时满足一致性、可用性和分区容错性这三个需求。另一方面,需要明确的一点是,对于一个分布式系统而言,分区容错性可以说是一个最基本的要求。为什么这样说,其实很简单,因为既然是一个分布式系统,那么分布式系统中的组件必然需要被部署到不同的节点,否则也就无所谓分布式系统了,因此必然出现子网络。而对于分布式系统而言,网络问题又是一个必定会出现的异常情况,因此分区容错性也就成为了一个分布式系统必然需要面对和解决的问题。因此系统架构设计师往往需要把精力花在如何根据业务特点在C(一致性)和A(可用性)之间寻求平衡。

  BASE理论

  BASE是Basically Available(基本可用)、Soft state(软状态)和Eventually consistent(最终一致性)三个短语的简写,是由来自eBay的架构师Dan Pritchett在其文章BASE: An Acid Alternative注 中第一次明确提出的。BASE是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的总结,是基于CAP定理逐步演化而来的,其核心思想是即使无法做到强一致性(Strong consistency),但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual consistency)。接下来我们着重对BASE中的三要素进行详细讲解。

  基本可用

  基本可用是指分布式系统在出现不可预知故障的时候,允许损失部分可用性——但请注意,这绝不等价于系统不可用。以下两个就是“基本可用”的典型例子。

  响应时间上的损失:正常情况下,一个在线搜索引擎需要在0.5秒之内返回给用户相应的查询结果,但由于出现故障(比如系统部分机房发生断电或断网故障),查询结果的响应时间增加到了1~2秒。

  功能上的损失:正常情况下,在一个电子商务网站上进行购物,消费者几乎能够顺利地完成每一笔订单,但是在一些节日大促购物高峰的时候,由于消费者的购物行为激增,为了保护购物系统的稳定性,部分消费者可能会被引导到一个降级页面。

  弱状态

  弱状态也称为软状态,和硬状态相对,是指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时。

  最终一致性

  最终一致性强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。

  亚马逊首席技术官Werner Vogels在于2008年发表的一篇经典文章Eventually Consistent-

  Revisited中,对最终一致性进行了非常详细的介绍。他认为最终一致性是一种特殊的弱一致性:系统能够保证在没有其他新的更新操作的情况下,数据最终一定能够达到一致的状态,因此所有客户端对系统的数据访问都能够获取到最新的值。同时,在没有发生故障的前提下,数据达到一致状态的时间延迟,取决于网络延迟、系统负载和数据复制方案设计等因素。

  在实际工程实践中,最终一致性存在以下五类主要变种。

  因果一致性(Causal consistency)

  因果一致性是指,如果进程A在更新完某个数据项后通知了进程B,那么进程B之后对该数据项的访问都应该能够获取到进程A更新后的最新值,并且如果进程B要对该数据项进行更新操作的话,务必基于进程A更新后的最新值,即不能发生丢失更新情况。与此同时,与进程A无因果关系的进程C的数据访问则没有这样的限制。

  读己之所写(Read your writes)

  读己之所写是指,进程A更新一个数据项之后,它自己总是能够访问到更新过的最新值,而不会看到旧值。也就是说,对于单个数据获取者来说,其读取到的数据,一定不会比自己上次写入的值旧。因此,读己之所写也可以看作是一种特殊的因果一致性。  会话一致性(Session consistency)

  会话一致性将对系统数据的访问过程框定在了一个会话当中:系统能保证在同一个有效的会话中实现“读己之所写”的一致性,也就是说,执行更能操作之后,客户端能够在同一个会话中始终读取到该数据项的最新值。

  单调读一致性(Monotonic read consistency)

  单调读一致性是指如果一个进程从系统中读取出一个数据项的某个值后,那么系统对于该进程后续的任何数据访问都不应该返回更旧的值。

  单调写一致性(Monotonic write consistency)

  单调写一致性是指,一个系统需要能够保证来自同一个进程的写操作被顺序地执行。

  以上就是最终一致性的五类常见的变种,在实际系统实践中,可以将其中的若干个变种互相结合起来,以构建一个具有最终一致性特性的分布式系统。事实上,最终一致性并不是只有那些大型分布式系统才涉及的特性,许多现代的关系型数据库都采用了最终一致性模型。在现代关系型数据库中,大多都会采用同步和异步方式来实现主备数据复制技术。在同步方式中,数据的复制过程通常是更新事务的一部分,因此在事务完成后,主备数据库的数据就会达到一致。而在异步方式中,备库的更新往往会存在延时,这取决于事务日志在主备数据库之间传输的时间长短,如果传输时间过长或者甚至在日志传输过程中出现异常导致无法及时将事务应用到备库上,那么很显然,从备库中读取的数据将是旧的,因此就出现了数据不一致的情况。当然,无论是采用多次重试还是人为数据订正,关系型数据库还是能够保证最终数据达到一致——这就是系统提供最终一致性保证的经典案例。

  总的来说,BASE理论面向的是大型高可用可扩展的分布式系统,和传统事务的ACID特性是相反的,它完全不同于ACID的强一致性模型,而是提出通过牺牲强一致性来获得可用性,并允许数据在一段时间内是不一致的,但最终达到一致状态。但同时,在实际的分布式场景中,不同业务单元和组件对数据一致性的要求是不同的,因此在具体的分布式系统架构设计过程中,ACID特性与BASE理论往往又会结合在一起使用。

  小结

  计算机系统从集中式向分布式的变革伴随着包括分布式网络、分布式事务和分布式数据一致性等在内的一系列问题与挑战,同时也催生了一大批诸如ACID、CAP和BASE等经典理论的快速发展。

  本章由计算机系统从集中式向分布式发展的过程展开,围绕在分布式架构发展过程中碰到的一系列问题,结合ACID、CAP和BASE等分布式事务与一致性方面的经典理论,向读者介绍了分布式架构。

  ……


前言/序言

问题的提出

  在计算机科学领域,分布式一致性问题是一个相当重要,且被广泛探索与论证的问题,通常存在于诸如分布式文件系统、缓存系统和数据库等大型分布式存储系统中。

  什么是分布式一致性?分布式一致性分为哪些类型?分布式系统达到一致性后将会是一个什么样的状态?如果失去了一致性约束,分布式系统是否还可以依赖?如果一味地追求一致性,对系统的整体架构和性能又有多大影响?这一系列的问题,似乎都没有一个严格意义上准确的定义和答案。

终端用户

 IT技术的发展,让我们受益无穷,从日常生活的超市收银,到高端精细的火箭发射,现代社会中几乎所有行业,都离不开计算机技术的支持。

尽管计算机工程师们创造出了很多高科技的计算机产品来解决我们日常碰到的问题,但用户只会倾向于选择一些易用、好用的产品,那些难以使用的计算机产品最终都会被淘汰——这种易用性,其实就是用户体验的一部分。

计算机产品的用户体验,可以分为便捷性、安全性和稳定性等方面。在本书中,我们主要讨论的是用户在使用计算机产品过程中遇到的那些和一致性有关的问题。在此之前,我们首先来看一下计算机产品的终端用户是谁,他们的需求又是什么。

火车站售票

假如说我们的终端用户是一位经常做火车的旅行家,通常他是去车站的售票处购买车票,然后拿着车票去检票口,再坐上火车,开始一段美好的旅行——一切似乎都是那么和谐。想象一下,如果他选择的目的地是杭州,而某一趟开往杭州的火车只剩下最后一张车票了,可能在同一时刻,不同售票窗口的另一位乘客也购买了同一张车票。假如说售票系统没有进行一致性保障,两人都购票成功了。而在检票口检票的时候,其中一位乘客会被告知他的车票无效——当然,现代的中国铁路售票系统已经很少出现这样的问题了,但在这个例子中,我们可以看出,终端用户对于我们的系统的需求非常简单:

“请售票给我,如果没有余票了,请在售票的时候就告诉我票是无效票的。”

 这就对购票系统提出了严格的一致性要求——系统的数据(在本例中指的就是那趟开往杭州的火车的余票数),无论在哪个售票窗口,每时每刻都必须是准确无误的!

银行转账

假如说我们的终端用户是一名刚毕业的大学生,通常在拿到第一个月工资之后,都会选择向家里汇款。当他来到银行柜台,完成转账操作后,银行的柜台服务员会友善地提醒他:“您的转账将在N个工作日后到账!”此时这名毕业生有一些沮丧,会对那名柜台服务员叮嘱:“好吧,多久没关系,钱不要少就行了!”——这也成为了几乎所有的用户对于现代银行系统最基本的需求。

网上购物

假如说我们的终端用户是一名网上购物狂,当他看到一件库存量为5的心仪商品,会迅速地确认购买,写下收货地址,然后下单——然而,在下单的那个瞬间,系统可能会告知该用户:“库存量不足!”此时,绝大部分的消费者往往都会抱怨自己动作太慢,使得心爱的商品被其他人抢走了!

但其实有过网购系统开发经验的工程师一定明白,在商品详情页面上显示的那个库存量,通常不是该商品的真实库存量,只有在真正下单购买的时候,系统才会检查该商品的真实库存量。但是,谁在意呢?

在上面三个例子中,相信读者一定已经看出来了,我们的终端用户在使用不同的计算机产品时对于数据一致性的需求是不一样的:

有些系统,既要快速地响应用户,同时还要保证系统的数据对于任意客户端都是真实可靠的,就像火车站的售票系统。

还有些系统,需要为用户保证绝对可靠的数据安全,虽然在数据一致性上存在延时,但最终务必保证严格的一致,就像银行的转账系统。

另外的一些系统,虽然向用户展示了一些可以说是“错误”的数据,但是在整个系统使用过程中,一定会在某一个流程上对系统数据进行准确无误的检查,从而避免用户发生不必要的损失,就像网购系统。

更新的并发性

在计算机发展的早期阶段,受到底层硬件技术的制约,同时也是由于人们对于计算机系统的实际使用需求比较简单,因此很多上层的应用程序架构都是单线程模型的。以C语言为例,其诞生于上世纪70年代,当时几乎所有使用C语言开发的应用程序都是单线程的。从现在来看,单线程应用程序虽然在运行效率上无法和后来的多线程应用程序相比,但是在编程模型上相对简单,因此能够避免多线程程序中出现的不少并发问题。

随着计算机底层硬件技术和现代操作系统的不断发展,多线程技术开始被越来越多地引入到计算机编程模型之中,并对现代计算机应用程序的整体架构起到了至关重要的作用。

多线程的引入,为应用程序带来性能上的卓越提升,同时也带来了一个最大的副作用,那就是并发。《深入理解计算机系统》一书对并发进行了如下定义:如果逻辑控制流在时间上重叠,那么它们就是并发的。这里提到的逻辑控制流,通俗地讲,就是一次程序操作,比如读取或更新内存中变量的值。

在本书后面的讨论中,我们提到的“并发”都特指更新操作的并发,即有多个线程同时更新内存中变量的值——我们将这一现象称为更新的并发性。

分布式一致性问题

在分布式系统中另一个需要解决的重要问题就是数据的复制。在我们日常的开发经验中,相信很多开发人员都碰到过这样的问题:假设客户端C1将系统中的一个值K由V1更新为V2,但客户端C2无法立即读取到K的最新值,需要在一段时间之后才能读取到。读者可能也已经猜到了,上面这个例子就是常见的数据库之间复制的延时问题。

分布式系统对于数据的复制需求一般都来自于以下两个原因。

为了增加系统的可用性,以防止单点故障引起的系统不可用。

提高系统的整体性能,通过负载均衡技术,能够让分布在不同地方的数据副本都能够为用户提供服务。

数据复制在可用性和性能方面给分布式系统带来的巨大好处是不言而喻的,然而数据复制所带来的一致性挑战,也是每一个系统研发人员不得不面对的。

所谓的分布式一致性问题,是指在分布式环境中引入数据复制机制后,不同数据节点间可能出现的,并无法依靠计算机应用程序自身解决的数据不一致情况。简单地讲,数据一致性就是指在对一个副本数据进行更新的同时,必须确保也能够更新其他的副本,否则不同副本之间的数据将不再一致。

那怎么来解决这个问题呢?顺着上面提到的复制延时问题,很快就有人想到了一种解决办法,那就是:

 “既然是由于延时引起的问题,那我可以将写入的动作阻塞,直到数据复制完成后,才完成写入动作。”

没错,这似乎能解决问题,而且有一些系统的架构也确实直接使用了这个思路。但这个思路在解决一致性问题的同时,又带来了新的问题:写入的性能。如果你的应用场景有非常多的写请求,那么使用这个思路之后,后续的写请求都将会阻塞在前一个请求的写操作上,导致系统整理性能急剧下降。

总的来讲,我们无法找到一种能够满足分布式系统所有系统属性的分布式一致性解决方案。因此,如何既保证数据的一致性,同时又不影响系统运行的性能,是每一个分布式系统都需要重点考虑和权衡的。于是,一致性级别由此诞生。

强一致性

这种一致性级别是最符合用户直觉的,它要求系统写入什么,读出来的也会是什么,用户体验好,但实现起来往往对系统的性能影响比较大。

弱一致性

这种一致性级别约束了系统在写入成功后,不承诺立即可以读到写入的值,也不具体承诺多久之后数据能够达到一致,但会尽可能地保证到某个时间级别(比如秒级别)后,数据能够达到一致状态。弱一致性还可以再进行细分:

会话一致性:该一致性级别只保证对于写入的值,在同一个客户端会话中可以读到一致的值,但其他的会话不能保证。

用户一致性:该一致性级别只保证对于写入的值,在同一个用户中可以读到一致的值,但其他用户不能保证。

最终一致性

最终一致性是弱一致性的一个特例,系统会保证在一定时间内,能够达到一个数据一致的状态。这里之所以将最终一致性单独提出来,是因为它是弱一致性中非常重要的一种一致性模型,也是业界在大型分布式系统的数据一致性上比较推崇的模型。

本书将会从分布式一致性的理论出发,向读者讲解几种典型的分布式一致性协议是如何解决分布式一致性问题的。之后,本书则会深入介绍分布式一致性问题的工业解决方案——ZooKeeper,并着重向读者展示这一分布式协调框架的使用方法、内部实现以及运维技巧。

致谢

  首先要感谢现在的部门老大蒋江伟先生。第一次接触蒋江伟是在2011年,当时参加了他的一个讲座“淘宝前台系统优化实践——吞吐量优化”,对其中关于“编写GC友好代码”的内容有不解之处,于是私下请教。他耐心的讲解令我至今记忆犹新。两年前,他全面负责中间件团队之后,给予了我更大的帮助和鼓励,使我得到了极大的进步,真的非常感谢。本书的问世,离不开他的推荐。也正是这一份写作的责任感,让我有决心和毅力来对整个ZooKeeper内容进行了一次全面的整理。在这里,衷心祝福蒋江伟先生带领中间件团队走向新的高度。

  其次,本书的写作,离不开各位小伙伴们的支持和帮助,他们是各领域的资深专家,我向他们征集了很多有营养的内容。在这里,按照章节顺序,依次表示感谢:许泽彬参与了“问题提出”的写作;侯前明对Paxos算法的前世今生进行的整理;段培乐对晦涩的Paxos协议进行了细致的讲解;姜宇向我提供了他对于分布式事务的见解;徐伟辰参与了分布式锁服务Chubby相关的写作;叶成旭提供了他在上家公司时对Hypertable的学习和研究成果;高伟细致地向我展示了Curator这一ZooKeeper客户端的使用;陈杰提供了他在“自动化的DNS服务”场景中的经验总结;曹龙参与了Hadoop相关内容的写作;邓明鉴则贡献了他对HBase的深刻见解;作为产品的开源负责人,庄晓丹和王强提供了对消息中间件Metamorphosis技术架构的讲解;李鼎则向我全面展示了RPC服务框架Dubbo的技术细节;楼江航向我提供了Canal和Otter这两个分布式产品中的ZooKeeper应用场景;李雨前、柳明和温朝凯则一起写了终搜在产品演进过程中对ZooKeeper的使用和改进;封仲淹参与了对其自主产品JStorm的技术剖析……是你们一遍又一遍地对内容进行修改,才使得本书内容更为丰满。

  另外,也要感谢温文鎏、王林、许泽彬、高伟和段培乐等人对全书的审阅,正是你们提出的宝贵建议,对完善本书提供了非常大的帮助。

  感谢现在的同事陆学慧先生,从2013年下半年开始,他全面接手对ZooKeeper的开发和运维,在他身上感受到的专业和创新精神让我备受鼓舞。

  另外,感谢我的第一个主管马震先生,是他的帮助为我指引了方向,让我有机会进入ZooKeeper的世界,并负责这个产品在公司的发展。尽管由于业务调整,马震先生已经转岗到其他部门,但依然由衷祝福他工作顺利。

  还要感谢我的同事,阿里巴巴店铺平台的侯前明先生。本来该书作者应该是我们两个人,但是由于期间他的家庭又增加了一个小生命,导致其不得不中途退出。从本书的选题到写作大纲的制定,他都倾注了不少心血,相信如果有他一起创作,本书内容会更加丰满、深刻。这里表达遗憾的同时,也向这位两个孩子的父亲送去祝福,祝愿他生活美满。

  感谢本书的责任编辑刘芸女士,是她反复审稿和编排,才能让本书的内容趋于完美。

  感谢本书的封面设计吴海燕女士,她的努力已经无需言表,在技术书上的这一前卫、极富视觉冲击力的封面设计,深深震撼到了我,也希望读者朋友们能够喜欢。

  尤其感谢本书的策划编辑张春雨先生。作为一个南方人,我很少有机会和那些有着一口北方腔的朋友交谈,第一次接到张春雨先生电话的时候,我才真正领略了北京腔,也正是他的邀请,才能让我有机会进行本书的撰写,同时在前后将近1年半的漫长写作过程中,也是他的帮助和鼓励,才让我坚持完成并不断完善本书的内容。在这里,也衷心祝愿张春雨先生事业更上一层楼。

  最后,还有我的父母,在过去的1年时间里,多次放假没有回家,尽管父母一直鼓励我专注工作,专注于自己的事业,但我深知他们内心对儿子的牵挂,在这里也深深地向他们道一声:“谢谢”,也谨以此书献给我最亲爱的爸爸妈妈。

  倪超

  2014年12月于杭州淘宝城


点此购买


微服务架构设计模式
Kafka权威指南(图灵出品)
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

机器学习系列书籍

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }