A-A+

TenDB 1.4 InnoDB透明列压缩方案

2014年04月13日 TenDB 评论 3 条

腾讯游戏风雨十年,一直致力于带给玩家最好的快乐体验,为此也取得了巨大的成功。腾讯游戏的后台数据库一直守护着亿万玩家的数据,提供着稳定透明的服务。

腾讯后台数据库大部分使用的是MySQL数据库,现已大部分被替换为互娱DBA团队自己定制的TenDB。IO问题是传统关系型数据库中最热门话题,互娱DBA团队在业务处理过程中同样遇到类似问题。

案例一:IO问题。DNF某个大区的DB由于数据量过大,数据量远大于内存缓冲池,IO瓶颈制约DB整体性能,导致该大区不能提供稳定服务。

案例二:存储空间不足。仙侠传DB在合服过程中,由于数据量过大,导致合服失败。

对于上述问题,通用的方案或者是升级硬件,或者是在游戏server层修改存储逻辑,代价都很大。互娱DBA团队通过在TenDB 1.4版本增加InnoDB列压缩功能,对应用层透明并且节省了硬件成本从而有效解决该问题。

 

列压缩技术方案与应用

互娱游戏的后台数据库经常使用blob/text类型字段来存储数据,业务中blob/text类型字段占据了很大部分的存储空间,如仙侠传DB中约90%的存储内容为blob/text类型列。对这些blob/text字段能压缩存储,将大大降低存储空间,从而提高DB的整体性能。

  • 列压缩技术方案

TenDB列压缩的实现主要包括语法层面、存储格式、压缩/解压逻辑及导入导出优化等几个方面。

1. 列压缩功能是可配置的,为此在TenDB中增加compressed语法。

2. 存储格式:列压缩可以根据字段的长度来判断是否使用压缩存储,因为对于小数据量,压缩比不压缩可能更占用存储空间。目前,判断是否压缩的策略是:如果长度小于256字节,不压缩存储;如果长度大于256字节,压缩存储。压缩格式为:

 

首字节标记(1字节) 解压后长度(0-4字节) 压缩的内容

 

首字节标记:第一个bit,0表示未压缩(对应就无解压后长度),1表示压缩;第2,3位表示算法类型(现阶段版本只有zlib算法),第6,7,8位表示有几个字节来存储压缩长度。

解压后长度:表示数据在压缩前或解压“压缩的内容”的长度,由于BLOB字段约定的最大长度(longblob)是2^32-1,因此4字节的最大长度已经足够。另外,1-4字节的内容分别表示长度上限为2^8-1、2^16-1、2^24-1,2^32-1。该信息也用于解压后的内存分配。

压缩的内容:就是压缩后的数据。

3. 压缩算法

当前版本,压缩和解压基于mysql内置的zlib(1.2.3)压缩库,函数为:my_compress和my_uncompress。

上述定义的格式中,预留了其它类型的算法标记,后续会结合不同压缩算法中cpu开销与压缩率来权衡一种更适当的算法。

4. 压缩与解压

压缩和解压处理需要在统一的函数调用位置,该位置确定在存储引擎和server数据交换的handler接口中,即

Ø Server层从存储引擎获取数据前,存储引擎负责解压。

Ø Server层要存储数据,需要把数据压缩处理。

这样解压和压缩都集中在存储引擎和server间的数据交换接口中,存储引擎和SERVER的其他处理就不需考虑数据是否压缩与否的逻辑,简化整个问题。

压缩接口:row_mysql_store_col_in_innobase_format。由server层传下来的每一个列的数据,都会经由本函数完成数据转换(特殊处理索引)。

解压接口:row_sel_store_mysql_rec。本函数用于将InnoDB层从物理介质上读取到的数据传递到server层的类型。

5. 导入导出优化

导入导出优化主要是通过二方面来实现。首先是在server层增加新的语法SELECT SQL_COMPRESSED 、INSERT SQL_COMPRESSED。在使用SELECT SQL_COMPRESSED时,DB会略过对压缩数据的解压逻辑,直接导出。

INSERT SQL_COMPRESSED与SELECT SQL_COMPRESSED必须是配套使用的,使用INSERT SQL_COMPRESSED略过压缩逻辑直接存储数据。

其次是通过实现tmysqldump使用SELECT SQL_COMPRESSED语法来获取数据内容,在生成SQL语句时使用对符合条件的SQL使用INSERT SQL_COMPRESSED这种语法。

  • 列压缩应用

1. 配置列的压缩属性

在建表时语句指定blob/text类型的列具有compressed属性,这样该列的内容会被压缩存储。

CREATE TABLE `ServiceInfo_00` (

`Uin` int(10) unsigned NOT NULL DEFAULT '0',

`GameInfo` text,

`ServiceInfo` blob compressed,

PRIMARY KEY (`Uin`)

) ENGINE=InnoDB row_format=GCS DEFAULT CHARSET=latin1;

支持compressed属性的列类型包括:TINYBLOBBLOB, MEDIUMBLOBLONGBLOB, TINYTEXT, TEXT, MEDIUMTEXT, LONGTEXT

2. 修改列的压缩属性

对于线上正在运行的数据库,要将对其中的字段增加压缩属性,可以通过alter table来修改,alter table可以取消或增加压缩属性。

Alter table ServiceInfo_00 change ServiceInfo ServiceInfo blob, change GameInfo GameInfo text compressed;

因此,只需简单的alter table操作,就可以让DB中特定列压缩存储。以仙侠传DB中数据示例,一个1.3G的表,通过alter table增加compressed特征后为0.19G,压缩率为15%。在DB中,这样的表是100个,收益明显。

clip_image002

3. 透明压缩/解压

列属性指定为compressed之后,TenDB内部会根据实际需要进行压缩和解压处理。假设ServiceInfo_00.ServiceInfo、ServiceInfo_00.GameInfo列具有compressed属性,以下语句等价关系为

 

TenDB SQL语句 MySQL 等价语句
Select Uin, ServiceInfo from ServiceInfo_00; Select Uin, uncompress(ServiceInfo) from ServiceInfo_00;
Insert into ServiceInfo_00 (Uin, ServiceInfo) values(x, y); Insert into t1(Uin, ServiceInfo) values(x, compress(y));
Update ServiceInfo_00 set GameInfo = concat(GameInfo, ‘a’); Update ServiceInfo_00 set GameInfo =compress(concat(uncompress(GameInfo), ‘a’));

 

4. 导入导出优化

应用TenDB的列压缩后,在使用mysqldump进行导入导出时,在导出时会会执行select操作,那么会对所有的压缩数据进行解压;同样,在导入时也会对需要压缩的数据执行压缩操作。

通过改造mysqldump,增加选项enable-compress-optimization控制压缩的数据在导出与导入过程中,分别不进行解压与压缩,明显缩减导入导出时间。

 

收益与展望

  • 收益

互娱的游戏DB中,具有blob/text类型字段的数据表都能够应用compressed特性,仙侠传、TNT、天涯明月刀等游戏已使用该特性。

以仙侠传为例:仙侠传业务梦取之境大区的gamedb在使用TenDB的列压缩属性后,数据在压缩前160G,压缩后变成20G,压缩率为12.5%

以仙侠传一个大区的数据作压力测试,使用压缩特性后DB性能提升显著,

clip_image004

如上图,在100并发下,仙侠传在A5机型中的QPS由未压缩的253提升到列压缩后的2236,提升了8.8倍。

另外,在仙侠传的合服(两个或多个大区合并成一个大区)操作中,未压缩与压缩的合服时间对比为14239 vs 5749 , 时间节省为原来的40.3%。即合服操作导致的停服时间由原来4小时缩短到1.6小时。

  • 展望

现阶段已应用TenDB列压缩功能的游戏DB,已明显感受后使用列压缩后带来的收益:包括合服、回档中停机时长大幅度减小等。随着越来越多的游戏DB使用列压缩功能,列压缩带来的收益会越来越可观。

列压缩极大的减少了IO开销,相应也提升了CPU消耗,但当前应用CPU并不存在瓶颈。后续会对列压缩会提供多种压缩算法,可针对不同应用环境来进行选择从而更合理的平衡IO与CPU。同时,继续TenDB后续版本的开发,包括DB云化方案、冷热数据分离等,提供业内领先的优质DB服务。

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

本文链接地址: TenDB 1.4 InnoDB透明列压缩方案

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

  1. 晕,和我的实现基本类似。。。

    我也是在server层-innodb层数据转换那注入压缩/解压….不同的就是我是扩展的已有的column_format列属性….类似于 create table t1 (a blob column_format compressed)…

    • 哈,确实差不多!  你们现在应用效果怎样,怎么选择压缩算法的呢 ?

      在server与innodb交互时,对数据进行压缩/解压处理,比较有效可控;

      在cluster里面扩展column_format属性挺合适的;

      我们重用行格式的compressed到列上,等同于在列上的auto_increment, not null等标识的处理。

  2. Pingback: binlog压缩功能介绍 - 腾讯游戏DBA团队 | 腾讯游戏DBA团队

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

用户登录

分享到: