浅析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 ...
随机推荐
- 使用 Dockerfile 构建生产环境镜像
传统部署的坑: 1202 年了,如果你连 Docker 都不知道是什么,我建议买一本书看看--或者谷歌一下,博客已经写烂了. 为什么有这篇文章,是因为我在真正做容器化改造的时候,发现公司生产环境存在大 ...
- 利用python分析pdf数据,分析上市公司财报
import re import os.path import matplotlib import matplotlib.pyplot as plt from pdfminer.pdfparser i ...
- EntityCleanFramework
EF几乎是按照领域的概念诞生,它可以和Clean结合(ECF是我新想出的名字).ECF 是为了统一业务架构开发方式,也可以说成在 微服务架构 中服务的通用开发方式.当有了统一开发方式后,协作将更上一层 ...
- CTF比赛中Web的php伪协议类型题小结
php协议类型 file:// - 访问本地文件系统 http:// - 访问 HTTP(s) 网址 ftp:// - 访问 FTP(s) URLs php:// - 访问各个输入/输出流(I/O s ...
- 零基础入门——从零开始学习PHP反序列化笔记(二)
魔术方法 魔术方法介绍 __construct() 触发时机:实例化对象之前 构造函数,在实例化一个对象的时候,首先会去自动执行的一个方法; <?php class User { public ...
- 通过 tree shaking 移除无用代码
tree shaking 依赖于ES Module 的静态语法分析,在项目编译时移除无用的代码以减少文件体积. usedExports 在文件中,我们可能定义了变量但是暂时又没有用到,这样会造成空间的 ...
- 超详细的mysql总结(基本概念、DDL、DML)
开发中存在着各种数据,比如用户的个人信息.商品详情.购买记录,这些数据都要以一定的方式储存,如果以文本的形式储存,每一次获取都要读取文件,如果信息有修改则需要直接修改文本,大量的数据会需要保存大量的文 ...
- 使用wrk对api接口进行性能测试
安装 yum install -y openssl git git clone https://github.com/wg/wrk.git wrk cd wrk make cp wrk /usr/lo ...
- IDApython练习1-脚本去花
IDApython练习1-脚本去花 这里主要是练习IDApython脚本去花 1 这里 jz跳转条件是zf=1, jnz跳转条件是zf=0, 但是zf就2种可能,所以无论如何都会跳转到loc_411D ...
- k8s实战案例之运行WordPress
1.WordPress架构 LNMP案例之基于Nginx+PHP实现WordPress博客站点,要求Nginx+PHP运⾏在同⼀个Pod的不同容器;nginx主要作用是接入站点请求,如果请求静态资源n ...