大家好,我是砸锅。一个摸鱼八年的后端开发。熟悉 Go、Lua。今天和大家一起学习分布式技术😊
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 25 天,点击查看活动详情
数据复制
如何让存储服务高可用
- 避免故障出现
- 接受故障随时出现的可能,通过冗余的方法让系统在故障发生时,也能正常提供服务
数据复制的方案
对于一个数据集来说,每个保持完整数据集的节点称为副本,接受写请求的副本称为主副本,其他副本称为从副本,从副本可以接受读请求
基于是否有主副本、有一个还是多个,可以将数据复制的方案分为三种:
- 主从复制,整个系统只有一个主副本,其他都是从副本
- 多主复制,系统存在多个主副本,客户端将写请求发给其中一个主副本,这个主副本负责将数据变更发送到其他所有的主副本
- 无主复制,系统不存在主副本,每个副本都可以接受客户端的写请求,接受写请求的副本不会将数据变更同步到其他副本
主从复制
主从复制是最常见、最容易理解的复制方案。例如 Redis、MySQL、PostgreSQL、Kafka 等都支持主从复制
主从复制的工作流程主要就是将变更数据从主副本复制到从副本里,但是会出现一个问题:究竟是同步复制还是异步复制呢?
同步复制的好处就是所有数据同步都是从主副本复制到从副本的,主、从副本都有最新的数据版本,都可以对外提供读服务,并且数据都是正确的,系统的数据是强一致性的。缺点是同步过程里可能出现网络延迟、中断和机器故障,同步时间不可预测,比较影响系统可用性
异步复制的好处就是不需要等待同步结果就可以返回,用户体验好,并且数据更新操作不依赖从副本,所以不受网络和从副本机器故障的影响,写入性能和系统可用性大大提高。缺点是由于不是同步更新,可能主副本出现故障的时候,数据还没同步到从副本,这种情况在数据正确性要求高的场景是不可以接受的。在异步复制的场景下,如果要通过从副本读取数据,必须要读数据的时候加一个版本号,从副本小于或者等于版本号的最新数据,然后和主副本的版本相等或者超过才可以返回数据
当前分布式系统非常流行的数据复制方案就是水平分片和主从复制的组合方式,将全量数据拆分为多个副本,然后每个主从复制副本集内部做同步复制。这样的好处是提高了系统的写入性能和可用性,让主从复制的副本数量不再和机器数量强绑定
多主复制
多主复制模式是指在一个数据系统里,存在多个主从复制单元,每一个主从复制单元都可以处理读写请求,一个主从复制单元的主副本处理了写请求之后,需要复制到其他主从复制单元的主副本
如果主副本之间的复制是同步的话,出现冲突的时候就退化成主从复制的模式了。所以大多数多主复制的主副本之间都是采取异步模式
写入冲突是多个主副本同时接受吸入,并且主副本之间异步复制导致的,可以考虑在数据写入一个主副本之后,在主副本之间进行复制时,检查是否有冲突,如果有冲突则立即解决。这种方式称为写时解决冲突,实现方式有两种:预定义解决和自定义解决
预定义解决冲突是指由存储系统预先定义好规则,在冲突发生时依据预先定义好的规则,自动解决冲突,例如:
- 每个写操作分配一个时间戳,发生冲突时,只保留时间戳最大的版本数据。这一种方式会导致修改丢失
- 每个副本排好优先级,发生冲突时最高优先级的副本保留修改数据
- 研究一些可以自动解决冲突的数据结构
自定义解决冲突,由业务系统来定义冲突的解决方式
读时解决冲突,指的是写入数据时如果发生冲突,则不立即处理,而是选择将冲突的写入版本记录下来,等下次读取数据的时候,就将所有数据版本返回给业务层,在业务层处理冲突
- 用户自行解决冲突
- 自定义处理逻辑解决冲突
无主复制
无主复制意思是集群里没有主节点和从节点之分,所有节点的角色都是对等的,每个节点负责存储和处理一定范围的数据,并且由于高可用的要求,每一份数据都需要在多个节点存储
此文章为2月Day21学习笔记,内容来源于极客时间《深入浅出分布式技术原理》
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 25 天,点击查看活动详情