唯品会订单分库分表的实践总结以及关键步骤--转
原文地址:http://www.infoq.com/cn/articles/summary-and-key-steps-of-vip-orders-depots-table
随着唯品会业务的快速发展,订单量的不断增长,原有的订单存储架构已经不能满足公司的发展了,特别是在大促高峰期,原订单库已经成为抢购瓶颈,已经严重制约公司的发展。
唯品会旧订单库包含几十张订单相关表,旧订单库是典型的一主多从架构;主库容量已接近服务器物理空间上限,同时也已经达到MySQL的处理上限,很快将无法再处理新增订单。
旧订单库面临的问题有:
1、超大容量问题
- 订单相关表都已经是超大表,最大表的数据量已经是几十亿,数据库处理能力已经到了极限;
- 单库包含多个超大表,占用的硬盘空间已经接近了服务器的硬盘极限,很快将无空间可用;
2、性能问题
单一服务器处理能力是有限的,单一订单库的TPS也有上限,不管如何优化,总会有达到上限,这限制了单位时间的订单处理能力,这个问题在大促时更加明显,如果不重构,订单达到一定量以后,就无法再继续增长,严重影响到用户体验。
3、升级扩展问题
- 单一主库无法灵活的进行升级和扩展,无法满足公司快速发展要求;
- 所有的订单数据都放在同一库里面,存在单点故障的风险;
综上所述,容量、性能问题是急需解决的问题,扩展是为了将来3~5年内能够很好的满足唯品会快速发展的需要,而不需要每隔几个月花费人力物力去考虑扩容等问题。
解决方法思考
1、解决容量问题
我们可以考虑到最直接的方式是增加大容量硬盘,或者对IO有更高要求,还可以考虑增加SSD硬盘来解决容量的问题。此方法无法解决单表数据量问题。
可以对数据表历史数据进行归档,但也需要频繁进行归档操作,而且不能解决性能问题。
2、解决性能问题
提高数据库服务器的配置,这个可以提升一定数量的QPS和TPS,但仍然不能解决单服务器连接数、IO读写存在上限的问题,此方法仍然存在单点故障的问题。
拆分方法探讨
常见的数据库拆分方式有三种:垂直拆分、水平拆分、垂直水平拆分。
1、垂直拆分
垂直拆库是根据数据库里面的数据表的相关性进行拆分,比如:一个数据库里面既存在用户数据,又存在订单数据,那么垂直拆分可以把用户数据放到用户库、把订单数据放到订单库。如下图:
垂直拆表是对数据表进行垂直拆分的一种方式,常见的是把一个多字段的大表按常用字段和非常用字段进行拆分,每个表里面的数据记录数一般情况下是相同的,只是字段不一样,使用主键关联,如下图:
2、水平拆分
水平拆分是把单表按某个规则把数据分散到多个表的拆分方式,比如:把单表1亿数据按某个规则拆分,分别存储到10个相同结果的表,每个表的数据是1千万,拆分出来的表,可以分别放至到不同数据库中,即同时进行水平拆库操作,如下图:
水平拆分可以降低单表数据量,让每个单表的数据量保持在一定范围内,从而提升单表读写性能。但水平拆分后,同一业务数据分布在不同的表或库中,可能需要把单表事务改成跨表事务,需要转变数据统计方式等。
3、垂直水平拆分
垂直水平拆分,是综合了垂直和水平拆分方式的一种混合方式,垂直拆分把不同类型的数据存储到不同库中,再结合水平拆分,使单表数据量保持在合理范围内,提升总TPS,提升性能,如下图:
垂直拆分策略
原订单库把所有订单相关的数据(订单销售、订单售后、订单任务处理等数据)都放在同一数据库中,不符合电商系统分层设计,对于订单销售数据,性能第一,需要能够在大促高峰承受每分钟几万到几十万订单的压力;而售后数据,是在订单生成以后,用于订单物流、订单客服等,性能压力不明显,只要保证数据的及时性即可;所以根据这种情况,把原订单库进行垂直拆分,拆分成订单售后数据、订单销售数据、其他数据等,如下图:
水平拆分策略
垂直拆分从业务上把订单下单数据与下单后处理数据分开,但对于订单销售数据,由于数据量仍然巨大,最大的订单销售相关表达到几十亿的数据量,如果遇到大型促销(如:店庆128、419、618、双十一等等),数据库TPS达到上限,单销售库单订单表仍然无法满足需求,还需要进一步进行拆分,在这里使用水平拆分策略。
订单分表是首先考虑的,分表的目标是保证每个数据表的数量保持在1000~5000万左右,在这个量级下,数据表的大小与性能是最理想的。
如果几十个分表都放到一个订单库里面,运行于单组服务器上,则受限于单组服务器的处理能力,数据库的TPS有限,所以需要考虑分库,把分表放到分库里面,减轻单库的压力,增加总的订单TPS。
1、用户编号HASH切分
使用用户编号哈希取模,根据数据量评估,把单库拆分成n个库,n个库分别存放到m组服务器中,如下图:
每组服务器容纳4个库,如果将来单服务器达到性能、容量等瓶颈,可以直接把数据库水平扩展为2倍服务器集群,还可以继续扩展为4倍服务器集群。水平扩展可以支撑公司在未来3~5年的快速订单增长。
使用用户编号进行 sharding,可以使得创建订单的处理更简单,不需要进行跨库的事务处理,提高下单的性能与成功率。
2、订单号索引表
根据用户编号进行哈希分库分表,可以满足创建订单和通过用户编号维度进行查询操作的需求,但是根据统计,按订单号进行查询的占比达到80%以上,所以需要解决通过订单号进行订单的CURD等操作,所以需要建立订单号索引表。
订单号索引表是用于用户编号与订单号的对应关系表,根据订单号进行哈希取模,放到分库里面。根据订单号进行查询时,先查出订单号对应的用户编号,再根据用户编号取模查询去对应的库查询订单数据。
订单号与用户编号的关系在创建订单后是不会更改的,为了进一步提高性能,引入缓存,把订单号与用户编号的关系存放到缓存里面,减少查表操作,提升性能,索引不命中时再去查表,并把查询结果更新到缓存中。
3、分布式数据库集群
订单水平分库分表以后,通过用户编号,订单号的查询可以通过上面的方法快速定位到订单数据,但对于其他条件的查询、统计操作,无法简单做到,所以引入分布式数据库中间件。
下图是基本构架:
总结与思考
技术架构与业务场景息息相关,不能脱离实际的业务场景、历史架构、团队能力、数据体量等等去做架构重构,对于一家快速发展的电子商务公司,订单系统是核心,订单库是核心的核心,订单库的重构就像汽车在高速公路上跑着的过程中更换轮胎。
本文是对唯品会订单库重构——采用分库分表策略对原订单库表进行拆分的粗略总结,在订单库重构过程中遇到的问题远远超过这些,比如:历史数据的迁移、各外围系统的对接等,但这些在公司强大的技术团队面前,最终都顺利的解决,新旧订单库顺利的切换,给公司快速的业务发展提供坚实的保障。
转载于:https://www.cnblogs.com/davidwang456/p/6076365.html
唯品会订单分库分表的实践总结以及关键步骤--转相关推荐
- 唯品会订单分库分表的实践总结以及关键步骤
随着唯品会业务的快速发展,订单量的不断增长,原有的订单存储架构已经不能满足公司的发展了,特别是在大促高峰期,原订单库已经成为抢购瓶颈,已经严重制约公司的发展. 唯品会旧订单库包含几十张订单相关表,旧订 ...
- (转)唯品会订单分库分表的实践总结以及关键步骤
原文:http://www.infoq.com/cn/articles/summary-and-key-steps-of-vip-orders-depots-table 随着唯品会业务的快速发展,订单 ...
- 大众点评订单分库分表实践之路
http://dbaplus.cn/news-10-264-1.html 本文是关于大众点评订单分库分表实践的一个具体分享,包含对订单库的具体切分策略,以及我个人的一些思考. 背景 订单单表早已突破两 ...
- 唯品会的订单分库分表实践总结以及关键步骤
原创2016-06-27 叶明开.王鑫聊聊架构 聊聊架构 聊聊架构 微信号 archtime 功能介绍 在这里煮酒聊架构. 随着唯品会业务的快速发展,订单量的不断增长,原有的订单存储架构已经不能 ...
- 订单分库分表实践总结以及关键步骤
转载地址:http://mp.weixin.qq.com/s?__biz=MzA5Nzc4OTA1Mw==&mid=2659597584&idx=1&sn=67f5327423 ...
- 分库分表架构实践(文末送书)
作者介绍: 丁浪,现就职于某垂直电商平台,担任技术架构师.关注高并发.高可用的架构设计,对系统服务化.分库分表.性能调优等方面有深入研究和丰富实践经验.热衷于技术研究和分享. 来源:infoQ||聊聊 ...
- SQL数据库不用SQL语句能显示全表的内容_阿里巴巴数据库分库分表的实践
在2006年阿里巴巴B2B团队以开源方式研发了Cobar这一关系型数据的分布式处理系统.该系统在很大程度上解决了最初使用Oracle数据库因为存储数据变得越来越大带来的扩展性问题,并且为开发人员提供了 ...
- 【干货】分库分表最佳实践
何时分库分表 MySQL单表(innoDB)可以存储10亿级数据,只是这时候性能比较差,业界公认MySQL单表容量在1KW以下是最佳状态,因为这时它的BTREE索引树高在3~5之间. 参考阿里开发手册 ...
- 购物商城订单分库分表应该如何设计
目录 1.为什么有分库分表 2.分库分表模式分类 2.1 垂直分库 2.2 垂直分表 2.3 水平分库
最新文章
- 7-5 二分法求多项式单根 (20分)
- Java学习总结:10
- kafka项目启动_Kafka 探险 源码环境搭建
- python 决策树和随机森林_【python机器学习笔记】使用决策树和随机森林预测糖尿病...
- C语言实现封装、继承、多态
- 小学计算机教案表格式,小学信息技术教案表格数据处理.docx
- php如何跟踪调试,PHP使用debug_backtrace方法跟踪调试代码调用详解
- python统计元音总数_python – 元音序列计数
- ArcGIS Pro快速汉化方法-汉化GP
- C# 调用系统API 内核 简单样例
- C++ vector 类学习笔记(转)
- python题库大一_1000道Python题库系列分享三
- Centos7 Springboot 启动脚本
- L1-020. 帅到没朋友
- HSC-1th 2022 48h大赛 write-up
- java fifo lifo_栈方法 LIFO - 队方法 FIFO
- 用 texstudio, 外部 pdf 浏览器查看可以正常显示中文, 但是内置的 pdf 浏览器不能显示中文?
- Linux文件目录颜色的含义
- AI顶级期刊 IEEE T-PAMI 2020最新论文解读 | Deep Partial Multi-View Learning
- 关于数据库表名设计规范及是否需要前缀,优缺点是什么?
热门文章
- java exec执行tar_用java调用rpmbuild 报错,同一条命令直接复制到终端却能运行
- linux mint 18.3 内核,Linux Mint Linux用户可以升级到18.2 18.3”
- c语言课程设计坦克大战,funcodec++课程设计_坦克大战
- SQLServer数据表的创建
- mysql 22001_mysql ERROR 1264 (22003): Out of range value for column 'x' at row 1 错误
- java cordova_java – Cordova android后台插件在5分钟后被杀死
- C++ static静态成员函数详解
- sql 字符串函数(一)
- spyder 崩溃解决方案
- 112. Leetcode 673. 最长递增子序列的个数 (动态规划-子序列问题)