写在前面

  学习《redis入门指南》笔记,结合实践,只记录重要,明确,属于新知的相关内容。

节省空间

  1、redis对于它所支持的五种数据类型,每种都提供了两种及以上的编码方式去存储(具体对应的编码方式可以百度)。因为基于内存的缘故,所以为了平衡时间与空间的使用效率在元素数量较多或较少时采用不同的策略,当然对于使用者这是透明的。

  2、查看redis键值的内部编码方式

    OBJECT ENCODING key

  3、对于每一个键,都会有一个结构提存储它的数据类型,编码格式,数据地址等信息。

 typedef struct redisObject
{
unsigned type:; // 这种语法叫做位字段
unsigned notused:;
unsigned encoding:;
unsigned lru:;
int refcount;
void *ptr;
}

   4、对于字符串类型(示意结构如下),键值可以用一个64位整数表示时,就会使用数据指针表示数据内容(REDIS_ENCODING_INT编码方式),以节省空间;redis3.0引入了REDIS_ENCODING_EMBSTR编码方式,在键值长度小于39时,字符串本身就会跟在redisObject结构之后,减少申请释放内存次数;当对REDIS_ENCODING_EMBSTR编码方式的字符串做任何修改后,都会改为REDIS_ENCODING_RAW编码方式;redis启动后,会预先建立10000个从0~9999这些数字的redisObject结构,当我们set这些值时会直接引用向它们,并自增refcount这个引用,但如果在配置文件参数中设置了maxmemory参数,将不会预先存储这些共享对象。

 struct shshdr          // 仅仅是示意结构
{
int len;
int free;
char buf[];
}

  5、对于散列类型,当字段个数小于hash-max-ziplist-entries(配置文件参数,默认512)并且每个字段值长度小于hash-max-ziplist-value(配置文件参数,默认64)时,采用REDIS_ENCODING_ZIPLIST(示意结构如下)编码,否则采用REDIS_ENCODING_HT(真正的散列表);对于redis的键值对存储也是用散列表,但并不使用redisObject结构,所以数字键名不会比字符串名节省空间。

 zlbytes // uint32 整个结构占用的空间
zltail // uint32 末尾元素偏移
zllen // unit16 元素数量 ————————————————————
元素1 ----------------------> | 前一个元素大小 |
元素2 | 当前元素的编码类型 |
元素3 | 当前元素大小 |
...... | 当前元素内容 |
zlend // 结尾标识,永远为255 ————————————————————

  REDIS_ENCODING_ZIPLIST中的每个元素由四部分构成。

  第一部分存储前一个元素大小,用于倒序查找,当前一个元素小于254字节时,第一部分占用一个字节,否则占用5个字节;

  第二、三部分为元素编码类型和大小,当元素长度不大于63字节时,编码为ZIP_STR_06B(即0<<6),同时第三部分用6个二进制位记录长度,此时二、三部分占用一个字节;当元素长度大于63且小于16383字节时,二、三部分占用2字节,大于16383时占用5字节;

  第四部分如果元素内容可以转为数字的话会用相应数字存储,并用二、三部分来表示元素数字的类型(int16_t,int32_t等)。

  使用REDIS_ENCODING_ZIPLIST存储散列类型时,元素1存储字段1,元素2存储字段1值;插入,删除,查找(一跳一跳查找,跳过字段值)时都将移动后面的元素或遍历,因此上文的两个参数不能过大。

  6、对于列表类型,有REDIS_ENCODING_LINKEDLIST 和REDIS_ENCODING_ZIPLIST两种编码,也有list-max-ziplist-entries和list-max-ziplist-value两个参数控制变换编码的时机;REDIS_ENCODING_LINKEDLIST即双向链表,优化方式与字符串类型的键值相同;较新版本的redis增加了REDIS_ENCODING_QUICKLIST编码方式,它将一个长列表分成若干个以链表形式组织的ziplist,在减少空间占用的同时,提示REDIS_ENCODING_ZIPLIST编码的性能。

  7、对于集合类型,有REDIS_ENCODING_HT和REDIS_ENCODING_INTSET(结构如下),当元素都为整数且元素个数小于set-max-intset-entries(配置文件参数,默认512)时,采用REDIS_ENCODING_INTSET;intset默认的encoding是INTSET_ENC_INT16(即2字节),当无法满足时会升级为INTSET_ENC_INT32或INTSET_ENC_INT64,同时调整之前的元素;intset按序存储,采用二分查找,插入和删除效率较低;当初先非数字元素时,编码立刻变为REDIS_ENCODING_HT,此时即便将非数字元素删除,编码也不会回转。

 typedef struct intset
{
uint32_t encoding;
uint32_t length;
int8_t contents[];
} intset;

  8、对于有序集合类型,有REDIS_ENCODING_SKIPLIST和REDIS_ENCODING_ZIPLIST,同样有两个参数zset-max-ziplist-entries和zset-max-ziplist-value去控制何时变换编码为跳跃表REDIS_ENCODING_SKIPLIST;在这种编码方式下使用两种数据结构来存储有序集合类型键值,散列表用来存储元素值与元素分数的映射关系以实现O(1)时间复杂度的命令,跳跃表存储元素分数及到元素的映射用以实现排序功能;这里的跳跃表允许分数相同的元素存在,并且增加了指向前一个元素的指针以实现倒序查找;此时元素值是用redisObject结构存储的,与字符串类型键值优化方式相同,分数按照double存储;采用REDIS_ENCODING_ZIPLIST时,按照“元素1的值,元素1的分数”的顺序排列,并且分数是有序的。

 

redis入门指南(四)—— redis如何节省空间的更多相关文章

  1. redis入门指南-安装redis

    纸上得来终觉浅 绝知此事要躬行 Redis官方不支持window.微软发布了可在redis的分支.不建议使用 但我确实用了. win7 redis2.8.4  php5.6  apache2.4 ht ...

  2. Redis入门指南之一(简介)

    1. 简介 Redis是一个开源的.高性能的.基于键值对的缓存与存储系统,通过提供多种键值数据类型来适应不同的场景下的缓存与存储需求.同时Redis的诸多高级功能使其可以胜任消息队列.任务队列等不同的 ...

  3. redis入门指南(七)—— 安全、协议、管理工具及命令属性

    写在前面 学习<redis入门指南>笔记,结合实践,只记录重要,明确,属于新知的相关内容. 安全 1.可以使用bind参数绑定一个地址,使redis只接受这个地址的连接. 2.使用requ ...

  4. Redis入门指南之三(入门)

    本节主要介绍Redis的5种数据类型,同时使用Python API来操作Redis,其中python版本为3.5, redis版本为4.0.2. redis-py 的API的使用可以分类为: (1)连 ...

  5. Redis入门指南之二(安装及配置)

    本节主要内容 1. 前言2. redis安装3. 启动和停止Redis 1. 前言 安装Redis需要知道自己需要哪个版本,有针对性的安装,比如如果需要redis GEO这个地理集合的特性,那么red ...

  6. redis入门指南(二)—— 数据操作相关命令

    写在前面 以下绝大部分内容取材于<redis入门指南>,部分结合个人知识,实践后得出. 只记录重要,明确,属于新知的相关内容,杜绝冗余和重复. 字符串 1.字符串类型是redis中最常见的 ...

  7. redis入门指南(三)—— 事务、过期时间、SORT命令、消息通知与管道

    写在前面 学习<redis入门指南>笔记,结合实践,只记录重要,明确,属于新知的相关内容. 事务 1.redis中的事务由一组命令的集合组成,要么都执行,要么都不执行,同时redis的事务 ...

  8. redis入门指南(五)—— 复制与哨兵

    写在前面 学习<redis入门指南>笔记,结合实践,只记录重要,明确,属于新知的相关内容. 一.复制 1.在复制中,数据库分为两类,一类主数据库,一类从数据库,主库用来读写,从库用来读,主 ...

  9. redis入门指南(六)—— 集群

    写在前面 学习<redis入门指南>笔记,结合实践,只记录重要,明确,属于新知的相关内容. 配置集群 1.配置集群,集群解决了单点故障以及单台机器内存上限的问题,使用集群时,只需要将配置文 ...

随机推荐

  1. 2019-02-07 selenium...

    今天是超级郁闷的一天 看教程 下了mysql-----配置-----不会----查资料------2小时后 mongodb-----配置------不会------查资料------1小时后 然后是各 ...

  2. python基础--程序交互、格式化输出、流程控制、break、continue

    在此申明一下,博客参照了https://www.cnblogs.com/jin-xin/,自己做了部分的改动 (1) 程序交互 #!/usr/bin/env python # -*- coding: ...

  3. pdb--Python调试器

    使用python编写程序,必然会遇见bug,而pdb就是python语言的一个好的debugger. 下面介绍pdb的使用方式 1. 单步执行代码,通过命令 python -m pdb xxx.py ...

  4. LNMP 环境更换Nginx 服务器为Tengine

    本人之前所使用 LNMP 环境一直是原生的Nginx服务器,最近几天看了好多大网站使用 淘宝团队基于Nginx开发的 Tengine 决定给自己的虚拟机也装个玩玩. 关于Tengine的介绍就不多说了 ...

  5. WeChair项目Beta冲刺(1/10)

    团队项目进行情况 1.昨日进展    Beta冲刺第一天 前期进展: 对代码进行优化,完成上阶段冲刺未完成的实名认证上传图片的功能,解决解密存在部分失败的bug问题 2.今日安排 前端:设计扫码占座功 ...

  6. oracle不足位数补零的实现sql语句

    select rpad('AAA',5,'0') from dual; 这样就可以了 [注意] 1.'AAA'为待补字符:5表示补齐后的总字符长度:0表示不足时补什么字符 2.rpad是右侧补0,左侧 ...

  7. JavaWeb网上图书商城完整项目--day02-3.regist页面输入框失去焦点进行校验

    当输入框输入数据之后,当输入框失去焦点的时候,我们需要对输入的数据进行校验 l  用户名校验: 用户名不能为空: 用户名长度必须在3 ~ 20之间: 用户名已被注册(需要异步访问服务器). l  登录 ...

  8. 入门大数据---Spark_Transformation和Action算子

    一.Transformation spark 常用的 Transformation 算子如下表: Transformation 算子 Meaning(含义) map(func) 对原 RDD 中每个元 ...

  9. openstack迁移计算节点所有云主机

    迁移计算节点所有云主机 -------高德置地 王锦雄   使用host-evacuate-live热迁移主机 查看主机目前的云主机情况 nova hypervisor-servers cloud1 ...

  10. python+opencv实现图像缩放

    x, y = img_.shape[0:2] img_ = cv2.resize(img_, (int(y/2), int(x/2))) 实现图像长宽缩小为原来的一半