Generic表和List表

TcaplusDB根据表记录类型的不同,又分为Generic表和List表,Generic表一个Key(1-8个字段)记录对应一个Record记录,List表一个Key(1-7个字段)记录对应多个Record记录。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

  • Pb表的所有key字段,序列后的总buffer长度不超过1022字节

1.2. 变更规则

  • 不允许对primarykey、splitkey、index做任何变更;

  • Value字段可以增加字段但不能减少字段,并且增加字段时要注意版本号的变更;

  • Value字段默认值可更改,Value字段最大长度只能改大不能改小;

  • 不允许删除Value字段,不允许更改Value字段名称和类型;

  • List类型表的最大元素个数只允许改大不允许改小,且最大元素个数不能超过10000;

1.3. Generic表

  • 可以建索引(见本地索引和全局索引)

  • 最多支持8个Key字段,api版本大于等于3.46支持256个Value字段,低于3.46版本支持128个Value字段

1.4. List表

  • 不能建索引

  • Key字段最多只能有7个,Value字段最多255个, 各有一个要预留给系统使用。

  • List支持方便的头尾操作, 适合邮件,留言板,战斗记录等场景。

  • List表需要指定单个Key记录下的最大元素个数(目前最大10000),超过最大元素个数时,可指定从头部或尾部删除老元素。默认采用FIFO方式淘汰。SortList表和普通List表一样有最大元素个数,插入超过最大元素个数N时,对于正序(从小排到大)总是保留最小的N个元素,倒序则反之,总是保留最大的N个元素。

  • SortList表最多支持同时指定4个排序字段。

  • 可以一次取出单个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表

TcaplusDB对List表的存储采用分级机制,包括:

  • 索引记录,FullKey + (idx1,idx2,idx3,……,idxn)

  • 数据记录,[FullKey+idx1,value1][FullKey+idx2,value2][……][FullKey+idxn,valuen]

因list表的实现机制上存在系统索引记录(每个key都会存在一条索引记录),所以业务实际记录数会小于TotalSize总记录数(key个数+实际记录数) 例如:遍历查询表里实际记录41条,其中key个数26个,那么count表的TotalSize总记录数为67

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

3.3. list表淘汰策略

/**
    @brief  设置LIST满时,插入元素时,删除旧元素的模式--TDR接口才能直接调用此方法
    @param  [in] chListShiftFlag    TCAPLUS_LIST_SHIFT_NONE: 不允许删除元素,若LIST满,插入失败;TCAPLUS_LIST_SHIFT_HEAD: 移除最前面的元素;TCAPLUS_LIST_SHIFT_TAIL: 移除最后面的元素
            如果表是排序List,必须要进行淘汰,且淘汰规则是根据字段的排序顺序进行自动制定的,用户调用该接口会失败
    @retval 0              设置成功
    @retval 非0            设置失败,具体错误参见 \link ErrorCode \endlink
    */
    int32_t SetListShiftFlag(IN const char chListShiftFlag = TCAPLUS_API_LIST_SHIFT_HEAD);

当设置为淘汰策略为TCAPLUS_LIST_SHIFT_HEAD(列表满了之后,淘汰列表头部的元素)时,配合尾部插入一起使用,便可实现类似先进先出的队列。

当设置为淘汰策略为TCAPLUS_LIST_SHIFT_TAIL(列表满了之后,淘汰列表尾部的元素)时,配合头部插入一起使用,也可实现类似先进先出的队列。

4. SortList表

最多允许4个排序字段(一级字段),且在建表的xml(tdr)中指定,具体格式如下:

<struct name="following_action_list" version="1" primarykey="game,myuin" customattr2="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"   customattr2="sort1"  desc="时间"/>
    <entry name="content"        type="string"   size="1024"         desc="动态详细内容"/>
</struct>

如上customattr2="TableType=SORTLIST;ListNum=1023;SortFieldNum=1"表示该表格类型为SORTLIST,SortRule=INSC表示升序排列,SortFieldNum=1表示排序字段有1个,customattr2="sort1"表示第一个排序字段。

  • 排序默认按照从小到大进行排序

  • 暂时不允许在表变更时从无序List变为SortList,也不允许从SortList变更为无序List,不允许表变更变换排序字段的顺序以及增减排序字段(这个均采用自己写so走表变更Key-Value方式实现)。

  • 排序字段最大字节数8B,排序字段的类型:byte, uint16,uint32,uint64,int16,int32,int64,float,double【string(包含\0最多8B,暂时不支持)】。

  • 排序是指Value字段参与排序,而不是Key。

使用说明:

排序

当已有数据结构排好序后,再采用ListAddAfter进行数据插入时,采用插入排序效果最佳。 允许多个排序字段联合排序(最多4个),先按照第一个字段进行排序,第一个字段相同时,再按照第二个字段排序,依次类推排序。

插入

对于ListAddAfter,流程是:先看是否已经满了,如果满了且不允许淘汰元素,则插入失败,如果满了,允许淘汰,则删掉那个元素,并且获取一个BiggestIndex,将新元素插在对应位置,并挪动其他元素。

而对于SortList,当用户进行ListAddAfter时,List数目超过最大元素个数N时,对于正序(从小排到大)总是保留最小的N个元素,也就是说插入的元素比当前最大值还大时,会插入失败(因为立即被淘汰)返回错误码 SVR_ERR_FULL_SORTLIST_CANT_INSERT,而倒序则反之,总是保留最大的N个元素。(即SetListShiftFlag中的淘汰规则对sortlist表失效,按照排序规则淘汰)

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";//多字段排序SortField=id_int32,id_uint32..

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

results matching ""

    No results matching ""