小红书如何应对万亿级社交网络关系挑战?图存储系统 REDtao 来了!( 二 )


写流程:客户端将写请求发送给 router,和读流程一样,会转发到对应的 Follower 节点上 。Follower 节点会转发写请求给 Leader 节点,Leader 节点转发给 MySQL,当 MySQL 返回写入成功后,Leader 会清除本地图缓存对应的 Key,并同步给其他所有 Follower 清除掉该 Key,保证数据的最终一致性 。
3.2 高可用REDtao 分为独立的两层:缓存层和持久层 。每一层都保证高可用性 。
自研的分布式缓存:
我们自研了实现图语义的分布式 cache 集群,支持故障自动检测和恢复、水平扩缩容 。
它是一个双层 cache,每个分片都有一个 Leader 和若干个 Follower 。所有的请求都先发给外层的 Follower,再由 Follower 转发给 Leader 。这样的好处是读压力大的时候只需要水平扩展 Follower,单点 Leader 写入的方式也降低了复杂度,更容易实现数据的一致性 。
如果一个副本故障,系统会在秒级别内进行切换 。当持久层发生故障时,分布式缓存层仍然可以对外提供读取服务 。
高可用的MySQL集群:
MySQL 集群通过自研的中间件实现了分库分表方案,并支持 MySQL 的水平扩容 。每个 MySQL 数据库有若干从库,并且与公司内部其他的 MySQL 运维方案一致,保证高可用性 。
限流保护功能:
为防止缓存击穿导致 MySQL 突发大量请求,从而导致 MySQL 宕机,我们通过限制每个主节点最大 MySQL 并发请求数来实现限流保护 MySQL 。达到最大并发请求限制之后的请求会被挂起等待,直到已有请求被处理返回,或者达到等待超时请求被拒绝不会被继续请求到 MySQL。限流阈值在线可调,根据 MySQL 集群规模调整对应限制 。
为防止爬虫或者作弊用户频繁刷同一条数据,我们利用 REDtaoQueue 顺序执行对写入或者点查同一条边的请求,队列长度会被限制,控制同一时间大量相同的请求执行 。相比于单个全局的队列控制所有请求的方式,基于每个请求的队列可以很好地限制单个同一请求,而不影响其他正常请求 。
3.3 极致性能数据结构的设计是 REDtao 高性能的重要保证 。我们采用了三层嵌套 HashTable 的设计, 通过根据某个起点 from_id 从第一级 HashTable 中查找到 REDtaoGraph,记录了所有 type 下对应的所有的出边信息 。接着,在第二级 HashTable 中,根据某个 type_id 查找到 AssocType 对应某个 type 下边所有出边的计数、索引以及其他元数据 。最终在最后一级 HashTable,通过 AssocType 的某个 to_id 查找到最终边信息 。我们记录了创建时间、更新时间、版本、数据以及 REDtaoQueue,time_index 则对应根据创建时间排序列表 。最后一级 HashTable 以及索引限制存储最新的 1000 个边信息,以限制超级点占据过多内存,同时集中提高最新热数据的查询命中率以及效率 。REDtaoQueue 用于排队当前某个关系的读写,只记录了当前最后一个请求的元数据 。每次查询或写入时,首先查询 REDtaoAssoc,若缓存不存在,则会首先创建只包含 REDtaoQueue 的对象;若缓存已存在,则会更新队列元数据,将自己设置为队列的最后一个请求,并挂起等待被执行 。

小红书如何应对万亿级社交网络关系挑战?图存储系统 REDtao 来了!

文章插图
图片
通过这种多层 hash+ 跳表的设计,我们能高效地组织点、边、索引、时间序链表之间的关系 。内存的申请、释放在同一个线程上完成 。
在线上环境中,我们的系统可以在一台 16 核的云厂商虚拟机上跑到 150w 查询请求/s,同时 CPU 利用率仅有 22.5%。下方是线上集群的一个监控图,单机的 QPS 到达 3w,每个 RPC 请求聚合了 50 个查询 。
小红书如何应对万亿级社交网络关系挑战?图存储系统 REDtao 来了!

文章插图
图片
小红书如何应对万亿级社交网络关系挑战?图存储系统 REDtao 来了!

文章插图
图片
小红书如何应对万亿级社交网络关系挑战?图存储系统 REDtao 来了!

文章插图
图片
3.4 易用性丰富的图语义 API :
我们在 REDtao 中封装了 25 个图语义的 API 给业务方使用,满足了业务方的增删改查的需求 。业务方无需自行编写 SQL 语句即可实现相应操作,使用方式更加简单和收敛 。
统一的访问 URL :
由于社区后端数据太大,我们按照不同的服务和优先级拆分成了几个 REDtao 集群 。为了让业务方不感知后端的集群拆分逻辑,我们实现了统一的接入层 。不同的业务方只需使用同一个服务 URL,通过 SDK 将请求发送到接入层 。接入层会接收到不同业务方的图语义的请求,并根据边的类型路由到不同的 REDtao 集群 。它通过订阅配置中心,能够实时感知到边的路由关系,从而实现统一的访问 URL,方便业务方使用 。


推荐阅读