小红书KV存储架构:万亿级数据与跨云多活不在话下( 三 )


针对以上模型 , 我们的优化思路:检查节点的状态和过去的延时选择2个节点中状态好的那个节点发送请求计算P99时延 , 超过P95时延则向另外一个节点发送一定数目的backupread请求数两个请求中任意一个请求返回成功则成功 , 如果超时则继续重试
小红书KV存储架构:万亿级数据与跨云多活不在话下
文章图片
图5Backup-read消峰
因为backupread转发不需要复制内存 , 通过索引来保证生命周期 , 而且只有超过P95时延的报文会被检查是否能发送backupread , 因此 , 只要5%的报文会发送两次 , 对集群基本不会增加压力 。 图6为一个集群中P999从35ms降低到4ms左右 , 效果非常明显 。 对比HBase同样的业务场景 , 客户端在同样的timeout的配置下 , 我们的方案提高了客户端的成功率 。
小红书KV存储架构:万亿级数据与跨云多活不在话下
文章图片
图6Backup-readP999优化对比
5)大Key检测
我们线上很多集群在业务使用过程中会偶发的产生一些毛刺 , 通过抓包发现 , 这里毛刺有很大一部分原因是因为大Key造成的 。 为了甄别这类问题 , 我们在Proxy层支持的大Key的可观测指标 。 Proxy在解析Redis的cmd可以附带统计KV的大小 。 对于string读类型的command , 读到的val值大于big-string-size判定为大key;对于写类型的command , 请求值大于big-string-size判定为大key;对于hash/zset则为一次读取的kv总数大小 。 通过增加read_size(所有读请求总共读到的字节数)和write_size(所有写请求总共写入的字节数)监控 , rate(read_size)/rate(total_req_amount)可以计算出平均请求值大小 。 大Key和热Key是KV系统不可避免的2个场景 , 针对大Key , 我们提供了Proxy层的数据压缩能力;对于热Key , 我们在Server层基于HeavyKeeper算法做了topK统计和处理 。
3、RedKVCluster
公司的存储需求场景比较多 , 如广告业务存储的标签和数据模型很多 , 同时是非常核心的业务 , 业务需要做资源隔离 。 为了减少节点故障缩小数据的爆炸半径 , 这里业务我们采用无中心管控的架构 , 即RedKV1.0架构 , 它能在部署和运维上能大大简化 。 无中心的集群架构采用的是Gossip协议 , 存储节点采用多进程多实例部署 , 如图7 。
小红书KV存储架构:万亿级数据与跨云多活不在话下
文章图片
图7Gossip管控的KVCluster
推荐模型训练的数据量非常大 , 上下游业务很多 , 承载的QPS高 , 对应集群的节点也比较多 , 在故障处理和扩缩容方面会触发gossip抖动 。 针对大集群的节点管理 , 我们采用有中心管控的架构 , 即RedKV2.0架构 。 基于Shard管理的中心架构能更好的支持数据迁移和集群扩缩容 , 存储节点采用单进程多实例部署 , 在多活场景中可以支持副本数弹性扩展 , 如图8 。 RedKV2.0的相关组件会在后续的技术文章中详细介绍 。
小红书KV存储架构:万亿级数据与跨云多活不在话下
文章图片
图8基于中心管控的KVCluster
1)Gossip优化
RedKV1.0采用Gossip协议通信 , 节点故障时主从节点的切换 , 最长影响时间为30s 。 一个节点出现故障时 , 集群中正常节点将故障节点标记为fail状态需要经过一段收敛时间 。 在这段时间内 , Proxy层有可能将用户请求转发给已经fail的节点 , 导致请求失败 。 减小集群收敛时间能有效减少Proxy层错误请求数量 , 提高集群的稳定性和可用性 。
RedKV1.0通过如下三个步骤加快视图收敛:探测时间优化
RedisGossip协议正常情况下会每隔100ms随机选取一个节点发送ping包 , 并更新节点的ping_sent值为发送ping包时间 。 如果集群很大 , 节点数很多 , 那么故障节点被ping到的概率就会变小 , 最多超过node_timeout/2时间给故障节点发送ping包 。 这样就会导致节点发生故障时 , 集群中正常节点不能第一时间ping到故障节点 , 从而无法立刻感知到故障节点发生了故障 。 为了减少这部分时间 , 当集群中有节点超过2s没有收到故障节点发送的pong报文时 , 就立马通知其他节点去ping故障节点 。 这样可以把节点故障到正常节点给故障节点发送ping的时间控制在2s左右 。 判定PFAIL时间优化