【分布式系统工程实践】随机访问KV存储引擎

简介:

Key-Value系统只需要支持简单的随机读(Get),写(Put)和删除(Del)操作。由于磁盘是顺序存储介质,因此可以往数据文件追加Key-Value记录并在内存中存放记录所在的磁盘位置,即索引信息。由于对同一个Key的更新(Put)操作以最后一个为准,内存中的索引只需要记录最新的Key-Value对位置即可,而对于删除操作,也是往数据文件追加一个删除记录。由于内存的大小有限,需要尽可能减小索引记录的大小,比如只支持64位的整数Key(其它类型的Key可以通过md5运算得到64位的整数值)。

内存中的索引信息包括64位的Key(8字节),Key-Value记录所在的磁盘位置(8字节),Key-Value记录在磁盘中的长度(4字节),另外,假设采用Hash的方式组织索引信息并采用采用链地址法解决冲突,每个索引项在Hash表中占用额外的8字节,最后,考虑到64位机的内存对齐,可以大致认为每个索引项占用32字节的内存空间,8GB内存存放的索引项条数为8GB / 32 = 2.5亿。如果每个Key-Value记录的平均大小为1KB,系统设计的磁盘内存比为1KB / 32 = 32 : 1,16GB的内存对应512GB的磁盘数据,满足大多数线上服务的需求。存储引擎需要实现如下几种操作:

读取操作(Get):先通过内存中的Hash索引找到Key-Value对的磁盘存储位置,接着执行一次随机读取操作。

写操作(Put):无论是插入还是更新已有的Key-Value记录,只需要将新数据追加到数据文件末尾,并更新内存中的Hash索引信息。

删除操作(Del):将删除操作追加到数据文件末尾,并删除内存中的Hash索引项。

如果不对索引信息进行持久化,系统宕机重启时需要重新读取所有的数据以重建索引,宕机恢复时间很长。将索引信息以同样的方式追加到索引文件中,写操作及删除操作的流程修改为:a, 追加数据到数据文件;b, 追加索引信息到索引文件;c, 更新内存中的Hash索引结构。当机器宕机时,通过读取索引文件来重建内存中的索引表,由于a和b两个操作不是原子的,可能出现数据文件更新但是索引文件没有更新的情况,因此,宕机恢复时除了读取索引文件的索引信息外,可能还需要读取数据文件中的最后几条记录。

更新和删除操作会产生很多的无用数据,这些垃圾数据的回收是通过定时合并操作实现的,一般可选择每天服务的低峰期,比如凌晨两点启动每日合并任务。

定时合并(Merge):采用0/1目录的方式,假设当前的服务目录编号为0,合并过程如下:

1, 关闭目录0的数据文件和索引文件,后续的更新操作(包括合并过程中的更新操作)都写入目录1中新开的文件;

2, 顺序读取目录0的索引文件,对每一个索引项,对比是否与内存中的内容一致,如果一致,说明是最新的有效索引,将对应的数据追加到目录1中的数据文件,同时生成相应的索引信息追加到目录1的索引文件中并修改内存中的索引项;

3, 合并过程结束时可以回收目录0中的数据文件和索引文件;

由于合并过程中可能有更新操作,且都需要追加目录1中的索引文件,因此,需要将索引文件编号分成两段,比如合并过程中写入的索引文件从1开始编号,最大不超过1000;更新操作写入的索引文件从1001开始编号。

上述介绍的存储引擎的特点就是简单,满足特定类型的应用,且随机读取基本做到了最优。当然,工程实践中还有很多工作需要细化,比如将数据分组从而利用多块磁盘,定时合并过程中记录进度从而宕机后可以从上次合并的位置开始继续执行,追加数据和索引文件是否fsync,如何通过异步group commit写磁盘保证不丢数据的前提下不损失并发能力,等等。总之,表面看似简单的事情做到极致往往很不简单。

说明:第一次接触随机存储引擎是在百度,一位目前在创业的大牛的作品,目前douban的Beansdb也使用了类似思想。另外,可以参考一篇文章:Bitcask: A Log-Structured Hash Table for Fast Key/Value Data

目录
相关文章
|
1月前
|
人工智能 安全 Java
分布式 Multi Agent 安全高可用探索与实践
在人工智能加速发展的今天,AI Agent 正在成为推动“人工智能+”战略落地的核心引擎。无论是技术趋势还是政策导向,都预示着一场深刻的变革正在发生。如果你也在探索 Agent 的应用场景,欢迎关注 AgentScope 项目,或尝试使用阿里云 MSE + Higress + Nacos 构建属于你的 AI 原生应用。一起,走进智能体的新世界。
447 36
|
1月前
|
关系型数据库 Apache 微服务
《聊聊分布式》分布式系统基石:深入理解CAP理论及其工程实践
CAP理论指出分布式系统中一致性、可用性、分区容错性三者不可兼得,必须根据业务需求进行权衡。实际应用中,不同场景选择不同策略:金融系统重一致(CP),社交应用重可用(AP),内网系统可选CA。现代架构更趋向动态调整与混合策略,灵活应对复杂需求。
|
3月前
|
数据采集 消息中间件 监控
单机与分布式:社交媒体热点采集的实践经验
在舆情监控与数据分析中,单机脚本适合小规模采集如微博热榜,而小红书等大规模、高时效性需求则需分布式架构。通过Redis队列、代理IP与多节点协作,可提升采集效率与稳定性,适应数据规模与变化速度。架构选择应根据实际需求,兼顾扩展性与维护成本。
106 2
|
6月前
|
人工智能 安全 应用服务中间件
阿里巴巴 MCP 分布式落地实践:快速转换 HSF 到 MCP server
本文分享了阿里巴巴内部将大规模HSF服务快速转换为MCP Server的实践经验,通过Higress网关实现MCP协议卸载,无需修改代码即可接入MCP生态。文章分析了MCP生态面临的挑战,如协议快速迭代和SDK不稳定性,并详细介绍了操作步骤及组件功能。强调MCP虽非终极解决方案,但作为AI业务工程化的起点具有重要意义。最后总结指出,MCP只是AI原生应用发展的第一步,未来还有更多可能性值得探索。
1165 49
|
1月前
|
消息中间件 运维 监控
《聊聊分布式》BASE理论 分布式系统可用性与一致性的工程平衡艺术
BASE理论是对CAP定理中可用性与分区容错性的实践延伸,通过“基本可用、软状态、最终一致性”三大核心,解决分布式系统中ACID模型的性能瓶颈。它以业务为导向,在保证系统高可用的同时,合理放宽强一致性要求,并借助补偿机制、消息队列等技术实现数据最终一致,广泛应用于电商、社交、外卖等大规模互联网场景。
|
1月前
|
消息中间件 分布式计算 资源调度
《聊聊分布式》ZooKeeper与ZAB协议:分布式协调的核心引擎
ZooKeeper是一个开源的分布式协调服务,基于ZAB协议实现数据一致性,提供分布式锁、配置管理、领导者选举等核心功能,具有高可用、强一致和简单易用的特点,广泛应用于Kafka、Hadoop等大型分布式系统中。
|
2月前
|
消息中间件 缓存 监控
中间件架构设计与实践:构建高性能分布式系统的核心基石
摘要 本文系统探讨了中间件技术及其在分布式系统中的核心价值。作者首先定义了中间件作为连接系统组件的"神经网络",强调其在数据传输、系统稳定性和扩展性中的关键作用。随后详细分类了中间件体系,包括通信中间件(如RabbitMQ/Kafka)、数据中间件(如Redis/MyCAT)等类型。文章重点剖析了消息中间件的实现机制,通过Spring Boot代码示例展示了消息生产者的完整实现,涵盖消息ID生成、持久化、批量发送及重试机制等关键技术点。最后,作者指出中间件架构设计对系统性能的决定性影响,
|
6月前
|
监控 Linux 应用服务中间件
Linux多节点多硬盘部署MinIO:分布式MinIO集群部署指南搭建高可用架构实践
通过以上步骤,已成功基于已有的 MinIO 服务,扩展为一个 MinIO 集群。该集群具有高可用性和容错性,适合生产环境使用。如果有任何问题,请检查日志或参考MinIO 官方文档。作者联系方式vx:2743642415。
2151 57
|
4月前
|
人工智能 分布式计算 DataWorks
分布式×多模态:当ODPS为AI装上“时空穿梭”引擎
本文深入探讨了多模态数据处理的技术挑战与解决方案,重点介绍了基于阿里云ODPS的多模态数据处理平台架构与实战经验。通过Object Table与MaxFrame的结合,实现了高效的非结构化数据管理与分布式计算,显著提升了AI模型训练效率,并在工业质检、多媒体理解等场景中展现出卓越性能。
|
6月前
|
安全 JavaScript 前端开发
HarmonyOS NEXT~HarmonyOS 语言仓颉:下一代分布式开发语言的技术解析与应用实践
HarmonyOS语言仓颉是华为专为HarmonyOS生态系统设计的新型编程语言,旨在解决分布式环境下的开发挑战。它以“编码创造”为理念,具备分布式原生、高性能与高效率、安全可靠三大核心特性。仓颉语言通过内置分布式能力简化跨设备开发,提供统一的编程模型和开发体验。文章从语言基础、关键特性、开发实践及未来展望四个方面剖析其技术优势,助力开发者掌握这一新兴工具,构建全场景分布式应用。
675 35

热门文章

最新文章