文档章节

主从DB与cache一致性

snowing1990
 snowing1990
发布于 2016/03/25 15:20
字数 1544
阅读 134
收藏 9
点赞 1
评论 0

本文主要讨论这么几个:

1)数据库主从延时为何会导致缓存数据不一致

2)优化思路与方案

 

一、需求缘起

上一篇《缓存架构设计细节二三事》中有一个小优化点,在只有主库时,通过“串行化”的思路可以解决缓存与数据库中数据不一致。引发大家热烈讨论的点是“在主从同步,读写分离的数据库架构下,有可能出现脏数据入缓存的情况,此时串行化方案不再适用了”,这就是本文要讨论的主。

 

二、为什么数据会不一致

为什么会读到脏数据,有这么几种情况:

1)单库情况下,服务层的并发读写,缓存与数据库的操作交叉进行


虽然只有一个DB,在上述诡异异常时序下,也可能脏数据入缓存:

1)请求A发起一个写操作,第一步淘汰了cache,然后这个请求因为各种原因在服务层卡住了(进行大量的业务逻辑计算,例如计算了1秒钟),如上图步骤1

2)请求B发起一个读操作,读cachecache miss,如上图步骤2

3)请求B继续读DB,读出来一个脏数据,然后脏数据入cache,如上图步骤3

4)请求A卡了很久后终于写数据库了,写入了最新的数据,如上图步骤4

这种情况虽然少见,但理论上是存在的 后发起的请求B在先发起的请求A中间完成了。

 

2)主从同步,读写分离的情况下,读从库读到旧数据

在数据库架构做了一主多从,读写分离时,更多的脏数据入缓存是下面这种情况:


1)请求A发起一个写操作,第一步淘汰了cache,如上图步骤1

2)请求A写数据库了,写入了最新的数据,如上图步骤2

3)请求B发起一个读操作,读cachecache miss,如上图步骤3

4)请求B继续读DB,读的是从库,此时主从同步还没有完成,读出来一个脏数据,然后脏数据入cache,如上图步4

5)最后数据库的主从同步完成了,如上图步骤5

这种情况请求A和请求B的时序是完全没有错的,是主动同步的时延(假设延时1秒钟)中间有读请求读从库读到脏数据导致的不一致。

 

那怎么来进行优化呢?


三、不一致优化思路

有同学说“那能不能先操作数据库,再淘汰缓存”,这个是不行的,在《缓存和数据库先操作谁》的文章中介绍过。

 

出现不一致的根本原因:

1)单库情况下,服务层在进行1s的逻辑计算过程中,可能读到旧数据入缓存

2)主从库+读写分离情况下,在1s钟主从同步延时过程中,可能读到旧数据入缓存

既然旧数据就是在那1s的间隙中入缓存的,是不是可以在写请求完成后,再休眠1s,再次淘汰缓存,就能将这1s内写入的脏数据再次淘汰掉呢?

是可以的

 

写请求的步骤由2步升级为3步:

1)先淘汰缓存

2)再写数据库(这两步和原来一样)

3)休眠1秒,再次淘汰缓存

这样的话,1秒内有脏数据如缓存,也会被再次淘汰掉,但带来的是:

1所有的写请求都阻塞了1秒,大大降低了写请求的吞吐量,增长了处理时间,业务上是接受不了的

 

再次分析,其实第二次淘汰缓存是为了保证缓存一致而做的操作,而不是业务要求,所以其实无需等待,用一个异步的timer,或者利用消息总线异步的来做这个事情即可


写请求由2步升级为2.5步:

1)先淘汰缓存

2)再写数据库(这两步和原来一样)

2.5)不再休眠1s,而是往消息总线esb发送一个消息,发送完成之后马上就能返回

这样的话,写请求的处理时间几乎没有增加,这个方法淘汰了缓存两次,因此被称为“缓存双淘汰”法。这个方法付出的代价是,缓存会增加1cache miss(代价几乎可以忽略)。

 

而在下游,有一个异步淘汰缓存的消费者,在接收到消息之后,asy-expire1s之后淘汰缓存。这样,即使1s内有脏数据入缓存,也有机会再次被淘汰掉。

 

上述方案有一个缺点需要业务线的写操作增加一个步骤有没有方案对业务线的代码没有任何入侵呢,是有的,这个方案在《细聊冗余表数据一致性》中也提到过,通过分析线下的binlog来异步淘汰缓存:


业务线的代码就不需要动了,新增一个线下的读binlog的异步淘汰模块,读取到binlog中的数据,异步的淘汰缓存。

 

提问:为什么上文总是说1s,这个1s是怎么来的?

回答:1s只是一个举例,需要根据业务的数据量与并发量,观察主从同步的时延来设定这个值。例如主从同步的时延为200ms,这个异步淘汰cache设置为258ms就是OK的。

 

四、总结

异常时序或者读从库导致脏数据入缓存时,可以用二次异步淘汰缓存双淘汰法来解决缓存与数据库中数据不一致,具体实施至少有三种方案:

1timer异步淘汰(本文没有细讲,本质就是起个线程专门异步二次淘汰缓存)

2总线异步淘汰

3binlog异步淘汰


本文转载自:

共有 人打赏支持
snowing1990
粉丝 4
博文 90
码字总数 2952
作品 0
程序员
数据库设计思路和要点

基本概念 单库 分片 解决单个数据表数据量太大的问题,将单个表的数据均匀的放入多个表中 复制 用于实现主从同步,主库的更新操作(insert/update/delete)向从库(1个或多个)进行同步,同步...

真爱2015 ⋅ 2016/09/28 ⋅ 1

数据库软件架构设计些什么

一、基本概念 概念一“单库” 概念二“分片” 分片解决的是“数据量太大”的问题,也就是通常说的“水平切分”。 一旦引入分片,势必有“数据路由”的概念,哪个数据访问哪个库。 路由规则通...

懂得-奉献 ⋅ 2016/12/02 ⋅ 0

DB主从一致性架构优化4种方法

原创 2016-05-18 58沈剑 架构师之路 需求缘起 大部分互联网的业务都是“读多写少”的场景,数据库层面,读性能往往成为瓶颈。如下图:业界通常采用“一主多从,读写分离,冗余多个读库”的数...

毛爷爷夸我帅 ⋅ 2016/12/06 ⋅ 0

redis部署手册

一、redis介绍 1、redis简介 REmote DIctionary Server(Redis)是一个基于key-value键值对的持久化数据库存储系统。redis和memcached缓存服务很像,但是redis支持的数据存储类型更丰富,包括...

次渠龙哥 ⋅ 2015/07/23 ⋅ 0

高可用数据库架构实践

数据存储架构 高可用数据库架构实践 单库,不多说了,就是一个库 。一旦引入分片,。 路由规则通常有3种方法: 范围:range 优点:简单,容易扩展 缺点:各库压力不均(新号段更活跃) 哈希:...

陶邦仁 ⋅ 2015/11/13 ⋅ 1

实录|互联网架构“高可用”在线技术交流

原创 2016-12-06 58沈剑+GitChat 架构师之路 架构师之路架构师之路 微信号 功能介绍 架构师之路,坚持撰写接地气的架构文章 前段时间,受@谢工 邀请,在GitChat平台首发《究竟啥才是互联网架...

毛爷爷夸我帅 ⋅ 2016/12/06 ⋅ 0

读写分离+主从复制 的索引问题

一般我们都是 当读数据 性能降低时,通过AB测试后,我们进行读写分离,一般读写分离都离不开主从复制 那么我想问2点: 1:如果做到主从DB 2台服务器数据库的一致性? 减少延迟。。 2:主数据...

本周网 ⋅ 2014/12/04 ⋅ 6

mysql主从一致性检测和修复

一、 简介 pt-table-checksum是著名的 percona-toolkit 工具集的工具之一。它通过在主库执行基于statement的sql语句来生成主库数据块的checksum,把相同的sql语句传递到从库,并在从库上计算...

stone_ ⋅ 2016/07/28 ⋅ 0

缓存与数据库一致性保证 (二)

本文主要讨论这么几个点: (1)啥时候数据库和缓存中的数据会不一致 (2)不一致优化思路 (3)如何保证数据库与缓存的一致性 一、需求缘起 上一篇《缓存架构设计细节二三事》(点击查看)引...

snowing1990 ⋅ 2016/03/17 ⋅ 0

缓存与数据库一致性保证

原创 2016-03-16 58沈剑 架构师之路 本文主要讨论这么几个问题: (1)啥时候数据库和缓存中的数据会不一致 (2)不一致优化思路 (3)如何保证数据库与缓存的一致性 一、需求缘起 上一篇《缓...

毛爷爷夸我帅 ⋅ 2016/12/06 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

JAVA RMI

什么是JAVA RMI Java RMI (Remote Method Invocation) 远程方法调用,能够让客户端像使用本地调用一样调用服务端 Java 虚拟机中的对象方法。RMI 是面向对象语言领域对 RPC (Remote Proced...

saulc ⋅ 19分钟前 ⋅ 0

Linux系统工程狮养成记

如今的社会,随着时代的发展,出现了很多职业,像电子类,计算机类的专业,出现了各种各样的工程师,有算法工程师,java工程师,前端工程师,后台工程师,Linux工程师,运维工程师等等,不同...

linux-tao ⋅ 29分钟前 ⋅ 0

进入编辑模式 vim命令模式 vim实践

1.

oschina130111 ⋅ 29分钟前 ⋅ 0

mysql用户管理、常用sql语句、mysql数据库备份恢复

1. mysql用户管理 mysql默认有一个root超级管理员账户,实际工作环境中不可能每个人都用此root权限,防止误操作、误删除,可以给单独的用户进行授权。 Mysql创建用户以及授权: grant all on...

laoba ⋅ 30分钟前 ⋅ 0

类型后面三个点(String...)和数组(String[])的区别

类型后面三个点(String…),是从Java 5开始,Java语言对方法参数支持一种新写法,叫可变长度参数列表,其语法就是类型后跟…,表示此处接受的参数为0到多个Object类型的对象,或者是一个Obj...

流氓兔- ⋅ 36分钟前 ⋅ 0

JEPLUS表格组件之表格合并——JEPLUS软件快速开发平台

JEPLUS表格组件之表格合并 我们在列表配置时会遇见这样的一种情况,需要对个人的数据进行统一化,对一些数据进行归类,这样展示出来美观又直观,在这篇笔记中我来给大家介绍下如何配置出来专...

JEPLUS ⋅ 37分钟前 ⋅ 0

golang 并发中全局唯一操作

package main// go 携程共享 数据// 加锁解锁操作// 同步锁import ("sync""fmt")// 创建Once结构var once = sync.Once{}func computed(data *int, lock *sync.Mut...

304158 ⋅ 37分钟前 ⋅ 0

Mobx入门之二:asynchronous actions

这一节主要看mobx怎么实现asynchronous actions 1 要实现的demo功能 输入地名,查询天气,利用openweathermap api 2 思想 observable观察数据:location地点、temperature温度 observer响应式...

pengqinmm ⋅ 40分钟前 ⋅ 0

【2018.0620学习笔记】【linux高级知识 13.4-13.6】

13.4 mysql用户管理 创建用户并授权: grant all on *.* to '用户名'@'ip' identified by '密码' //all是操作权限,*.*是库.表,指定格式是'用户名'@'localhost'才能用socket登录本地 gra...

lgsxp ⋅ 今天 ⋅ 0

Java强弱引用示例

package jdk;import java.lang.ref.PhantomReference;import java.lang.ref.ReferenceQueue;import java.lang.ref.SoftReference;import java.lang.ref.WeakReference;public ......

月下狼 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部