分库分表:订单中心,多key业务如何进行数据库切分
本篇将以“订单中心”为例,介绍“多key”类业务,随着数据量的逐步增大,数据库性能显著降低,数据库水平切分相关的架构实践。
什么是“多key”类业务
所谓的“多key”,是指一条元数据中,有多个属性上存在前台在线查询需求。
订单中心业务分析
订单中心是一个非常常见的“多key”业务,主要提供订单的查询与修改的服务,其核心元数据为:
Order(oid, buyer_uid, seller_uid, time, money, detail…);
其中:
- oid为订单ID,主键
- buyer_uid为买家uid
- seller_uid为卖家uid
- time, money, detail, …等为订单属性
数据库设计上,一般来说在业务初期,单库单表就能够搞定这个需求,典型的架构设计为:
- order-center:订单中心服务,对调用者提供友好的RPC接口。
- order-db:对订单进行数据存储。
随着订单量的越来越大,数据库需要进行水平切分,由于存在多个key上的查询需求,用哪个字段进行切分,成了需要解决的关键技术问题:
- 如果用 oid 来切分,
buyer_uid
和seller_uid
上的查询则需要遍历多库。- 如果用
buyer_uid
或seller_uid
来切分,其他属性上的查询则需要遍历多库。
总之,很难有一个完全之策,在展开技术方案之前,先一起梳理梳理查询需求。
订单中心数据查询需求分析
- 还是那句话,任何脱离业务的架构设计都是耍流氓,在进行架构讨论之前,首先要对业务进行简要分析,看看表结构上有哪些查询需求。
根据业务经验,订单中心往往有以下几类业务需求:
(1)用户侧,前台访问,最典型的有三类需求
订单实体查询:通过oid查询订单实体,90%都是这种需求。
用户订单列表查询:通过buyer_id分页查询用户历史订单列表,9%流量属于这种需求。
商家订单列表查询:通过seller_uid分页查询商家历史订单列表,1%流量属于这类需求。
- 前台访问的特点是:吞吐量大,服务要求高可用,对一致性要求较高。其中商家对一致性要求较低,可以接受一定程度的延迟。
(2)运营侧,后台访问。
根据产品、运营需求,访问模式各异:
按照时间,架构,商品和详情来进行查询
- 后台访问的特点:运营侧的查询基本上是批量的分页查询,访问量低,对可用性一致性的要求不高,允许秒甚至十秒级别的查询延迟。
订单中心数据查询需求解决方案-运营侧
后台运营侧的查询需求各异,基本是批量的分页查询,计算量和返回数据量较大,比较消耗数据库性能。
如果前台业务和后台业务公用一批服务和一个数据库,有可能导致,由于后台的“少数几个请求”的“批量查询”的“低效”访问,导致数据库的cpu偶尔瞬时100%,影响前台正常用户的访问(例如,订单查询超时)。
前台与后台访问的查询需求不同,对系统的要求也不一样,故应该两者解耦,实施“前台与后台分离”的架构设计。
前台:业务架构不变,站点访问,服务分层,数据库水平切分。
后台:业务需求则抽取独立的 web/service/db 来支持,解除系统之间的耦合,对于“业务复杂”、“并发量低”、“无需高可用”“能接受一定延时”的后台业务:
- 可以去掉 service 层,在运营后台 web 层通过 dao 直接访问数据层。
- 可以不需要反向代理,不需要集群冗余。
- 可以通过 MQ 或者线下异步同步数据,牺牲一些数据的实时性。
- 可以使用更契合大量数据允许接受更高延时的“索引外置”或者“HIVE”的设计方案。
订单中心数据查询需求解决方案-用户侧
明确了订单中心的访问需求后,问题转化为,前台的oid,buyer_id,seller_id如何来进行数据库的水平切分呢?
多个维度的查询较为复杂,对于复杂系统设计,可以逐步简化。
需要同时满足以下条件:
1.根据buyer_uid%n,可以定位到数据库
2.根据oid%n,可以定位到数据库
3.根据seller_uid%n,可以定位到数据库
以上业务是一个
- 1:N(1个买家:N个订单)和
- N:N(1个买家:N个卖家, 1个卖家:N个买家)的业务场景,
- 对于“多对多”的业务,水平切分应该使用“数据冗余法”。
假设没有seller_uid
订单中心,假设没有seller_uid
上的查询需求,而只有 oid 和buyer_uid
上的查询需求,就蜕化为一个“1对多”的业务场景,对于“1对多”的业务,水平切分应该使用“基因法”。
再次回顾一下,什么是分库基因?
通过
buyer_uid
分库,假设分为16个库,采用buyer_uid
%16的方式来进行数据库路由,所谓的模16,其本质是
buyer_uid
的最后4个bit决定这行数据落在哪个库上,这4个bit,就是分库基因。
也再次回顾一下,什么是基因法分库?
在订单数据 oid 生成时,oid 末端加入分库基因,让同一个buyer_uid
下的所有订单都含有相同基因,落在同一个分库上。
如上图所示,buyer_uid=666 的用户下了一个订单:
- 使用 buyer_uid%16 分库,决定这行数据要插入到哪个库中。
- 分库基因是 buyer_uid 的最后4个 bit,即1010。
- 在生成订单标识 oid 时,先使用一种分布式 ID 生成算法生成前 60bit(上图中绿色部分)。
- 将分库基因加入到 oid 的最后4个 bit(上图中粉色部分),拼装成最终64bit的订单 oid(上图中蓝色部分)。
通过这种方法保证,同一个用户下的所有订单oid,都落在同一个库上,oid的最后4个bit都相同,于是:
- 通过 buyer_uid%16 能够定位到库。
- 通过 oid%16 也能定位到库。
假设没有oid
订单中心,假设没有 oid 上的查询需求,而只有 buyer_uid 和 seller_uid 上的查询需求,就蜕化为一个“多对多”的业务场景,对于“多对多”的业务,水平切分应该使用“数据冗余法”。
如上图所示:
- 当有订单生成时,通过 buyer_uid 分库,oid 中融入分库基因,写入 DB-buyer 库。
- 通过线下异步的方式,通过 binlog+canal,将数据冗余到 DB-seller 库中。
- buyer 库通过
buyer_uid
分库,seller 库通过seller_uid
分库,前者满足 oid 和buyer_uid
的查询需求,后者满足seller_uid
的查询需求。
数据冗余的方法有很多种:
- 服务同步双写。
- 服务异步双写。
- 线下异步双写(上图所示,是线下异步双写)。
不管哪种方案,因为两步操作不能保证原子性,总有出现数据不一致的可能,高吞吐分布式事务是业内尚未解决的难题,此时的架构优化方向,并不是完全保证数据的一致,而是尽早的发现不一致,并修复不一致。
最终一致性,是高吞吐互联网业务一致性的常用实践。保证数据最终一致性的方案有三种:
- 冗余数据全量定时扫描。
- 冗余数据增量日志扫描。
- 冗余数据线上消息实时检测。
这些方案细节在“多对多”业务水平拆分的文章里详细展开分析过,便不再赘述。
oid/buyer_uid/seller_uid同时存在
通过上述分析:
- 如果没有
seller_uid
,“多key”业务会蜕化为“1对多”业务,此时应该使用“基因法”分库:使用buyer_uid
分库,在oid中加入分库基因- 如果没有oid,“多key”业务会蜕化为“多对多”业务,此时应该使用“数据冗余法”分库:使用
buyer_uid
和seller_uid
来分别分库,冗余数据,满足不同属性上的查询需求- 如果 oid/buyer_uid/seller_uid 同时存在,可以使用上述两种方案的综合方案,来解决“多key”业务的数据库水平切分难题。
订单中心数据库切分方法--数据冗余法
• 当有订单生成时,通过buyer_uid分库,oid中融入分库基因,写入DB-buyer库
• 通过线下异步的方式,通过binlog+canal,将数据冗余到DB-seller库中
• buyer库通过buyer_uid分库,seller库通过seller_uid分库,前者满足oid和buyer_uid的查询需求,后者满足seller_uid的查询需求
为什么要冗余数据?
互联网数据量很大的业务场景,往往数据库需要进行水平切分来降低单库数据量。
水平切分会有一个patitionkey,通过patition key的查询能够直接定位到库,但是非patitionkey上的查询可能就需要扫描多个库了。
此时常见的架构设计方案,是使用数据冗余这种反范式设计来满足分库后不同维度的查询需求。
- 例如:订单业务,对用户和商家都有订单查询需求:
Order(oid,info_detail);
T(buyer_uid,seller_uid,oid);
如果用buyer_uid来分库,seller_uid的查询就需要扫描多库。
如果用seller_uid来分库,buyer_uid的查询就需要扫描多库。
此时可以使用数据冗余来分别满足buyer_uid和seller_uid上的查询需求:
T1(buyer_uid,seller_uid,oid)
T2(seller_uid,buyer_uid,oid)
同一个数据,冗余两份,一份以buyer_uid来分库,满足买家的查询需求;一份以seller_uid来分库,满足卖家的查询需求。
订单中心数据库切分方法|如何实现数据冗余
1.服务同步双写
服务同步双写,即由服务层同步写冗余数据。
流程如图:
(1)业务应用代用服务层,写入数据
(2)服务层将数据写入DB1
(3)服务层将数据写入DB2
(4)服务层返回新增数据成功给业务应用
- 优点:
- 简单,服务层由单写,改为两次写人
- 数据一致性较高,双写成功后才返回
- 缺点:
- 因为由单写变为了两次写入,请求时间增长
- 数据仍有可能不一致(数据写入DB1后,服务宕机或重启,则数据无法写人DB2)
2.线下异步双写
为了屏蔽“复杂性”,数据双写由线下服务或者任务来完成,不再由服务层完成。
流程如图:
(1)业务应用代用服务层,写入数据
(2)服务层将数据写入DB1
(3)服务层返回新增数据成功给业务应用
(4)数据会被写入到数据库的log中
(5)线下服务或者任务读取数据库log
(6)线下服务或者任务插入T2数据
- 优点:
- 数据双写与业务完全解耦
- 请求处理时间短
- 缺点:
- 返回业务新增成功时,会存在一个数据不一致的时间窗口,但能保证最终一致性
- 数据一致性依赖于线下服务或者任务的可凹陷
原文:https://blog.csdn.net/sunhuiliang85/article/details/78418546
参考:https://blog.csdn.net/qq_18145031/article/details/77867853
分库分表:订单中心,多key业务如何进行数据库切分相关推荐
- Java互联网架构-Mysql分库分表订单生成系统实战分析
分库分表的必要性 首先我们来了解一下为什么要做分库分表.在我们的业务(web应用)中,关系型数据库本身比较容易成为系统性能瓶颈,单机存储容量.连接数.处理能力等都很有限,数据库本身的"有状态 ...
- 如何彻底解决烦人的 MySQL 分库分表问题?写一个更好的数据库!
作者 | 黄东旭 责编 | 郭 芮 我还清楚记得,五年前的这个时候,当时还在豌豆荚,午后与刘奇和崔秋的闲聊关于未来数据库的想象,就像一粒种子一样,到了今天看起来也竟枝繁叶茂郁郁葱葱,有点感慨.按照 ...
- mysql分库分表中间件6_当当开源sharding-jdbc,轻量级数据库分库分表中间件
近期,当当开源了数据库分库分表中间件sharding-jdbc. Sharding-JDBC是当当应用框架ddframe中,从关系型数据库模块dd-rdb中分离出来的数据库水平分片框架,实现透明化数据 ...
- 当当网mysql分库分表策略_当当开源sharding-jdbc,轻量级数据库分库分表中间件
近期,当当开源了数据库分库分表中间件sharding-jdbc. Sharding-JDBC是当当应用框架ddframe中,从关系型数据库模块dd-rdb中分离出来的数据库水平分片框架,实现透明化数据 ...
- 数据库改造:怎样用MySQL对10亿级订单量进行分库分表?
一.背景 随着公司业务增长,如果每天1000多万笔订单的话,3个月将有约10亿的订单量,之前数据库采用单库单表的形式已经不满足于业务需求,数据库改造迫在眉睫. 二.订单数据如何划分 我们可以将订单数据 ...
- 10亿级订单系统分库分表设计思路
一.背景 随着公司业务增长,如果每天1000多万笔订单的话,3个月将有约10亿的订单量,之前数据库采用单库单表的形式已经不满足于业务需求,数据库改造迫在眉睫. 二.订单数据如何划分 我们可以将订单数据 ...
- 商城订单模块实战 - 数据库设计、ABA问题处理、读写分离分库分表
引言 订单系统可以说是整个电商系统中最重要的一个子系统,因此订单数据可以算作电商企业最重要的数据资产.这篇文章我们来看看在我们的商城系统中订单服务是如何实现的,特别是在设计和实现一个订单系统的过程中有 ...
- 数据库分库分表,何时分?怎样分?
点击上方"方志朋",选择"置顶或者星标" 你的关注意义重大! 一. 数据切分 关系型数据库本身比较容易成为系统瓶颈,单机存储容量.连接数.处理能力都有限.当单表 ...
- 史上更全面的数据库分库分表、数据一致性、主键分配思路!
作者:butterfly100 cnblogs.com/butterfly100/p/9034281.html 一. 数据切分 关系型数据库本身比较容易成为系统瓶颈,单机存储容量.连接数.处理能力都有 ...
最新文章
- Java传输对象模式
- 队列的链式存储和实现(C语言)【队列】(8)
- 【struts2】struts2配置文件—struts.properties
- ​4种实现多列布局css
- python是动态语言_Python是动态语言:动态添加或删除属性、方法
- 中移4G模块-ML302-OpenCpu开发-51单片机串口转I2C
- NumPy:数组计算
- oc传参数给js_【一句话攻略】彻底理解JS中的回调(Callback)函数
- 小米路由青春版-2.1.26开发版固件
- 地图历史大反转!GISer如何查看历史影像
- Word 文档乱码-请选择使文档可读的编码 重启电脑-不是解决方法的解决方法(可能已经晚了)
- C#项目之 GMap.net 标记点及 绘制多点之间的距离
- 小米手环2来电不震动,来电不提醒怎么办
- DAY10微信小程序项目开发技术总结
- 顺应数字化转型趋势化解“上云”风险,擎天Enclave保障数据安全
- iOS textField属性详解
- Java流程控制——用户交互Scanner
- Photoshop CC 2017 For Mac安装教程
- 思科AP常见型号和WiFi标准POE标准对应表
- 3. 描述性统计分析