【分布式系统工程实践】随机访问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

目录
相关文章
|
21天前
|
负载均衡 监控 Dubbo
Java微服务架构设计与实践:构建可伸缩的分布式系统
【4月更文挑战第2天】微服务架构响应现代业务需求,通过拆分大型应用为独立服务实现模块化和可扩展性。Java中的Spring Boot和Dubbo等框架支持服务注册、负载均衡等功能。遵循单一职责、自治性和面向接口原则,每个服务专注特定逻辑,独立部署运行。实际项目中,如电商系统,服务按功能拆分,提升可维护性和扩展性。还需考虑服务通信、数据一致性和监控等复杂话题。Java微服务架构助力构建高效、灵活的应用,应对未来挑战。
Java微服务架构设计与实践:构建可伸缩的分布式系统
|
21天前
|
存储 分布式计算 分布式数据库
【专栏】云计算与分布式系统架构在数字化时代的关键作用。云计算,凭借弹性、可扩展性和高可用性,提供便捷的计算环境
【4月更文挑战第27天】本文探讨了云计算与分布式系统架构在数字化时代的关键作用。云计算,凭借弹性、可扩展性和高可用性,提供便捷的计算环境;分布式系统架构则通过多计算机协同工作,实现任务并行和容错。两者相互依存,共同推动企业数字化转型、科技创新、公共服务升级及数字经济发展。虚拟化、分布式存储和计算、网络技术是其核心技术。未来,深化研究与应用这些技术将促进数字化时代的持续进步。
|
15天前
|
Cloud Native 数据管理 关系型数据库
【阿里云云原生专栏】云原生数据管理:阿里云数据库服务的分布式实践
【5月更文挑战第21天】阿里云数据库服务在云原生时代展现优势,应对分布式数据管理挑战。PolarDB等服务保证高可用和弹性,通过多副本机制和分布式事务确保数据一致性和可靠性。示例代码展示了在阿里云数据库上进行分布式事务操作。此外,丰富的监控工具协助用户管理数据库性能,支持企业的数字化转型和业务增长。
188 1
|
21天前
|
存储 Java 分布式数据库
【分布式计算框架】HBase数据库编程实践
【分布式计算框架】HBase数据库编程实践
23 1
|
21天前
|
分布式计算 并行计算 Java
【分布式计算框架】 MapReduce编程初级实践
【分布式计算框架】 MapReduce编程初级实践
20 2
|
21天前
|
分布式计算 数据可视化 Hadoop
【分布式计算框架】HDFS常用操作及编程实践
【分布式计算框架】HDFS常用操作及编程实践
9 1
|
21天前
|
存储 自然语言处理 搜索推荐
分布式搜索引擎ElasticSearch
Elasticsearch是一款强大的开源搜索引擎,用于快速搜索和数据分析。它在GitHub、电商搜索、百度搜索等场景中广泛应用。Elasticsearch是ELK(Elasticsearch、Logstash、Kibana)技术栈的核心,用于存储、搜索和分析数据。它基于Apache Lucene构建,提供分布式搜索能力。相比其他搜索引擎,如Solr,Elasticsearch更受欢迎。倒排索引是其高效搜索的关键,通过将词条与文档ID关联,实现快速模糊搜索,避免全表扫描。
87 3
|
21天前
|
存储 大数据 Apache
深入理解ZooKeeper:分布式协调服务的核心与实践
【5月更文挑战第7天】ZooKeeper是Apache的分布式协调服务,确保大规模分布式系统中的数据一致性与高可用性。其特点包括强一致性、高可用性、可靠性、顺序性和实时性。使用ZooKeeper涉及安装配置、启动服务、客户端连接及执行操作。实际应用中,面临性能瓶颈、不可伸缩性和单点故障等问题,可通过水平扩展、集成其他服务和多集群备份来解决。理解ZooKeeper原理和实践,有助于构建高效分布式系统。
|
21天前
|
存储 搜索推荐 Java
Java远程连接本地开源分布式搜索引擎ElasticSearch
Java远程连接本地开源分布式搜索引擎ElasticSearch
|
21天前
|
缓存 分布式计算 负载均衡
Java分布式系统设计与实践
Java分布式系统设计与实践
39 0