redis访问速度和内存优化实践经验
Posted Frogjie
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis访问速度和内存优化实践经验相关的知识,希望对你有一定的参考价值。
内存优化
1. 平时的key很有可能是md5,sha1之类的字符串。如果key直接以字符串的方式,md5需要32个字节,sha1需要40个字节。但是md5和sha1这种类型的字符串是由规律的:每个字符都是0~f。也就是说,每个字符只需要4位就可以表示。所以我们可以在把md5或者sha1当做key直接存进去之前,把32字节md5压缩成16字节的二进制数据,把40字节的sha1压缩成20字节的二进制数据。这样,redis中所有key所占的内存就会少一半。
2. 对value使用压缩算法。平时业务中存储的value很多情况下都是json或者xml之类的形式。这种形式的数据中一般存在大量相同的字符,所以一般常见的压缩算法压缩这类数据的压缩比很高。比如有相关统计,gzip压缩json可以节省60%的空间。
3. 尽量不要频繁追加字符串类数据。redis自己实现了一个叫SDS的结构体来存储字符串数据。数据流存储在SDS的一个buffer中。此外,SDS维护了这个buffer的长度。当第一次给SDS中存放数据时,比如存放的数据是5个字节,redis会给SDS的buffer申请5个字节的大小。但是如果这个字符串发生了追加的操作,比如追加了10个字节。为了提高运行速度,防止下次追加时又要申请内存,SDS会申请30个字节给buffer(15个字节用来存储数据,另外15字节个用作下次追加数据)。如果buffer在1M以内,每次预分配的字节数和存储数据的字节数是一样的,相当于buffer会翻倍。如果buffer在1M以上,则每次预分配是1M。redis一般用来存储一些小的value,如果每个字符串都只追加一次,那么变相地相当于所有的value都用了2倍的空间。换句话说,就是redis用在value上的存储会翻一倍。
4. 巧用ziplist。ziplist会把数据压缩到一块连续的内存上,而不像链表或者hash表,需要存储一大堆指针来指向数据本身。redis中很多数据结构底层编码实现方式之一就是ziplist,而且大都提供了阈值(比如,list或者hash在元素超过多少个时,不再使用ziplist编码)。如果list的元素个数是已知的,而且比较固定,那么可以适当地调高这些阈值,让一些像list或者hash的结构使用ziplist来编码,这样可以大幅降低list或者hash的占用内存大小。当然,ziplist本身是用时间换取空间的,每次插入或者读取都是一种类似于解压的操作。如果元素个数较多或者value较大,那么就不建议这么做了。
访问速度优化
1. 打包命令,多个命令只做一次网络传输。redis的事务有个选项可以修改:$multi = $redis->multi(Redis::PIPELINE)。这样做的好处是多个命令会在一次网络传输中全部发送到server端(发送的字节数受TCP的最大字节数影响,多个命令可能会被拆成多个TCP包发送。但是也比一个TCP包只发送一条命令强得多)。这样做的不好的地方是,此时的multi已经不保证Redis版的事务了。如果对事务有一定的要求,那么此方法最好不要用。
2. 使用压缩算法压缩value,减小在网络中传输的字节数。现在的cpu是很强大的,瓶颈一般在网络传输上。如果可以减小在网络传输的数据大小,那么访问速度也会应声提高。
以上是关于redis访问速度和内存优化实践经验的主要内容,如果未能解决你的问题,请参考以下文章