系列文章是博主对沈剑的《架构师训练营》分享内容的个人笔记总结,原内容公众号“成为架构师”。
主从不一致
主从不一致的情况发生在主库更新的时候,向从库同步存在延迟,这个时侯业务刚好对主库更新的内容进行访问,但读的是从库,也就读到了更新前的数据。
这种不一致性是binlog主从同步的延时造成的,最大也就秒级,针对这一特性,通常有以下三种处理方式:
忽略不计
如果业务侧是可以忍受读到短时间的一个脏数据的(通常只要用户刷新一下就是正确数据),那么忽略不计其实是最经济实惠的方式,只要业务允许,那么我们的架构也可以简单一些。
强制读主
强制读主的方式就是抛弃读写分离的架构设计了
那么我们对于提升读性能当然还有缓存的方式,关于缓存的一致性在缓存篇再做讨论。
选择性读主
这是一种颇有意思的设计方式,需要缓存进行配合。
它的写过程是这样的:
- 假设一个主从同步的时延,比如说是1s
- 在写入主库之前,先在缓存set一个key,这个key是用来标的哪些数据是被更新了的(比如说更新row的表、主键等),缓存的失效时间就是主从同步的时延,也就是1s
- 后续步骤也就是写入主,主从同步,与正常流程没有区别
它的读过程是这样的:
- 尝试从缓存中获取要查询数据的对应的key
- 如果能够从缓存中取到,说明还有同步的时延,这个时候则读主
- 如果拿不到,则说明主从此时认为是同步的,则直接读从库
主主不一致
主主不一致的情况要比主从不一致严重,因为如果没有外部力量去处理这个不一致状态,那它就一直处于不一致状态下,会对业务造成更大的影响。
为什么会出现
通常是主主同步时主键冲突引起的,比如说如果主库都是使用自增id,这时同时有两个写入请求分别到达两个主库,二者分别在各自的基础上自增,那么在同步的时候就出现了主键冲突,导致数据丢失。
数据库层面处理
所以为了避免主主不一致,这里的核心就是避免主键冲突,在数据库层面有一种简单的做法:不同初始值,相同增长步长
图中就是一个简单的例子,左边初始为1,步长为2,那么刚好就都是奇数主键,右边初始为2,步长为2,那么刚好都是偶数主键,两库同步之后就是全量数据,不会有主键冲突。
但是这样子会给运维造成负担,毕竟数据库配置不一样就需要额外的管理成本。
上游层面处理
一种更加推荐的做法就是由第三方来保证一个全局自增的主键,所以库都从这个生产者获取主键,比如说,比较著名的分布式自增主键生成算法 —— 雪花算法
影子主不服务
这就是keepalived + VIP的方式,让一个主变为影子主,它只在对外提供服务的主库挂了的时候接替它上任,这就不会发生不一致的情况,但是使用率只有50%。
本篇简单的阐释了一下数据库一致性问题的解决思路和基本的方法论,接下来将进入数据库扩展性问题的讨论。
上一篇回顾:【成为架构师3-9】数据库:垂直拆分与高可用
下一篇更精彩:持续更新中…