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


Gossip协议现有实现方式是超过node_timeout(通常为15s)时间没有收到pong报文 , 就将节点状态置为pfail 。 本次优化将这个时间设置为3s(可配置) , 如果24小时内(可配置)首次超过3s没有收到pong报文 , 就将节点置为pfail状态 。 如果24小时内频繁出现 , 那可能是网络抖动造成 , 还走原来的路径等待node_timeout 。 减少PFAIL到FAIL的判定时间
只有一个节点收到集群1/2的节点的PFAIL信息的时候 , 才会将故障节点判定为FAIL状态 。 而PFAIL这个信息是通过Gossip协议交互的 , 最久需要1/2node_timeout才会通知到其他节点 。 因此为了加速PFAIL到FAIL的状态 , 所有的节点按照统一的规则选出一个种子节点 , PFAIL信息除了随机发送一个节点意外 , 还会通知这个种子节点 。 这样种子节点能在最快的时间学习到集群所有节点的PFAIL信息 , 从而将故障节点标记为FAIL状态广播到集群 。
2)RedKVServer
RedKVServer配置多个IO线程同时监听一个端口来接受连接请求 , 每个线程上的连接数目会随机均衡 。 每个线程只解析自己连接上的请求 , 并将解析出的报文通过key挂到对应的请求队列上 , 每个队列由一个Worker线程处理 。 这样同一个key/同一个slot上的请求都会落到同一根Worker线程上处理 , 避免了对key进行加锁 , 减少锁冲突和线程切换 。 Worker线程中会对数据进行重编码 , 存储到Rocksdb本地存储引擎 。
RedKV内部的线程模型如下图9:
小红书KV存储架构:万亿级数据与跨云多活不在话下
文章图片
图9RedKVServer无锁线程模型
3)数据存储
RedKV当前支持的数据类型有string、hash和zset , 数据节点选择RocksDB作为本地存储引擎 , 集群创建时支持配置多副本 , 主从节点离散部署 。 采用hash打散的方式存储连续slot分片的数据 , 能比较好地避免热点key问题 。 不同的数据类型包含(MetaKey,MetaValue)和(DataKey,DataValue),设计格式如下:MetaKey
小红书KV存储架构:万亿级数据与跨云多活不在话下
文章图片
MetaValue
小红书KV存储架构:万亿级数据与跨云多活不在话下
文章图片
小红书KV存储架构:万亿级数据与跨云多活不在话下】DataKey
小红书KV存储架构:万亿级数据与跨云多活不在话下
文章图片
DataValue
小红书KV存储架构:万亿级数据与跨云多活不在话下
文章图片
在如上的编码方式下 , key的设计中保留的slot信息 , 可以在扩缩容的场景中通过slot灵活地做数据迁移 。
四、生态功能
1、数据复制
与传统解决方案引入同步组件的方式不同 , 我们快速实现了单向数据同步以及集群扩容需求 , 整体架构去除了对第三方组件的依赖 , 通过扩展Redis复制协议实现了RedKV数据节点的直接复制 , 如图10 。 单向复制的限制是扩容需要基于2n做节点同步 , 扩容完成后后台任务根据3.3.3中定义的key的分片删除不是本节点的数据 。
在多活的部署形态下 , 多云集群的一对多的数据复制采用单向复制对主集群性能侵入较大 , 因此我们实现了基于中心管控的数据复制策略 。 该策略支持多个集群的分片异构部署 , 通过Checkpoint方式定向同步数据 , 不再需要额外的后台任务去做数据淘汰 , 能很好的支持多对多的多云集群数据复制、数据破环和扩缩容 。
小红书KV存储架构:万亿级数据与跨云多活不在话下
文章图片
图10RedKV的数据复制
2、数据批量导入
小红书大量的离线业务数据存储在S3Hive中 , 每天会有部分数据需要增量更新 , 其他的数据会被淘汰 。 这类场景有几个挑战: