写在前面

  学习《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. Charles抓包2-Charles抓包https请求

    目录 1.开启SSL代理 2.安装证书 3.导出证书 4.浏览器安装证书 1.开启SSL代理 菜单,代理-->SSL代理设置 勾选启用SSL代理 在包括选项,添加主机:*,端口:443 确定保存 ...

  2. skfpdb.db、cc3268.dll、system_V2.dat、JI60JS.dat文件内容、发票数据查询

    cc3268.dll.skfpdb.db.xxxxx_V2.dat,system.dat,JI60JS.dat,log.dat,system_V2.dat,JI60JS_V2.dat,log_V2.d ...

  3. cookie与session区别?

    参考 cookie与session的区别是什么 Java中Cookie的使用(Cookie 和Session的区别) 什么是会话? 用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭 ...

  4. 利用VS自带发布功能实现web项目快速部署

    你还在使用最原始的方法部署服务器吗?还在把项目文件全部复制然后黏贴到服务器上?这种方法太low而且又慢又不安全(存在源码泄露等安全性问题),如果你是这样,那你自己肯定也为此烦恼不已. 下面我所要讲到的 ...

  5. 使用IDEA+Gradle构建Spring5源码并调试(手把手教程全图解)

    一.前言   说一说我要写这篇文章的初衷吧,前段时间有小伙伴在微信群求教怎样构建spring源码,他在网上找了n个教程跟着后面花了两天时间都没构建好,正好我最近因工作原因从mac换成windows,开 ...

  6. 键盘侠Linux教程(五)| 基本权限管理

    基本权限管理 权限的介绍 权限位的含义 前面讲解ls命令时,我们已经知道长格式显示的第一列就是文件的权限,例如: [root@es ~]# ls -l anaconda-ks.cfg -rw----- ...

  7. Tensorflow 中(批量)读取数据的案列分析及TFRecord文件的打包与读取

    内容概要: 单一数据读取方式: 第一种:slice_input_producer() # 返回值可以直接通过 Session.run([images, labels])查看,且第一个参数必须放在列表中 ...

  8. 利用python打印杨辉三角

    用python打印杨辉三角 介绍 杨辉三角,是初高中时候的一个数列,其核心思想就是说生成一个数列,该数列中的每一个元素,都是之前一个数列中,同样位置的元素和前一个元素的和. 正好在python中,也就 ...

  9. eclipse .project文件 .classpath文件的作用

    .classpath文件的作用 可以参考.classpath文件的作用 .project文件的作用 确保你自己的eclipse能创建Java项目,并且正确编译运行helloworld,给eclipse ...

  10. linux 上设置mysql开机自启

    此方式是通过安装包安装的,如果是yum安装的rpm包,可参考yum安装MySQL8.0 三个月之前安装的mysql,记得是设置了开机自启,但是今天再次进入的时候发现,无法登录,报错如下 原因是mysq ...