socc 19 echash 部分代码讲解 三 chunk,stripe,hashnode
一、概念与结构关系
1. chunk
- 一个 chunk 是 实际数据写入的最小单元,通常大小是固定的(例如 4KB)。
- 每个 chunk 是存储在某个具体 memcached 节点上的一块内存区域。
- 每个 chunk 中存储多个
<key, value>
对,也就是多个对象。 - 状态通过
enum chunk_stat
管理,如Waitting
,Sealed
,Sealed_repair
等。
2. stripe
- 一个 stripe 是纠删码单位,表示一组 chunk 的集合。
- 通常表示为一个
(N, K)
编码的结构,例如RS(5, 3)
表示:每个 stripe 包含 3 个数据 chunk 和 2 个校验 chunk。 stripe
中的每个 chunk 分布在不同的hash ring
上。stripe_list
记录所有 stripe 的分布信息,每个条目是struct chunk_info_st stripe_list[][RING_SIZE]
。
3. hash_node
hash_node
是一个记录对象索引的哈希结构,用来建立 key 到其存储位置的映射。key
是字符串形式的对象标识;value
是 64 位压缩信息:包括所在 chunk ID、在 chunk 中的位置、value 长度、key 长度;- 用于快速查找 key 存在的位置,并辅助后续的读取或删除操作。
二、数据写入/读取流程(带纠删码)
📥 写入流程(key-value)
步骤一:选择 ring 和 chunk
- 使用一致性哈希对 key 进行哈希,选出目标 ring;
- 在该 ring 的
chunk_waitting_list
中查找空闲 chunk(或新建); - 将 key/value 写入 chunk 内部缓冲区,并更新 chunk 的
chunk_used_size
、KV_num
等。
步骤二:更新索引结构
- 使用
create_value()
生成压缩的 value 元信息(包含 chunk_id、偏移、长度等); - 使用
hash_node
将 key-value 映射关系插入hash_table
中。
步骤三:达到 seal 条件后编码
- 当某个 chunk 满足
chunk_used_size > CHUNK_SEALED_FACTOR * CHUNK_SIZE
,则该 chunk 进入 Sealed 状态; - 收集该 stripe 的 K 个数据 chunk;
- 使用 Reed-Solomon 算法生成 N-K 个校验 chunk,形成完整的 stripe;
- 每个 chunk 分布到不同的 ring 中,更新
stripe_list
。
📤 读取流程
步骤一:查找索引
- 用 key 计算哈希,查找
hash_table
; - 若找到
hash_node
,读取 value,解析出 chunk ID、偏移、长度等信息。
步骤二:定位并访问 memcached 节点
- 根据 chunk_id 找到其所在 ring 和 memcached 节点;
- 使用 memcached API 拉取该 chunk 的指定位置内容;
- 返回完整的 value 数据。
🛠 恢复与修复流程(故障容错)
- 某个 chunk 或节点失效时,只要 K 个 chunk 中任意 K 个可用,就可通过纠删码恢复缺失数据;
- 利用
stripe_list
定位 stripe 内其他 chunk; - 对其他 chunk 拉取数据后使用解码逻辑恢复出丢失部分;
- 重新写入新的节点,更新
hash_table
。
三、三者的关系总结
元素 | 内容 | 关系 |
---|---|---|
chunk | 存储 key-value 的基本单元 | 多个 chunk 组成一个 stripe |
stripe | 纠删码单位(N 个 chunk) | 包括 K 个数据块和 N-K 个校验块,分布在不同 ring 上 |
hash_node | key -> chunk+offset 的索引 | key 写入 chunk 后,用 hash_node 保存位置信息 |
一个 key 写入过程就是:
➤ 写入 chunk(buffer) → 达到阈值形成 stripe → 纠删码编码 → 分布存储 → 更新 hash_node
如你愿意,我可以为这个系统画一张结构图,或继续往下扩展 chunk 和 stripe 的编码实现、节点迁移或读写缓存优化。你希望哪部分展开?