PB表

PB表是指通过PB(Protobuf)协议定义和访问的数据表。

除PB表之外,TcaplusDB同时还提供了TDR表

PB表与TDR表并无本质区别,用户可以根据自己对PB或TDR的熟悉程度,来决定使用PB表还是TDR表。需要注意的是当前TcaplusDB的PB表和TDR表支持的功能范围有些差异(详情见TcaplusDB是什么-2.3. 表 章节介绍),用户在选择使用体种表类型的时候,也需要考虑功能是否能满足业务需求。

1. 关于Protobuf

Protobuf是Google开发的一种描述性语言,针对结构化数据进行序列化,同时强调简单性和性能。

官方文档:https://developers.google.com/protocol-buffers

2. PB表定义文件示例

以下是protobuf表game_players.proto的示例,您可以将文件上传到控制台并创建该表。

syntax = "proto3";         // 指定protobuf语言版本,proto3.

// 导入TcaplusDB公共定义服务 
import "tcaplusservice.optionv1.proto";

message game_players {  // 定义TcaplusDB表,包含message类型

// 基于选择项tcaplusservice.tcaplus_primary_key创建主键字段
// TcaplusDB单个表最多能指定8个主键字段(3.37.0及其之后版本)
    option(tcaplusservice.tcaplus_primary_key) = "player_id, player_name, player_email";
    option(tcaplusservice.tcaplus_sharding_key) = "player_id";

    // 基于选择项tcaplusservice.tcaplus_index创建主键索引
    option(tcaplusservice.tcaplus_index) = "index_1(player_id, player_name)";
    option(tcaplusservice.tcaplus_index) = "index_2(player_id, player_email)";

    // TcaplusDB支持的数值类型:
    // int32, int64, uint32, uint64, sint32, sint64, bool, fixed64, sfixed64, double, fixed32, sfixed32, float, string, bytes
    // 嵌套类型: message

    // 主键字段
    int64 player_id = 1; 
    string player_name = 2;
    string player_email = 3;

    // 普通(非主键) 字段
    int32 game_server_id = 4;
    repeated string login_timestamp = 5;
    repeated string logout_timestamp = 6;
    bool is_online = 7;

    payment pay = 8;
}

message payment {

int64 pay_id = 1;
uint64 amount = 2;
int64 method = 3;

}

3. PB表定义文件说明

3.1. TcaplusDB相关属性

TcaplusDB 表定义可以在 protobuf 语法基础上通过 option 进行扩展,可以实现更丰富的语义功能,可定义的内容如下表所示。

详细的定义格式为:option(tcaplusservice.选项) = "值";

选项名称 功能说明 设置示例 必填
tcaplus_primary_key 设置 TcaplusDB 表主键字段 option(tcaplusservice.tcaplus_primary_key) = "uin,name,region";
tcaplus_index 设置 TcaplusDB 表索引键字段 option(tcaplusservice.tcaplus_index) = "index_1(uin,region)";
tcaplus_sharding_key 用户可以自定义表分片键。默认不需要设置,当定义了有效索引(tcaplus_index)时才需要设置,而且索引必须包含分片键字段。若未定义分片键,所有本地索引的交集字段为分片键即splittablekey option(tcaplusservice.tcaplus_sharding_key) = "uin";
tcaplus_field_cipher_suite 如需使用字段加密功能,请参考设置示例进行设置;如果用户需要指定自己的加密算法,请参考 API 中的例子 option(tcaplusservice.tcaplus_field_cipher_suite) = "DefaultAesCipherSuite";
tcaplus_cipher_md5 如需使用字段加密功能,需要设置用户侧保存加密密码字符串的 MD5 option(tcaplusservice.tcaplus_cipher_md5)= "62fee3b53619b7f303c939964c6f2c4b";

3.1.1 tcaplus_primary_key(主键 )

tcaplus_primary_key属性指明此元素对应数据库表的主键,如果有多个成员组成表的主键,则成员名之间用逗号(',')隔开,单个表最多能指定8个主键字段。

约束:

  1. 作为主键的成员不能为复合数据类型,只能是基本内置数据类型。

  2. 作为主键的成员其取值不能为NULL。

  3. TcaplusDB会把所有的主键字段序列化打包到一个buffer,最大长度限制为1022字节。

option(tcaplusservice.tcaplus_primary_key) = "player_id, player_name, player_email";

根据上面的描述,game_players表使用player_id, player_name, player_email三个成员作为主键。

3.1.2. tcaplus_sharding_key(分表属性/分表因子)

如何选择分表因子

tcaplus_sharding_key属性用户可以自定义表分片键。

约束:

作为此成员不能为复合数据类型,只能是基本内置数据类型。

option(tcaplusservice.tcaplus_sharding_key) = "player_id";

3.1.3. tcaplus_index(本地索引)

tcaplus_index属性用于设置TcaplusDB 表索引键字段。

option(tcaplusservice.tcaplus_index) = "player_email";

3.2. 文件定义信息

文件定义信息区域主要定义当前表描述文件的公共信息,主要涉及如下3种类型的内容:

选项名称 功能说明 值示例 必填
syntax 指明当前文件书写的语法规范版本。 支持 proto2、proto3
package 指明当前文件自定义包名,包名可以避免对 message 类型之间的名字冲突。 包名信息
import 引入 TcaplusDB 表的一些公共信息,必须在您的表定义中被引用。 tcaplusservice.optionv1.proto

3.3. 表定义信息

表定义信息主要通过 message 定义表的格式,在 message 中可对表的扩展信息进行定义,也可以对表的字段信息进行定义。

3.4. 字段定义信息

TcaplusDB 定义字段的格式为:字段修饰符 字段类型 字段名称 = 标识号[特殊定义]; PB表中必须至少定义一个value字段

3.4.1. 字段修饰符

proto2 支持3种类型的限定修饰符,proto3 不再支持 required 修饰,默认为 optional 类型。

  • required:表示字段为必填字段,proto2 中主键字段必须被 required 修饰。

  • optional:表示此字段为可选字段,支持设定字段的默认值。

  • repeated:表示该字段可以包含0 - N个元素,其特性和 optional 一样,但是每一次可以包含多个值,可看作是在传递一个数组的值, 对于标量类型(如整型和浮点型)建议使用 [packed = true] 修饰,而非标量类型(string和message等)不能使用[packed = true],这是proto2的特性。

3.4.2. 字段类型

TcaplusDB 支持普通字段以及嵌套型字段,详细的字段介绍见下表。

proto3数据类型与编程语言类型映射

.proto 类型 C++ 类型 Java 类型 Python 类型 Go 类型 Ruby 类型 C# 类型 PHP 类型 Dart 类型 描述
double double double float float64 Float double float double
float float float float float32 Float float float double
int32 int32 int int int32 Fixnum 或 Bignum (根据需要) int integer int 使用可变长度编码。 负数编码效率低下–如果您的字段可能具有负值,请改用sint32。
int64 int64 long int/long int64 Bignum long integer/string Int64 使用可变长度编码。 负数编码效率低下–如果您的字段可能具有负值,请改用sint64。
uint32 uint32 int int/long uint32 Fixnum 或 Bignum (根据需要) uint integer int 使用可变长度编码。
uint64 uint64 long int/long uint64 Bignum ulong integer/string Int64 使用可变长度编码。
sint32 int32 int int int32 Fixnum 或 Bignum (根据需要) int integer int 使用可变长度编码。
sint64 int64 long int/long int64 Bignum long integer/string Int64 使用可变长度编码。 有符号的int值。 与常规int32相比,它们更有效地编码负数。
fixed32 uint32 int int/long uint32 Fixnum 或 Bignum (根据需要) uint integer int 始终为四个字节。 如果值通常大于2^28^,则比uint32更有效。
fixed64 uint64 long int/long uint64 Bignum ulong integer/string Int64 始终为八个字节。如果值通常大于2^56^,则比uint64更有效。
sfixed32 int32 int int int32 Fixnum 或 Bignum (根据需要) int integer int 始终为四个字节。
sfixed64 int64 long int/long int64 Bignum long integer/string Int64 始终为八个字节。
bool bool boolean bool bool TrueClass/FalseClass bool boolean bool
string string String str/unicode string String (UTF-8) string string String 字符串必须始终包含UTF-8编码或7位ASCII文本。
bytes string ByteString str []byte String (ASCII-8BIT) ByteString string 可以包含不超过2^32^个任意字节序列。

参考链接:https://developers.google.com/protocol-buffers/docs/proto3

proto2数据类型与编程语言类型映射

.proto 类型 C++ 类型 Java 类型 Python 类型 Go 类型 描述
double double double float *float64
float float float float *float32
int32 int32 int int *int32 使用可变长度编码。负数编码效率低下–如果您的字段可能具有负值,请改用sint32。
int64 int64 long int/long *int64 使用可变长度编码。负数编码效率低下–如果您的字段可能具有负值,请改用sint64。
uint32 uint32 int int/long *uint32 使用可变长度编码。
uint64 uint64 long int/long *uint64 使用可变长度编码。
sint32 int32 int int *int32 使用可变长度编码。有符号的int值。与常规int32相比,它们更有效地编码负数。
sint64 int64 long int/long *int64 使用可变长度编码。有符号的int值。与常规int64相比,它们更有效地编码负数。
fixed32 uint32 int int/long *uint32 始终为四个字节。如果值通常大于228,则比uint32更有效。
fixed64 uint64 long int/long *uint64 始终为八个字节。如果值通常大于256,则比uint64更有效。
sfixed32 int32 int int *int32 始终为四个字节。
sfixed64 int64 long int/long *int64 始终为八个字节。
bool bool boolean bool *bool
string string String unicode (Python 2) 或 str (Python 3) *string 字符串必须始终包含UTF-8编码或7位ASCII文本。
bytes string ByteString bytes []byte 可以包含任意字节序列。

参考链接:https://developers.google.com/protocol-buffers/docs/proto

3.4.3. 字段名称

针对当前属性而进行对字段进行命名,支持大小写字母,数字与下划线。建议字段的命名采用驼峰式命名方式,不能以数字开头。

3.4.4. 标识号

标识号使用范围:[1,2^29 - 1],不可使用 [19000-19999] 标识号,因为 Protobuf 协议实现中对这些标识号进行了预留,若使用,则会报错。

每个字段在进行编码时都会占用内存,而占用内存大小取决于标识号:

  • 范围 [1,15] 标识号的字段在编码时占用1个字节。

  • 范围 [16,2047] 标识号的字段在编码时占用2个字节。

3.4.5. 特殊定义

  • 当 repeated 修饰的字段需要指定 packed=true 选项。用法如下:

    repeated int64 lockid = 6 [packed = true];
    
  • 使用 optional 修饰的字段可以通过 default = 1 指定其默认值(pb3不支持默认值)。用法如下:

    optional int32 logintime = 5 [default = 1];
    
  • 字段类型为 string 和 bytes 类型的字段可以指定为加密字段。用法如下:

    required string name = 2[(tcaplusservice.tcaplus_crypto) = true];
    

3.4.6. 嵌套类型信息

TcaplusDB 支持嵌套类型,嵌套类型可以包含另一个嵌套类型作为其字段,也可以在嵌套类型内定义一个新的嵌套类型。

嵌套类型的定义与表的定义相似,均是通过 message 进行声明,但是结构体中不能包含扩展信息定义,如"主键","索引"等定义。

TcaplusDB 支持最多32层连续嵌套,但是不建议大量使用嵌套,嵌套层数过多会导致数据访问性能降低。

message game_players {  
    option(tcaplusservice.tcaplus_primary_key) = "player_id, player_name, player_email";
    int64 player_id = 1; 
    string player_name = 2;
    string player_email = 3;
    int32 game_server_id = 4;
    repeated string login_timestamp = 5;
    repeated string logout_timestamp = 6;
    bool is_online = 7;
    payment pay = 8;
}

message payment {
int64 pay_id = 1;
uint64 amount = 2;
int64 method = 3;
}

4. PB表修改限制

  1. 主键字段不能删除。

  2. 主键字段名和字段类型不能改变。

  3. 不能增加主键字段。

  4. 对于非主键字段,required字段不可以删除,但optional字段可以删除。

  5. 同标识号的字段名称和字段类型不能改变。字段的标识号不可变更。也就是说字段的标识号+名称+类型一旦定义不可修改,只能删除。

  6. 增加的普通字段名要符合命名规则, 不能修改原有字段类型、名称及字段标号。

  7. 本地索引不能新增,删除和修改,必须在建表就定义好

4.1. 示例1:增加字段

syntax = "proto3";         

import "tcaplusservice.optionv1.proto";

message game_players {  

    option(tcaplusservice.tcaplus_primary_key) = "player_id, player_name, player_email";
    option(tcaplusservice.tcaplus_index) = "index_1(player_id, player_name)";
    option(tcaplusservice.tcaplus_index) = "index_2(player_id, player_email)";

    int64 player_id = 1; 
    string player_name = 2;
    string player_email = 3;

    int32 game_server_id = 4;
    repeated string login_timestamp = 5;
    repeated string logout_timestamp = 6;
    bool is_online = 7;

    payment pay = 8;

    string player_email_copy = 9; // 增加value字段
}

message payment {

int64 pay_id = 1;
uint64 amount = 2;
int64 method = 3;

}

results matching ""

    No results matching ""