Redis-跳跃表(skiplist)
什么是跳跃表? 看笔记”跳跃表(skiplist) “,本文主要介绍跳跃表在 Redis 的应用、核心数据结构和 API 。
用途说真的,跳跃表在 Redis 中使用不是特别广泛,只用在了两个地方。
作为有序集合键实现之一(如果一个有序集合包含的元素数量比较多,又或者有序集合中元素的成员(member)是比较长的字符串时,Redis就会使用跳跃表来作为有序集合键的底层实现。)
集群节点中用作内部数据结构。
数据结构
- 这样的结构,获取表头、表尾节点,表长,以及表中最高层数的复杂度均为O(1)。
- 位于图片最左边的是zskiplist结构,由 redis.h/zskiplist 定义:
``` C
typedef struct zskiplist {
// 头节点,尾节点(指向跳跃表的表头节点,表尾节点)
struct zskiplistNode *header, *tail;
// 节点数量-记录跳跃表的长度,也即是跳跃表目前包含节点的数量(表头节点不计算在内)
unsigned long length;
// 目前表内节点的最大层数-记录目前跳跃表内,层数最大的那个 ...
Redis-压缩表(ziplist)
定义压缩表没有数据结构代码定义,完全是通过一系列特殊编码的连续内存块组成的顺序性数据结构。它为了节约内存而而开发的。即:通过特殊的编码方式将数据存储在连续的内存中。
用途
在3.2之前是列表键的底层实现之一,在3.2之后被quicklist替代。
是有序集合键的底层实现之一。
是哈希键的底层实现之一。( 当一个哈希只包含少量键值对,并且每个键值对的键和值要么就是小整数值,要么就是长度比较短的字符串)
数据结构一个压缩列表可以包含任意多个节点(entry),每个节点可以保存一个字节数组或者一个整数数。
压缩列表结构
示例:
下图,展示了一个总长为80字节,包含3个节点的压缩列表。如果我们有一个指向压缩列表起始地址的指针p,那么表为节点的地址就是P+60。
压缩列表节点结构每个压缩列表节点可以保存一个字节数组或者一个整数值。字节数组可以是以下三种长度中的一种。
长度小于等于63(2^6-1)字节的字节数组;
长度小于等于16383(2^14-1)字节的字节数组
长度小于等于4294967295(2^32-1)字节的字节数组
整数值可以是以下6种长度中的一种:
4位长,介于0至 ...
Redis-双向链表(ADlist)
Redis使用C语言并没有内置中这种数据结构,所以Redis构建了自己的链表实现。
用途
在3.2之前是列表键的底层实现之一,在3.2之后被quicklist替代。
发布与订阅、慢查询、监视器等功能
Redis服务器使用链表保存多个客服端的状态信息
构建客户端输出缓冲区(outpub buffer)
数据结构
每个链表使用一个list结构来表示;
表头的前置节点和表尾的后置节点都可以指向NULL,因此Redis实现的是`无环链表`。
Redis-字典(dict)
字典,又称为符号表、关联数组、映射,是一种用于保存键值对的抽象数据结构。Redis使用C语言并没有内置中这种数据结构,所以Redis构建了自己的字典实现。
用途
是哈希键的底层实现之一;当一个哈希键包含了数量比较多的元素,或者包含的元素都是比较长的字符串时,就会选用字典作为哈希键的底层实现。
Redis的数据库就是使用字典作为底层实现的,对数据的CURD操作也是对构建在对字典的操作上的。
字典的结构
整体结构图
dict结构,在Redis中的字典dict.h/dict中定义:
1234567891011typedef struct dict{ //类型特定函数(dictType保存了一簇用于操作特定类型键值对的函数,Redis会为用途不同的字典设置不同的类型特定函数) dictType *type; //私有数据(保存了需要传给dictType类型特定函数的可选参数) void *privdata; //哈希表(数组中每一项都是一个dictht哈希表,一般情况下,字典只是用ht[0]哈希表,ht[1]只会在对hr[0]进行 ...
Redis-整数集合(intset)
用途整数集合是集合键(外数据结构set)的底层实现之一(当集合元素都是整数且元素数量不多时使用),它可以保存整数值,并且保证集合中不会出现重复元素。
数据结构inset结构体定义如下:
12345typedef struct intset { uint32_t encoding; // 编码方式,一个元素所需要的内存大小 uint32_t length; // 集合长度 int8_t contents[]; // 集合数组} intset;
encoding为inset的编码方式,有3种编码方式,分别对应不同范围的整型: #define INTSET_ENC_INT16 (sizeof(int16_t)) // -3276832767 #define INTSET_ENC_INT32 (sizeof(int32_t)) // -21474836482147483647 #define INTSET_ENC_INT64 (sizeof(int64_t)) // -2 ...
Redis-简单动态字符串(SDS)
引言:没有直接使用C语音的传统字符串表示,即:以空字符串结尾的字符数组,以下简称C字符串。而是自己构建名为SDS(simple dynamic string)的抽象类型。
为什么Redis使用SDS而不是C字符串?基于对字符串的安全性、效率以及功能方面的要求,C字符串不能满足。SDS具有以下优点:
常数复杂度获取字符串长度 - C字符串不记录自身长度
杜绝缓冲区溢出 - SDS会根据长度检查空间,自动扩容注:上面2点,是由于C字符串不记录自身长度导致的。
减少修改字符串长度时所需的内存重分配次数在一般程序中,每次修改字符串长度时,都会执行一次内存重新分配。SDS通过“未使用空间”,解除了字符串长度和底层数组长度的关联,并实现空间预分配和惰性空间分配释放两种优化策略。
二进制安全 - SDS API以处理二进制的方式来处理SDS存放在buf数组的数据,
兼容部分C字符串函数
SDS用途
保存数据库中字符串值
用作缓冲区:AOF模块中的AOF缓冲区以及客户端状态中的缓冲区
数据结构在3.2版本以前SDS只有一种数据结构,到了3.2版本以后SDS根据存储的内容会选择不同的数据结构, ...
Redis之源码结构属性
redisServer123456789101112131415161718struct redisServer {int dbnum;//服务器的数据库数量,值由服务器配置的“databases”选项决定,默认为16redisDb *db;//数组,保存着服务器中的所有数据库list *clients;//一个链表,保存了所有客户端状态,每个链表元素都是“redisClient”结构/*服务器时间缓存*/time_t unixtime;//保存秒级精度的系统当前UNIX时间戳,减少获取系统当前时间的系统调用次数,100毫秒更新一次long long mstime;//保存毫秒级精度的系统当前UNIX时间戳unsigned lruclock;//默认每10秒更新一次,用于计算数据库键的空转时长,数据库键的空转时长 = 服务器的“lruclock”属性值 - 数据库键值对象的“lru”属性值/*RDB持久化*/long long dirty;//修改计数器(记录距离上一次成功执行 save 命令或者 bgsave 命令之后,Redis服务器进行了多少次修改)time_t las ...
Redis 内部逻辑浅析
数据库操作
数据库服务器: redisServer结构 - db、dbnum属性服务器上数据库: redisDb结构 - dict、expires属性客户端:redisClient结构 - db属性
属性db是一个数组,保存着服务器上所有的数据库。
属性dbnum为服务器上数据库数量,默认值为16。切换数据库:redisClient结构中db属性记录了客户端的目标数据库(本质上它是一个redisDb结构的指针)。
切换数据库使用 SELECT <目标数据库号码>,本质就是改变db指针内容。
键空间键空间,即:redisDb结构的字典dict属性,保存数据库中所有键值对.对键的增删改查操作都是通过对健空间字典进行操作实现的。
读取键空间时维护操作
根据键是否存在,来更新服务器的键空间命中次数或不命中次数,可以使用INFO stats命令查看keyspace_hits属性和keyspace_misses属性。
更新键的LRU(最后一次使用)时间,这个值可以用于计算键的闲置时间。可以使用OBJECT idletime命令查看key的闲置空间。
检查键是否过期,过期会删除 ...
Redis使用指南
引言
Redis是一个开源的、高性能的(key-value)分布式内存数据库,基于内存上运行。Redis是单进程多路IO复用模型每秒写8万次,读11万次。
Redis能干嘛?可以用作数据库、缓存和消息中间件MQ。
持久化数据
缓存
发布订阅系统
计时器、计数器(浏览量)
地图信息分析
…数据共享
性能测试redis-benchmark(官方自带的性能测试工具!)
12# 测试:100个并发连接 100000请求redis-benchmark -h localhost -p 6379 -c 100 -n 100000
命令
命令不区分大小写
12345678910111213#切换数据库> select 1#清空数据库> flushdb> flushall#查看数据条数> DBSIZE#查看所有key> keys *#判断键是否存在> exists <key># 查看当前key的一个类型!> type name
String1234567891011121314151617181920212223242526272 ...
Git 基础操作手册
仓库操作
配置1、查看配置
123456# 列出所有配置git config --list# 列出所有配置以及配置文件路径git config --list --show-origin# 查看某一项配置git config <key>
2、用户信息
设置全局信息,全局信息只需要设置一次,会在系统上的所有 git 仓库适用。
12git config --global user.name "John Doe"git config --global user.email johndoe@example.com
当你想针对特定项目使用不同的用户名称与邮件地址时,可以在那个项目目录下运行没有 --global 选项的命令来配置。
12git config user.name "John Doe"git config user.email johndoe@example.com
3、文本编辑器
git 默认的编辑器是 vim, 可以设置默认编辑器,例如设置为 vscode。
1git config --global core.edit ...