MyException - 我的异常网
当前位置:我的异常网» 互联网 » Internet一致性架构设计 - 冗余表数据一致性

Internet一致性架构设计 - 冗余表数据一致性

www.MyException.Cn  网友分享于:2013-09-28  浏览:0次
互联网一致性架构设计 -- 冗余表数据一致性

互联网一致性架构设计 -- 冗余表数据一致性

 

 

需求分析

 

       互联网很多业务场景的数据量很大,此时数据库架构要进行水平切分,水平切分会有一个patition key,通过patition key的查询能够直接定位到库,但是非patition key上的查询可能就需要扫描多个库了。

 

例如订单表,业务上对用户和商家都有订单查询需求:

 

    Order(oid, info_detail)

    T(buyer_id, seller_id, oid)

 

    1. 如果用buyer_id来分库,seller_id的查询就需要扫描多库。

    2. 如果用seller_id来分库,buyer_id的查询就需要扫描多库。

 

 

解决方法:为了做到高吞吐量低延时的查询,往往使用“数据冗余”的方式来实现,就是文章标题里说的“冗余表”:

 

    T1(buyer_id, seller_id, oid)

    T2(seller_id, buyer_id, oid)

 

同一个数据,冗余两份

 

    一份以buyer_id来分库,满足买家的查询需求

    一份以seller_id来分库,满足卖家的查询需求

 

 

 

 

 

冗余表的实现方案

 

 

    方法一:服务同步写

 

  1. 业务方调用服务,新增数据
  2. 服务先插入T1数据
  3. 服务再插入T2数据
  4. 服务返回业务方新增数据成功


 

    优点

 

  • 不复杂,服务层由单次写,变两次写
  • 数据一致性相对较高(因为双写成功才返回)

 

    缺点

 

  • 请求的处理时间增加(要插入次,时间加倍)
  • 数据仍可能不一致,例如第二步写入T1完成后服务重启,则数据不会写入T2
  • 如果系统对处理时间比较敏感,不考虑使用。

 

 

    方法二:服务异步写

 

       数据的双写并不再由服务来完成,服务层异步发出一个消息,通过消息总线发送给一个专门的数据复制服务来写入冗余数据。

 

  1. 业务方调用服务,新增数据
  2. 服务先插入T1数据
  3. 服务向消息总线发送一个异步消息(发出即可,不用等返回,通常很快就能完成)
  4. 服务返回业务方新增数据成功
  5. 消息总线将消息投递给数据同步中心
  6. 数据同步中心插入T2数据

 

    优点

 

  • 请求处理时间短(只插入1次)

 

    缺点

 

  • 系统的复杂性增加了,多引入了一个组件(消息总线)和一个服务(专用的数据复制服务)
  • 因为返回业务线数据插入成功时,数据还不一定插入到T2中,因此数据有一个不一致时间窗口(这个窗口很短,最终是一致的)
  • 在消息总线丢失消息时,冗余表数据会不一致
  • 如果想解除“数据冗余”对系统的耦合,建议使用下面方案

 

 

    方法三:线下异步写

 

       数据的双写不再由服务层来完成,而是由线下的一个服务或者任务来完成。

 

  • 业务方调用服务,新增数据
  • 服务先插入T1数据
  • 服务返回业务方新增数据成功
  • 数据会被写入到数据库的log中
  • 线下服务或者任务读取数据库的log
  • 线下服务或者任务插入T2数据


 

    优点

 

  • 数据双写与业务完全解耦
  • 请求处理时间短(只插入1次)

 

    缺点

 

  • 返回业务线数据插入成功时,数据还不一定插入到T2中,因此数据有一个不一致时间窗口(这个窗口很短,最终是一致的)
  • 数据的一致性依赖于线下服务或者任务的可靠性

 

 

    问题

 

       上述三种方案各有优缺点,但不管哪种方案,都会面临“究竟先写T1还是先写T2”的问题?这该怎么办呢?

 

 

 

 

究竟先写正表还是反表

 

    解决方法:谁先做对业务的影响较小,就谁先执行。

 

以上文的订单生成业务为例,buyer和seller冗余表都需要插入数据:

 

  • T1(buyer_id, seller_id, oid)
  • T2(seller_id, buyer_id, oid)

 

    1. 用户下单时,如果“先插入buyer表T1,再插入seller冗余表T2”,当第一步成功、第二步失败时,出现的业务影响是“买家能看到自己的订单,卖家看不到推送的订单”

 

    2. 相反,如果“先插入seller表T2,再插入buyer冗余表T1”,当第一步成功、第二步失败时,出现的业务影响是“卖家能看到推送的订单,卖家看不到自己的订单”

 

    3. 由于这个生成订单的动作是买家发起的,买家如果看不到订单,会觉得非常奇怪,并且无法支付以推动订单状态的流转,此时即使卖家看到有人下单也是没有意义的。

 

    4. 因此,在此例中,应该先插入buyer表T1,再插入seller表T2。

 

 

 

 

 

如何保证数据的一致性

 

 

    方法一:线下扫面正反冗余表全部数据

 

   线下启动一个离线的扫描工具,不停的比对正表T1和反表T2,如果发现数据不一致,就进行补偿修复。



 

    优点

 

  • 比较简单,开发代价小
  • 线上服务无需修改,修复工具与线上服务解耦

 

    缺点

 

  • 扫描效率低,会扫描大量的“已经能够保证一致”的数据
  • 由于扫描的数据量大,扫描一轮的时间比较长,即数据如果不一致,不一致的时间窗口比较长

 

 

    方法二:线下扫描增量数据

 

    每次只扫描增量的日志数据,就能够极大提高效率,缩短数据不一致的时间窗口。当然,我们还是需要一个离线的扫描工具,不停的比对日志log1和日志log2,如果发现数据不一致,就进行补偿修复。

 

  1. 写入正表T1
  2. 第一步成功后,写入日志log1
  3. 写入反表T2
  4. 第二步成功后,写入日志log2


 

    优点

 

  • 虽比方法一复杂,但仍然是比较简单的
  • 数据扫描效率高,只扫描增量数据

 

    缺点

 

  • 线上服务略有修改(代价不高,多写了2条日志)
  • 虽然比方法一更实时,但时效性还是不高,不一致窗口取决于扫描的周期
  • 依然不是实时的,所以要看下一个方案

 

 

    方法三:实时线上“消息对”检测

 

    这次不是写日志了,而是向消息总线发送消息;这次不是需要一个周期扫描的离线工具了,而是一个实时订阅消息的服务不停的收消息。

 

    假设正常情况下,msg1和msg2的接收时间应该在3s以内,如果检测服务在收到msg1后没有收到msg2,就尝试检测数据的一致性,不一致时进行补偿修复。

   
 

    优点

 

  • 效率高
  • 实时性高

 

    缺点

 

  • 方案比较复杂,上线引入了消息总线这个组件
  • 线下多了一个订阅总线的检测服务

文章评论

老程序员的下场
老程序员的下场
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
程序员都该阅读的书
程序员都该阅读的书
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
鲜为人知的编程真相
鲜为人知的编程真相
每天工作4小时的程序员
每天工作4小时的程序员
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
如何成为一名黑客
如何成为一名黑客
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
程序员必看的十大电影
程序员必看的十大电影
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
那些争议最大的编程观点
那些争议最大的编程观点
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
我是如何打败拖延症的
我是如何打败拖延症的
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
程序员的鄙视链
程序员的鄙视链
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
Java程序员必看电影
Java程序员必看电影
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
编程语言是女人
编程语言是女人
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
漫画:程序员的工作
漫画:程序员的工作
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
旅行,写作,编程
旅行,写作,编程
中美印日四国程序员比较
中美印日四国程序员比较
我的丈夫是个程序员
我的丈夫是个程序员
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
程序员和编码员之间的区别
程序员和编码员之间的区别
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
为什么程序员都是夜猫子
为什么程序员都是夜猫子
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
程序员应该关注的一些事儿
程序员应该关注的一些事儿
总结2014中国互联网十大段子
总结2014中国互联网十大段子
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有