A-A+

TenDB Cluster-腾讯互娱分布式数据库解决方案

2015年04月14日 TenDBCluster 暂无评论

总体架构

2012年,互娱从原来的单一实例管理到GCS 1.0的DB管理架构转变后,实现了业务自助开区、存储资源管理和高可用等特性,满足了业务较快速发展的需求。

但是,随着手游的爆发,业务的生命周期变得更短,存储层的扩缩容操作渐渐频繁。另外,游戏分区分服的特性导致了不同区服有不同的负载要求,这都对db管理,特别是成本管理带来了较大的难度。

因此,2014年,互娱DBA团队实现了GCS 2.0 --TenDB Cluster的分布式数据库解决方案。

TenDB Cluster的分布式数据库集群有以下特点:

多种数据分布策略
支持哈希、范围、列表等算法,将数据水平分布到各个节点上,用户可自定义数据分布策略,提高应用的存储和处理性能。
完善的可用性和数据保护支持
实现数据分片后存储节点的冗余与互备,在硬件或软件故障时,有效保障数据处理不间断。
节点动态在线扩展
支持按需在线动态增减节点,实现线性扩展。在线动态增减节点和其他组件时,集群业务运行不受影响。完全兼容MySQL协议
应用层访问跟单一MySQL无异,原则上支持任意类型SQL,应用层无需做任何修改
方便的部署和管理工具
提供了统一的部署、管理和监控工具,管理系统可以对任一节点进行部署、管理和监控。

技术方案选型

互娱游戏业务db层访问特点

  1. 业务量大,包含自研和代理业务,含MMOG、手游、页游等不同模式。
  2. 不同开发商会使用不同的ORM工具来抽象db层的操作,这些工具会生成各种各样类型的SQL访问db。
  3. 绝大部分是KV式访问,少量join/order by/group by/in/not in查询
  4. 部分会使用存储过程

而下面简单对比了业界分布式数据库集群的实现方案。

团队一开始也是希望基于中间件(mysql-proxy)的形式来组建支持分库分表的集群方案,但考虑到无法预估广大开发商的SQL用法。若需开发商改造SQL(ORM工具)来适配分布式DB解决方案的话,推动起来必定十分困难。而如果后面每种语句都逐步支持和兼容的话,又会导致庞大且繁琐的工作。

因此,我们最终使用了存储引擎而非中间件的技术来作为分布式数据库的解决方案。使用这种方案的好处是,MySQL的全部命令几乎都是原生支持的。

实现原理

使用过federated存储引擎的可能知道,两个mysql间可以建立dblink。

create table test_federated( 
    id int primary key,
    name varchar(20)
) engine = federated  CONNECTION='mysql://username:password@real_host:real_port/db_name/test_federated';

由于MySQL特殊的插件式存储引擎架构,server层负责SQL解析、SQL优化、数据库对象(视图、存储过程等)管理;存储引擎层负责数据存储、索引支持、事务、buffer等,两者之间通过约定好的handler接口进行交互。

因此,federated存储引擎只要数据增删改查和其他必要hanlder接口,SQL解析、优化与执行交给server层处理,几乎支持执行任意类型SQL访问。

受到这个启发,就可以基于MySQL本身的架构,再加上分区表的特性,可以实现一个支持分库分表的分布式存储引擎。

在我们正准备着手实现的时候,发现有一个spider存储引擎的开源解决方案,在想法上不谋而合。不过经过我们测试,spider原版本在性能和稳定性上都有较大的问题,也一直没有release。

1422949952_39

TenDB Cluster就是在spider 3.1基础上开发而成,进一步提高了性能、稳定性和兼容性,并结合互娱业务特性整合而成的分布式数据库解决方案。

具体优化点:

  1. 优化update/delete/replace实现,优化direct接口实现,避免无谓SQL优化行为,提高性能。
  2. 优化事务实现,按需启用事务。
  3. 优化获取远程连接流程,避免过多无用连接,增加连接池监控视图
  4. 增加定期空闲连接回收策略,避免占用大量连接资源。
  5. 优化info接口实现,减少无谓show table status/show index请求
  6. 修复一个分区连接失败会导致所有分区无法访问的问题(无分区独立性)
  7. 解决当分区表不含主键,性能大幅下降的问题
  8. 支持字符串作为分区键
  9. 增加性能分析视图和跨分区访问审计功能。
  10. 修复多处由于字符集、时区、常量运算等导致结果不正确问题。
  11. 修改优化器,优化聚集函数(count/sum/min/max+group by)的实现
  12. 修复多处在并发环境下的crash问题
  13. 修复mysql连接指定CLIENT_FOUND_ROWS后,affected_rows结果不对问题

优化后的Spider引擎更加稳定,功能也更加丰富,性能较原版提升30%。

例如,Spider跟普通分区表一样支持范围/hash/列表分区,以列表分区作为一个例子:

CREATE TABLE `test_spider` (
  `id` bigint(20) NOT NULL,
  `name` varchar(20),
  `age` int,
  `level` int,
  PRIMARY KEY (`id`),
  KEY idx_level(`level`)
) ENGINE=SPIDER DEFAULT CHARSET=utf8
/*!50100 PARTITION BY LIST (crc32(id)%4)
(PARTITION pt0 VALUES IN (0) COMMENT = 'database "d1_0", table "test_spider", server "SP0" ENGINE = SPIDER,
 PARTITION pt1 VALUES IN (1) COMMENT = 'database "d1_0", table "test_spider", server "SP1" ENGINE = SPIDER,
 PARTITION pt2 VALUES IN (2) COMMENT = 'database "d1_0", table "test_spider", server "SP2" ENGINE = SPIDER,
 PARTITION pt3 VALUES IN (3) COMMENT = 'database "d1_0", table "test_spider", server "SP3" ENGINE = SPIDER) */

Spider扩展了partition子句的comment字段,可指定分区后端db的地址(server标识)及库表名。server字段会读取表mysql.servers中的后端db ip地址和port等信息。

DML

指定分区键
select * from test_spider where id = 1 and level > 3;
update test_spider set level = 10 where id = 2;
根据分区规则,语法分析识别分区键,将语句路由到指定后端。

不带分区键
select * from test_spider where level > 3;
select * from test_spider where age = 5;
update test_spider set level = 3 where level = 2;
所有后端执行,结果合并返回。

order by
select * from test_spider where level > 3 order by age desc;
所有后端执行
select * from test_spider where level > 3, Spider负责排序。

count/min/max/sum
select count(*) from test_spider where age > 10 group by level;
所有后端执行
select count(*), level from test_spider where age > 10 group by level.
Spider负责将相同level结果相加后返回。

join
select t1.* from t1, t2 where t1.c1 = t2.c1 and t2.c2 = 'a' and t1.c2 = 'b';
连接在mysql优化器中有不同的执行计划。

以上操作上,mysql优化器原默认形式往往是较差的执行路径(原单机的优化策略在分布式环境中往往是较差的)。因此,Spider在这类语句执行时,都做了相应优化。

DDL

建表语句会根据系统中定义的分表策略将普通建表语句转换成Spider形式并会在后端db执行相应建表。

alter会在Spider节点和后端db中执行。

mysql协议

应用层可能使用了一些特殊的mysql协议特性。

特殊状态信息
select @@last_insert_id;

API
兼容API的所有连接option
例如,mysql_real_connect 指定 CLIENT_FOUND_ROWS 建立连接,使用row_matched 替代 row_affected

会话级状态保持
例如设置字符集,不会因为使用后端连接池不同连接而导致状态出错。
set names gbk;
insert *** (with gbk characters);
set names utf8;
update *** (with utf characters);

权限

应用层的权限管理将在Spider中完成,权限语句和管理模式跟单一mysql完全一致。

其他管理语句

另外,除了普通delete/insert/update/select语句,DB管理侧还有大量的管理语句可能需要使用,例如
show processlist;
show table status;
show variables;
show status;
flush tables;

这些语句是Spider都可以支持,真正做到运维习惯的平滑迁移。

线性扩展能力

模块说明

  • DNS: 业务通过唯一的名字来获取集群服务,访问模式跟单一db无异(也可用LVS/TGW替代)。
  • 接入层:负责分库分表、SQL路由转发、跨分表聚合运算等(由核心组件Spider存储引擎构成)
  • 存储层:普通mysql/TenDB实例,一主一备。
  • monitor:接入层和存储层的监控模块,包括健康检查和性能数据上报
  • 性能服务器:收集MONITOR上报的性能数据,为自助扩缩容提供决策支持
  • 配置服务器:维护接入层和存储层分库分表的配置关系及集群容量信息

在线扩缩容

TenDB Cluster集群中的接入层和存储层都可以自由扩展,并且所有节点间并没有强耦合关系,因此,具有较好的线性扩展能力。

例如,以存储节点扩展为例,支持同样的600G数据(来源于QQGame业务),后端1~3个存储节点的处理性能是线性增强的。

1422951589_94

  • 接入层扩缩容:名字服务下加入/删除具有相同路由规则的Spider节点
  • 存储层扩缩容:目前接入层屏蔽了存储层的路由规则细节,应用无需对此进行感知,扩缩容在集群内部自动完成即可。 若成倍扩容,就是将1/2的数据(db实例)通过mysql热备的方式进行搬迁,再修改Spider的路由信息。

另外,为了保证多个Spider节点路由的一致性,存储层扩容会有短暂的只读锁。

LOCK SPIDER ALL READ ONLY
更新路由信息
UNLOCK SPIDER ALL

另外,TenDB Cluster集群方案也不是说存储节点越多就性能越好。由于可能存在跨分区SQL操作,节点间的网络交互、spider节点的运算复杂性等问题会随存储层节点的增多而进一步扩大。因此,在实际应用中,不建议使用过多的存储节点,建议最多16或32个。

高可用

根据Spider节点和存储节点的心跳信息,可以判断其存活性。并且,在TenDB Cluster架构上,并没有全局节点,单一节点故障不会影响全局服务。

同时,当节点故障,DBHA能自动进行容灾处理:
- 若接入节点Spider故障,会自动剔除。
- 若存储节点RemoteDB故障,检查主备数据一致后,修改Spider的路由执行到相应的热备中去。

高可用行为大部分继承了原GCS 1.0 DBHA的原理,可参考《GCS DB高可用-决策与故障处理

后续规划

  1. 自动扩缩容
    虽然目前支持集群的一键扩缩容行为,但真正的扩缩容还需要通过根据收集的性能数据和容量信息手动发起(性能达到预设阀值会有告警)。后续需要支持自动扩缩容行为。
  2. 数据一致性
    存储节点主备数据一致性依赖mysql的单线程的replication机制,数据存在落后及丢失的隐患(同步落后有告警)。 在TenDB Cluster集群中数据分库分表后,可升级mysql 5.6的库级多线程复制(Spider接入节点对后端db无要求)。
    同时,DB侧提供了定时数据校验和数据差异修复工具,以较低成本的方式来保证数据的一致性。
  3. 性能
    纯KV的普通SQL,尤其是指定分区键的,Spider引擎除了必要的语法分析外,已经绕开了大量优化器和handler接口行为,大大提高了该类语句的执行效率。
    但分区表的处理效率还不是很高,当分区个数增多,性能有下降趋势,这是一个优化方向。(目前业务使用的最大分区数是16/32)
    另外,对于distinct、join等操作,mysql的优化策略仍比较差,导致该类查询性能不高,需要对优化器深入研究后进行优化。
  4. 自增列
    当一个集群存储多个spider节点时,目前自增列性能并不好,每次插入需要计算所有分片的最大值再做+1存储。因此,后续会提供一种更廉价的方式来实现自增列,但只保证局部递增和全局唯一,保证不了绝对递增和连续。业务可以根据自己的特性来选择不同的实现方案。
  5. 事务
    单机事务:相同存储节点上的事务可以保证,跟原来一致。 分布式事务:TenDB Cluster本身是支持的,但这种事务原则上只能保证非故障时候的ACID特性。 虽然spider原作者号称支持XA事务,但我们认为性能影响较大且实际作用不大,故禁用了该部分特性。另外,mysql本身并没有全局事务的概念,在全局一致性读或其他分布式事务概念上是不够严谨的。因此,通常情况下不建议启用分布式事务。
  6. 管理工具
    作为DB管理团队,我们管理着不同业务成千上万的DB服务器。基于TenDB Cluster的管理工具,包括监控、性能分析、数据迁移、数据校验与修复、日常报表、问题排查等工具仍需日益完善。

原创文章,转载请注明: 转载自腾讯游戏DBA团队

本文链接地址: TenDB Cluster-腾讯互娱分布式数据库解决方案

文章的脚注信息由WordPress的wp-posturl插件自动生成

Copyright © 腾讯游戏DBA团队 保留所有权利.  

用户登录

分享到: