gameserver 如何剔除某个无效的 tcaproxy(接入层)节点?
TcaplusDB API 在这里对 tcaproxy 异常做了容灾的处理,API 剔除无效的 tcaproxy 进程的方式主要有2个:
1. API 物理上认为某个 tcaproxy 不可用,API 每隔1秒对起链接的所有的 tcaproxy 发送心跳检测包,如果某个 gameserver 在10s内没有从 tcaproxy 收到相应的心跳回包,则 API 会主动断开与 tcaproxy 的 TCP 链接, 在下个 onupdate 时主动去链接该 tcaproxy 。
2. API 逻辑上认为 tcaproxy 不可用,是每隔10s去计算下某个 tcaproxy 的请求和响应比,作为判断依据,其中 API 为某个请求包超时的阈值是3s,大于3次则认为该 tcaproxy 不可用,请求不会再发给该 tcaproxy ,在60s后发送 getmetdata 请求,如果 tcaproxy 能够正确处理 getmetadata 的请求,则 API 再次认为该 tcaproxy 可用,请求会再次发送给该 tcaproxy。
从现象上看,gameserver 在10s内发现某个 tcaproxy 不可用,则不会再向该 tcaproxy 节点发送数据了。
gameserver 是怎么选择 tcaproxy(接入层)节点的?
gameserver 本地维护了一致性的 Hash 环,凡是某个 tcaproxy(接入层)节点认证通过后即增加到 Hash 环上,如果某个 tcaproxy(接入层)节点缩容后或者由于机器异常导致 gameserver 与 tcaproxy(接入层)之间的 TCP 链接断掉后,gameserver 会从 Hash 环上摘除该 tcaproxy(接入层)节点。gameserver 根据请求里的主键计算 hash 值(如果是 batchget 请求,会随机的选择单个 tcaproxy(接入层)节点),然后在一致性 Hash 环上选择单个 tcaproxy(接入层)节点发送出去。
TcaplusDB 有压缩功能吗?
TcaplusDB 有压缩功能,采用的压缩算法是 Google snappy 压缩算法,包括协议压缩,即 gameserver <--> tcaproxy(接入层)间的请求包/响应包的压缩功能;数据压缩,即 tcapsvr(存储层)在数据存储时会压缩需要存储的数据,如果您需要节省 gameserver <--> tcaproxy 间的网络流量,推荐开启协议压缩,调用 TcaplusDB API 的函数 SetCompressSwitch,推荐您开启 tcapsvr(存储层)压缩,节省磁盘空间、提高 IO 磁盘性能的同时压缩、解压缩耗费的 CPU 也是可控的问题。
TcaplusDB API 是线程安全的吗?
TcaplusDB API 是非线程安全的,主要是 tlog、tdr 等组件是非线程安全的,推荐单个线程采用单个 API 对象,单个游戏区采用单个 API 对象,如果需要跨游戏区交互,建议单个 gameserver 维护多个 API 对象。
tcaproxy(接入层)的容灾是怎么做的?
tcaproxy(接入层)采用对等设计方案,即单个游戏区下面的所有 tcaproxy(接入层)节点都包含了单个游戏区下所有表的路由信息,如果某个 tcaproxy(接入层)故障后,只要其余的 tcaproxy(接入层)节点不会过载,则 gameserver 会剔除异常的 tcaproxy(接入层)节点,不会影响 gameserver 的使用,tcaproxy(接入层)没有单点的风险。
tcapsvr(存储层)的容灾是怎么做的?
tcapsvr(存储层)采用一主(tcapsvr master)一从(tcapsvr slave)的模式运行,tcapsvr master/slave 实时的在同步数据,采用同城异 IDC 部署,确保主从同步时延小于10ms,如果 tcapsvr slave 异常,不会影响 gameserver 的使用(没有开启读分流, gameserver 的请求是 tcapsvr master 处理,如果开启读分流后,tcapsvr slave 会协助处理部分读请求),DBA 进行 tcapsvr slave 重建即可;如果 tcapsvr master 异常,则 tcapsvr slave 会进行故障恢复,DBA 再申请新的机器的 tcapsvr slave 重建即可,tcapsvr(存储层)没有单点的风险。
TcaplusDB 有过载保护吗?
接入层、存储层都有进程级的过载保护措施,保障业务高峰时服务不雪崩。
TcaplusDB 的冷热数据交换原理是什么?
TcaplusDB 采用内存 + SSD 盘存储,单个引擎文件,前1GB映射在内存,热数据尽量放在内存,冷数据放在磁盘,采用 LRU 算法进行冷热数据交换,gameserver 的 get 操作触发 LRU 换入操作,tcapsvr(存储层)的 LRU 线程负责 LRU 换出操作,尽量保证热数据存储在内存里,确保 cache 命中率高、单次读写延时低。
tcaproxy(接入层)是怎么选择 tcapsvr(存储层)的?
每个表定义的有分表因子,如果没有定义分表,分表因子则默认是主键,tcaproxy(接入层)根据 hash(分表因子)%1w,选择对应的 tcapsvr(存储层),故分表因子离散度要高。
TcaplusDB 锁的级别是什么?
TcaplusDB 锁的粒度是记录级别。
如果 shard 数目过大、过小会对 Tcaplus 的增删改查性能、引擎调优这些有影响吗?
影响可以忽略不计,线上大表都至少分几百个 shard。
业务的 shard 数量会考虑一些什么因素?
一般考虑: 每个 shard 有1G在内存里,其中约500MB存 Key,300MB存 Value,尽可能多的 Key 在内存里可以提升性能,增加 shard 单 shard 最大256G,文件太大也影响一些恢复操作。
Tcaplus 高频读数据有没有穿透的问题呢?
Tcaplus 有过载保护,穿透导致服务过载时,在接入层就会拒绝部分请求了。
如果瞬间涌入大量请求的话,tcaproxy 和 tcapsvr 会有排队机制吗?
会有排队机制,超过处理能力会大时延、超时等。Tcaproxy 的话,跟请求连接数有关,会按连接分散到 proxy 处理;Tcapsvr 的话,跟请求数据是否分散有关,集中在少数 shard 或 key 的话,会有排队。
遍历原理
Tcaplus 支持全表遍历操作,包括 generic 表和 list 表,会根据 sharding 逻辑在各个该表分布的 tcapsvr 上发起遍历任务,因此,整个遍历请求性能相对较低,建议设置从 tcapsvr slave 上遍历数据(从 tcapsvr slave 上遍历数据,不会影响 tcapsvr master 对外提供服务),即接口:SetOnlyReadFromSlave(bool flag)。
如果每次要拉取的数据不多,可以优先考虑本地索引能否满足需求。
遍历器一旦开始以后,Tcaplus 的 tcapsvr 会启动内部迭代器分时间片去遍历读取树上的节点数据,先找 key 后找 value,然后将遍历到的数据打包到 buffer 里面,返回给 service api,service api 内部的遍历逻辑会根据预期 seq 与收到的 seq 是否一致,来判断是否丢包、收到重复的包等,一旦确认收到的包符合预期,则主线程调用 RecvResponse 时可以拿到完整包,然后调用 FetchRecord 可以解析到一条业务记录,遍历可以随时中断和终止,可以有条件的恢复。整体而言,遍历在 service api 内部采用的是 ping-pong 自动触发机制,在收到符合预期的包以后会自动决定是否要继续发起下一个遍历请求(例如后端存储 svr 明确返回了 BUSY 的错误,则遍历会中断),一直到明确遍历完成或业务停止遍历。