【深入理解 TcaplusDB 技术】理解预设 Schema 表类型
TcaplusDB 需要预设 Schema,同时提供两种表类型:Generic 表和 List 表,Generic 表一个 Key(1-8 个字段)记录对应一个 Value 记录,List 表一个 Key(1-7 个字段)记录对应多个 Value 记录。List 表根据是否进行排序分为普通 list 表和 sortlist 表,对于普通 List 表,Tcaplus 内部是无序插入的,用户取出一个 Key 下的所有 Value 时,Value 内部是无序的。SortList 表按照某个指定的 Value 字段进行排序插入,用户可以按照从大到小或者从小到大的顺序进行取值。在 PB 和 TDR 表中都存在这三种 schema 模式,用户可以根据需求选择合适的模式。
1. 数据表及相关规则
1.1. 数据表规则
数据表名称不超过 32 字节(包含'\0'结尾)
字段名不超过 32 字节(包含'\0'结尾)
每个 Key 字段不超过 1024 字节
每个 Value 字段不超过 10MB
单条记录 Pack 后长度不超过 10MB
1.2. 变更规则
不允许对 primarykey、splitkey、index 做任何变更;
Value 字段可以增加字段但不能减少字段,并且增加字段时要注意版本号的变更;
Value 字段默认值可更改,Value 字段最大长度只能改大不能改小;
不允许删除 Value 字段,不允许更改 Value 字段名称和类型;
List 类型表的最大元素个数只允许改大不允许改小,且最大元素个数不能超过 10000;
1.3. Generic 表
1.4. List 表
不能建索引
Key 字段最多只能有 7 个,Value 字段最多 255 个, 各有一个要预留给系统使用。
List 支持方便的头尾操作, 适合邮件,留言板,战斗记录等场景
List 表需要指定单个 Key 记录下的最大元素个数(目前最大 10000),超过最大元素个数时,可指定从头部或尾部删除老元素。默认采用 FIFO 方式淘汰。SortList 表和普通 List 表一样有最大元素个数,插入超过最大元素个数 N 时,对于正序(从小排到大)总是保留最小的 N 个元素,倒序则反之,总是保留最大的 N 个元素。
可以一次取出单个 Key 下的所有 Value,Value 内部的排列无序。
2. Generic 表
2.1. TDR-Generic 表示例
<struct name="PLAYERONLINECNT" version="1" primarykey="TimeStamp,GameSvrID" splittablekey="TimeStamp">
<entry name="TimeStamp" type="uint32" desc="单位为分钟" />
<entry name="GameSvrID" type="string" size="64" />
<entry name="GameAppID" type="string" size="64" desc="gameapp id" />
<entry name="OnlineCntIOS" type="uint32" defaultvalue="0" desc="ios在线人数" />
<entry name="OnlineCntAndroid" type="uint32" defaultvalue="0" desc="android在线人数" />
<entry name="BinaryLen" type="smalluint" defaultvalue="1" desc="数据来源数据长度;长度为0时,忽略来源检查"/>
<entry name="binary" type="tinyint" desc="二进制" count= "1000" refer="BinaryLen" />
<entry name="binary2" type="tinyint" desc="二进制2" count= "1000" refer="BinaryLen" />
<entry name="strstr" type="string" size="64" desc="字符串"/>
<index name="index_id" column="TimeStamp"/>
</struct>
复制代码
2.2. PB-Gneric 表示例
message pb_generic_index_shardingkey {
option(tcaplusservice.tcaplus_primary_key) = "openid,tconndid,timekey,svrid";
option(tcaplusservice.tcaplus_index) = "index_openid(openid)";
option(tcaplusservice.tcaplus_index) = "index_openid_tconndid(openid,tconndid)";
option(tcaplusservice.tcaplus_index) = "index_full_key(openid,tconndid,timekey,svrid)";
option(tcaplusservice.tcaplus_sharding_key) = "openid";
//4个key
required uint32 openid = 1; //QQ Uin
required string timekey = 2[(tcaplusservice.tcaplus_size) = 20, (tcaplusservice.tcaplus_desc) = "bingo"];
required int32 tconndid = 3;
required string svrid = 4;
//value
required string gamesvrid = 5[(tcaplusservice.tcaplus_size) = 11];
repeated property other_property= 6 ;//其他扩展属性
optional item_bag items = 7;
repeated int64 lockid = 8 [packed = true];
optional bytes val = 9;
optional pay_info pay = 10;
optional uint32 id_uint32 = 11;
optional int32 id_int32 = 12;
}
复制代码
3. List 表
Tcaplus 对 List 表的存储采用分级机制,包括:
索引记录,Fullkey + (idx1,idx2,idx3,……,idxn)
数据记录,[FullKey+idx1,value1][FullKey+idx2,value2][……][FullKey+idxn,valuen]
3.1. TDR-List 表示例
<struct name="following_action_list" version="1" primarykey="game,myuin">
<entry name="game" type="uint64" defaultvalue="0" desc="游戏ID"/>
<entry name="myuin" type="uint32" desc="QQ号"/>
<entry name="actiontype" type="uint8" defaultvalue="0" desc="1-分享图片,2-赞图片,3-评论图片"/>
<entry name="uin2" type="uint32" desc="关注人QQ号"/>
<entry name="nick2" type="string" size="128" desc="关注人昵称"/>
<entry name="sex" type="uint8" defaultvalue="0" desc="关注人性别男0女1"/>
<entry name="pid" type="string" size="33" desc="关注人操作图片ID"/>
<entry name="time" type="uint32" desc="时间"/>
<entry name="content" type="string" size="1024" desc="动态详细内容"/>
</struct>
复制代码
3.2. PB-List 表示例
syntax = "proto3";
package myTcaplusTable;
import "tcaplusservice.optionv1.proto";
message tb_online_list {
option(tcaplusservice.tcaplus_primary_key) = "openid,tconndid,timekey";
option(tcaplusservice.tcaplus_customattr) = "TableType=LIST;ListNum=1900";
int32 openid = 1; //QQ Uin
int32 tconndid = 2;
string timekey = 3;
string gamesvrid = 4;
int32 logintime = 5 ;
repeated int64 lockid = 6;
pay_info pay = 7;
message pay_info {
uint64 total_money = 1;
uint64 pay_times = 2;
}
map<string, pay_info> projects = 8;
}
复制代码
4. SortList 表
最多允许 4 个排序字段,且在建表的 xml(tdr)中指定,具体格式如下:
<struct name="following_action_list" version="1" primarykey="game,myuin" customattr="TableType=SORTLIST;SortRule=INSC;SortFieldNum=1">
<entry name="game" type="uint64" defaultvalue="0" desc="游戏ID"/>
<entry name="myuin" type="uint32" desc="QQ号"/>
<entry name="actiontype" type="uint8" defaultvalue="0" desc="1-分享图片,2-赞图片,3-评论图片"/>
<entry name="uin2" type="uint32" desc="关注人QQ号"/>
<entry name="nick2" type="string" size="128" desc="关注人昵称"/>
<entry name="sex" type="uint8" defaultvalue="0" desc="关注人性别男0女1"/>
<entry name="pid" type="string" size="33" desc="关注人操作图片ID"/>
<entry name="time" type="uint32" customattr="sort1" desc="时间"/>
<entry name="content" type="string" size="1024" desc="动态详细内容"/>
</struct>
复制代码
如上 customattr="TableType=SORTLIST;ListNum=1023;SortFieldNum=1"表示该表格类型为 SORTLIST,SortRule=INSC 表示升序排列,SortFieldNum=1 表示排序字段有 1 个,customattr="sort1"表示第一个排序字段。
排序默认按照从小到大进行排序,在 ServiceApi 中可以指定是从小到大取还是从大到小取。
暂时不允许在表变更时从无序 List 变为 SortList,也不允许从 SortList 变更为无序 List,不允许表变更变换排序字段的顺序以及增减排序字段(这个均采用自己写 so 走表变更 Key-Value 方式实现)。
排序字段最大字节数 8B,排序字段的类型:byte, uint16,uint32,uint64,int16,int32,int64,float,double【string(包含\0 最多 8B,暂时不支持)】。
排序是指 Value 字段参与排序,而不是 Key。
使用说明:
排序
当已有数据结构排好序后,再采用 ListAddAfter 进行数据插入时,采用插入排序效果最佳。
插入
对于 ListAddAfter,流程是:先看是否已经满了,如果满了且不允许淘汰元素,则插入失败,如果满了,允许淘汰,则删掉那个元素,并且获取一个 BiggestIndex,将新元素插在对应位置,并挪动其他元素。
而对于 SortList,当用户进行 ListAddAfter 时,List 数目超过最大元素个数 N 时,对于正序(从小排到大)总是保留最小的 N 个元素,也就是说插入的元素比当前最大值还大时,会插入失败(因为立即被淘汰),而倒序则反之,总是保留最大的 N 个元素。
4.1. TDR-Sortlist 表示例
<struct name="table_Sortlist_single" primarykey="key, name" customattr2="TableType=SORTLIST;ListNum=1023;SortFieldNum=1;SortRule=DESC" version="5" desc="用于list表遍历测试, 需要4个shard, 建表list最大1023个元素" >
<entry name="key" type="uint32" desc="单个uint32作为KEY的时候, hashcode = key % 10000"/>
<entry name="name" type="int16" />
<entry name="level" type="uint32" />
<entry name="value1" type="string" size="102400" defaultvalue="" desc="最大长度:100KB"/>
<entry name="value2" type="string" size="102400" defaultvalue="" desc="最大长度:100KB"/>
<entry name="type_int8" type="int8" desc="type_int8" />
<entry name="type_uint8" type="uint8" desc="type_uint8"/>
<entry name="type_int16" type="int16" desc="type_int16" customattr2="sort1"/>
<entry name="type_uint16" type="uint16" desc="type_uint16"/>
<entry name="type_int32" type="int32" desc="type_int32"/>
<entry name="type_uint32" type="uint32" desc="type_uint32"/>
<entry name="type_int64" type="int64" desc="type_int64"/>
<entry name="type_uint64" type="uint64" desc="type_uint64"/>
<entry name="type_float" type="float" desc="type_float"/>
<entry name="type_double" type="double" desc="type_double"/>
<entry name="type_short" type="short" desc="type_short"/>
<entry name="type_string" type="string" desc="type_string" size="20"/>
<entry name="type_tinyint" type="tinyint" desc="type_tinyint"/>
<entry name="type_datetime" type="datetime" desc="type_datetime"/>
</struct>
复制代码
4.2. PB-SortList 表示例
message pb_sortedlist {
option(tcaplusservice.tcaplus_primary_key) = "openid,tconndid,timekey,svrid";
option(tcaplusservice.tcaplus_customattr) = "TableType=SORTLIST;ListNum=1900;SortField=id_int32";
//4个key
required uint32 openid = 1; //QQ Uin
required string timekey = 2[(tcaplusservice.tcaplus_size) = 20, (tcaplusservice.tcaplus_desc) = "bingo"];
required int32 tconndid = 3;
required string svrid = 4;
//value
required string gamesvrid = 5[(tcaplusservice.tcaplus_size) = 11];
repeated property other_property= 6 ;//其他扩展属性
optional item_bag items = 7;
repeated int64 lockid = 8 [packed = true];
optional bytes val = 9;
optional pay_info pay = 10;
optional uint32 id_uint32 = 11;
optional int32 id_int32 = 12;
}
复制代码
TcaplusDB 是腾讯出品的分布式 NoSQL 数据库,存储和调度的代码完全自研。具备缓存+落地融合架构、PB 级存储、毫秒级时延、无损水平扩展和复杂数据结构等特性。同时具备丰富的生态、便捷的迁移、极低的运维成本和五个九高可用等特点。客户覆盖游戏、互联网、政务、金融、制造和物联网等领域。
评论