专栏名称: 企业存储技术
企业存储、服务器、SSD、灾备等领域技术分享,交流 | @唐僧_huangliang (新浪微博 )
目录
相关文章推荐
51好读  ›  专栏  ›  企业存储技术

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

企业存储技术  · 公众号  ·  · 2025-03-05 07:40

正文

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

问题背景

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

在一切正常的情况下,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来说,有两种情况:

  • 和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版本号与哈希表中存储的值做对比:







请到「今天看啥」查看全文