redis入门指南(四)—— redis如何节省空间
写在前面
学习《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如何节省空间的更多相关文章
- redis入门指南-安装redis
纸上得来终觉浅 绝知此事要躬行 Redis官方不支持window.微软发布了可在redis的分支.不建议使用 但我确实用了. win7 redis2.8.4 php5.6 apache2.4 ht ...
- Redis入门指南之一(简介)
1. 简介 Redis是一个开源的.高性能的.基于键值对的缓存与存储系统,通过提供多种键值数据类型来适应不同的场景下的缓存与存储需求.同时Redis的诸多高级功能使其可以胜任消息队列.任务队列等不同的 ...
- redis入门指南(七)—— 安全、协议、管理工具及命令属性
写在前面 学习<redis入门指南>笔记,结合实践,只记录重要,明确,属于新知的相关内容. 安全 1.可以使用bind参数绑定一个地址,使redis只接受这个地址的连接. 2.使用requ ...
- Redis入门指南之三(入门)
本节主要介绍Redis的5种数据类型,同时使用Python API来操作Redis,其中python版本为3.5, redis版本为4.0.2. redis-py 的API的使用可以分类为: (1)连 ...
- Redis入门指南之二(安装及配置)
本节主要内容 1. 前言2. redis安装3. 启动和停止Redis 1. 前言 安装Redis需要知道自己需要哪个版本,有针对性的安装,比如如果需要redis GEO这个地理集合的特性,那么red ...
- redis入门指南(二)—— 数据操作相关命令
写在前面 以下绝大部分内容取材于<redis入门指南>,部分结合个人知识,实践后得出. 只记录重要,明确,属于新知的相关内容,杜绝冗余和重复. 字符串 1.字符串类型是redis中最常见的 ...
- redis入门指南(三)—— 事务、过期时间、SORT命令、消息通知与管道
写在前面 学习<redis入门指南>笔记,结合实践,只记录重要,明确,属于新知的相关内容. 事务 1.redis中的事务由一组命令的集合组成,要么都执行,要么都不执行,同时redis的事务 ...
- redis入门指南(五)—— 复制与哨兵
写在前面 学习<redis入门指南>笔记,结合实践,只记录重要,明确,属于新知的相关内容. 一.复制 1.在复制中,数据库分为两类,一类主数据库,一类从数据库,主库用来读写,从库用来读,主 ...
- redis入门指南(六)—— 集群
写在前面 学习<redis入门指南>笔记,结合实践,只记录重要,明确,属于新知的相关内容. 配置集群 1.配置集群,集群解决了单点故障以及单台机器内存上限的问题,使用集群时,只需要将配置文 ...
随机推荐
- excel如何快速统计出某一分类的最大值?
问题:如何统计出某一分类的最大值? 解答:利用分类汇总或透视表快速搞定! 思路1:利用分类汇总功能 具体操作方法如下: 选中数据区任意一个单元格,然后点击“数据-分类汇总”按钮.(下图 1 处). 在 ...
- flink实时数仓从入门到实战
第一章.flink实时数仓入门 一.依赖 <!--Licensed to the Apache Software Foundation (ASF) under oneor more contri ...
- 大数据之Hudi + Kylin的准实时数仓实现
问题导读:1.数据库.数据仓库如何理解?2.数据湖有什么用途?解决什么问题?3.数据仓库的加载链路如何实现?4.Hudi新一代数据湖项目有什么优势? 在近期的 Apache Kylin × Apach ...
- Arduino+sim800C家居安防火灾报警 拨打电话 发送短信例程程序
家居安防报警器,参考程序. 火灾报警 涉及用sim800c发短信,拨打电话通知. 接线: Sim800c 3.3V -> Arduino 3.3V Sim800c GND -> Ardui ...
- 《Java并发编程的艺术》 第9章 Java中的线程池
第9章 Java中的线程池 在开发过程中,合理地使用线程池能带来3个好处: 降低资源消耗.通过重复利用已创建的线程 降低线程创建和销毁造成的消耗. 提高响应速度.当任务到达时,任务可以不需要等到线程创 ...
- cb20a_c++_string类型的查找
cb20a_c++_string类型的查找s.find(args) //精确匹配,顺序查找, abc, 连续的包含在abcde,或者fabcde;s.rfind(args) //精确匹配.反向查找s. ...
- spring源码分析——BeanPostProcessor接口
BeanPostProcessor是处理bean的后置接口,beanDefinitionMaps中的BeanDefinition实例化完成后,完成populateBean,属性设置,完成 初始化后,这 ...
- 线程基础9-quene讲解
在学习Java 多线程并发开发过程中,了解到DelayQueue类的主要作用:是一个无界的BlockingQueue,用于放置实现了Delayed接口的对象,其中的对象只能在其到期时才能从队列中取走. ...
- 最简单的jQuery轮播图(原理解析)
html: <div class="middle_right"> <div id="lunbobox"> <div id=&quo ...
- Kali Day1
一.最新版本的Kali Linux的账号名和密码都是kali. 如何切换root 步骤如下: 1. 设置密码 sudo passwd root 2. 切换身份 su 3. 图示 二.快捷键 1. K ...