典型技术问题
1. TcaplusDB表结构发生更变,后台如何做版本控制?
TcaplusDB根据表的版本号(Version No.)解决多版本兼容性问题,即TcaplusDB存储层会存储同一个表不同版本号的数据;因此gameserver或客户端进行数据读写操作时,需要指定表的版本号。
当不同客户端对同一张表进行交替写,并且客户端各自使用不同版本的表定义的时候,pb表和tdr表对于差异字段的处理方式是不同的。
假设gamesvr1: 表有abc字段
假设gamesvr2: 表有ab字段
假设tcaplusDb: 表有abc字段
对于PB表:
1、假设abc是pb表的字段, 两个svr交替写, c字段会清空。
对于TDR表:
1、假设abc是tdr表的一级字段, 两个svr交替写, c字段不会给清空。
2、假设abc是tdr表的二级字段, 两个svr交替写, c字段会清空。
2. TcaplusDB如何处理请求延时?
请求在3s内没有响应时,TcaplusDB会打印包含关键字timeout的错误日志;建议客户端请求代码中也增加超时逻辑或重试次数。
3. TcaplusDB如何保证读写请求稳定性?
TcaplusDB默认采用Master-Slave模式,Master负责用户请求的读写,Slave充当热备节点。当出现QPS突增,读写分流会自动开启,即Master承当写操作,Slave承担读操作直至后台扩容完毕。
4. TcaplusDB是否支持保存策略(retention policy)?
支持,TcaplusDB会默认保留所有数据,支持用户设定保存时间,数据过期会自动淘汰,当前工单支持。
5. TcaplusDB是否支持跨地域迁移?
支持,TcaplusDB同时支持热迁移(采用跨区热备的方式)和冷迁移,支持数据导出为Json文件,也支持MySQL数据导入TcaplusDB,当前均为工单支持。
6. TcaplusDB如何保证热数据?
TcaplusDB采用LRU缓存算法保证数据热度。
7. 对于游戏玩家数据,TcaplusDB如何存储?
一条TcaplusDB记录(Record)即为单个玩家的数据, 按照主键字段或索引进行数据操作。
8. TcaplusDB表创建后可否增加索引或修改主键?
不可以,如有修改需求请重建表。
9. TcaplusDB能否支持事务?
暂不支持,建议将相关的字段定义在同一个表里进行操作,获得类事务体验。
10. 是否会保证一个线程里的非同步请求相关应答会按照顺序处理?是否需要用syncld来进行同步处理?(以功能为主,不使用同步api的情况下)
同一个线程里,同一个key的读写操作是按照顺序处理的,即保序。不同的key的读写操作顺序不保证,如果项目组采用asyncid来标志请求和响应的映射关系,是可以的,这种是透传字段,包括asyncid、sequence、userbuff。
11. delete性能如何?是否需要update命令来替代delete?
delete就是一次普通的写操作,性能上没有问题,项目组可以随时进行delete操作。
12. 线程与并发
TcaplusDB C++ API是单线程实现且不支持多线程,一个tcaplus C++ api对象对应一个request和response,由于TcaplusDB C++ API是非线程安全的,所以不能多个线程使用同一个TcaplusDB C++ API对象。如果需要实现并发场景,推荐单个线程使用单个TcaplusDB C++ API对象。从线上运营来说,TcaplusDB C++ API实例在单个机器上保持1-2个已经足够了,一个TcaplusDB C++ API实例的qps可达到7-10万。 TcaplusDB Go API 单实例支持多协程。
13. SDK内存占用情况如何?
一个TcaplusDB API实例将占用200M左右物理内存,实例采用静态分配的方式,内存消耗主要在协议上,收包发包各自一个结构体,故需要预分配一些内存。注:不同的TcaplusDB API版本,因为支持的单条记录大小不一样,预分配的内存可能有差别。
14. Tcaplus主键可以是结构体?还是只能是基础类型?
不建议使用结构体,理论上结构体是没问题的,不过用结构体后,不便于后期用各种工具或问题定位、回档、提供key。
15. 请求读取数据报错525
一般是后端超时了,如果并发量大,可能是gameserver与tcaproxy之间通信问题,可以看下:
- tcaproxy是否正常
- TcaplusDB API版本号是否大于了接入层版本号
- tcaproxy的TCP连接数目是否超限
16. 分布式索引进行delete有支持where的方法吗?
可以采用分布式索引,读出来,再单条单条的删除。
17. 重新添加的表格组,对应表新增全局索引,回档恢复数据进去,索引都还在吗,还是会重做索引?
分布式索引是在数据插入时进行自动维护的,当我们采用数据导入方式进行时,数据会同步到全局索引去
18. 如果一个表有多个primary_key, 通过指定其中一个primary_key并删除对应的数据吗?
主键,按照delete删除。本地索引,按照deletebypartkey删除。
19. telnet ip port可以通tcapdir地址,但是连接数据库集群失败如何排查?
- telnet 9999端口
- 需确认是腾讯云环境还是普通集群环境,腾讯云需要连客户自己的vip+9999端口,普通集群连真实dirip+9999端口
- 因为一个集群有多个dir,最好拿到api连接日志,看连哪个dir失败,或者连上dir了但proxy版本比api版本高导致失败
20. Tcaplus是否支持单个app下不同的zone能采用不同的协议
Tcaplus支持单个app下不同的zone能采用不同的协议,即zone1为PB协议,zone2为TDR协议
21. 表重建或删除再新建会影响缓存的配置吗?
重建可以保留,删除再新增,缓写就没有了,删表的时候就会删除缓写。
22. 增加列需要重建表格吗?
增加列只用执行在线变更就行。
22. 表结构里的count扩大是否需要重建表?
不需要,可以直接修改,并且不用加版本号,count只能改大不能改小。
23. 删除某一张表或者删除表中的某一行,需要变更tables.xml的版本号吗?
是已经存在的表是不可以删除字段,只能追加字段,如果需要删除字段需要整表删除然后重建。
24.业务侧扩大blob的长度,是否可以支持业务侧无感的动态调整?
可以的,count定义了refer,count值可以修改大,且不需要增加版本号。
25. 表变更修改了一级字段之后是否需要更新缓写呢?
如果这些字段不需要配置缓写,那么就不用动,如果需要配置则要更新下缓写配置。
26. Redis替代场景
26.1 TcaplusDB是否能代替redis的pub/sub功能?
目前TcaplusDB没有pub/sub功能,可以采用list表来模拟实现,类似进程A去list表写数据,进程B从list表读数据这种,会增加代码改造成本。
26.2 是否支持redis的expired(自动到期功能)?
目前TcaplusDB支持数据淘汰,比如账号表设置了30天淘汰,那么会淘汰掉30天内没有任何写操作的数据,是物理删除,即该功能是支持的。
26.3 TcaplusDB Client有setttl,想问下是否还支持api?
单条记录设置setttl,是TcaplusDB API 支持的,但是项目组的使用场景可以设置成全表数据淘汰,即单个表上亿条记录,淘汰标准是1个,比如按照30天内没有任何写操作来淘汰。
26.4 是否可以使用tcaplus的list table来代替redis的stored set功能?
如果是TopN,采用list表即可完成,即该功能是支持的。
26.5 是否有像redis的pipeline之类的,用一次请求(request)就能处理多个query? 比如,有10个query的话,用1个请求就能处理10个query。
TcaplusDB提供了批量操作来满足类似场景的需求,具体可参考SDK:https://github.com/tencentyun/tcaplusdb-go-sdk/blob/v0.0.10/tdr/request/batchget_req.go
27. List表index的增长规则
- idx从0开始
- idx按照步长1从0开始自增,直到自增到int类型的最大值,然后会选择一个空闲的idx使用,即不管什么情况下,正在使用的idx不会重复
如果key删除,idx从0开始,也可以保持从上次idx开始 默认从0开始,也可以通过SetFlags设置从上次idx开始
/*TCAPLUS_FLAG_LIST_RESERVE_INDEX_HAVING_NO_ELEMENTS * 设置此标志后,List表删除最后一个元素时需要保留index和version。 * ListDelete ListDeleteBatch ListDeleteAll操作在删除list表最后一个元素时, * 设置此标志在写入新的List记录时,版本号依次增长,不会被重置为1。 * * 适用场景: * 业务需要确定某个表在删除最后一个元素时是否需要保留index和version * 主要涉及List表的使用体验 * */ int SetFlags(int32_t flag);
index是不连续的,只会增加比如:1 2 3 4 5 删除了3变成了 1 2 4 5 ,如果AddRecord(2)就变成了 1 2 6 4 5
如果key下的 list元素都被删除,等同于key也被删除
- listaddafter支持队头删除,队尾插入;或者队头插入,队尾删除
- listdelete,删除idx
- TCAPLUS_API_LIST_PRE_FIRST_INDEX:新元素插入在第一个元素之前 TCAPLUS_API_LIST_LAST_INDEX:新元素插入在最后一个元素之后
28. increase相关接口的上限问题,假如当前值是97,这时候increase5同时上限设置为100会增加成功一部分吗?
不会更新成功,会返回SVR_ERR_FAIL_OUT_OF_USER_DEF_RANGE 错误码
29. tcaplus对表进行insert操作,如果先后2次insert操作的主键相同,第二次是覆盖第一次,还是第二次操作失败?
第二次会报-1293 SVR_ERR_FAIL_RECORD_EXIST insert的记录已存在
30. protoc文件中可以定义的类型,tcaplus都能使用吗?例如any类型
可以,但条件更新没有对any、union支持
31. go sdk 怎么设置遍历备表?
通过SetOnlyReadFromSlave接口调用设置
32. ListGetAllRequest 返回报错 SVR_ERR_FAIL_INVALID_SUBSCRIPT
按照offset和limit拉取时,传的参数不对,请检查offset和limit参数设置
33. 本地索引和分布式索引(全局索引)的创建方式
本地索引在表结构文件中定义,一旦定义无法修改删除;分布式索引在对应的控制台页面(oms或者腾讯云控制台页面)创建,可以修改重建
34. 分布式索引(全局索引)支持字符串的分词模糊搜索吗?
支持like模糊查询,还不支持分词检索
35. 表定义中的字段是否可以删除?
已存在的表不能删除字段
36. PB表的add操作,add因为数据已存在时,有没有办法返回已有数据?
可以,在int SetMessageOption(const ::google::protobuf::Message &msg, int32_t item, const std::string &option) 函数中option设置变更记录的所有字段旧数据,具体参考章节9.TcaplusDB下载中心 pb api中函数注释。
37. TcaplusDB Go SDK支持通过域名的方式连接目录服务器(Tcapdir)吗?
支持通过域名的方式连接目录服务器(Tcapdir)。
38. TcaplusDB的list结构,有接口只查询list内元素数量吗?
目前不能查询一个list的size大小
39. Tcaplus list表元素满时默认的淘汰方式是哪种?
有三种淘汰方式,默认TCAPLUS_LIST_SHIFT_HEAD 移除最前面的元素。
- TCAPLUS_LIST_SHIFT_NONE: 不允许删除元素,若LIST满,插入失败;
- TCAPLUS_LIST_SHIFT_HEAD: 移除最前面的元素;
- TCAPLUS_LIST_SHIFT_TAIL: 移除最后面的元素
sortlist表不支持业务指定淘汰方式,对于SortList,当用户进行ListAddAfter时,List数目超过最大元素个数N时,对于正序(从小排到大)总是保留最小的N个元素,也就是说插入的元素比当前最大值还大时,会插入失败(因为立即被淘汰),而倒序则反之,总是保留最大的N个元素。
40. Tcaplus 单行记录的淘汰假如设置了300秒淘汰,是插入后300秒淘汰吗,这段时间怎么续租约呢?
表级别数据淘汰,是根据记录最后修改时间淘汰;即update或replace会自动续期。精确度大概为天级别。 适合场景:如保留最近30天的邮件或战斗记录。 记录级别通过setttl设置和续期, 适合对ttl时间比较精确或不同记录的淘汰时间不同的场景。 精确到毫秒。
41.一个TcaplusServer对象只能访问一个set内的不同zone
1、多个TcaplusServer对象是不是可以实现跨set访问--只能访问一个set,不能跨set;跨set可以用多个api,即多个TcaplusServer对象 2、多个TcaplusServer对象内存占用如何--每个api实际内存占用在40M左右
42.UpdateNetwork api的这个接口,内部会调用类似sleep或epoll_wait的接口吗?
UpdateNetwork是用户线程,不会sleep,通过网络线程收发包,只有网络线程会epollwait,网络线程用户不用关注
43.同时调用了 SetResultFlag(2) SetResultFlagForFail(0) 会怎样表现呢?
建议不要一起用,SetResultFlagForFail和SetResultFlagForSuccess推荐这两个函数搭配使用。如果同时用调用了 SetResultFlag(2) SetResultFlagForFail(0),会以最后一次设置为准
44.Tcaplus可以直接使用RepeatedPtrField作为表字段做存储操作吗?proto基础类型和结构类型作为基础tcaplus表字段存储方式有什么区别吗?
可以,无区别,注意结构嵌套深可能更消耗cpu。
45.咨询下Tcalpus有原子操作的api吗,是否支持事务?
所有操作单条记录的请求都是原子性的; Tcaplus有乐观锁,支持单key的事务,TCAPLUS_CMD_INCREASE_REQ自增自减操作、单key下的条件更新操作支持,其他操作不支持事务
46.FieldGet接口里面的dottedpaths 字段,如果为空,是返回所有字段呢?还是仅返回key字段,其他普通字段全部为空呢?
FieldGet是返回需要的字段,如果为空的话只有key字段,想要返回全量字段可以使用Get
47.getbypartkey情形下,业务只想获得符合条件的记录条数,可以只返回记录条数吗?
可以通过调用SetResultLimit(1) 来获取一条记录,但本次可以通过GetRecordMatchCount 来拉取总数。
48.list类型表的ListNum支持修改吗?
list类型表的ListNum支持改大,不能改小;ListNum为必填属性,一般由业务预估大小在表定义中设置;
49. 表结构里的size扩大是否需要修改字段的version?
不需要,可以直接修改,size只能改大不能改小。
50. 在不知道list表的index的情况下,有没有方式能获取到最新的n条记录?
如果本身插入就是按时间顺序addafter 的话,可以直接从尾部listgetall,SetResultLimit可以指定数量参数。或者使用sortlist表,加个时间字段,按时间排序。
51.tdr go api的 xml转go文件的工具在哪里下载转换?
https://git.woa.com/tsf4g/TdrCodeGen python tdr.py table.xml,得到相应表的go源码目录table/table.go,将table放到自己的go的工程目录即可使用
52.API访问报错:dir sign up fail, ret:-279,如何处理?
检查业务密码是否正确;检查dir地址是否正确
53.Tcaplus能否支持模糊查询,以及忽略大小写?
支持模糊查询,需要创建分布式索引查询。区分大小写
54.同一个进程里可以有多个不同的TcaplusService::TcaplusServer吗?
可以的,持有多个service api的handle,分别初始化
55.内部用户新机器部署sdk出现无法连上dir的问题,Can't find a valid dir server(注:仅限内部用户可能会遇到,腾讯云等外部用户不会产生该问题)
DNS设置问题,通过在http://scr.ied.com/#/sojob/create上重新刷dns解决
56.全局索引模糊查询咨询:
- 一张表的多个字段都建了全局索引,查询(A and B and C)的时候。会求ABC的交集再回表拉数据。还是找到满足某一个条件A的主键就回表拉数据,后面再过滤条件B,C?
- ABC的交集再回表拉数
- 对于like %str% 这种字符串查询是走全表扫描吗?还是也可以支持,比如字符串AA_BB_CC,可以索引命中AA或BB或CC?
- %str%这种基本上会走全表扫描查询了,所以不建议使用前缀模糊匹配查询;
- 对一张表的全局索引的查询,如果数据量多、查询很多导致负载高的时候是支持扩容的吗?
- 可以支持扩容的,但是扩容是需要一定的时间的,所以建议提前预估好
57.GO api中的Error()返回的是string如何获取错误码code?
GO api中的Error()的string类型返回值可以通过terror.ErrorCode强转错误码,获取error code
if err != nil {
terr,_ := err.(terror.ErrorCode)
fmt.Println(terr.Error())
}
58.请问list表,TCAPLUS_API_LIST_GETALL_REQ查询list表所有数据,返回的数据是有序的吗?
需要考虑业务侧设置的插入顺序和元素满时淘汰策略
- TCAPLUS_LIST_LAST_INDEX : 队尾插入,listgetall的时候,是按照插入顺序返回的
- TCAPLUS_LIST_PRE_FIRST_INDEX:队首插入,listgetall的时候,是按照插入顺序逆序返回的
- 当list成员满的时候,需要进行淘汰,淘汰也分为队首淘汰,或者队尾淘汰,根据业务侧的设置来淘汰
59.ttl相关的操作,是不是不支持在 insert数据的时候,同时设置ttl?
是的,需要先插入后再设置ttl
60.过期淘汰的数据是否会同步删除全局索引系统中的数据?
过期淘汰的数据会同步删除掉全局索引系统里的数据