这是我参与2022首次更文挑战的第22天,活动详情查看:2022首次更文挑战
数据复制【数据库一致性问题】
上次提到在异步复制中会存在一致性问题,提出了最终一致性的概念,接下来提出在最终一致性中可能会遇到的问题以及解决思路
感觉和缓存与数据库的数据一致性有着异曲同工之妙
复制滞后问题
读自己的写
用户写入不久就要查看数据的时候,从节点可能没有完成与主节点的同步,当用户从从节点获取数据的时候可能会出现类似数据丢失的情况,类似丢失修改
在这种情况下需要保证“写后读一致性”,也即读写一致性
- 用户在修改后,读取的该数据保证是最新的,其他的用户可能需要一段时间才可以看到最新的该提交数据,所以形象地称为 写后读一致性
如何实现:
-
用户最近被修改的东西(可能被修改)从主数据库进行读取,其他数据从从数据库读取,可以对一些可能会进行数据修改的函数方法进行标记,当使用这些方法的时候(处于某一种特殊状态的时候)从主数据库进行数据的读取
-
如果该数据会被广泛地被用户大规模集体修改,需要一定的延迟读取规则,如在修改完成的多久以内只允许在主数据库内部读取数据
-
时间戳,可以用通过对比时间戳的方法来判断是否应该使用当前节点的数据,客户端会记录最新的更新时间,在每次请求的时候都发送对应时间戳\
-
- 客户端需要知道上次更新的时间戳,较为麻烦,同时难以解决跨设备的问题
单调读
当存在很多从结点的时候,不同节点之间的复制情况可能会不一致,有些从节点可能完成了数据的复制但是有些可能没有,用户会出现类似不可重复读的情况
- 实际上然用户每次都从同一个地方读取数据即可,使用hash或者其他方式来绑定数据的读取
前缀一致读
当多条数据有因果关系的时候(比如说两次有因果关系的购物数据),加上主从数据库之间存在数据同步延迟,读取到数据的顺序和实际写入的数据并不一样
- 数据库分区可能会带来这种情况,数据库分区意味着原本有因果关系的写入命令被分散到不同区上面吗,丢失了数据之间的联系信息
以上述例子说明,用户通过顺序获取方式获取消费记录,因此可能会先获取到新的记录(从主节点上),然后获取到旧的记录(从从节点上),这个时候因果关系就改变了
- 可以通过一个全局的分区来处理这些有关系的数据
在一些数据库上已经实现了分布式事务,在数据库层实现了数据一致性的保障,通常也可以在应用层进行实现,但是逻辑会较为复杂