浅析KV存储之长尾时延解决办法
本文分享自华为云社区《浅析KV存储之长尾时延问题,华为云 GeminiDB Redis 探寻行业更优解决方案!》,作者:华为云数据库GaussDB NoSQL团队。
目前,KV存储的广泛使用极大程度上源于快速访问的业务需求,而这种业务通常对时延敏感度高,在较好的平均性能下,还需要解决特定场景下的性能抖动。开源Redis在AOF重写、RDB、主从同步等操作时,为不影响主线程,采用fork创建子线程去执行,但由于主线程仍在提供服务,触发Copy-On-Write时会引起性能抖动,导致长尾时延。
华为云GeminiDB(原华为云GaussDB NoSQL,后统称为GeminiDB)是采用存算分离架构的NoSQL多模数据库,在性能、稳定性方面业界领先。KV接口上,GeminiDB 100%兼容Redis 5.0协议,用户无需修改代码即可平迁到GeminiDB。针对业界的Redis fork技术痛点,GeminiDB提供了终极的优化方案。
我们先来看下业界的两种通用解法:
业界解法一:实现层面优化fork问题
常规的解决方案是在fork实现层进行魔改,也就是找到造成fork长尾时延的代码所在然后对其进行优化。通过多次实验发现,fork的执行时间随着实例大小增长而剧增,其中最耗时的是页表拷贝操作,如下图(a)所示,在Invoke Fork操作之后,主进程需要花时间进行页表拷贝,服务出现毛刺现象。

由此产生fork重写的核心思路:由于父进程在fork原生内部实现中并不纯粹,其在页表复制时仍需陷入内核态,出现短暂阻塞现象。通过将父进程耗时占比最高的页拷贝操作移至子进程去执行,足以大幅削弱父进程在fork过程中的阻塞现象,从而可以在对程序无任何修改的条件下解决原生fork带来的长尾时延。
业界有种算法,如上图(b)所示,可以通过让子进程去异步完成页表拷贝动作(Copy Page Table)和主进程主动同步页表(Proactively Synchronize)来解决毛刺以及主子进程的可能不一致问题,可以做到主进程近乎零阻塞。不难看出,修改fork算法有以下几点优势:
1. 实现层面消除了fork场景带来的长尾时延。
2. 对内存型键值存储服务完全透明。
但由于涉及魔改操作系统fork实现,导致维护和演进成本较高,向前兼容性较差。相比之下,在架构层面去解决这个问题,或许更加简单且自然。
业界解法二:架构层面优化fork问题
除了针对fork的优化,直接消除fork或许是工程上更加迫切的需要。
我们分析一下,之所以会有fork的引入,是因为Redis做了AOF重写、RDB、主从同步的操作。恰恰对于Redis这种内存型KV存储而言,AOF操作可以保证了数据不丢,而RDB和主从同步也是其持久化需要。但如果是非易失型KV存储,从内存到持久化介质的链路就不存在,类RDB和类主从同步操作也就可以交给存储层独立解决,从而彻底消除fork所带来的长尾时延。
基于此,业界有些数据库将KV数据通过其存储引擎直接写入持久化介质中,且在计算层做了性能上的高度优化,达到了不劣于开源Redis的性能:
以PMem为存储底座的存算分离架构
采用PMem作为其主要持久化存储介质的存储引擎,在某种程度上来说,其兼具DRAM的性能和字节寻址能力以及SSD的可持久化特性。下图是几种存储介质的对比:

同时,通过实现存储引擎的Cache模块,在服务运行期间存放业务热数据的数据页会被加载到PMem上,在处理用户请求期间不再直接操作SSD上的数据页,而是操作读写延迟更低的PMem,使得计算层的性能以及吞吐量得到了进一步的提升。
总的来说,使用PMem存储底座的优势在于:
1. 没有fork场景,不存在fork带来的长尾时延。
2. 提供了比开源Redis更大的容量。3. 数据可冷热分级存储。
但是,强依赖PMem也带来了一些难以解决的问题:
1. 非易失型内存编程难度高且鲁棒性差,需要框架和工具层面去降低其开发难度,总的来说,开发和维护成本过高。
2. 由于编程复杂,而且Redis索引结构繁多,数据模型相关API高达300多个,造成Redis命令兼容的实现可靠性极具下降,同样面临如何降低编码复杂度的问题。3. PMem相比于DRAM有数量级的性能下降,在读性能上有3倍以上的性能下降以及10倍以上的带宽减少,性能问题不可忽视。
在可靠性和开发维护成本上,以PMem为存储底座的架构还是有一定不足之处。
华为云的NoSQL数据库GeminiDB在这方面有更加强大的实现方案。GeminiDB兼容Redis接口(原GaussDB(for Redis),后统称为GeminiDB兼容Redis接口),以RocksDB+分布式文件系统+高性能存储池为底座,实现了领先的存算分离架构,综合表现更佳。
GeminiDB存算分离架构
华为云GeminiDB兼容Redis接口,存储架构采用RocksDB+分布式文件系统+高性能存储池,如下图所示,在架构层面消除了长尾时延的影响外,通过高性能存储池提供高可靠存储特性,分布式文件系统封装高性能存储池向外暴露类标准文件系统接口,降低开发难度。

而在性能选择方面,选择RocksDB作为存储引擎。它针对快速、低延迟的存储进行了优化,具有极高的写入吞吐。同时,RocksDB支持预写日志,范围扫描和前缀搜索,在高并发读写以及大容量存储时能够提供一致性的保证。RockDB的追加写特征恰好解决了磁盘I/O最耗时磁盘寻道时间,达到了接近内存随机读写的性能。
高可靠的实现,选择华为研发的高性能存储池分布式存储,最高支持128TB的海量存储,支持跨AZ部署、故障秒级切换,保证了在极度恶劣的情况的数据无损和快速恢复,支持数据的自动备份。
除此之外,分布式文件系统借助HDFS Snapshot实现了秒级快照,产生整个文件系统或某个目录在某个时刻的镜像,向用户提供了数据恢复、数据备份、数据测试的能力。
简言之,通过RocksDB+分布式文件系统+高性能存储池的存储架构,已经做到:
1. 低时延,基于高性能的存储架构,访问时延有了高度保障。
2. 大容量,基于存算分离,存储层可自由扩容。3. 低成本,基于冷热数据分级存储,贴合客户诉求。4. 高可靠, 基于分布式文件系统+高性能存储池,支持优秀的数据备份和数据同步特性,且不对主进程造成时延影响。
不过,RocksDB的数据存储模式也会带来一些复杂性。由于RocksDB存在读、写和空间放大的问题,且三者相互制约。尽管RocksDB提供了多种Compaction策略和参数以适应不同应用场景,但由于影响因子过多,策略的选择和调参成本会比较高。
小结
通过不同解决方案之间的对比,在解决长尾时延的问题上,架构解决方案更加贴合大多数客户诉求。同时,在大部分场景下,GeminiDB兼容Redis接口的架构相比于业界方案提供了更高的可靠性和良好的性能表现,预计年底可达到单片百万QPS的性能水平。
附录
更多产品信息,欢迎访问官方博客:bbs.huaweicloud.com/blogs/248875
浅析KV存储之长尾时延解决办法的更多相关文章
- openfire存储中文字符乱码解决办法
转载于: Xmpp问题总结:处理Openfire 中文乱码问题(2) openfire是一个非常不错的IM服务器,而且是纯Java实现,具有多个平台的版本,他的数据存储可以采用多种数据库,如MySQL ...
- SQLite实现用户数据存储+Android之app:lintVitalRelease解决办法
今日所学 SQLite实现用户数据存储 遇到的问题 界面没能显示出存在数据库中的信息 明日计划 查找界面没能显示出存在数据库中的信息的原因 报错:app:lintVitalRelease 解决办法: ...
- sql server存储特殊字符解决办法
好久没来院子了,最近在学java了,再加上项目比较紧,最近都没怎么上,其实这几天在项目中学到不少东西,都能写下来,但是久而久之就忘了,还是得养成及时总结的好习惯啊,还有有时间一定要把那个小项目整理下来 ...
- HBase 高性能加入数据 - 按批多“粮仓”式解决办法
摘要:如何从HBase中的海量数据中,以很快的速度的获取大批量数据,这一议题已经在<HBase 高性能获取数据>(http://www.cnblogs.com/wgp13x/p/42451 ...
- 高性能kv存储之Redis、Redis Cluster、Pika:如何应对4000亿的日访问量?
一.背景介绍 随着360公司业务发展,业务使用kv存储的需求越来越大.为了应对kv存储需求爆发式的增长和多使用场景的需求,360web平台部致力于打造一个全方位,适用于多场景需求的kv解决方案.目前, ...
- 当web.config文件放置在共享目录下(UNC),启动IIS会提示有错误信息500.19,伴随有错误代码0x80070003和错误代码0x80070005的解决办法
最近遇到一个很有意思的使用环境,操作人员将所有的网站应用内容投放到共享存储里面,并且使用微软的SMB协议将其以CIFS的方式共享出来,使用Windows Server 2008 R2的IIS将其连接起 ...
- 调用微信退款接口或发红包接口时出现System.Security.Cryptography.CryptographicException: 出现了内部错误 解决办法
我总结了一下出现证书无法加载的原因有以下三个 1.证书密码不正确,微信证书密码就是商户号 解决办法:请检查证书密码是不是和商户号一致 2.IIS设置错误,未加载用户配置文件 解决办法:找到网站使用的应 ...
- Redis与KV存储(RocksDB)融合之编码方式
Redis与KV存储(RocksDB)融合之编码方式 简介 Redis 是目前 NoSQL 领域的当红炸子鸡,它象一把瑞士军刀,小巧.锋利.实用,特别适合解决一些使用传统关系数据库难以解决的问题.Re ...
- Tomcat内存溢出的三种情况及解决办法分析
Tomcat内存溢出的原因 在生产环境中tomcat内存设置不好很容易出现内存溢出.造成内存溢出是不一样的,当然处理方式也不一样. 这里根据平时遇到的情况和相关资料进行一个总结.常见的一般会有下面三种 ...
- webdav不识别软链接?解决办法?
webdav不识别软链接?解决办法? 在使用webdav实现公网存储共享的时候,发现webdav并不支持软链接的共享,如下源代码可以100%确定这个问题 /* ### for now, only pr ...
随机推荐
- Blazor前后端框架Known-V1.2.6
V1.2.6 Known是基于C#和Blazor开发的前后端分离快速开发框架,开箱即用,跨平台,一处代码,多处运行. Gitee: https://gitee.com/known/Known Gith ...
- 修复mbr分区
修复mbr分区 实验条件 1.备份mbr引导扇区到其他磁盘 2.模拟破坏mbr引导扇区 3.引导镜像急救模式进行mbr扇区恢复 实验 1,添加一块新的磁盘 2,分区,查看分区情况 3,格式化,并挂载 ...
- [selenium]点击元素出现的obscure问题
前言 我们一般使用如下方式点击元素: elem = driver.find_element(...) elem.click() # 或者使用带等待条件的方式 elem = WebDriverWait( ...
- MySql之锁
MySql之锁 一.全局锁 对整个数据库加锁 应用:数据库所有表备份 二.表级锁 1.表锁 分为两类: 表共享读锁read lock 表独占写锁write lock 2.元数据锁 避免DML语句和DD ...
- JS标识符
什么是标识符? 变量名 函数名 属性名都称为标识符. 定义标识符规范如下 1) 标识符只能由字母 数字 下划线 $组成. 2) 标识符不能以数字开头,例如: 1name. 3) 标识符不能实JS中的关 ...
- SpringBoot3之Web编程
标签:Rest.拦截器.swagger.测试; 一.简介 基于web包的依赖,SpringBoot可以快速启动一个web容器,简化项目的开发: 在web开发中又涉及如下几个功能点: 拦截器:可以让接口 ...
- 调研capacitor兼容openharmony平台可行性
团队可能需要对开源的 capacitor 跨平台框架进行扩展,以生产支持 OpenHarmony 平台的应用,在此调研可行性.实现路径和预期工作量. 可行性分析 在验证 capacitor 是否可以将 ...
- Unity的AssetPostprocessor之Model之动画:深入解析与实用案例 3
Unity AssetPostprocessor的Model的动画相关的函数修改实际应用 在Unity中,AssetPostprocessor是一个非常有用的工具,它可以在导入资源时自动执行一些操作. ...
- [ABC132D] Blue and Red Balls
2023-01-16 题目 题目传送门 翻译 翻译 难度&重要性(1~10):3 题目来源 AtCoder 题目算法 dp 解题思路 因为蓝球的数量是固定的,题目让我们求,在取 \(i\) 次 ...
- 《SQL与数据库基础》20. 主从复制
目录 主从复制 原理 搭建 主库配置 从库配置 测试 本文以 MySQL 为例 主从复制 主从复制是指将主数据库的 DDL 和 DML 操作通过二进制日志传到从库服务器中,然后在从库上对这些日志重新执 ...