## 什么是复制
复制是指分布系统中,多台机器上保持相同副本的机制.
## 多副本能够解决的问题?
1. 地理位置上的副本,能够降低延迟.高性能
2.部分组件失效后,系统依然能够工作,高可用
3.副本能沟通工数据访问服务,从而提高吞吐量.
## 复制中的挑战
1.复制的内容不是一层不变的.数据会一直增加,导致复制一直不能停
2.采用的复制方式是同步的还是异步的.当复制失效的时候如何处理?
## 复制的方式
1.主从复制
2.多主复制
3.无主复制
## 主从方式
多个副本中,分为主副本和从副本.主副本负责接受用户的写入请求.然后将修改内容变为日志或者流发送到从库.从库进行按照顺序来修改.
大多数的关系数据库,非关系数据库,MongoDB,Redis,也支持数据库,MQ消息kafka,RabbitMQ也支持数据库.同时zookeeper也支持数据库等.
主从同步是常用的一种方式.
## 同步复制和异步复制
同步:主节点等待复制到从节点的请求后返回.且不会被打断
异步:主节点不等待主节点复制到从节点的请求,且不会打断.
半异步:多个从节点的时候,保证一个同步,其他从节点异步.
同步: 优势是一致性高,缺点是:吞吐率差
异步: 优势是一致性低,缺点是:吞吐率高
半同步:兼顾两者.
同时系统中提供了一种链式复制的技术.
异步复制带来的问题是:"复制滞后性问题"
## 如何添加一个新节点进来.
添加新节点意味着从头开始进行同步.
一种方式是:
1.生成一个快照版本文件.这个快照版本基于一个事务标号.不同的系统有不同的称呼.(binglog coordinates)或者 log sequence number
2.将这个快照版本文件拷贝到新的从节点中.
3.从节点连接到主节点,获取到 快照版本之后的日志.
4.将获取到的日志在从节点上进行回放.这个过程是追赶.
数据库系统分为两个部分:第一步是备份迁移,第二步是追赶.有的是全自动的,还有一种是手动的.
## 处理失效节点
1.从节点实现:追赶恢复
从节点由于一些原因失效的,发生了重启,然后继续连接上主节点,进行重新追赶.
2.主节点失效: 节点切换
主节点的切换是failover,比较复杂,步骤如下:
1.发现主节点失效:目前有效的只有一种是 心跳+超时?不同的系统 心跳间隔和超时阈值不同
2.确定新的主节点: 可以由多数节点投票选出,或者由其他的一些固定策略来选出
3.其他从节点接受新的主节点:当原的主节点需要接受新的主节点,同时自动降级为从节点.
4.通知客户端新的主节点:客户端需要能够将请求发送到新的主节点中.
其中可能会遇到的情况如下:
1.主节点失效了,重新回来,没有意识到角色的变换.试图发送请求给其他节点.
2.可能会出现数据没有完全同步的问题,导致数据不一致的问题.例如mysql的id自增.
3.发生脑裂,导致集群中同时又两个主节点.这个时候可能会关闭其中一个,或者导致两个都关闭了.
4.这个当中超时时间设置多久,如果设置得过长,发现和恢复问题的时间就太长,如果太短,可能会导致不必要的切换.
## 复制的东西是什么(复制日志的实现)
1. 基于语言的复制,执行的语句是什么,就复制什么.有点是实现起来简单.缺点是其中可能会出现不确定的内容,例如函数中带有now(),触发器啥的.
2.wal日志的复制方式.wal日志记录的对于磁盘文件中的某些位置的修改.这种堆lsm或者是btree类型的数据库都可以.但是缺点是无法不停机升级系统版本.因为不同版本,对于数据的引用和描述可能会有差异.
3.逻辑日志的复制:没有每一行的修改的逻辑数据.但是如果是对于多行的修改,就在日志中添加一个事务的标识来标记事务情况.
4.基于触发器的复制.这个没有遇到过.
## 复制滞后性的问题
很多时候我们无法选择同步复制,因为这样可能会影响到写操作的可用性.往往大多数时候会选择异步复制.这个时候会有复制滞后性的问题.
### 解决思路
1.读自己写一致性
如果写后读的场景不太多的话,可以从主库读
如果写后读很多的话,这里就统计一下一个合适的时间,然后等待合适的时长去从库读
客户端记录住写入返回的时间戳,然后用这个时间戳去从库查询,保证这个时间戳之前的 所有操作都到了.
2.单调读
这种情况是每次读取的数据不会回滚.出现的场景是:读取的数据在多个版本中不同展示.这种情况在看nba的时候可能会出现,比分忽高忽低.
3.前缀一致读
读取的数据可能顺序会不同.例如有两个因果关系的两句话,读取返回的可能会有不同.
对于这种问题:一种解决方案是 将有因果关系的数据交给一个分区来完成.这种方案可能会让性能比较差.(当区域分布在全球各地的时候,可能会比较困难)
有一些happen-before的算法来表示因果关系.
## 多主节点复制
主从复制在很多时候能够解决问题.但是当用户分布在全球的时候,这个时候只有一个主节点的时候,这个时候性能就比较差劲了.
这个时候可以让多个节点作为主节点,可以接收复制.
### 适用场景
单个数据中心使用一个主节点就好.多数据中心的时候需要适用多主节点.
由于多数据中心的高可用和离用户更近的原则,需要在每个数据中心设置一个主节点+冲突解决.内部依然是主从复制.数据中心之间由主节点进行数据合并.
### 多主的缺点
会数据冲突
### 优点
1.性能,离用户更近
2.当一个数据中心失败了,不需要重新确定主节点.有其他的主节点.
3.容忍失败.
多主复制的适用场景:
离线客户端的操作,这种就是每个本地就是主库.然后连上系统后进行同步,解决冲突.
协作编辑:运行多个用户同时编辑文档.先运用在本地,然后同步到其他编辑者哪里.
### 如何解决冲突
1.避免冲突
2.解决冲突(1.分配一个全局的写入Id,后面的覆盖前面的;2.将冲突值进行合并,收敛到一致,3.按照固定的格式,将冲突记录下来,后期交个用户来解决)
### 解决冲突的时机
1.写入解决.在发生冲突的时候,就提示用户,需要解决冲突了.或者调用用户的写入进行解冲突
2.在读取的时候解决,将冲突提示用户.
### 拓扑结构
第一种是环形拓扑结构
第二种是星型拓扑结构
第三种:广播拓扑结构(最常用)
环形解重复通知的方式:在每一条记录中写入每个节点已经处理过的标记信息.避免重复转发.
环形和星型的缺点是:如果一个节点失效了,可能会影响到其他节点.
广播的方式的缺点是:顺序不一样,可能会导致覆盖的问题.
## 无主节点复制
一开始都是无中心复制的系统,后来关系数据库带动了中心复制的潮流.亚马逊的Dynamo数据库重启了无中心复制.
###如何解决冲突:
由于在分布式系统中,互相并不知道对方的情况,但是全局知道互相的顺序.这个时候就需要处理并发合并的问题了.
每一次每个用户添加消息的时候都会分配一个全局的递增的版本号.每个人都是从0开始.
任何一个用户添加一个数值的时候,都会带上自己的版本号,同时自己有的全量的信息.然后讲对应的版本号的值设置为这次提交的值.并将版本号改为当前最大的最.为了理解添加和删除.这里会记录删除,而不是减少一个元素.这样后期可以merge.
//todo 添加 zk ,mysql ,redis,hbase,hdfs,kafka,rabbitMq,mongodb的复制的具体是如何实现的.
系统架构,复制语义,复制方式,复制滞后性如何解决.
节点失效(从节点,主节点)
新加入节点是如何处理的.
标签:异步,##,复制,冲突,节点,### From: https://www.cnblogs.com/xxuuzz/p/16608988.html