zStorage 如何在多路径下保证数据一致性

注:本文内容引用自张洋老师的知乎文章 https://zhuanlan.zhihu.com/p/...,他是一位存储研发专家。

问题背景

zStorage 典型的部署拓扑结构如下图所示:采用 3 个存储节点,数据保存 3 副本,2 个或更多计算节点。存储节点用于承载 zStorage 分布式块存储系统,通过 FrontEnd(简称 FE)向外提供 NVMe-oF/iSCSI 块存储协议。计算节点用于承载计算任务,例如 Oracle、MogDB 等数据库业务。计算节点通过 NVMe-oF/iSCSI 块存储协议映射 zStorage 卷,每个卷可以使用多路径,通过不同的 FE 发起 IO 操作。

image.png

在一切正常的情况下,IO 通过路径 1 进行处理。一旦出现异常,例如路径 1 的网络故障,导致 IO 切换到路径 2 处理。这里有一个短暂的同步问题:

  • 通过路径 1 发起一个写操作 IO1,将某个位置 X 修改为:例如“111”。
  • 路径 1 故障超时,通过路径 2 重发 IO1,位置 X 成功修改为“111”。
  • 继续通过路径 2 发起 IO2,将位置 X 修改为“222”。
  • 路径 1 上的 IO1(已失效超时)重新将位置 X 修改为“111”。

以上四个步骤中,出现了失效的旧数据覆盖新数据的情况,导致数据丢失,这是一个严重的问题。该问题为本文将要讨论的主要问题:zStorage 是如何处理多路径下可能出现的数据不一致问题?

FE 引入分布式锁

FE 通过 MDS 的 CAS 语义实现分布式锁逻辑,用以保证:

  • zStorage 旧版本的锁语义:某个卷的 IO 只能在持有锁的 FE 上处理。在这种语义下,只要是同一个卷,无论是多少个计算节点下发 IO,都统一在一个 FE 上处理。锁的粒度为:卷+FE。
  • zStorage 新版本的锁语义:某个计算节点针对某个卷的 IO 只能在持有锁的 FE 上处理。在这种语义下,针对同一个卷,不同的计算节点的 IO 可以通过不同的 FE 处理。锁的粒度为:HOST+卷+FE。

对于本文要讨论的问题来说,两种语义是类似的,本文按照“zStorage 旧版本的锁语义”继续讨论。

在 zStorage 系统中,monitor 负责维护集群的状态,管理和维护节点、OSD、PG 等视图信息。

当出现异常情况,需要切换路径时,假如从路径 1 切换到路径 2。对于路径 1 的 FE 来说,有两种情况:

Image

  • 和 monitor 租约正常,通信正常,仅和 HOST 通信异常。这种情况下,该 FE 会收到路径切换通知,清理挂起的 IO,保证全部发送出去,并释放锁。
  • 和 monitor 租约异常,无法通信,或者该 FE 崩溃退出。这种情况下,由于租约超时,新路径的 FE 会自动抢占到锁。

以上两种情况,实际上还未解决前面提到的旧 IO 覆盖新 IO 的问题,只是将问题后推到了 ChunkServer(简称 CS)。后续还需要 FE 和 CS 配合,以识别出旧 IO(即:失效的 IO)。

ChunkServer 引入 IO 版本号

在 FE 和 CS 的通信协议中,增加 IO 版本号信息。在 FE 端,每当路径发生切换后,会增加 IO 版本号,以区分旧路径和新路径上的 IO。

在 CS 端如何识别出失效的 IO,以防止旧数据覆盖新数据呢?在 CS 内存中,维护了一个以“volume_id”为 key,“io_version”为值的键值哈希表。每次 IO 都将 IO 版本号与哈希表中存储的值做对比:

  • 如果比表中的大:更新表,IO 继续往下处理;
  • 如果与表中的相同:IO 继续往下处理;
  • 如果比表中的小:回复失败。

这其中又有两种情况可以细化讨论:

PG Leader 未发生切换

Image

如果 PG 的 leader 没有发生过切换,一直在同一个 CS 上,这种情况比较简单,都是同一个 CS 上做 IO 失效的检查。只需要按照上述流程保证旧版本的 IO 返回失败即可。

PG Leader 发生了切换

Image

当 old PG Leader 出现网络异常导致分区,另外两个 Follower 会重新选举一个 new PG Leader。这时候可能会短暂(选举超时时间)存在两个 Leader 的情况。但是 old Leader 会因为日志无法写入大多数副本,所以无法 commit,这个 IO 也无法返回。直到 old Leader 下台以后,返回 Not Leader 错误。当 FE 收到 Not Leader 或者 IO 超时,便会将 IO 重新发送到 new Leader 上。这之后的流程和“PG Leader 未发生切换”的情况便一致了。

总结

在 zStorage 系统中,确保多路径下的数据一致性是关键问题。通过分布式锁机制,zStorage 保证了路径切换时,IO 请求能够准确路由到持锁的 FE,避免旧数据覆盖新数据。FE 与 CS 的协作以及 CS 端的 IO 版本号机制,确保了路径切换和 PG Leader 切换时的数据一致性。

作者

扩展阅读:《企业存储技术》文章分类索引更新(微信公众号合集标签)

END

作者:“云和恩墨 zStorage 分布式存储团队” 张洋
原文:企业存储技术

推荐阅读

欢迎关注企业存储技术极术专栏,欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。
推荐阅读
关注数
5624
内容数
284
关注存储、服务器、图形工作站、AI硬件等方面技术。WeChat:490834312
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息