深度解析:腾讯云分布式数据库 DCDB

这些问题,腾讯全部遇到过

我们知道,集中式(单机)数据库在存储容量、并发性能、快速扩容等都会因业务增长而达到瓶颈。而在业务发展初期,团队很难准确预测数据库增长的速度和规模,只有靠拍脑袋确定规模进行设备选型:

  • 若达不到预期,会导致资源浪费;
  • 若超过预期,则会出现扩展难题;
  • 若成为行业领先,那么性能瓶颈又摆在了面前。
  • 还有集中式数据库一系列容灾、恢复、管理等一系列问题,都让人糟心。

多数情况下,互联网业务往往都会超出预期,随之而来的问题就令人头疼了。为解决上述问题,腾讯数据库团队曾经选择多种方向,也考察过商业数据库基于共享存储的体系架构(RAC)。我们发现,RAC架构无法通过增加计算节点来“线性的”提升数据库集群性能,因为共享存储的体系架构中多个节点对同一个数据块有对等访问权限,这就意味着所有数据都是全局资源,任何节点在操作数据时必须加锁以防止其它节点的干扰,为了协调节点间的访问,就必须通过密集的消息通信来传递资源锁。在传统企业IT(内部ERP、OA)等系统上,这样的问题并不明显;然而当其面对的是互联网海量处理应用是,这种资源锁机制严重限制了RAC架构的扩展能力。其次,从运营成本角度上讲,商业数据库高昂的授权费用、昂贵的硬件成本,都制约了业务的快速发展。因此,腾讯最终选择了分布式数据库方案。

时至今日,放眼互联网行业,排名靠前企业的核心业务都在使用分布式数据库,我们不禁要问,这其中有什么秘密?

分布式数据库为什么能解决容量、并发、扩展等难题

了解分布式数据库,需要先了解垂直切分(分库)、水平切分(分表)两种方案:

  • 垂直切分(通常也叫做“分库”)也就是按功能切分数据库,这种切分方法跟业务紧密相关,实施思路也比较直接,比如“京东JD”等电商平台,一个原有一个数据库实例,按功能切分为会员数据库、商品数据库、交易数据库、物流数据库等多个数据库实例,共同承担业务压力。有时候,垂直拆分并不能彻底解决压力问题,因为单台数据库服务器的负载和容量也是有限的,随着业务发展势必也会成为瓶颈,解决这些问题的常见方案就是水平切分了。
  • 水平切分(又叫做“分表”)是按照某种规则,将一个表的数据分散到多个物理独立的数据库服务器中,这些“独立”的数据库“分片”;多个分片组成一个逻辑完整的数据库实例。一般来说,分表的前提是分库。

水平拆分的方案,实际上是分布式数据库的基础原理,他的每个节点都参与计算和数据存储,而且每个节点都仅计算和存储一部分数据。因此,无论业务的规模如何增长,我们仅需要在分布式集群中不断的添加设备,用新设备去应对增长的计算和存储需要就够了。

腾讯云分布式数据库DCDB

腾讯云分布式数据库(DCDB)是部署在腾讯云上的一种,面向OLTP业务支持自动水平拆分(分表)的share nothing架构的分布式数据库。DCDB也是随着腾讯业务规模不断扩大而发展起来的,从2004年开始,腾讯部分业务就已经开始遇到单机数据库架构已经无法支撑,进而开始研究分布式架构,业务发展最终推动了数据库架构技术的不断革新,面对日益复杂的需求。截止到2017年,包括微信支付,腾讯充值,阅文集团等腾讯公司交易、转账等核心系统90%以上都使用了腾讯分布式数据库(DCDB)。

DCDB的前身是腾讯自研TDSQL,我们的设计理念是淡化复杂的拆分、扩展等逻辑,让开发者使用DCDB就像使用集中式单机数据库一样顺利

当前,DCDB已支持MySQL 5.7、5.6(基于Percona、MariaDB分支),未来计划进一步支持PostgreSQL引擎(基于腾讯自研PostgreSQL-XZ分布式引擎)等。

DCDB整个集群架构简图如下图,这种集群架构极大简化了各个节点之间的通信机制,也简化了对于硬件的需求,这就意味着即使是简单的x86服务器,也可以搭建出类似于小型机、共享存储等一样稳定可靠的数据库。

大多数情况下,可以用您熟悉的对象映射框架使用DCDB。对于分表,建议您尽量使用基础的SQL语句,因为这样能达到最佳性能,特别是几亿甚至几百亿条记录的情况下。这意味着,某些情况下,您可能需要一定的改造,才可以接入DCDB。

分布式数据库DCDB的分表方案

关系型数据库是一个二维模型,数据的切分通常就需要找到一个分表字段(shardkey)以确定拆分维度,再通过定义规则来实现数据库的拆分。业内的几种常见的分表规则如下:

  • 基于日期顺序(Time),如按年拆分,2015年一个分表,2016年一个分表。
  • 基于某字段划分范围(Range),如按用户ID划分,0~1000一个分表,1001~2000一个分表。
  • 基于某字段求模(HASH),将求模后的值,再按Range方式分散到不同库中。

无论是Time、Range都有个主要缺点就是可能导致严重数据倾斜,即多个物理节点(又叫做分片)之间负载和数据容量严重不均衡。在大部分数据库系统中,数据都有明显的冷热特征——显然当前的订单被访问的概率比半年前的订单要高的多(更热)——而采用Time分表或range分表,就意味大部分热数据将会被路由在少数几个分表中,而存储冷数据的设备性能却被浪费掉了。

因此,DCDB通常采用某个字段求模(HASH)的方案进行分表,而计算HASH的某个字段就叫做shardkey。因为HASH算法本身就能够基本保证数据相对均匀的分散在不同的物理设备中(某些特殊情况下除外,我们将在后续章节进行介绍)。

HASH的过程大致就是,当某条记录(SQL)请求时被发起时,DCDB 会理解 SQL 语句的含义,然后按照拆分键的值和执行策略将 SQL 路由到对应分表进行执行,如下图所示,先通过hash算法计算,再路由到各个节点上。

而如果一个查询 SQL 语句的数据涉及到多个分表,此时SQL会被路由到多个分表执行,DCDB 会将各个分表返回的数据按照原始 SQL 语义进行合并,并将最终结果返回给用户。

读取数据时(如果有明确shardkey值):

  1. 业务发送select请求中含有shardkey时,网关通过对shardkey进行hash
  2. 不同的hash值范围对应不同的分表
  3. 数据根据分表算法,将数据从对应的分表中取出

读取数据时(如果没有明确shardkey值):

  1. 业务发送select请求没有shardkey时,将请求发往所有分表
  2. 各个分表查询自身内容,发回Proxy;
  3. Proxy根据SQL规则,对数据进行聚合,再答复给网关

从上述原理来看,查询SQL中含有shardkey值比不含shardkey值效率将会更高。

如何选择拆分键

拆分键是在水平拆分过程中用于生成拆分规则的数据表字段,必须在建表时就指定好。DCDB建议拆分键要尽可能找到数据表中的数据在业务逻辑上的主体,并确定大部分(或核心的)数据库操作都是围绕这个主体的数据进行,然后可使用该主体对应的字段作为拆分键进行分表,该分表方案通常叫做groupshard(按组分表),如下图:

Groupshard方案,可以确保不同分表的某些关联数据和复杂的业务逻辑运算,可以聚合到一个物理分片内,进而减轻分布式数据库本身一些使用缺陷。例如,某电商平台订单表和用户表都是基于用户维度(UserID)拆分,平台就可以很容易的通过联合查询(不会存在跨节点join,或分布式事务)快速计算某个用户近期产生了多少订单。 下面的一些典型选择拆分键的应用场景:

  • 面向用户的互联网应用,都是围绕用户维度来做各种操作,那么业务逻辑主体就是用户,可使用用户对应的字段作为拆分键;
  • 电商应用或O2O应用,都是围绕卖家/买家维度来进行各种操作,那么业务逻辑主体就是卖家/买家,可使用卖家/买家对应的字段作为拆分键;但请注意,某些情况下几个超大卖家占到绝大多数交易额,这种情况会导致某几个分片的负载和压力明显高于其他分片,我们会在后面章节予以说明。
  • 游戏类的应用,是围绕玩家维度来做各种操作,那么业务逻辑主体就是玩家,可使用玩家对应的字段作为拆分键;
  • 物联网方面的应用,则是基于物联信息进行操作,那么业务逻辑主体就是传感器/SIM卡,可使用传感器、独立设备、SIM卡的IMEI作为对应的字段作为拆分键;
  • 税务/工商类/社保的应用,主要是基于纳税人/法人/居民的信息来开展前台业务,那么业务逻辑主体就是纳税人/法人,可使用纳税人/法人对应的字段作为拆分键。
  • 以此类推,其它类型的应用场景,大多也能找到合适的业务逻辑主体作为拆分键的选择。

拆分键的限制 为了提高语法解析效率,避免因为shardkey设置导致路由错误,DCDB规定了拆分键设定的技术限制(请参考腾讯云官方文档):

  1. 如存在主键或者唯一索引,则shardkey字段必须是主键以及所有唯一索引的一部分;
  2. shardkey字段的类型必须是int,bigint,smallint,char,varchar;
  3. shardkey字段的值尽量使用ascii码,网关不会转换字符集,所以不同字符集可能会路由到不同的分区(且尽量不要有中文);
  4. 不能update shardkey字段的值,如必须则先delete,再insert;
  5. shardkey= 放在create语句的最后面,如下示例:
mysql> create table test.right ( a int not null,b int not null, c char(20) not null,primary key(a,b) ,unique key(a,c)) shardkey=a; Query OK, 0 rows affected (0.12 sec) 

6. 访问数据尽量都能带上shardkey字段,可以极大的提升效率;

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏程序人生 阅读快乐

UNIX 环境高级编程(第3版 )

《UNIX环境高级编程(第3版)》是被誉为UNIX编程“圣经”的Advanced Programming in the UNIX Environment一书的第...

432
来自专栏黄希彤的专栏

没有扩容机器,抗住了70多倍的流量增长

登录服务器一看 log,访问量增长的有点厉害啊,疑似 CC 攻击,打开了各种防护,流量还是居高不下...

8513
来自专栏Crossin的编程教室

21天精通编程

各位愚人节快乐! 在目前的科技条件下,21天精通一门编程语言是不可能滴。 不过21天入门 Python,了解编程,学会写几个小程序,倒是不断在我们的教室中发生着...

2826
来自专栏架构师小秘圈

分库分表架构实践

作者介绍: 丁浪,现就职于某垂直电商平台,担任技术架构师。关注高并发、高可用的架构设计,对系统服务化、分库分表、性能调优等方面有深入研究和丰富实践经验。热衷于技...

4644
来自专栏挖掘大数据

国家电网推进全业务数据中心建设

2016年10 月9 日,习近平总书记在中共中央政治局第三十六次集体学习时强调,要深刻认识互联网在国家管理和社会治理中的作用,以推行电子政务、建设新型智慧城市等...

3170
来自专栏SDNLAB

SDN实战团分享(三十二):ZStack架构及其网络功能简介

先说些题外话 SDN 群里大牛很多,从平时讨论中学习到不少,我的背景相对更偏云计算一些,我对 SDN 的角度可能也与大家有一些不同。 举例来说,前段时间发生了...

4405
来自专栏飞总聊IT

苹果公司开源FoundationDB的简单分析

美国时间 2018年4月19日,苹果公司宣布开源FoundationDB。FoundationDB 本来是一个开源项目,于2015年被苹果收购以后,其代码从Gi...

1442
来自专栏程序员互动联盟

如何成为一个黑客?

很多人要成为高大上的黑客需要学习哪些基本功? 能盗取账号,能攻击服务器? 再牛的黑客起码是一个合格的程序员 所以说想成为黑客先成为合格的程序再说,说别的就是空谈...

3997
来自专栏JAVA高级架构开发

代码规范固然重要,但是不要再黑程序员了...

第一次看到一侧关于程序猿代码没有规范而被枪杀的文章,开始有朋友在群里吐槽几个平时代码比较“诗意”的同事,大家也就一笑而过了。

460
来自专栏Java架构沉思录

十分钟搞懂负载均衡

我们知道负载均衡层的作用是“将来源于外部的处理压力通过某种规律/手段分摊到内部各个处理节点上”,那么不同的业务场景需要的负载均衡方式又是不一样的,架构师还要考虑...

852

扫码关注云+社区