有奖捉虫:办公协同&微信生态&物联网文档专题 HOT

表格概述

表格是数据的集合,是业务数据根据表格的定义存放在一起的组合形式。 从游戏业务角度来看,一张表可负责一个业务模块的一段相关数据集合,例如用户表、道具表。
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 表中都存在 Generic 表、 List 表、SortList 表这三种 Schema 模式,用户可以根据需求选择合适的模式。
如下示例的玩家表数据,该表可用于存储有关某一游戏中所有玩家的相关信息:游戏角色名、性别、种族、等级、战斗值、装备、坐骑、物品等信息。
{
player_id:11474,
player_name: "测试账号2",
gender:0,
ethnicity:"精灵",
FightingPower:10,
equipment:
{
helmet:0,
Warframe:0,
gloves:0,
necklace:0,
pants:0,
Shoes:0
},
horse:"0"
}
{
player_id:11475,
player_name: "测试账号1",
gender:1,
ethnicity:"兽人",
FightingPower:1477,
equipment:
{
helmet:1478,
Warframe:21,
gloves:554,
necklace:12,
pants:64,
Shoes:122
},
horse:"3"
}

记录

多个同一对象字段值的集合,称之为记录。上述示例的玩家角色表中,一个玩家角色的所有信息,由多个属性字段值组成,其所有信息表示这个玩家角色信息在此游戏的集合。单条记录支持最大10MB。

字段

字段描述了指定对象的某一特征。上述示例,玩家角色的一个独立属性我们称之为一个字段,如玩家角色表中的 player_name、ethnicity。

主键字段

由如上示例表可看出,每条记录都有标志记录唯一性的字段,用于将表中的记录区分开来,我们称之为主键字段。上述示例的玩家角色表中,主键字段包含 player_id 以及 player_name。TcaplusDB 最大支持8个主键字段。

普通字段

每条记录除了标志其唯一性的字段外,还有其他的属性,这些属性所构成的字段,称之为普通字段。上述示例的玩家角色表中,普通字段则为 equipment,FightingPower 等属性。TcaplusDB 支持最多128个普通字段。

分片字段

TcaplusDB 是分布式数据库系统,可以为表格提供更高规格的并发请求能力。如果用户设置了分片字段,TcaplusDB 将自动根据当前表格访问情况,通过对分片字段 Hash 计算从而自动调整表格分片。如果用户不设置,那么系统将默认采用主键字段作为分片字段。
分片字段的设置与后台数据分布相关,用户需要评估作为分片字段的字段取值是否离散。取值有限的字段如性别、星期等都不建议设置为分片字段,建议使用 ID、name 类的字段作为分片字段。

字段类型

TcaplusDB 支持多种数据类型,支持的类型如下:
字段类型
字段介绍
int32
使用可变长度编码,此类型表示值介于 -2^31 到 +2^31 之间的有符号整数,但是负数表示效率较低。
int64
使用可变长度编码,此类型表示值介于 -2^63 到 +2^63 之间的有符号整数。
uint32
使用可变长度编码,该类型表示值为 0 到 2^32 的无符号整数。
uint64
使用可变长度编码,该类型表示值为 0 到 2^64 的无符号整数。
sint32
可变长度有符号的 int 值,与常规 int32 相比,可以更有效地表示负数。
sint64
可变长度有符号的 int 值,与常规 int64 相比,可以更有效地表示负数。
bool
布尔类型,表示真 Ture 或假 False。
fixed32
定长数字类型,始终占用四个字节。如果值通常大于 2^28,则比 uint32 更有效率。
fixed64
定长数字类型,始终占用八个字节。如果值通常大于 2^56,则比 uint64 更有效率。
sfixed32
定长数字类型,始终占用四个字节。
sfixed64
定长数字类型,始终占用八个字节。
float
浮点类型,浮点数占 4 个字节,用 32 位二进制描述。
double
双精度类型,浮点数占 8 个字节,用 64 位二进制描述。
string
字符串类型,只能为 UTF-8 编码或 7 位 ASCII 文本,并且长度不能超过 2^32。
bytes
二进制类型,可以包含任意长度不超过 2^32 的字节序列。
message
嵌套类型,可连续嵌套,支持最高嵌套128层,嵌套层数过多会影响性能。

表格定义格式

TcaplusDB 支持 Protocol Buffers、TDR 数据存储格式,这是一种轻便高效的结构化数据存储格式,主要用于将结构化数据序列化存储。 详细关于表的格式可通过 表描述语言 查看。

Generic 表

基本特点

可以建索引,请参见 索引
最多支持8个 Key 字段,256个 Value 字段。
单个 Key 最大1KB, 单个 Value 最大10MB,整条记录最大10MB。

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>

PB-Generic 表示例

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;
}

List表

基本特点

不能建索引。
Key 字段最多只能有7个,Value 字段最多255个, 各有一个要预留给系统使用。
List 支持方便的头尾操作, 适合邮件,留言板,战斗记录等场景。
List 表需要指定单个 Key 记录下的最大元素个数(目前最大10000),超过最大元素个数时,可指定从头部或尾部删除老元素。
可以一次取出单个 Key 下的所有 Value,Value 内部的排列无序。
Tcaplus 对 List 表的存储采用分级机制,包括:
索引记录,Fullkey + (idx1,idx2,idx3,……,idxn)
数据记录,[FullKey+idx1,value1][FullKey+idx2,value2][……][FullKey+idxn,valuen]

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>

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;
}

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" 表示第一个排序字段。

使用限制

排序默认按照从小到大进行排序。
暂时不允许在表变更时从无序 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 时,需要变更下 ServiceApi 里面的接口说明,因为我们默认是按照从小到大的顺序进行排序,当用户需要淘汰最后一个元素时,即淘汰最大的元素,当用户需要淘汰队头的元素时,即淘汰最小的元素。

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>

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;
}