【记录】优化Redis存储

本文介绍了如何通过改变Redis的存储结构和编码方式,结合protobuf序列化和哈希算法,有效降低存储空间。在原有字符串key-value存储占用1.2T内存的情况下,优化后仅使用100G,节省了约90%的存储空间。优化方案包括使用hash+ziplist结构,protobuf序列化value,并探讨了可能的hash冲突和压缩算法选择。
摘要由CSDN通过智能技术生成

Redis存储的现状

Redis 是一个开源的,支持网络的,基于内存的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如字符串(strings)、散列(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等。平时我们使用最多的命令应该是GET和SET,操作最多的结构类型应该是字符串类型了。

对于大多数的项目,应用程序产生的数据量并不是很多,使用字符串类型足以解决应用的性能瓶颈 或 临时性数据存储的需求。然而,对于海量数据的需求场景,使用字符串数据类型进行存储,会极大的占用redis的存储空间,导致运维成本增高,且当发生扩容、备份、灾备转移等操作时,会导致这类操作时间极为漫长和集群不稳定的情况发生。

今天逛技术网站时,看到一篇关于Redis存储压缩方案的文章描述,觉得很实用也很贴切,感谢作者的分享,特此学习和记录一下,参考链接:信也项目实战-Redis存储压缩方案

先来看一下,优化Redis存储之前后项目的情况:

  1. 项目初期调研时预估只需要存储大约6亿条目的数据量,当时的测算是300G左右的容量是足够的;
  2. 当项目上线半个月后,发现当初预估的数据量级与实际数据量级有严重偏差,实际的数据量到后续已增长到50亿+,且每天保持3000W左右的增长量,Redis集群从最初的200G扩容到了1.5T;
  3. 随之而来的是项目成本飙升,Redis集群自动备份失败,因为需要备份的数据量级过大导致拉取超时,扩容时间超长,超过3小时+,同时还容易偶发长查询等问题。

这些问题就是制定Redis大数据量级存储压缩方案的原因了。

Redis存储压缩方案

方案对比如下:

  • 原存储方案:key(strings数据结构),value(多字段,采用json序列化);
  • 新存储方案:key(hashs数据结构,key-feild —— ziplist编码方式),value(采用protobuf序列化),节省存储空间:80%+;

画张图来分析下两个方案的思路:

优化分析:

strings类型中,key使用int编码的话,一个字符串占用8个字节,而embstr编码要占用32个字节,所以实际中int编码方式要比embstr编码节省75%的内存空间,当然这里不是重点,接下来分析hash类型。hash类型中,配置文件默认了ziplist编码的一些参数(hash-max-ziplist-entries=512; hash-max-ziplist-value=64;):有key的最大数量(即field-value域值对的数量不超过512),其中value的字符串长度不超过64个字节,否则ziplist编码将转换为hashtable编码方式存储。因此,实际使用中要预估好key的数量和内层field-value域值对的value长度。

这里,我们把key称为bucket,使用ziplist编码方式时,怎么计算需要bucket的数量呢?假如要往Redis存储100W条数据,100W/512 = 1953,即至少要有bucket。然而,如果所有的key要将进行哈希计算,尽量保证key均摊到所有bucket里。但由于哈希函数的不确定性,未必能完全平均分配,以及还要考虑未来数据的增长量,所以我们要预留出足够的空间,比如这里分配3000个bucket。

那如何通过选定哈希算法,将key放到bucket里呢?这里,可以采用高效而且均衡的知名算法crc32,该哈希算法可以将一个字符串变成一个long型的数字,通过获取这个MD5型的key的crc32后,再对bucket的数量进行取余,就可以确定该key要被放到哪个bucket中。

在确定了key的哈希算法后,对于内层的field,我们则选用另一个hash算法,这样可以避免field和key出现hash碰撞而导致覆盖的情况发生。field选用bkdr哈希算法 或直接通过Java的hashCode计算,结果也会得到一个long整型的数字,这里value暂时不做优化。至此,替换方案大致完成了,看下效果:

  • 原存储方案:key-value : 2c0c903b2df742be86f8264c13780225 → 2c0c903b2df742be86f8264c13780225;
  • 新存储方案:key-field-value :key为778,field是17276529,value是2c0c903b2df742be86f8264c13780225;

经过实测,采用字符串key-value方式直接存储,100W条数据占用了大概146MB的存储空间;而换成hash+ziplist存储方式,100W条数据占用了大概47MB的存储空间,大约减少了68%的存储空间。另外,将100W数据存入3000个bucket后,整体hash比较均衡,每个bucket下大概分布了300多个field-value域值对,目前一个key内的元素数量还只有339个,没有超过配置值hash-max-ziplist-entries=512。此时,我们可以尝试再多写入100W的数据,因为200W/512=3906,它已经超过了当时我们设计的3000个bucket,所以单个bucket中的元素个数已经超过了默认配置hash-max-ziplist-entries=512,Redis会自动改为hashtable编码,不再使用ziplist编码了。如果按ziplist编码存储100W数据占用47MB内存空间来计算,理论上200W的数据量只会占用不到100MB的内存空间,但编码被改成hashtable后,经测试内存占用却增长到了256MB,进一步实际证明了hashtable编码存储比ziplist编码存储会占用更多的存储空间。

采用hash的重点在于,理论上只要不发生两次hash算法后,均产生相同的值,那么就可以完全依靠key-field来找到原始的value,这一点可以通过计算总量进行确认。实际上,在bucket数量较多时,且每个bucket下,value数量不是很多,发生连续碰撞概率极低,实测在存储50亿情况下,未发生明显碰撞。但我们在经过110亿+的数据验证后,发现有6个碰撞情况产生,所以对于数据量级极大且精度要求极高的场景,这一点需要注意!!

通过改变数据结构类型和内部编码方式优化了key 和 field, 接下来,该是考虑对大字符串的value做优化了。实际中,存储的value是个多字段属性的对象,为了使用方便,设计初期直接采用了json序列化成字符串进行了存储,这样会额外浪费较多的存储空间,该如何对value也进行存储优化呢?

具体的优化方式有:压缩 或 序列化,通过一系列的调研和比对,选用了Google的protobuf序列化进行value处理,可以达到极致性能和节省大量空间的目的。同一个对象经过不同序列化方式生成字符串后的效果:

  • 原存储方案:JSON序列化,占用约178字节;
  • 新存储方案:protobuf序列化,只占用了约53字节;

经过对比可知:protobuf序列化节省了约70%的存储空间,而采用hash数据结构时,配置文件默认value不能超过64个字节,否则会将ziplist编码方式转换为hashtable编码,而protobuf序列化没有超过,刚好匹配了ziplist编码。即使以后还需要在此对象上扩展字段,而value可能会超过64字节,我们也可以去调整hash-max-ziplist-value的配置改到128字节,即使再多扩展几个字段,相信也不会超过此配置值的。值得注意的是,像hash-max-ziplist-value、hash-max-ziplist-entries等参数配置,不宜改得太大,这样对cpu的压力会更大,对查询时的性能影响肯定更大,需要在存储空间和性能上取其平衡。

对于压缩算法,在对象较小的场景下,压缩算法的压缩比不高,且性能上也有一定的损耗;如果在有较大字符串的场景下,推荐使用google的snappy压缩算法,经过实测后发现此压缩算法在性能、压缩比、资源消耗等上有明显优势。以下是作者调研的压缩算法实际情况,可以在实际项目中参考使用:

方案缺点:

  1. hash结构不支持对单个field的超时设置,但可以通过代码来控制删除,对于那些不需要超时的长期存放的数据,则没有这种顾虑;
  2. 还是会存在较小的hash冲突概率,对于数据量极大且要求极其精确的场合,应谨慎采用该压缩方案。

方案整体效果:

  • 字符串key-value存储方案的redis集群情况:50亿数据时,redis集群占用了1.2T的内存;
  • hash+ziplist+protobuf存储方案的redis集群情况:使用ziplist的方式存储1亿的数据预估仅使用了1G的内存空间,即使是需要存储50亿的数据,100G的内存也是足够的,比当时的1.2T节省约90%的存储空间。

整个集群从1.5T降到了100G,且目前仅使用了30G不到,效果还是很显著的!!!

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
大数据存储方式概述 随着信息社会的发展,越来越多的信息被数据化,尤其是伴随着Internet的发展,数 据呈爆炸式增长。从存储服务的发展趋势来看,一方面,是对数据的存储量的需求越来 越大,另一方面,是对数据的有效管理提出了更高的要求。首先是存储容量的急剧膨胀,从 而对于存储服务器提出了更大的需求;其次是数据持续时间的增加。最后,对数据存储 的管理提出了更高的要求。数据的多样化、地理上的分散性、对重要数据的保护等等都 对数据管理提出了更高的要求。随着数字图书馆、电子商务、多媒体传输等用的不断发 展,数据从GB、TB到PB量级海量急速增长。存储产品已不再是附属于服务器的辅助设备 ,而成为互联网中最主要的花费所在。海量存储技术已成为继计算机浪潮和互联网浪潮之 后的第三次浪潮,磁盘阵列与网络存储成为先锋。 1. 海量数据存储简介 海量存储的含义在于,其在数据存储中的容量增长是没有止境的。因此,用户需要不 断地扩张存储空间。但是,存储容量的增长往往同存储性能并不成正比。这也就造成了 数据存储上的误区和障碍。海量存储技术的概念已经不仅仅是单台的存储设备。而多个 存储设备的连接使得数据管理成为一大难题.因此,统一平台的数据管理产品近年来受到 了广大用户的欢迎.这一类型产品能够整合不同平台的存储设备在一个单一的控制界面上 ,结合虚拟化软件对存储资源进行管理。这样的产品无疑简化了用户的管理。 数据容量的增长是无限的,如果只是一味的添加存储设备,那么无疑会大幅增加存储 成本。因此,海量存储对于数据的精简也提出了要求。同时,不同应用对于存储容量的 需求也有所不同,而应用所要求的存储空间往往并不能得到充分利用,这也造成了浪费 。 针对以上的问题,重复数据删除和自动精简配置两项技术在近年来受到了广泛的关注 和追捧。重复数据删除通过文件块级的比对,将重复的数据块删除而只留下单一实例。 这一做法使得冗余的存储空间得到释放,从客观上增加了存储容量。 2. 企业在处理海量数据存储中存在的问题 目前企业存储面临几个问题,一是存储数据的成本在不断地增加,如何削减开支节约 成本以保证高可用性;二是数据存储容量爆炸性增长且难以预估;三是越来越复杂的环 境使得存储的数据无法管理.企业信息架构如何适应现状去提供一个较为理想的解决方案 ,目前业界有几个发展方向。 1.存储虚拟化 对于存储面临的难题,业界采用的解决手段之一就是存储虚拟化。虚拟存储的概念实 际上在早期的计算机虚拟存储器中就已经很好地得以体现,常说的网络存储虚拟化只不 过是在更大规模范围内体现存储虚拟化的思想。该技术通过聚合多个存储设备的空间, 灵活部署存储空间的分配,从而实现现有存储空间高利用率,避免了不必要的设备开支 . 存储虚拟化的好处显而易见,可实现存储系统的整合,提高存储空间的利用率,简化 系统的管理,保护原有投资等。越来越多的厂商正积极投身于存储虚拟化领域,比如数 据复制、自动精简配置等技术也用到了虚拟化技术.虚拟化并不是一个单独的产品,而是 存储系统的一项基本功能。它对于整合异构存储环境、降低系统整体拥有成本是十分有 效的。在存储系统的各个层面和不同应用领域都广泛使用虚拟化这个概念.考虑整个存储 层次大体分为应用、文件和块设备三个层次,相应的虚拟化技术也大致可以按这三个层 次分类. 目前大部分设备提供商和服务提供商都在自己的产品中包含存储虚拟化技术,使得用 户能够方便地使用。 2.容量扩展 目前而言,在发展趋势上,存储管理的重点已经从对存储资源的管理转变到对数据资 源的管理。随着存储系统规模的不断扩大,数据如何在存储系统中进行时空分布成为保 证数据的存取性能、安全性和经济性的重要问题。面对信息海量增长对存储扩容的需求 ,目前主流厂商均提出了各自的解决方案.由于存储现状比较复杂,存储技术的发展业界 还没有形成统一的认识,因此在应对存储容量增长的问题上,尚存在很大的提升空间。 技术是发展的,数据的世界也是在不断变化的过程中走向完美。企业信息架构的"分"与 "合"的情况并不绝对.目前、出现了许多的融合技术,如 NAS与SAN的融合,统一存储网等等.这些都将对企业信息架构产生不同的影响。至于到底 采用哪种技术更合适,取决于企业自身对数据的需求。 3. 海量数据存储技术 为了支持大规模数据的存储、传输与处理,针对海量数据存储目前主要开展如下三个 方向的研究: 1. 虚拟存储技术 存储虚拟化的核心工作是物理存储设备到单一逻辑资源池的映射,通过虚拟化技术, 为用户和应用程序提供了虚拟磁盘或虚拟卷,并且用户可以根据需求对它进行任意分割 、合并、重新组合等操作,并分配给特定的主机或应用程序,为用户隐藏或屏蔽了具体的 物理设备的各种物理特性。存储虚拟化可以提高存储利用率,降低成本,简化存储管理, 而基于网络的虚拟存储
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值