拯救爆表的MySQL:小红书万亿级存储系统自研与迁移之路( 三 )


拯救爆表的MySQL:小红书万亿级存储系统自研与迁移之路

文章插图

拯救爆表的MySQL:小红书万亿级存储系统自研与迁移之路

文章插图

拯救爆表的MySQL:小红书万亿级存储系统自研与迁移之路

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

文章插图
5、数据的一致性
作为社交图谱数据,数据的一致性至关重要 。我们需要严格保证数据的最终一致性以及一定场景下的强一致性 。为此,我们采取了以下措施:
缓存更新冲突的解决:
REDtao 为每个写入请求生成一个全局递增的唯一版本号 。在使用 MySQL 数据更新本地缓存时,需要比较版本号 , 如果版本号比缓存的数据版本低,则会拒绝此更新请求,以避免冲突 。
写后读的一致性:
Proxy 会将同一个 fromId 的点或边请求路由到同一个读 cache 节点上,以保证读取数据一致性 。
主节点异常场景:
Leader 节点收到更新请求后 , 会将更新请求变为 invalidate cache 请求异步的发送给其他 follower,以保证 follower 上的数据最终一致 。在异常情况下,如果 Leader 发送的队列已满导致 invalidate cache 请求丢失,那么会将其他的 follower cache 全部清除掉 。如果 Leader 故障 , 新选举的 Leader 也会通知其他 follower 将 cache 清除 。此外,Leader 会对访问 MySQL 的请求进行限流,从而保证即使个别分片的cache被清除掉也不会将 MySQL 打崩 。
少量强一致的请求:
由于 MySQL 的从库也提供读服务,对于少量要求强一致的读请求,客户端可以将请求染上特殊标志,REDtao 会透传该标志 , 数据库 Proxy 层会根据该标志将读请求转发到 MySQL 主库上,从而保证数据的强一致 。
6、跨云多活
跨云多活是公司的重要战略,也是 REDtao 支持的一个重要特性 。REDtao 的跨云多活架构整体如下:
拯救爆表的MySQL:小红书万亿级存储系统自研与迁移之路

文章插图
这里不同于 Facebook Tao 的跨云多活实现,Facebook Tao 的跨云多活实现如下图:
拯救爆表的MySQL:小红书万亿级存储系统自研与迁移之路

文章插图
Facebook 的方案依赖于底层的 MySQL 的主从复制都通过 DTS Replication 来做 。而 MySQL 原生的主从复制是自身功能 , DTS 服务并不包含 MySQL 的主从复制 。该方案需要对 MySQL 和 DTS 做一定的改造 。前面说到,我们的缓存和持久层是解藕的,在架构上不一样 。
因此,REDtao 的跨云多活架构是我们结合自身场景下的设计,它在不改动现有 MySQL 功能的前提下实现了跨云多活功能:
1)持久层我们通过 MySQL 原生的主从 binlog 同步将数据复制到其他云的从库上 。其他云上的写请求和少量要求强一致读将被转发到主库上 。正常的读请求将读取本区的 MySQL 数据库,满足读请求对时延的要求 。
2)缓存层的数据一致性是通过 MySQL DTS 订阅服务实现的,将 binlog 转换为 invalidate cache 请求,以清理掉本区 REDtao cache 层的 stale 数据 。由于读请求会随机读取本区的任何一个 MySQL 数据库,因此 DTS 订阅使用了一个延迟订阅的功能,保证从 binlog 同步最慢的节点中读取日志,避免 DTS 的 invalidate cache 请求和本区 read cache miss 的请求发生冲突从而导致数据不一致 。
7、云原生
REDtao 的云原生特性重点体现在弹性伸缩、支持多 AZ 和 Region 数据分布、产品可以实现在不同的云厂商间迁移等几个方面 。REDtao 在设计之初就考虑到支持弹性扩缩容、故障自动检测及恢复 。
随着 Kube.NETes 云原生技术越来越成熟,我们也在思考如何利用 k8s 的能力将部署和虚拟机解绑,进一步云原生化,方便在不同的云厂商之间部署和迁移 。REDtao 实现了一个运行在 Kubernetes 集群上的 Operator,以实现更快的部署、扩容和坏机替换 。为了让 k8s 能感知集群分片的分配并且控制同一分片下的 Pods 调度在不同宿主机上,集群分组分片分配由 k8s Operator 渲染并控制创建 DuplicateSet (小红书自研 k8s 资源对象) 。REDtao 则会创建主从并根据 Operator 渲染出来的分片信息创建集群,单个 Pod 故障重启会重新加入集群,无需重新创建整个集群 。集群升级时 , Operator 通过感知主从分配控制先从后主的顺序,按照分片分配的顺序滚动升级以减少升级期间线上影响 。


推荐阅读