hbase和leveldb、rocksdb有哪些异同,并做了哪些提升
发布时间:2025-05-25 00:41:40 发布人:远客网络
一、hbase和leveldb、rocksdb有哪些异同,并做了哪些提升
1、Leveldb、Rocksdb以及HBase作为数据库解决方案,它们各自拥有独特的特性与用途,本文旨在探讨这三者之间的异同,并分析它们的提升之处。
2、Leveldb与Rocksdb均属于嵌入式数据库,它们设计为在单一服务器上运行,无需额外的客户端或服务端部署。Leveldb由Google的两位Fellow设计,专为高速读写操作优化,读取速度达到6万/s,写入速度远超读取速度,每秒可执行40万次写入操作,性能十分出众。
3、Rocksdb在Leveldb的基础上进行了优化与增强,提供多线程文件合并功能,更高效地利用多核CPU资源,减少文件合并期间的系统停顿。此外,它支持多个Memtable,即使一个Memtable已满,仍能通过开辟更多Memtable来避免系统停顿。Rocksdb还支持一次获取多个K-V值,相较于Leveldb只能获取单个K-V,此功能在数据访问效率上有显著提升。同时,Rocksdb提供了数据备份功能,而Leveldb则不支持。
4、尽管Rocksdb在底层支持HDFS,能够实现数据的多副本存储,但其前端并未实现分片功能,因此无法满足分布式系统的扩展需求。实际应用中,开发者常将Leveldb或Rocksdb作为数据存储系统的基础引擎,通过实现分片与多副本,构建真正的分布式存储系统,如微信开源的PaxosStore便是如此设计。
5、HBase作为分布式存储系统,不仅支持在线的K-V查询,还提供批量查询功能(Leveldb和Rocksdb亦可实现)。HBase通过HMaster、HRegionServer和Zookeeper等组件实现分片管理,提供Java API用于数据访问,同时基于HDFS实现数据的多副本存放,以提高数据的可靠性和性能。
6、总的来说,Leveldb、Rocksdb与HBase在性能、数据管理与扩展性方面各有侧重。选择合适的数据库系统需根据具体应用需求和场景进行考量。
二、MQTT Broker 选型
在构建分布式系统时,选择合适的MQTT Broker至关重要,它负责接收发布者发布的消息并将其分发给不同的订阅者。市面上有许多MQTT Broker可供选择,以下是一些常用选项的对比与分析。
Mosquitto是由Eclipse出品的开源MQTT Broker,基于C/C++语言编写,当前版本为1.5.8。其特点包括支持MQTT 3.1/3.1.1协议,但性能上存在一些限制,如内存优化、多线程的锁机制等。它适合运行在低功耗设备上,如嵌入式传感器、手机和微处理器,但不适用于大规模云服务。官方文档显示其理论支持约10万连接,实际使用中还需根据具体情况进行评估。
EMQ,一款国人开发的开源MQTT Broker,目前版本为2.0和3.0,2.0版本支持本地共享订阅,3.0版本新增集群共享订阅功能。EMQ具有完整QoS支持、单节点100万连接能力、分布式集群支持、多种验证插件(如LDAP、MySQL、PostgreSQL等)以及API、Web监控界面等特性。官方宣称支持MQTT 3.1、3.1.1和5.0版本,并在性能上做了优化。然而,开源版本不支持服务器内部消息持久化,这是其一个显著限制。
HiveMQ是一款企业级MQTT Broker,使用Java编写,功能丰富,支持MQTT 3.1、3.1.1和5.0版本,完整QoS支持,分布式集群,持久化支持,流量控制,IPv6支持等。其唯一限制在于高昂的费用,没有公开源码供参考。集群基于Jgroups,数据同步通过自定义一致性哈希和VectorClock实现。多线程和并发控制使用Google的guava库,代码质量高。
MqttWk是一个基于nutzboot、netty、redis和kafka实现的MQTT服务开源Broker,代码简洁易懂。它支持MQTT和Websocket连接方式,集群功能和消息分发重试,但存在一些限制,如消息队列非队列结构、消息分发重试机制较差、主题限制等。它是上生产的项目,经历过2万设备连接的考验。
Jmqtt是一个基于Java的开源MQTT Broker,对现有开源Broker进行了优化,特别是在CONNECT处理和Session过期管理方面。支持MQTT和Websocket连接方式,使用RocksDB进行本地存储,但不支持集群和SSL。
Moquette是一个功能齐全的Java编写的开源MQTT Broker,提供完整的QoS服务和认证方式,支持多种持久化存储。然而,0.10版本中存在内存泄漏问题,官方修复后发布为irubant/moquette。其集群功能仅使用Hazelcast作为消息总线,不支持共享订阅。
综上所述,选择合适的MQTT Broker需考虑应用的具体需求,包括连接数量、协议版本、性能要求、集群支持、消息持久化、安全认证等因素。在选择时,应充分评估各Broker的特性和限制,以满足实际应用场景的需要。
三、lockdiru盘忘记密码删除文件
1、lockdiru盘忘记密码删除文件(lockdir文件夹加密忘记密码怎么办)背景介绍在一个典型的分布式文件系统中,目录文件元数据操作(包括创建目录或文件,重命名,修改权限等)在整个文件系统操作中占很大比例,因此元数据服务在整个文件系统中扮演着重要的角色,随着大规模机器学习、大数据分析和企业级数据湖等应用,分布式文件系统数据规模已经从 PB级到 EB级,当前多数分布式文件系统(如 HDFS等)面临着元数据扩展性的挑战。
2、以 Google、Facebook和 Microsoft等为代表的公司基本实现了能够管理 EB级数据规模的分布式文件系统,这些系统的共同架构特征是依赖于底层分布式数据库能力来实现元数据性能的水平扩展,如 Google Colossus基于 BigTable,Facebook基于 ZippyDB,Microsoft ADLSv2基于 Table Storage,还有一些开源文件系统包括 CephFS和 HopsFS等也基本实现了水平扩展的能力。
3、这些文件系统实现由于对底层分布式数据库的依赖,对文件系统的语义支持程度也各有不同,如大多数基于分布式文件系统的计算分析框架依赖底层目录原子 Rename操作来提供数据的原子更新,而 Tectonic和 Colossus因为底层数据库不支持跨分区事务所以不保证跨目录 Rename的原子性,而 ADLSv2支持对任意目录的原子 Rename。
4、DanceNN是公司自研的一个目录树元信息存储系统,致力于解决所有分布式存储系统的目录树需求(包括不限于 HDFS,NAS等),极大简化上层存储系统依赖的目录树操作复杂性,包括不限于原子 Rename、递归删除等。解决超大规模目录树存储场景下的扩展性、性能、异构系统间的全局统一命名空间等问题,打造全球领先的通用分布式目录树服务。
5、当前 DanceNN已经为公司在线 ByteNAS,离线 HDFS两大分布式文件系统提供目录树元数据服务。
6、(本篇主要介绍在离线大数据场景 HDFS文件系统下 DanceNN的应用,考虑篇幅,DanceNN在 ByteNAS的应用会在后续系列文章介绍,敬请期待)
7、字节 HDFS元数据系统分三个阶段演进:
8、最开始公司使用 HDFS原生 NameNode,虽然进行了大量优化,依然面临下列问题:
9、元数据(包括目录树,文件和 Block副本等)全内存存储,单机承载能力有限基于 Java语言实现,在大内存场景 GC停顿时间比较长,严重影响 SLA使用全局一把读写锁,读写吞吐性能较差随着集群数据规模增加,重启恢复时间达到小时级别DanceNN v1
10、DanceNN v1的设计目标是为了解决上述 NameNode遇到的问题。
11、重新实现 HDFS协议层,将目录树文件相关元数据存储到 RocksDB存储引擎,提供 10倍元数据承载使用 C++实现,避免 GC问题,同时使用高效数据结构组织内存 Block信息,减少内存使用实现一套细粒度目录锁机制,极大提升不同目录文件操作间的并发请求路径全异步化,支持请求优先级处理重点优化块汇报和重启加载流程,降低不可用时间
12、DanceNNv1最终在 2019年完成全量上线,线上效果基本达到设计目标。
13、下面是一个十几亿文件数规模集群,切换后大致性能对比:
14、DanceNN v1开发中遇到很多技术挑战,如为了保证上线过程对业务无感知,支持现有多种 HDFS客户端访问,后端需要完全兼容原有的 Hadoop HDFS协议。
15、一直以来 HDFS都是使用 Federation方式来管理目录树,将全局 Namespace按 path映射到多组元数据独立的 DanceNN v1集群,单组 DanceNN v1集群有单机瓶颈,能处理的吞吐和容量有限,随着公司业务数据的增长,单组 DanceNN v1集群达到性能极限,就需要在两个集群之间频繁迁移数据,为了保证数据一致性需要在迁移过程中上层业务停写,对业务影响比较大,并且当数据量大的情况下迁移比较慢,这些问题给整个系统带来非常大的运维压力,降低服务的稳定性。
16、通用目录树服务,支持多协议包括 HDFS,POSIX等单一全局 Namespace容量、吞吐支持水平扩展高可用,故障恢复时间在秒级内包括跨目录 Rename等写操作支持事务高性能,基于 C++实现,依赖 Brpc等高性能框架
17、Distributed DanceNN目前已经在 HDFS部分集群上线,正在进行存量集群的平滑迁移。
18、最新 HDFS分布式文件系统实现采用分层架构,主要包括三层:
19、数据层:用于存储文件内容,处理 Block级别的 IO请求由 DataNode节点提供服务Namespace层:负责目录树相关元数据,处理目录和文件创建、删除、Rename和鉴权等请求由 Distributed DanceNN集群提供服务文件块层:负责文件相关的元数据、文件与 Block的映射以及 Block副本位置信息,处理文件创建删除,文件 Block的添加等请求一个 BSGroup负责管理集群部分文件块元数据,由多台的 DanceBS组成提供高可用服务通过 BSGroup动态扩容来适应集群负载,当某个 BSGroup快达到性能极限后可以控制写入DanceProxyC++实现,基于高性能框架 Brpc实现了 Hadoop RPC协议,支持高吞吐,无缝对接现有 HDFS Client。主要负责对 HDFS Client请求的解析,拆分处理后,将 Namespace相关的请求发送到 DanceNN集群,文件块相关的请求路由到对应的 BSGroup处理,当所有后端请求回复后生成最终客户端的响应。DanceProxy通过一定的请求路由策略来实现多组 BSGroup负载均衡。DanceNN接口
20、Distributed DanceNN为文件系统提供主要接口如下:
21、class DanceNNClient{ public: DanceNNClient()= default; virtual~DanceNNClient()= default;//...// Create directories recursively, eg: MkDir/home/tiger. ErrorCode MkDir(const MkDirReq& req);// Delete a directory, eg: RmDir/home/tiger. ErrorCode RmDir(const RmDirReq& req);// Change the name or location of a file or directory,// eg: Rename/tmp/foobar.txt/home/tiger/foobar.txt. ErrorCode Rename(const RenameReq& req);// Create a file, eg: Create/tmp/foobar.txt. ErrorCode Create(const CreateReq& req, CreateRsp* rsp);// Delete a file, eg: Unlink/tmp/foobar.txt. ErrorCode Unlink(const UnlinkReq& req, UnlinkRsp* rsp);// Summarize a file or directory, eg: Du/home/tiger. ErrorCode Du(const DuReq& req, DuRsp* rsp);// Get status of a file or directory, eg: Stat/home/tiger/foobar.txt. ErrorCode Stat(const StatReq& req, StatRsp* rsp);// List directory contents, eg: Ls/home/tiger. ErrorCode Ls(const LsReq& req, LsRsp* rsp);// Create a symbolic link named link_path which contains the string target.// eg: Symlink/home/foo.txt/home/bar.txt ErrorCode Symlink(const SymlinkReq& req);// Read value of a symbolic link. ErrorCode ReadLink(const ReadLinkReq& req, ReadLinkRsp* rsp);// Change permissions of a file or directory. ErrorCode ChMod(const ChModReq& req);// Change ownership of a file or directory. ErrorCode ChOwn(const ChOwnReq& req);// Change file last access and modification times. ErrorCode UTimeNs(const UTimeNsReq& req, UTimeNsRsp* rsp);// Set an extended attribute value. ErrorCode SetXAttr(const SetXAttrReq& req, SetXAttrRsp* rsp);// List extended attribute names. ErrorCode GetXAttrs(const GetXAttrsReq& req, GetXAttrsRsp* rsp);// remove an extended attribute. ErrorCode RemoveXAttr(const RemoveXAttrReq& req, RemoveXAttrRsp* rsp);//...};DanceNN架构功能介绍Distributed DanceNN基于底层分布式事务 KV存储来构建,实现容量和吞吐水平扩展,主要功能:
22、HDFS等协议层的高效实现服务无状态化,支持高可用服务节点的快速扩缩容提供高性能低延迟的访问对 Namespace进行子树划分,充分利用子树 Cache Locality集群根据负载均衡策略对子树进行调度模块划分SDK
23、缓存集群子树、NameServer位置等信息,解析用户请求并路由到后端服务节点上,如果服务节点响应请求不合法,可能强制 SDK刷新相应的集群缓存。
24、NameServer作为服务节点,无状态,支持横向扩展HDFS/POSIX Protocol Layer:处理客户端请求,实现了 HDFS等协议层语义,包括路径解析,权限校验,删除进入回收站等Subtree Manager:管理分配给当前节点的子树,负责用户请求检查,子树迁移处理等Heartbeater:进程启动后会自动注册到集群,定期向 NameMaster更新心跳和负载信息等DistributedLock Manager:基于 LockTable,对跨目录 Rename请求进行并发控制Latch Manager:对所有路径读写请求进行加锁处理,降低底层事务冲突,支持 Cache的并发访问Strong Consistent Cache:维护了当前节点子树的 dentry和 inode强一致 CacheData Acess Layer:对底层 KV存储的访问接口的抽象,上层读写操作都会映射到底层 KV存储请求NameMaster作为管理节点,无状态,多台,通过选主实现,由主节点提供服务AdminTask Scheduler:后台管理相关任务调度执行,包括子树切分,扩容等Load Balancer:根据集群 NameServer负载状态,通过自动子树迁移来完成负载均衡NameServer Manager:监控 NameServer健康状态,进行相应的宕机处理Statistics:通过消费集群变更日志,实时收集统计信息并展示Distributed Transactional KV Store数据存储层,使用自研的强一致 KV存储系统 ByteKV提供水平伸缩能电脑力支持分布式事务,提供 Snapshot隔离级别支持多机房数据灾备BinLog StoreBinLog存储,使用自研的低延迟分布式日志系统 ByteJournal,支持 Exactly Once语义从底层 KV存储系统中实时抽取数据变更日志,主要用于 PITR和其他组件的实时消费等GC(Garbage collector)从 BinLog Store实时消费变更日志,读到文件删除记录后,向文件块服务下发删除命令,及时清理用户数据Quota对用户认领的目录,会周期性全量、实时增量的统计文件总数和空间总量,容量超限后限制用户写关键设计存储格式
25、一般基于分布式存储的元数据格式有两种方案:
26、方案一类似 Google Colossus,以全路径作为 key,元数据作为 value存储,优点有:
27、路径解析非常高效,直接通过用户请求的 path从底层的 KV存储读取对应 inode的元数据即可扫描目录可以通过前缀对 KV存储进行扫描
28、跨目录 Rename代价大,需要对目录下的所有文件和目录进行移动Key占用的空间相对比较大
29、另外一种类似 Facebook Tectonic和开源的 HopsFS,以父目录 inode id+目录或文件名作为 key,元数据作为 value存储,这种优点有:
30、跨目录 Rename非常轻量,只需要修改源和目标节点以及它们的父节点扫描目录同样可以用父目录 inode id作为前缀进行扫描
31、路径解析网络延迟高,需要从 Root依次递归读取相关节点元数据直到目标节点例如:MkDir/tmp/foo/bar.txt,有四次元数据网络访问:/、/tmp、/tmp/foo和/tmp/foo/bar.txt层级越小,访问热点越明显,从而导致底层存储负载严重不均衡例如:每个请求都要读取一次根目录/的元数据
32、考虑到跨目录 Rename请求在线上集群占电脑比较高的比例,并且对于大目录 Rename延迟不可控,DanceNN主要采用第二种方案,方案二的两个缺点通过下面的子树分区来解决。
33、DanceNN通过将全局 Namespace进行子树分区,子树被指定一个 NameServer实例维护子树缓存。
34、维护这个子树下所有目录和文件元数据的强一致缓存缓存项有一定淘汰策略包括 LRU,TTL等所有请求路径在这个子树下的可以直接访问本地缓存,未命中需要从底层 KV存储进行加载并填充缓存通过对缓存项添加版本的方法来指定某个目录下所有元数据的缓存过期,有利于子树快速迁移清理
35、利用子树本地缓存,路径解析和读请求基本能够命中缓存,降低整体延迟,也避免了靠近根节点访问的热点问题。
36、在子树迁移、跨子树 Rename等操作过程中,为了避免请求读取过期的子树缓存,需要将相关的路径进行冻结,冻结期间该路径下的所有操作会被阻塞,由 SDK负责重试,整个流程在亚秒级内完成路径冻结后会将该目录下的所有缓存项设置为过期冻结的路径信息会被持久化到底层的 KV存储,重启后会重新加载刷新
37、子树管理主要由 NameMaster负责:
38、支持通过管理员命令进行手动子树分裂和子树迁移定期监控集群节点的负载状态,动态调整子树在集群分布定期统计子树的访问吞吐,提供子树分裂建议,未来支持启发式算法选择子树完成分裂
39、目录/调度到 NameServer#1,目录/b调度到 NameServer#2,目录/b/d调度到 NameServer#3
40、MkDir/a请求发送到 NameServer#1,发送到其他 NameServer会校验失败,返回重定向错误,让 SDK刷新缓存重试Stat/b/d请求将会发送到 NameServer#3,直接电脑读取本地缓存即可ChMod/b请求将会发送到 NameServer#2,更新 b目录的权限信息并持久化,对 NameServer#2和 NameServer#3进行 Cache刷新,最后回复客户端并发控制
41、底层 KV存储系统 ByteKV支持单条记录的 Put、Delete和 Get语义,其中 Put支持 CAS语义,还提供多条记录的原子性写入接口 WriteBatch。
42、客户端写操作一般会涉及多个文件或目录的更新,例如 Create/tmp/foobar.txt会更新/tmp的 mtime记录、创建 foobar.txt记录等,DanceNN会将多条记录的更新转换成 ByteKV WriteBatch请求,保证了整个操作的原子性。
43、虽然 ByteKV提供事务的 ACID属性且支持 Snapshot隔离级别,但是对于多个并发写操作如果涉及底层数据变更之间没有 Overlap的话,仍然会有 Write Skew异常,这可能导致元数据完整性被破坏。
44、其中一个例子是并发 Rename异常,如下图:
45、单个 Rename/a/b/d/e操作或者单个 Rename/b/d/a/c操作都符合预期,但是如果两者并发执行(且都能成功),可以导致目录 a,c,d,e的元数据出现环,破坏了目录树结构的完整性。
46、我们选择使用分布式锁机制来解决,对于可能导致异常的并发请求进行串行处理,基于底层 KV存储设计了 Lock Table,支持对于元数据记录进行加锁,提供持久性、水平扩展、读写锁、锁超时清理和幂等功能。
47、为了支持对子树内部缓存的并发访问和更新,维护缓存的强一致,会对操作涉及的缓存项进行加锁(Latch),例如:Create/home/tiger/foobar.txt,会先对 tiger和 foobar.txt对应的缓存项加写 Latch,再进行更新操作;Stat/home/tiger会对 tiger缓存项加读 Latch,再进行读取。
48、为了提升服务的整体性能做了非常多的优化,下面列两个重要优化:
49、例如:有些业务像大型 MapReduce任务会在相同目录一下子创建几千个目录或文件。
50、一般来说根据文件系统语义创建文件或目录都会更新父目录相关的元数据(如 HDFS协议更新父目录的 mtime,POSIX要求更新父目录 mtime,nlink等),这就导致同目录下创建文件操作对父目录元数据的更新产生严重的事务冲突,另外底层 KV存储系统是多机房部署,机房延迟更高,进一步降低了这些操作的并发度。
51、DanceNN对于热点目录下的创建删除等操作只加读 latch,之后放到一个 ExecutionQueue中,由一个的轻量 Bthread协程进行后台异步串行处理,将这些请求组合成一定大小的 Batch发送给底层的 KV存储,这样避免了底层事务冲突,提升几十倍吞吐。
52、有些场景可能会导致目录的更新请求阻塞了这个目录下的其他请求,例如:
53、SetXAttr/home/tiger和 Stat/home/tiger/foobar.txt无法并发执行,因为第一个对 tiger缓存项加写 Latch,后面请求读 tiger元数据缓存项会被阻塞。
54、DanceNN使用类似 Read-Write-Commit Lock实现对 Latch进行管理,每个 Latch有 Read、Write和 Commit三种类型,其中 Read-Read、Read-Write请求可以并发,Write-Write、Any-Commit请求互斥。
55、基于这种实现,上述两个请求能够在保证数据一致性的情况下并发执行。
56、当客户端因为超时或网络故障而失败时,进行重试会导致同一个请求到达 Server多次。有些请求如 Create或者 Unlink是非幂等的请求,对于这样的操作,需要在 Server端识别以保证只处理一次。
57、在单机场景中,我们通常使用一个内存的 Hash表来处理重试请求,Hash表的 key为{ClientId, CallId},value为{State, Response},当请求 A到来之后,我们会插入{Inprocess State}到 Hash表;这之后,如果重试请求 B到来,会直接阻塞住请求 B,等待第请求 A执行成功后唤醒 B。当 A执行成功之后,我们会将{Finished State, Response}写到 Hash表并唤醒 B,B会看到更新的 Finished状态后响应客户端。
58、类似的 DanceNN写请求会在底层的 WriteBatch请求里加一条 Request记录,这样可以保证后续的重试请求操作一定会在底层出现事务 CAS失败,上层发现后会读取该 Request记录直接响应客户端。另外,何时删除 Request记录呢,我们会给记录设置一个相对较长时间的 TTL,可以保证该记录在 TTL结束之后一定已经处理完成了。
59、DanceNN使用 1台 NameServer,分布式 KV存储系统使用 100+台数据节点,三机房五副本部署(2+ 2+ 1),跨机房延迟 2-3ms左右,客户端通过 NNThroughputBenchmark元数据压测脚本分别使用单线程和 6K线程并发进行压测。
60、读吞吐:单台 NameServer支持读请求 500K,随着 NameServer数量的增加吞吐基本能够线性增长;
61、写吞吐:目前依赖底层 KV存储的写事务性能,随着底层 KV节点数据量的增加也能够实现线性增长。
62、随着字节跳动的持续发展,业务对底层分布式文件系统的可用性、性能和扩展性的要求也越来越高,欢迎对分布式存储、文件系统以及 NFS/POSIX/HDFS文件协议等技术感兴趣的同学加入我们,基于业界前沿技术(如新型存储介质)构建下一代大规模分布式文件系统。
63、联系邮箱:huangdongfa@bytedance.com
64、参考资料Colossus under the hood: a peek into Google’s scalable storage systemFacebook’s Tectonic Filesystem: Efficiency from ExascaleHopsFS: Scaling Hierarchical File System Metadata Using NewSQL DatabasesAzure Data Lake Storage Gen2Ceph: A Scalable, High-Performance Distributed File SystemLocoFS: A Loosely-Coupled Metadata Service for Distributed File Systems字节跳动自研强一致在线 KV&表格存储实践-上篇