分布式系统下如何进行数据复制?(上)

在开始讨论数据复制之前,我们需要一个理由为什么要进行数据复制?数据复制显然会给应用带来更高的复杂性,那么我们给出最大理由就是数据复制可以备份数据,使得节点挂掉的时候,保证数据不被丢失,应用还可以使用,而不仅仅因为这个,数据复制还会给我们带来一个更好读性能的提升,因为请求可以分发到不同节点,读取数据,而不是局限在一个节点,除了这两个,还有一个比较隐性的选择,如果是多地的复制,还可以减少对使用者的延迟。所以我们选择了数据复制,在下面的讨论当中,我们有一个前提,不考虑数据分区,而是假设数据集足够少。

对于数据间的复制,最流行的算法有三种:single-leader,multi-leader和leaderless。从三个算法的命名中,我们可以看出其中都牵扯到leader和follower的概念。那我们就从这两个概念开始吧。

什么是leader呢?别名有很多,例如master/primary。它负责接收client发出的request,如果是write的话,会先写入leader本身的storage,如果是read的话,则会分发给follower。那么follower呢?别名readreplicas, slaves, secondaries, hot standbys。它负责接收leader的log,然后更新自身的复制数据,也会返回leader发过来的read request需要的reponse。

这时我们注意到,leader和follower的数据交互,可以有两种选择,一个是同步,一个是异步。同步的意义是指当leader发送request给follower时,会一直等待所有follower回复了ok,才会确认这次请求是成功的,异步则相反,leader发送消息后,会立马确认成功,不会等待follower回复ok。如果稍微深入的话,我们可以发现选择同步的话,我们可以很好的保证数据的一致,但是随之而来的则是放弃了性能,而异步则无法保证leader发出的消息,follower是否真的接受到了吗?于是trade-off又出来了,一种特殊的半同步方式,follower发送消息,只会等待其中一个follower确认成功了,就会确认ok。

当然,leader和follower不可能时一成不变的,leader只有当其挂了之后,才会考虑设立新的leader。所以设立新的followe反倒是比较常见的情况,不考虑细节抽象的来看的话,首先确定leader在某个时刻的snapshot,再将这snapshot复制到新的follower,新的follower会连接leader获得最新的数据变化,最后这时follower就可以使用了,不过会在后台处理之前的snapshot。

作为一个分布式系统,最重要的一点就是如何处理Node Outages。在single-leader的情况下,follower如果失去了联系,很简单,只要等待恢复就好,反正有log的存在。那么最核心的问题就是leader宕机了,这个就是failover了。那么碰上这种情况,就要先确定leader是不是真的挂了,然后选择新的leader,可以使用专门的controller node处理,最后再重新注册新的leader。说起来容易,做起来实则非常难。有这么几个问题需要解决,1.如果是异步复制,新的leader和旧的leader中间的gap遗漏的数据怎么处理?2.旧的leader如果又活过来,follower该听谁的?(split brain)。3.如何确定合适的timeout去确定leader挂了。

最后再来看看该如何执行日志的复制。一般而言有下面几种方法:

1. statement-based复制

基于database的insert,update和delete语句去处理数据。这个方法听起来很靠谱,然而会有一些情况无法处理,比如statement使用了nondeterministic函数(NOW这些取决于当时情况的语句)、自增函数或者取决于当时存在数据的函数,甚至副作用也会存在。

2. Write-ahead log Shipping

对于基于log的database,可以直接选择复制log给follower。不过这个最大的影响是没有考虑到follower中间的版本不一致的问题,如果follower间有些先进行升级了,有些还是老的版本,那么对于log的解析就会出现不同的情况。

3. Logical(row-based)log replication

这个是log的基础上再做进一步处理,使其变得和要处理的数据一模一样。

原文发布于微信公众号 - 鸿的学习笔记(shujuxuexizhilu)

原文发表时间:2018-02-05

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏无所事事者爱嘲笑

ionic2 (真正)修改应用图标和启动画面

1606
来自专栏姬小光

姬小光前端小讲堂【第006期】

在前几期的成果中,我们做出来的页面只有一些“静态”的内容,只能给用户大眼瞪小眼的看,那么别人家的网页上那些飞来飞去的,若隐若现的东西都是咋搞的呢?

832
来自专栏后端技术探索

进程,线程,协程与并行,并发

进程的出现是为了更好的利用CPU资源使到并发成为可能。 假设有两个任务A和B,当A遇到IO操作,CPU默默的等待任务A读取完操作再去执行任务B,这样无疑是对CP...

1353
来自专栏linux、Python学习

Linux运维工程师必备的80个监控工具全集(上)

随着互联网行业的不断发展,各种监控工具多得不可胜数。这里列出网上最全的监控工具。让你可以拥有超过80种方式来管理你的机器。

1270
来自专栏Rainbond开源「容器云平台」

开源Rainbond发布v3.4.2更新:应用插件体系进入beta版本

1303
来自专栏Golang语言社区

【Go 语言社区】如何实现单服务器300万个长连接的?

不是吹牛,理论上完全可以达到。 (以下参考值皆是Linux平台上) 1,Linux单个进程可以维持的连接数(fd)理论值是通过ulimit -a设置,或在se...

66610
来自专栏JAVA同学会

Kafka 简介

在Kafka中,客户端和服务器之间的通信是通过一种简单的,高性能的,语言不可知的TCP协议完成的。

3054
来自专栏Crossin的编程教室

【Python 第31课】 读文件

之前,我们写的程序绝大多数都依赖于从命令行输入。假如某个程序需要输入很多数据,比如一次考试的全班学生成绩,再这么输就略显痛苦了。一个常见的办法就是把学生的成绩都...

3497
来自专栏Debian社区

Parsix GNU/Linux 项目宣布即将终止

基于 Debian 的 Parsix 发行版已经宣布将会在 Debian Stretch 发布六个月后终止。官方表示 Parsix GNU/Linux 8.15...

912
来自专栏IT技术精选文摘

分布式存储理论与实践初探 (二)

数据分布 分布式存储系统需要将数据分布到多个节点,并在多个节点之间实现负载均衡。常见的数据分布的方式有两种:一种是哈希分布,如一致性哈希,典型的系统是Amazo...

2226

扫码关注云+社区