【转载】细聊冗余表数据一致性(架构师之路)

本文主要讨论四个问题:

(1)为什么会有冗余表的需求

(2)如何实现冗余表

(3)正反冗余表谁先执行

(4)冗余表如何保证数据的一致性

 

一、需求缘起

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

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

Order(oid, info_detail)

T(buyer_id, seller_id, oid)

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

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

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

T1(buyer_id, seller_id, oid)

T2(seller_id, buyer_id, oid)

同一个数据,冗余两份,一份以buyer_id来分库,满足买家的查询需求;

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

 

二、冗余表的实现方案

【方法一:服务同步写】

24a6e9839da29bcb35d0baa58e9c8a59
顾名思义,由服务层同步写冗余数据,如上图1-4流程:

(1)业务方调用服务,新增数据

(2)服务先插入T1数据

(3)服务再插入T2数据

(4)服务返回业务方新增数据成功

优点

(1)不复杂,服务层由单次写,变两次写

(2)数据一致性相对较高(因为双写成功才返回)

缺点

(1)请求的处理时间增加(要插入次,时间加倍)

(2)数据仍可能不一致,例如第二步写入T1完成后服务重启,则数据不会写入T2

如果系统对处理时间比较敏感,引出常用的第二种方案

【方法二:服务异步写】

1c37ee5000920093e7d59dadd48caf86
数据的双写并不再由服务来完成,服务层异步发出一个消息,通过消息总线发送给一个专门的数据复制服务来写入冗余数据,如上图1-6流程:

(1)业务方调用服务,新增数据

(2)服务先插入T1数据

(3)服务向消息总线发送一个异步消息(发出即可,不用等返回,通常很快就能完成)

(4)服务返回业务方新增数据成功

(5)消息总线将消息投递给数据同步中心

(6)数据同步中心插入T2数据

优点

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

缺点

(1)系统的复杂性增加了,多引入了一个组件(消息总线)和一个服务(专用的数据复制服务)

(2)因为返回业务线数据插入成功时,数据还不一定插入到T2中,因此数据有一个不一致时间窗口(这个窗口很短,最终是一致的)

(3)在消息总线丢失消息时,冗余表数据会不一致

如果想解除“数据冗余”对系统的耦合,引出常用的第三种方案

【方法三:线下异步写】

e79918ae2ee508a6a7ee378c37b70180
数据的双写不再由服务层来完成,而是由线下的一个服务或者任务来完成,如上图1-6流程:

(1)业务方调用服务,新增数据

(2)服务先插入T1数据

(3)服务返回业务方新增数据成功

(4)数据会被写入到数据库的log中

(5)线下服务或者任务读取数据库的log

(6)线下服务或者任务插入T2数据

优点

(1)数据双写与业务完全解耦

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

缺点

(1)返回业务线数据插入成功时,数据还不一定插入到T2中,因此数据有一个不一致时间窗口(这个窗口很短,最终是一致的)

(2)数据的一致性依赖于线下服务或者任务的可靠性

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

 

三、究竟先写正表还是反表

对于一个不能保证事务性的操作,一定涉及“哪个任务先做,哪个任务后做”的问题,解决这个问题的方向是:

【如果出现不一致】,谁先做对业务的影响较小,就谁先执行。

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

T1(buyer_id, seller_id, oid)

T2(seller_id, buyer_id, oid)

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

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

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

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

however,记住结论:如果出现不一致】,谁先做对业务的影响较小,就谁先执行。

四、如何保证数据的一致性

从二节和第三节的讨论可以看到,不管哪种方案,因为两步操作不能保证原子性,总有出现数据不一致的可能,那如何解决呢?

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

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

优点

(1)比较简单,开发代价小

(2)线上服务无需修改,修复工具与线上服务解耦

缺点

(1)扫描效率低,会扫描大量的“已经能够保证一致”的数据

(2)由于扫描的数据量大,扫描一轮的时间比较长,即数据如果不一致,不一致的时间窗口比较长

有没有只扫描“可能存在不一致可能性”的数据,而不是每次扫描全部数据,以提高效率的优化方法呢?

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

9b8a4e73fd2426d511f9c266f803c25d
每次只扫描增量的日志数据,就能够极大提高效率,缩短数据不一致的时间窗口,如上图1-4流程所示:

(1)写入正表T1

(2)第一步成功后,写入日志log1

(3)写入反表T2

(4)第二步成功后,写入日志log2

当然,我们还是需要一个离线的扫描工具,不停的比对日志log1和日志log2,如果发现数据不一致,就进行补偿修复

优点

(1)虽比方法一复杂,但仍然是比较简单的

(2)数据扫描效率高,只扫描增量数据

缺点

(1)线上服务略有修改(代价不高,多写了2条日志)

(2)虽然比方法一更实时,但时效性还是不高,不一致窗口取决于扫描的周期

有没有实时检测一致性并进行修复的方法呢?

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

14dafce4ce22db72057d011e26dfdbc2
这次不是写日志了,而是向消息总线发送消息,如上图1-4流程所示:

(1)写入正表T1

(2)第一步成功后,发送消息msg1

(3)写入反表T2

(4)第二步成功后,发送消息msg2

这次不是需要一个周期扫描的离线工具了,而是一个实时订阅消息的服务不停的收消息。

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

优点

(1)效率高

(2)实时性高

缺点

(1)方案比较复杂,上线引入了消息总线这个组件

(2)线下多了一个订阅总线的检测服务

however,技术方案本身就是一个投入产出比的折衷,可以根据业务对一致性的需求程度决定使用哪一种方法。我这边有过好友数据正反表的业务,使用的就是方法二。

==【完】==

 

【转自】58沈剑 架构师之路

转载于:https://www.cnblogs.com/bad-man/p/7866312.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/540128.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ethtool如何让接口闪灯_如何解决专业家庭影院与卡拉OK的声学问题?

现在越来越多的专业家庭影院走进人们的家中,享受体验娱乐氛围的空间。在实际的生活中,许多人都把这个空间设计为多功能的影音娱乐室,集看电影、听音乐、卡拉OK、游戏娱乐等于一体,在这其中看电影与卡拉OK将这两个功能组合在同一个…

tensorflow学习笔记(1):sess.run()

原址:https://www.2cto.com/kf/201610/559887.html session.run() session.run([fetch1, fetch2]) import tensorflow as tf state tf.Variable(0.0,dtypetf.float32) one tf.constant(1.0,dtypetf.float32) new_val tf.add(state, one) update tf.assign(st…

关于MapReduce单词统计的例子:

要统计的文件的文件名为hello hello中的内容如下 hello  you hello  me 通过MapReduce程序统计出文件中的各个单词出现了几次.(两个单词之间通过tab键进行的分割) 1 import java.io.IOException;2 3 import mapreduce.WordCountApp.WordCountMapper.WordCountReducer;4 5 i…

朵朵糖故事机器人怎么更新_“故事贩卖机”专栏创始人温酒的新作,奇幻世界的暖心物语很治愈...

我有酒,你有故事吗?2015年,知乎上一个叫“故事贩卖机”的专栏横空出世,凭着一个个脑洞大开的故事,这个温吞而又温暖的专栏很快得到了读者的认可。而其中的创始人兼主打写手温酒,更是被粉丝们亲切地称呼为“…

python3 通过百度地图API获取城市POI点并存于CSV格式

原文信息: 作者:WenWu_Both 出处:http://blog.csdn.net/wenwu_both/article/ 版权:本文版权归作者和CSDN博客共有 转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中…

使用dropwizard(3)-加入DI-dagger2

前言 习惯了Spring全家桶,对spring的容器爱不释手。使用dropwizard,看起来确实很轻,然而,真正使用的时候不得不面临一个问题。我们不可能一个resource就能把所有的业务逻辑囊括!那么,必然就要有负责处理逻辑…

日历对象导哪个包_微信新表情瞬间炸裂,文物表情包永恒萌呆!

11月18日晚微信上架了6个全新表情瞬间炸裂网友一天时间阅读达16.2亿,讨论15.8万次#微信新表情#话题翻白眼、666、让我看看叹气、苦涩、裂开微信新表情虽然666但文物表情包的呆萌也能让人瞬间裂开更能完全诠释我的各(bu)种(wen ding)情绪先对比一下最新的6个表情[翻白…

Tensorflow一些常用基本概念与函数(1)

文章转至 作者:林海山波出处:https://me.csdn.net/lenbow版权:本文版权归作者和CSDN博客共有 写这篇博客只为自己学习路上做个笔记,方便自己学习记忆,大家如果想看详细文章可以去原作者主页去看,同时他…

Lineageos14 20180525更新

一、ROM注意事项 拒绝任何无意义二次打包! C大停止更新Lineageos14,我来接力。 二、ROM更新日志 20180525更新: 1、常规更新 2、安全补丁2018年5月5日 20180406更新: 1、增加通话录音,常规更新 2、安全补丁2018年3月…

蓝牙连接不上车要hfp_如何正确使用车载蓝牙播放器呢?

车载蓝牙是以无线蓝牙技术为基础而设计研发的车内无线免提系统。可以连接我们设计进行听歌和打电话十分方便,下面诺金小编带大家一起来看看!下面诺金小编带大家一起来看看一、首先是把手机和车载蓝牙播放器打开,搜索车载蓝牙播放器“809”&am…

使用Eclipse+PyDev创建Django项目一windows下

开发条件:eclipsepydev插件django editor插件 关于eclipse安装小编就不多做介绍,我自己用的版本如下 1.安装pydev插件 启动Eclipse, 点击Help->Install New Software 弹出如下框 点击add 分别在 Name中填:Pydev, Location中填http://pydev.org/up…

如何避免踩坑--初创技术团队组建风险预估

闲来无事翻翻微信,发现有不少朋友公司在招技术负责人,跟他们聊了几句,发现大多数认知都是技术部门的效率与进度达不到要求,机缘巧合下,有幸到了Y公司跟其Boss会面,得知其技术团队效率低下,总是不…

查询空缺_携程旅行2021校招开启,9大类职位,1000+岗位空缺,本科及以上学历...

携程旅行2021秋季校招正式开启!携程集团(纳斯达克股票代码:TCOM)是一家领先的在线旅游服务提供商,旗下品牌包括携程、Trip.com、天巡和去哪儿。携程集团能够整合复杂的旅游相关信息并通过其先进的移动端App、网站以及24小时无间断的免费客户服…

Django web开发笔记

一、Django开发环境搭建: 1.安装python:django可运行于版本python 2.7、3.x 2.安装相应的IDE 3.安装pip:sudo apt-get install python-pip(linux为例) 4.安装django:1)pip安装:sudo pip ins…

android 前置摄像头预览时 镜像翻转_全面屏时代,原来手机前置摄像头都隐藏着一些缺点,你发现了吗?...

随着真全面屏时代的到来,人们已经不再满足于刘海屏、水滴屏以及挖孔屏等,越来越多的手机厂商和消费者开始追求"100%全面屏"。于是如何解决手机前置摄像头便成了最大的难题,毕竟只要在屏幕上放置摄像头必然会影响屏占比,…

Java 调用 Python 方法学习笔记

文章转载自: 作者:IT_xiao_bai 来源:CSDN 原文:https://blog.csdn.net/IT_xiao_bai/article/details/79074988 前一阵自刚好用python做了一个sae的算法模型,结果公…

catia怎么将特征参数化_VSLAM中特征点的参数化表示

VSLAM中特征点的参数化表示有很多,最直接的是用三维坐标XYZ来表示,但通常大家更喜欢用逆深度表示,因为逆深度优势在于能够建模无穷远点。Open VINS文档中给出了五种特征参数化表示:Global XYZ,Global Inverse Depth&am…

【广州】Web前端工程师

互联网公司找人咯~ 我们公司:道乐科技(Dollar Tech)成立于2013年11月,是一家致力于为资产管理和财富管理行业提供技术、产品和运营服务的科技金融企业。三年来,道乐人始终坚持“以客户为中心,为客户提供高品…

Java 调用 Python 方法学习笔记---之---java调用python深度学习模型运算并返回运算结果给前端(2)

上一章写到Java 调用 Python 方法学习的三种方法,这里强调第三种方法。第三种方法本质上和第二种方法是一样的,都是应用到 Runtime.getRuntime().exec() 去执行文件。要深度理解这种方法,首先要先理解一下Runtime.getRuntime().exec() 。 R…

tbslog乱码转换_日文游戏乱码怎么办 乱码转换工具LocaleEmulator

by Nicho Feb.23,2017许多日文游戏有诸多地区限制,在 win7、win8、win10 上玩时候会经常遇到日文游戏乱码的情况,这时候就得用到乱码转换工具了,下面我们就来详细说明下使用方法。常用的有 microsoft locale、applocale、NTLEA 等&…