一文搞懂 Redis下降内存占用方式

前言

Redis是当前比较热门的NOSQL数据库之一,和Memcache同样,数据都是缓存在计算机内存中。彻底开源免费,遵照BSD协议,是一个高性能的key-value数据库。经过在内存中读写数据,大大提升了数据读写速度,能够说Redis是实现网站高并发不可或缺的一部分。redis

下降Redis的内存占用有助于减小建立快照和加载快照所需的时间、提高载入AOF文件和重写AOF文件时的效率、缩短从服务器进行同步所需的时间”,而且能让Redis存储更多的数据而无需添加额外的硬件。数据库

本文将介绍如下3种很是有价值的下降Redis内存占用的方法。数组

  • 短结构( short structure )
  • 分片结构( shared structure )
  • 打包存储二进制位和字节

短结构

Redis为列表、集合、散列、有序集合提供了一组配置选项,这些选项可让redis以更节约的方式存储较短的结构。缓存

ziplist压缩列表(列表、散列、有序集合)

一般状况下使用的存储方式:bash

当列表、散列、有序集合的长度较短或者体积较小的时候,redis将会采用一种名为ziplist的紧凑存储方式来存储这些结构。服务器

ziplist是列表、散列、有序集合这三种不一样类型的对象的一种非结构化表示,它会以序列化的方式存储数据,这些序列化的数据每次被读取的时候都须要进行解码,每次写入的时候也要进行编码。数据结构

双向列表与压缩列表的区别:并发

为了了解压缩列表比其余数据结构更加节约内存,咱们以列表结构为例进行深刻研究。高并发

典型的双向列表性能

在典型双向列表里面,每一个值都都会有一个节点表示。每一个节点都会带有指向链表前一个节点和后一个节点的指针,以及一个指向节点包含的字符串值的指针。

每一个节点包含的字符串值都会分为三部分进行存储。包括字符串长度、字符串值中剩余可用字节数量、以空字符结尾的字符串自己。

例子:

倘若一个某个节点存储了’abc’字符串,在32位的平台下保守估计须要21个字节的额外开销(三个指针+两个int+空字符即:3*4+2*4+1=21)

由例子可知存储一个3字节字符串就须要付出至少21个字节的额外开销。

ziplist

压缩列表是由节点组成的序列,每一个节点包含两个长度和一个字符串。第一个长度记录前一个节点的长度(用于对压缩列表从后向前遍历);第二个长度是记录本当前点的长度;被存储的字符串。

例子:

存储字符串’abc’,两个长度均可以用1字节来存储,所以所带来的额外开销为2字节(两个长度即1+1=2)

结论:

压缩列表是经过避免存储额外的指针和元数据,从而达到下降额外的开销。

intset整数集合(集合)

前提条件,集合中包含的全部member均可以被解析为十进制整数。

以有序数组的方式存储集合不只能够下降内存消耗,还能够提高集合操做的执行速度。

配置:

1 set-max-intset-entries 512 #限制集合中member个数,超出则不采起intset存储复制代码

性能问题

无论列表、散列、有序集合、集合,当超出限制的条件后,就会转换为更为典型的底层结构类型。由于随着紧凑结构的体积不断变大,操做这些结构的速度将会变得愈来愈慢。 

分片结构

分片的本质就是基于简单的规则将数据划分为更小的部分,而后根据数据所属的部分来决定将数据发送到哪一个位置上。不少数据库使用这种技术来扩展存储空间,并提升本身所能处理的负载量。

结合前面讲到的,咱们不难发现分片结构对于redis的重要意义。所以咱们须要在配置文件中关于ziplist以及intset的相关配置作出适当的调整。

回到顶部

分片式散列

散列分片主要是根据基础键以及散列包含的键计算出分片键ID,而后再与基础键拼接成一个完整的分片键。在执行hset与hget以及大部分hash命令时,都须要先将key(field)经过shardKey方法处理,获得分片键才可以进行下一步操做。

分片式集合

如何构造分片式集合才可以让它更节省内存,性能更增强大呢?主要的思路就是,将集合里面的存储的数据尽可能在不改变其原有功能的状况下转换成能够被解析为十进制的数据。根据前面所讲到的,当集合中的全部成员都可以被解析为十进制数据时,将会采用intset存储方式,这不只可以节省内存,并且还能够提升响应的性能。

例子:

倘若要某个大型网站须要存储每一天的惟一用户访问量。那么就可使用将用户的惟一标识符转化成十进制数字,再存入分片式set中。

打包存储二进制位和字节

结合前面所讲的分片技术,采用string分片结构为大量连续的ID用户存储信息。

使用定长字符串,为每个ID分配n个字节进行存储相应的信息。

接下来咱们将采用存储用户国家、省份的例子进行讲解:

倘若某个用户须要存储中国、广东省这两个信息,采用utf8字符集,那么至少须要消耗5*3=15个字节。若是网站的用户量大的话,这样的作法将会占用不少资源。接下来咱们采用的方法每一个用户仅仅只须要占用两个字节就能够完成存储信息。

具体思路步骤:

  1. 首先咱们为国家、以及各国家的省份信息创建相应的’信息表格’
  2. 将’信息表格’建好后,也意味着每一个国家,省份都有相应的索引号
  3. 看到这里你们应该都想到了吧,对就是使用两个索引做为用户存储的信息,不过须要注意的是咱们还须要对这两个索引进行相应的处理
  4. 将索引当作ASCII码,将其转换为对应ASCII(0~255)所指定的字符
  5. 使用前面所讲的分片技术,定长分片string结构,将用户的存储位置找出来(redis中一个string不能超过512M)
  6. 实现信息的写入以及取出(getrange、setrange)


因为平台篇幅限制,为了你们更好的阅读,关于Redis的文档小编已经打包整理好了,有感兴趣的程序猿(媛),能够加 QQ群 538700182 私聊群主 免费获取

相关文章
相关标签/搜索