TDR(Tencent Data Representation)是腾讯推出的,进行游戏开发的基础组件,所有的组件都是基于TDR进行开发。DR数据表示组件以程序库、TDR工具的形式发布。TDR-API本质是相当于一套独立于数据结构的算法,常用API的功能涉及网络编解码、XML数据输入输出、数据可视化、对象关系映射、数据排序。TDR工具实现各种元数据格式之间的转换,并且可以根据XML格式的元数据描述生成C/C++数据结构定义头文件。TDR工具还能够生成实现指定功能的代码,目前支持生成C++\AS3\C#三种语言的代码,支持的功能包括网络编解码、XML数据输入输出、数据可视化。
Tdr使用Xml来描述定义协议文件,可用tdr工具转换成对应的头文件和cpp文件。生成结构体,cmdID的定义和对应的打解包函数。生成之后的结构体和函数可以直接在程序中应用。Tdr支持生成C++\AS3\C#语言。因为游戏存在运营过程中动态更新,在实际的游戏协议应用中,最关注的是协议的兼容性问题,包括CS协议和SS协议的兼容性。Tdr通过版本号来进行协议兼容性的处理,新加字段需要增加对应的版本号,和整个tdr的版本号。Tdr打包的时候会打上对应的最大版本号和字段版本号。打包可以根据对方的版本号进行打包,解包的时候根据数据的版本号进行解包。支持高版本对低版本的兼容。
<struct name="users" version="1" primarykey="user_id,username,role_id" splittablekey="user_id" desc="user table">
<entry name="user_id" type="uint64" desc="user id"/>
<entry name="username" type="string" size="64" desc="login username"/>
<entry name="role_id" type="int32" desc="a user can have multiple roles"/>
<entry name="level" type="int32" defaultvalue="1" desc="role's level"/>
<entry name="role_name" type="string" size="1024" desc="role's name" version="100"/>
<entry name="last_login_time" type="string" size="64" defaultvalue="" desc="user login timestamp" version="101"/>
<entry name="last_logout_time" type="string" size="64" defaultvalue="" desc="user logout timestamp" version="102"/>
<index name="index1" column="user_id"/>
struct>
例如以上的协议中,后面几个字段都是新增字段,需要严格按照版本号递增,除了修改具体结构中的版本号之外,还需要修改整体的版本号。
<metalib name="tcaplus_tb" tagsetversion="1" version="1">
这样tdr打包的数据中就有了具体的整体版本号信息和字段版本号信息。可以做到高版本兼容低版本,但是低版本无法兼容高版本。在实际的上线版本运营中,新增字段必须严格按照版本号升级,要注意具体新增字段和总版本号的同步更新。同时又存在cs协议和ss协议,所以新增字段的时候修改点比较多,检查版本号的步骤比较繁琐,需要人工保证。
标准的XML文件头如下:
前期为了减少字符编码问题带来的影响,先使用GBK作为字符编码。长期来讲,应使用UTF-8作为字符编码,以支持多语言和可移植性。
目前暂时先使用:
一个XML文件只能有一个根元素(Root Element)。对于元数据描述用途的文档,根元素是metalib。表明该XML文件的内容是一个元数据描述集合。
这是一个tdr建表的例子:
<metalib name="tcaplus_tb" tagsetversion="1" version="1">
<struct name="TestInfo" version="1" desc="" >
<entry name="d" type="uint64" />
<entry name="test" type="uint64" />
struct>
<struct name="TableInfo" version="1" desc="" >
<entry name="c" type="TestInfo" />
<entry name="test" type="uint64" />
<entry name="string_array" type="string" size="100" />
<entry name="binary" type="tinyint" />
struct>
<struct name="simple_struct" version="4">
<entry name="c_int8" type="int8" defaultvalue="-1"/>
<entry name="c_uint8" type="uint8" defaultvalue="2"/>
<entry name="c_int16" type="int16" defaultvalue="-3"/>
<entry name="c_uint16" type="uint16" defaultvalue="4"/>
<entry name="c_int32" type="int32" defaultvalue="-5"/>
<entry name="c_uint32" type="uint32" defaultvalue="6"/>
<entry name="c_int64" type="int64" defaultvalue="-7"/>
<entry name="c_uint64" type="uint64" defaultvalue="8"/>
struct>
<union name="union_type" version="1">
<entry name="Id" type="int32" id="0" defaultvalue="0" desc="id" />
<entry name="Name" type="string" id="1" size="64" defaultvalue="hello" desc="name" />
union>
<struct name="struct_type" version="1">
<entry name="x" type="int32" defaultvalue="0" desc="x" />
<entry name="y" type="int32" defaultvalue="0" desc="y" />
<entry name="score" type="double" defaultvalue="1.11" version="2" />
<entry name="rank" type="uint8" defaultvalue="1" version="3" />
<entry name="title" type="string" size="48" desc="title" />
<entry name="level2_struct" type="struct_nested" version="2" />
struct>
<struct name="table_list" version="1" primarykey="uin,name,key1" splittablekey="uin" customattr2="TableType=LIST;ListNum=100;DataProtocolType=PLAIN">
<entry name="uin" type="uint64" desc="QQ"/>
<entry name="name" type="string" size="255" desc="Name"/>
<entry name="key1" type="uint8" desc="key4"/>
<entry name="level" type="int32" defaultvalue="1" />
<entry name="count" type="uint8" defaultvalue="0" />
<entry name="array_count" type="uint32" defaultvalue="1" />
<entry name="items" type="uint64" count="10" refer="array_count"/>
<entry name="c_int8" type="int8" defaultvalue="-1"/>
<entry name="c_uint8" type="uint8" defaultvalue="2"/>
<entry name="c_int16" type="int16" defaultvalue="-3"/>
<entry name="c_uint16" type="uint16" defaultvalue="4"/>
<entry name="c_int32" type="int32" defaultvalue="-5"/>
<entry name="c_uint32" type="uint32" defaultvalue="6"/>
<entry name="c_int64" type="int64" defaultvalue="-7"/>
<entry name="c_uint64" type="uint64"/>
<entry name="c_float" type="float" defaultvalue="1.23456789" version="2"/>
<entry name="c_double" type="double" defaultvalue="9.87654321" version="3" />
<entry name="c_string" type="string" size="200" version="3" />
<entry name="c_string_128K" type="string" size="VALUE_128KB_SIZE" defaultvalue="123456789"/>
<entry name="c_string_256K" type="string" size="VALUE_256KB_SIZE" defaultvalue="123456789"/>
<entry name="c_binary" type="tinyint" count="10" refer="array_count" />
<entry name="binary" type="tinyint" version="5"/>
<entry name="selector" type="short" />
<entry name="single_struct" type="struct_type"/>
<entry name="simple_struct" type="simple_struct" version="4"/>
<entry name="single_union_selector" type="int8" defaultvalue="0" />
<entry name="single_union" type="union_type" select="single_union_selector" />
<entry name="array" type="TableInfo" count="3" refer="array_count"/>
<entry name="c_union" type="union_type" select="selector"/>
<entry name="union_array" type="union_type" count="3" select="selector" refer="array_count"/>
<entry name="c_struct" type="struct_type"/>
<entry name="struct_array" type="struct_type" count="3" refer="array_count"/>
<index name="index1" column="uin"/>
<index name="index2" column="uin,name"/>
struct>
metalib>
说明:
另外,您可以使用union创建嵌套类型。
<union name="union_type" version="1">
<entry name="Id" type="int32" id="0" defaultvalue="0" desc="id" />
<entry name="Name" type="string" id="1" size="64" defaultvalue="hello" desc="name" />
union>
customattr2:
TableType:用于指定表格类型,如list或者sortlist,若不指定类型默认为generic表,且generic表无需添加customattr2属性,关于表格类型的说明请见 Generic表和List表。
ListNum:用于定义list或者sortlist表中,单个key最多可以指向多少个value值,若超过该值可指定从头部或尾部删除老元素。
SortFieldNum:用于sortlist表中,表示该表有多少个排序字段,每个排序字段需要用customattr2标识,如第一个为“sort1”,第二个“sort2”。
SortRule:用于sortlist表中,表示该表的排序方式,如DESC表示降序,INSC升序。如果有多个排序字段,按照sort的序号进行排序,序号小的字段优先级更高。比如排序是降序:sort1不同时按sort1降序;sort1相同时按sort2降序,以此类推。
<struct name="following_action_list" version="1" primarykey="game,myuin", customattr2="TableType=SORTLIST;ListNum=1023;SortFieldNum=1;SortRule=DESC">
<entry name="TimeStamp" type="uint32" desc="单位为分钟" />
<entry name="time" type="uint32" customattr2="sort1" desc="时间"/>
struct>
接下来会对示例中提到的相关属性进行详细描述。
TcaplusDB是腾讯出品的分布式NoSQL数据库,存储和调度的代码完全自研。具备缓存+落地融合架构、PB级存储、毫秒级时延、无损水平扩展和复杂数据结构等特性。同时具备丰富的生态、便捷的迁移、极低的运维成本和五个九高可用等特点。客户覆盖游戏、互联网、政务、金融、制造和物联网等领域。