Redis小记(一)
1、redis的数据结构
(1)动态字符串(SDS)
redis自身构建了一个简单动态字符串的抽象类型,SDS,在redis里,包含字符串的键值对在底层都是由SDS来实现的。
除了用来保存数据库的字符串值之外,SDS还被用来作缓冲区:AOF模块中的AOF缓冲区、客户端输入缓冲区。
SDS的结构:free,当free属性值为0时,表示SDS没有分配未使用空间;len,SDS保存的字符串长度;buf[],char数组类型,将保存的字符串值拆分保存,最后跟一个空字符 \0 ,空字符不计算到len属性里。
SDS的特性:len属性,在获取字符串长度时时间复杂会降低,仅为O(1),避免了获取字符串长度成为redis性能瓶颈,
通过len属性杜绝缓冲区溢出
通过空间预分配和惰性空间分配来减少修改字符串时带来的内存重分配次数,空间预分配,当SDS中保存一个长度为5的字符串,此时SDS的属性len=5,free=0,在其后添加一个长度为5的字符串,再加上一个空字符,此时长度为len=5+5+1 =11而SDS会在分配一个长度为11的空闲空间,SDS属性len=11,free=11;惰性空间,SDS属性len=11,free=0,减少字符串3位,此时SDS属性len=8,free=3,SDS不会把空余空间收回,而是交给free进行记录,以供下次使用
可以保存文本和二进制数据
(2)链表
链表可以提供高效的节点重排能力、顺序性节点访问、并且可以通过增删节点来灵活的调节链表长度,因此redis中对链表应用很广泛,例如列表键、发布/订阅、慢查询、监视器、构建客户区缓冲区等
每个链表节点都由一个ListNode结构表示,都有执向前节点和后节点的指针以及链表长度等信息,redis中实现的是双向无环链表,根据不同类型的特定函数,可以保存不同类型的值
(3)字典(symbol table)
用于保存键值对的抽象数据结构,字典中一个键可以和一个值进行关联,redis中数据库底层就是通过自身构建的字典来实现的,对数据库的增删改查也都是在对字典进行操作
Redis中字典的底层是由哈希表实现的,一个哈希表有多个哈希节点,每个节点保存了字典的一个键值对,字典的结构包含类型特定函数 type属性;私有数据privdata;哈希表ht[2]每个字典携带两个哈希表,一个存储数据,一个rehash时使用;rehash索引 trehashidx,当rehash不再进行时,值为-1
Redis中字典所使用的哈希表中主要包含哈希表数组 table、哈希表大小size、哈希表大小掩码值sizemask用于计算索引值、哈希表已有节点数量used
哈希表数组table使用dictEntry结构,dictEntry结构都保存着一个键值对和一个指向下一个节点的指针,形成一个链表,这个指针还可以将多个哈希值相同的键值对连接在一起,避免发生键冲突的问题
当要将一个新的键值对添加到字典里时,需要先根据键值对的键计算出哈希值和索引值,redis中使用MurmurHash2算法来计算哈希值,然后根据索引值,将包含新键值对的哈希表放到字典中哈希数组指定的索引上。

当哈希表中保存的键值对过多或过少时,需要对哈希表的大小进行处理,此时可以通过重新散列(rehash)来处理
重新散列的过程:根据ht[0]哈希表的used属性定义ht[1]的大小,扩展操作中ht[1]的大小是第一个大于等于ht[0].used*2的2^n,如果是收缩操作,ht[1]的大小是第一个大于等于ht[0].used的2^n,例如:扩展:ht[0].used =4,4*2=8,8=2^3,那么ht[1]的大小就是8,收缩:若ht[0].used=6,第一个大于等于6的2的n次方是2^3,那么ht[1]的大小就是8
将ht[0]中的键值对重新计算哈希值和索引值,然后保存到ht[1]指定位置上
释放ht[0],将ht[1]设置为ht[0],并在ht[1]新建一个空白的哈希表,以供下一次rehash使用
(4)跳跃表(skiplist)
一种有序的数据结构,通过在每个节点维持多个指向其他节点的指针,实现快速访问,Redis中有序集合键(set)底层由跳跃表来实现以及集群节点中跳跃表作内部数据结构。
跳跃表由zskiplistNode结构和zskiplist结构组成,zskiplistNode表示跳跃表节点,zskiplist用于存储跳跃表节点相关信息,包含跳跃表的表头节点header属性、跳跃表的表尾节点tail属性、记录跳跃表层数最大的节点数level属性、跳跃表长度length属性
(5)压缩列表(ziplist)
redis中列表和哈希的底层实现之一,当要保存少量的整数值、小数值或者较短的字符串,redis就会使用压缩列表作为底层实现
压缩列表的出现是为了redis 节约内存,它是由一系列的特殊编码的连续内存块组成顺序型结构,一个压缩列表可以包含任意多个节点,每个节点可以保存一个字节数组或一个整数值
(6)整数集合(intset)
Redis中集合的底层实现之一,当集合中都是整数时,redis默认使用整数集合作为集合的底层实现。intset结构包含三个属性,encoding编码格式、length数量、contents[]保存数据的数组,从小到大排序,是整数集合的底层实现,数组保存的数据类型由encoding来确定,程序会根据新添加的数据类型来改变数组的类型
2、redis的对象
redis中基于数据结构来创建了一个对象系统,系统中包含字符串对象、列表对象、哈希对象、集合对象和有序集合对象,通过这些对象来实现数据库、键值对,redis队象系统还通过引用计数技术实现内存回收机制和对象共享机制
redis使用对象来表示数据库中的键和值,每当我们在数据库中新建一个键值对时,我们都会创建至少两个对象,键值对的键和键值对的值
redis中每个对象都是由redisobject结构表示,包含type属性、encoding(编码类型属性)、ptr(指向底层实现数据结构的,数据结构有对象的encoding决定)


每种不同类型的对象都至少使用两种编码

(1)字符串对象
字符串编码的对象可以是int、raw、embstr
字符串对象保存的是整数值并且这个整数值可以用long类型表示,那么字符串对象会把整数值保存在ptr属性里并设置编码为int
字符串对象保存的是字符串值,若长度大于32字节,那么字符串对象会把字符串值保存在SDS里,并设置编码为raw,若小于32字节,那么字符串对象会设置编码为embstr
字符串对象保存的是long double 类型的值,那么字符串对象编码设置为embstr或raw
(2)列表对象
列表对象的编码是zipList(压缩列表)或者linkedlist(双端链表)
linkedList编码的列表对象在底层双端链表中包含了多个字符串对象
字符串对象是redis对象中唯一一个被其他四种类型嵌套的对象
列表对象保存的字符串长度<64字节,数量小于<512个,使用zipList,反之使用linkedlist,但是这两个值在配置文件中可以修改,list-max-ziplist-value和list-max-ziplist-entries
(3)哈希对象
哈希对象编码是ziplist(底层压缩列表)和hashtable(底层字典,每一个键、值都是字符串对象)
哈希对象对象保存的字符串长度<64字节,数量小于<512个,使用zipList,反之使用hashtable,但是这两个值在配置文件中可以修改,hash-max-ziplist-value和hash-max-ziplist-entries
(4)集合对象
集合对象编码是intset(底层整数集合)和hashtable(底层字典,每一个键、值都是字符串对象)
集合对象保存的值都是整数值且数量不超过512个,使用inset,反之使用hashtable,数量值在配置文件中可以修改,set-max-inset-value
(5)有序集合对象
有序集合对象编码是ziplist(底层压缩列表,从小到大排序)和skiplist(底层zset,一个zset包含一个跳跃表和一个字典,从小到大排序)
有序集合同时使用跳跃表和字典实现的原因:通过保留字典和跳跃表的优点,提高有序集合的查找和范围性操作的性能和效率
有序集合对象保存的值数量小于128,所有成员长度<64字节,使用ziplist,反之使用skiplist,但是这两个值在配置文件中可以修改,zset-max-ziplist-value和zset-max-ziplist-entries
(6)内存回收
redis在自己的对象系统中构建一个引用计数技术实现的内存回收机制,程序跟踪对象的引用计数信息,适当的时候自动释放对象并进行内存回收。
每个对象的引用计数信息由redisObject结构的refcount属性记录。
创建一个新对象时,初始化计数值为1,当对象被一个新程序使用时,引用计数加一,不再被程序使用时,引用计数减一,当引用计数为0时,对象占用的内存会被释放。
(7)对象共享
redis对象共享通过对象的计数属性实现,将数据库键的指针值指向同一个现有的值对象,被共享的值对象的引用计数增加一。
但是共享对象不包含字符串对象,若是字符串对象共享,验证时间会大大提升,验证int类型,复杂度为O(1),而验证字符串类型复杂度为O(N),多个对象复杂度为O(N^2)
(8)其他
SET、GET、APPEND、STRLEN等命令只能对字符串键执行
HDEL、HSET、HGET、HLEN等命令只能对哈希键执行
RPUSH、LPOP、LINSERT、LLEN等命令只能对列表键执行
SADD、SPOP、SINTER、SCARD等命令只能对集合键执行
ZADD、ZCARD、ZRANK、ZSCORE等命令只能对有序集合键执行
Redis小记(一)的更多相关文章
- Redis 小记
最近感觉自己像是又回到了起点,知识层面上落人太多,尤其是去年早些时候几乎啥也没干成,觉得什么也不会了,只能再次从零开始,所以决定再喝两个疗程的巩固巩固. 话不多说,我们先来看看 Redis 官方是怎么 ...
- 「Nosql」Redis小记-内存解析&内存消耗篇
*博客搬家:初版发布于 2017/08/12 18:32 原博客地址:https://my.oschina.net/sunqinwen/blog/1507171 Redis内存消耗分析 注:本文 ...
- Redis小记(三)
1.复制 通过slaveof命令或设置slaveof选项,实现一个服务器去复制另一个服务器,被复制的是主服务器,执行复制的是从服务器,复制过程中主从双方数据库保持数据一致 2.8版本以前,可分为初次复 ...
- Redis小记(二)
1.redis数据库 redis数据库属于内存数据库,若不将数据存到磁盘中,服务器进程退出,数据也会消失 redis所有数据库都保存在redisServer结构的db数组中,db数组的每一项都是一个r ...
- MongoDB 小记
之前本人说过一款非关系型数据库的代表 Redis 的 < Redis 小记 >文章,觉得意犹未尽,今天就来介绍一款数据库 MongoDB ,先来看一下 MongoDB是一款基于分布式文件存 ...
- Redis Sentinel配置小记
Sentinel是一个管理多个redis实例的工具,它可以实现对redis的监控.通知.自动故障转移.sentinel不断的检测redis实例是否可以正常工作,通过API向其他程序报告redis的状态 ...
- Docker 小记 — MySQL 与 Redis 配置
前言 本篇随笔是继 "Docker Engine" 与 "Compose & Swarm" 之后的一个实例补充,初衷是记录测试环境中的一次 MySQL ...
- Redis 学习小记
由于是学习笔记,我就不来各种啰嗦,介绍这个介绍那个,也不上交给国家,或者各种对比,相信如果你真心用 redis 的话,就不会去跟 MySql,Memcached,MongoDB 等做对比了. 我原先用 ...
- 小记redis持久化的机制
刚学redis,就经常看到两种持久化机制在眼头晃,RDB和AOF,然而当时学的还知道这两东西是啥玩意,过段时间又忘了,中文记忆这两种概念总感觉有些别扭.今心血来潮翻看redis的配置文件,豁然开朗,仿 ...
随机推荐
- 使用Arcgis时,在sde空间库常用的相关函数
一.Oracle库中配置好sde空间库常见的场景 1.在sde库中创建表:community 创建表:community 字段:id(INTEGER), shape(ST_GEOMETRY) 2.往s ...
- js区别对象和数组的三种方法
var arr = {}||[]; 区分arr是数组还是对象 1.arr.constructor ...
- 超简单集成华为HMS ML Kit文本识别SDK,一键实现账单号自动录入
前言 在之前的文章<超简单集成华为HMS Core MLKit通用卡证识别SDK,一键实现各种卡绑定>中我们给大家介绍了华为HMS ML Kit通用卡证识别技术是如何通过拍照自动识别卡 ...
- 手写区分PC还是手机移动端
区分首先要了解window.navigator 输出navigator appCodeName: "Mozilla" appName: "Netscape" a ...
- Vue企业级优雅实战03-准备工作04-全局设置
本文包括如下几个部分: 初始化环境变量文件 JS 配置文件初始化:如是否开启 Mock 数据.加载本地菜单.URL 请求路径等: 国际化文件初始化:初始化国际化文件的结构: 整合 Element UI ...
- 深入了解Kafka【五】Partition和消费者的关系
1.消费者与Partition 以下来自<kafak权威指南>第4章. 假设主题T1有四个分区. 1.1.一个消费者组 1.1.1.消费者数量小于分区数量 只有一个消费者时,消费者1将收到 ...
- JavaScript函数及面向对象
函数及面向对象 目录 函数及面向对象 1. 定义函数 1. 定义方式一 2. 定义方式二 2. 调用函数 1. 参数问题 2. arguments 3. rest 3. 变量的作用域 1 . var的 ...
- IDEA创建新空项目
IDEA创建新空项目 File -> New -> Project -> Empty Project -> 然后OK 这个是什么都不能做的,然后我们创建Module. File ...
- 如何入门Pytorch之四:搭建神经网络训练MNIST
上一节我们学习了Pytorch优化网络的基本方法,本节我们将以MNIST数据集为例,通过搭建一个完整的神经网络,来加深对Pytorch的理解. 一.数据集 MNIST是一个非常经典的数据集,下载链接: ...
- VMware安装Centos7并联网使用
一.安装VMware VMwareworkstation官方下载地址: https://www.vmware.com/cn/products/workstation-pro/workstation-p ...