大数据&云计算|作为数据库核心成员,如何让淘宝不卡顿?
本文插图
阿里妹导读:TDDL(Tabao Distributed Data Layer)是淘宝开源的一个用于访问数据库的中间件 , 集成了分库分表 , 主备 , 读写分离 , 权重调配 , 动态数据库配置等功能 。 本文以2007年TDDL初诞生时的视角 , 介绍TDDL是如何一步步设计成型的 , 希望能帮助同学们简单收获:常规数据库效率问题解决思路、TDDL框架设计基本思路以及分布式数据库设计思路等 。
文末福利:《MySQL实操》技术公开课 。
时间倒转穿越回2007年年底
一觉醒来 , 我还是照常去上班 , 走到西溪湿地附近 , 马路没有 , 高楼没有 , 有的是小山坡和金色的稻田 。 一番打听之后 , 才知道此时没有什么西溪园区 。 没办法 , 硬着头皮去滨江上班 , 一刷卡 , 才发现我并不是我 , 我现在的身份是淘宝数据库团队的核心成员 。
此时全国上下在迎接着奥运的到来 , 一片祥和 。 淘宝网成交额突破400亿 , 日活用户达1000万 。 工程师们都非常兴奋 , 磨刀霍霍 。 但是也遇到了棘手的问题 。
一 分析当前的现状
1.1 现有业务背景
淘宝网给中国市场提供了全新的购物形式 , 在互联网的大潮下 , 用户暴增 , 成交量暴增 , 公司持续飞速增长 。
截止2007年 , 淘宝网成交额突破400亿 , 日活用户达1000万 。
全天有1000万用户访问淘宝 。 而绝大多数用户都是在网上逛 , 什么也不买 。
1.2 当前的问题
1.2.1 用户体验与反馈
用户普遍反馈逛淘宝卡顿 , 操作延迟特别明显 。
1.2.2 分析核心原因
大量的用户在浏览商品 , 并不下单 。 这个人数和场景的比例有20:1 。
说明:数据库模式事务 , 写操作会对表或者行加写锁 , 阻塞读操作 。
业务数据集中在一张表里 , 如user表 。 一张表里数据破几千万 。 查询一条数据需要好几秒(单表数据量太大) 。
说明:一张表数据提升 , 必然会导致检索变慢 ,这是必然事实 。 不论如何加索引或者优化都无法解决的 。
所有表集中在一个库里 , 所有库集中在一个机器里 。 数据库集中在一台机器上 , 动不动就说硬盘不够了(单机单库) 。
说明:所有业务共用一份物理机器资源 。 机器存在瓶颈:磁盘和CPU不够用且后期拓展性不佳 。
1.2.3 总结问题
20:1读写比例场景 。
单表单库数据量太大 。
小型机与单机场景 , 抗不住当前规模 。
本文插图
当前现状
二 我要做什么?
如何满足当前每天1000万用户逛淘宝的需求 , 且用户体验好(最基本要求:响应快) 。
如何满足未来有上亿用户的访问 , 甚至是同时访问 , 且用户体验好(最基本要求:响应快) 。
高筑墙 , 广积粮 , 积极做好准备 。
提炼核心:
提高数据库操作速度 。
同时能应对未来规模变化 。
三 我能做什么?
为实现以上两大目标 , 我能做什么?
3.1 提高数据库操作速度 , 通用方法
提炼常见的通用方法:
sql优化
排除语法问题 , 烂sql
下推优化
下推的目的:提前过滤数据 -> 减少网络传输、并行计算 。
提前过滤数据
小表驱动大表等
建立索引
查询频率高的热点字段
区分度高的(DISTINCT column_name)/COUNT(*) , 以主键为榜样(1/COUNT(*))
长度小
尽量能覆盖常用查询字段
注意索引失效的场景
分库分表
垂直分库分表
水平分库分表
读写分离
缓存的使用
等等 。
3.2 如何应对未来的持续变化? 分页标题
必须支持动态扩容 。
必须走分布式化路线 , 百分百不动摇 。
3.3 结合定位 , 分析自己能做的
3.3.1 分析我们的架构定位
(1)大前提
我们要做通用型框架 , 不参与业务 。
从软件设计原则出发 , 开闭原则:对扩展开放 , 对修改关闭 。
说明:大修改就意味着不稳定 , 因此:我们要做到尽可能少的修改原来的代码 。 在程序需要进行拓展的时候 , 不能去修改原有的代码 , 实现一个热插拔的效果 。
(2)当前架构现状
淘宝网主要使用hibernate/ibatis传统框架:
本文插图
初始框架
(3)分析我们的架构定位
淘宝数据库团队当时使用映射框架(hibernate/ibatis)作为数据库交互入库 , 为了不让他们修改代码 , 那我们只能在ibatis/hibenate这类映射框架之下 。
同时jdbc是与底层数据库交互的Java数据库连接驱动程序 , 是基础能力 , 我们要使用它 , 而不是改造它 。
结论:我得把TDDL安插于ibatis/jdbc之间 , 于是有了第一张架构图:
本文插图
TDDL的定位
3.4 总结 , 我们能做什么?
本文插图
结合我们的目标 , 通用方法 , 大前提以及架构定位 , 分析下我们能做和不能做的 。
不能做的:
索引 , 因为这个是设计阶段 , 强业务相关 。 与大前提冲突:我们不参与业务 。
能做的:
语法优化
排除sql问题
下推优化
分表分库(自动水平分表 , 水平分库)
读写分离(读写分离/分布式化与动态扩容)
四 我们如何做?
4.1 语法优化
为达到语法优化的目的 , 我们需要具备什么能力?
简单来说:
我们需要认识这个别人提交给我的sql 。
我能拆解sql 。
优化与重组这个sql 。
本文插图
专业点来说:语义分析能力 。
sql解析
sql规则制定
sql优化
sql重组
因此:我们需要设计一个sql解析器 , sql优化器 。
4.1.1 解析器
解析器的核心是词法分析、语法语义分析 , 也就是说来了一条 select/update/insert/delete语句 , 你能认识它 , 而且你知道下一步该怎么处理 , 同时为后面的优化器打下基础 。
核心:将sql解析为一棵语法树 。
例:
sql语法树:
本文插图
4.1.2 优化器
核心:
在sql解析成sql语法树后 , 使用sql优化规则(1. 语法优化 2. 下推优化) ,通过对树进行左旋 , 右旋 , 删除子树来对语法树进行重构sql语法树 。
将重构的语法树进行遍历得到优化后的sql 。
(1)语法优化
函数提前计算
判断永真/永假式
合并范围
类型处理
(2)下推优化
Where条件下推
说明:提前条件过滤 , 提前获取数据 , 减少后期计算/IO/网络成本 。
JOIN中非join列的条件下推
说明:提前过滤 , 减轻后期join计算成本 , 达到“小表驱动”的目的 。
等值条件的推导
说明:同理 , 提前过滤 。
4.1.3 总结
sql解析器
负责将sql语句化为sql语法树 。
sql优化器
负责将sql语法树利用sql优化规则 , 重构sql语法树 。分页标题
将sql语法树转化为sql语句 。
4.2 分表分库
单库单表的问题:
几年前 , 业务简单 , 应用的数据比较少 , 表结构也不复杂 。 只有一个数据库 , 数据库中的表是一张完整的表 。 而到了今天 , 2007年了 , 业务复杂起来了 , 数据量爆增 , 单表数据破千万甚至上亿条 , 一条DML语句 , 死慢死慢的 。 这种情况下加索引已不再有显著的效果 。
这个时候 , 数据库效率瓶颈不是靠加索引 , sql优化能搞定的 。
正确出路:分表分库 , 通过将表拆分 , 来降低单表数据量 , 进而提高数据库操作效率 。
分表分为:
垂直分表
水平分表
分库分为:
垂直分库
水平分库
由于TDDL不参与业务 , 而垂直分库分表是强业务相关的 , 因此TDDL暂不参与垂直分库分表 , 只在水平分库分表方向上努力 。
4.2.1 垂直分表
垂直拆分是将一张表垂直拆成多个表 。 往往是把常用的列独立成一张主表 。 不常用的列以及特别长的列拆分成另一张拓展表 。
本文插图
简单垂直分表举例
核心要素:
冷热分离 , 把常用的列放在一个表 , 不常用的放在一个表 。
大字段列独立存放 , 如描述信息 。
关联关系的列紧密的放在一起 。
它带来的提升是:
为了避免IO争抢并减少锁表的几率 , 查看详情的用户与商品信息浏览互不影响 。
充分发挥热门数据的操作效率 , 商品信息的操作的高效率不会被商品描述的低效率所拖累 。
4.2.2 水平分表
水平分表是在同一个数据库内 , 把同一个表的数据按一定规则拆到多个表中 。
本文插图
简单水平分表举例
简单点的技巧:按照枚举类型区分 。
作用总结:
库内的水平分表 , 解决了单一表数据量过大的问题 , 分出来的小表中只包含一部分数据 , 从而使得单个表的数据量变小 , 提高检索性能 。
避免IO争抢并减少锁表的几率 。
4.2.3 垂直分库
垂直分库是指按照业务将表进行分类 , 分布到不同的数据库上面 , 每个库可以放在不同的服务器上 , 它的核心理念是专库专用 。
本文插图
垂直分库
作用总结:
解决业务层面的耦合 , 业务清晰 。
高并发场景下 , 垂直分库一定程度的提升IO、数据库连接数、降低单机硬件资源的瓶颈 。
能对不同业务的数据进行分级管理、维护、监控、扩展等 。
垂直分库通过将表按业务分类 , 然后分布在不同数据库 , 并且可以将这些数据库部署在不同服务器上 , 从而达到多个服务器共同分摊压力的效果 , 但是依然没有解决单表数据量过大的问题 。
4.2.4 水平分库(TDDL 核心)
水平分库是把同一个表的数据按一定规则拆到不同的数据库中 , 每个库可以放在不同的服务器上 。
本文插图
水平分库
作用总结:
解决了单库单表数据量过大的问题 , 理论上解决了高并发的性能瓶颈 。
水平分库核心要解决的问题:
如何知道数据在哪个库里?- 路由问题
结果合并
全局唯一主键ID
分布式事务(暂时不支持)
4.2.5 水平分库——问题解决
(1)自动路由算法
sql转发:在水平拆分后 , 数据被分散到多张表里 。 原来的一个sql需要拆解 , 进行转发路由 。
例:
分页标题
本文插图
拆分表的数据访问——SQL转发
其中拆分和寻找的算法:怎么知道对应哪个表?即自动路由算法 。 常见的有:固定哈希算法和一致性哈希算法 。
a)固定哈希算法
本文插图
b)一致性哈希算法
一致性哈希算法在1997年由麻省理工学院提出 , 是一种特殊的哈希算法 , 目的是解决分布式缓存的问题 。
一致性哈希算法的优势:
极好的应对了服务器宕机的场景 。
很好的支持后期服务器扩容 。
在引入虚拟节点后:能很好的平衡各节点的数据分布 。
由于一致性哈希算法的优势 , 此算法几乎是所有分布式场景下使用的方案 , 包括mysql的分布式、redis的分布式等 。
本文插图
(2) 结果合并
本文插图
升华:引入fork-Join , 提升操作速度(多线程并发重点场景 , 代码中也很常用哦) 。
任务拆分
多路并行操作
结果合并
本文插图
(3)全局唯一主键
优势:简单高效 。
缺点:无法保证自增顺序 。
例:
表1新增一条数据 , 于是给表1分配1000个主键ID ,直到它用完 。
同理 , 表2、表3在新增数据时 , 也给它们分配1000个主键ID 。 直到它用完 。
当它们的1000个主键ID用完后 , 继续给它们分配1000个即可 。
重复下去 , 可保证各库表上的主键不重叠 , 唯一 。
本文插图
这种产生全局唯一id的方式相当有效 , 保证基本的全局唯一特性和高性能的同时 , 可以对生成id的数据库分机架分机房部署达到容灾的目的 。
4.2.6 分表分库总结
本文插图
架构师角度:
优先考虑缓存降低对数据库的读操作 。
再考虑读写分离 , 降低数据库写操作 。
最后开始数据拆分 , 切分模式:首先垂直(纵向)拆分、再次水平拆分 。
首先考虑按照业务垂直拆分 。
再考虑水平拆分:先分库(设置数据路由规则 , 把数据分配到不同的库中) 。
最后再考虑分表 , 单表拆分到数据1000万以内 。
个人开发角度:
优先使用分表分库框架(直接使用) 。
优先考虑缓存降低对数据库的读操作 。
自己垂直分表 。
自己水平分表 。
之所以先垂直拆分才水平拆分 , 是因为垂直拆分后数据业务清晰而且单一 , 更加方便指定水平的标准 。
4.3 分布式化
分布式化是大潮 , 是大规模服务器最后都要走的一步 。
本文插图
分布式数据库架构演变
4.3.1 读写分离
设计读写分离的数据库 , 有两大意义:
主从只负责各自的写和读 , 极大程度的缓解X锁和S锁的竞争 。
从库可配置myisam引擎 , 提升查询性能以及节约系统开销 。
说明:myisam查询效率高于默认的innodb效率 。 参考:myisam和innodb的区别 。
分页标题
本文插图
核心问题:
数据的备份同步问题:参考4.4.3 。
读写比例支持动态设置:结合业务 , 如淘宝可设置为20:1 。
4.3.2 容灾
主备倒换:提高可靠性 > 应对个别数据库宕机场景 , 尤其主库宕机 。
本文插图
主备倒换
说明:DB2主库宕机后 , 自动将主库转为DB3 。
核心问题:
数据的备份同步问题:binlog 参考4.4.3 。
检测数据库的在线状态:心跳机制 。
4.3.3 数据备份与同步
当只有单机或者一份数据时 , 一但数据库出问题 , 那么整体服务将不可用 , 而且更严重的是会造成数据损害丢失不可逆 。
在读写分离与主备倒换的场景下 , 核心要解决的是多个数据库的数据同步与备份问题 。
当前主流的是采用日志备份方式(redis也类似) 。
实现原理:binlog日志备份 。
本文插图
数据备份:bin-log同步
说明:
主库负责写操作 , 在数据变更时 , 会写入binlog , 同时通知各从库 。
从库收到通知后 , IO线程会主动过来读取主库的binlog , 并写入自己的log 。
写完从库log后 , 通知sql线程 , sql线程读取自己的日志 , 写入从库 。
4.3.4 动态扩容
动态扩容的意义在于:随着后期业务量增大 , 数据库个数可以通过增多的方式来应对 , 而相对的改造代价很小 。
扩容前:
本文插图
扩容后:
本文插图
核心内容:
在添加新库时
注册机器与库
路由算法调整:固定哈希算法-调整模数/一致性哈希算法天然支持扩容
可选的权重调整
修改权重 , 数据插入偏向于新库5 。
在各库数量平衡时 , 触发修改回原来平衡的权重 , 以保证后续的均衡分配 。
五 架构成型
sql流向
下图介绍sql从流入TDD到流入数据库 , 期间TDDL各模块对Sql的处理 。
本文插图
架构图
本文插图
下图介绍了TDDL三层的位置以及作用 。
本文插图
核心能力图
TDDL 核心能力 , 核心组建示意图 , 其中标出了各模块核心要解决功能 , 核心算法等 。
本文插图
参考
TDDL 官方文档
https://mw.alibaba-inc.com/products/tddl/_book/
TDD产品原理介绍
https://gitlab.alibaba-inc.com/middleware/tddl5-wiki/raw/master/docs/Tddl_Intro.ppt
TDDL(07-10年)初始版本介绍
https://wenku.baidu.com/view/9cb630ab7f1922791788e825.html
阿里云SQL调优指南
https://help.aliyun.com/document_detail/144293.html
一致性哈希算法原理
https://www.cnblogs.com/lpfuture/p/5796398.html
TDDL初期源码(码云)
https://gitee.com/justwe9891/TDDL
MyISAM与InnoDB 的区别(9个不同点)
MySQL实操 分页标题
RDS MySQL版基于阿里云分布式文件系统和SSD盘高性能存储 , 提供了容灾、备份、恢复、监控、迁移等全套解决方案 。 本课程共36课时 , 讲解MySQL基于阿里云云服务器ECS的安装、配置 , 通过学习与实操 , 掌握MySQL的工作原理、使用技巧以及优化 , 并具备云端使用MySQL的能力 。
【大数据&云计算|作为数据库核心成员,如何让淘宝不卡顿?】
- 贸易|英国与欧盟基于共同利益达成“微型”贸易协议
- 人民日报海外版|各方利好点亮黄金周——中国消费潜力加速释放原创版权禁止商业转载 授权>>
- 新华网|前三季度我国期货市场成交同比增长超四成原创版权禁止商业转载 授权>>
- 新华网|全国铁路今起实施新列车运行图原创版权禁止商业转载 授权>>
- 经济日报|促进市场化并购重组 推动上市公司做优做强原创版权禁止商业转载 授权>>
- 食品|常态化防控新冠肺炎疫情 云南建立冷链食品“全链条”数据库
- 暗淡青春|一根数据线居然卖354元
- 世界说|海量疑似病例遭忽略,或成新定时炸弹,美国疫情“暗数据”曝光
- 张丽|一组数据读懂相城环卫的小长假
- |Mac最好的键鼠:罗技MX Keys & Master 3