简介 本文主要是讲解Redis 6的ACL的实现原理。基本使用详见:Redis 6.0新特性——ACLs,以及Redis启动过程分析。 启动初始化 初始化默认用户 ACL子模块在Redis启动过程中初始化,下面代码主要是初始化ACL的结构: /* * 初始化ACL子系统 * */ void ACLInit(void) { Redis ACL配置信息主要有两种方式: 在redis.conf文件中通过user 配置项配置的ACL信息。 比如:user worker +@list +@connection ~jobs:* on >ffa9203c493aa99 在redis.conf中配置aclfile所配置的文件中。 格式如下图所示: 通过user方式 通过加载redis.conf配置文件中读取user配置项加载ACL信息。
文章目录 一、排序命令 二、命令实现 1.排序对象定义 2.sort key命令实现 3.alpha选项实现 4.by选项实现 三、排序源码 总结 一、排序命令 Redis 的sort命令可以对列表键 、集合键或者有序集合键的值进行排序,如下所示: //列表排序 redis>rpush nums 3 1 2 redis>lrange nums 0 -1 3 1 2 redis>sort nums 1 2 3 //集合排序,alpha表示按照字母顺序排序 redis>sadd str aaa bbb ccc redis>smembers str bbb aaa ccc //集合元素是无序的 redis grade 0 -1 sjx wyq wyl //为每个学生设置序号 redis>mset wyl_id 1 sjx_id 2 wyq_id 3 redis>sort grade by *_id wyl 三、排序源码 redis排序相关代码均位于sort.c中,sort使用的排序函数如下: /* sortCompare() is used by qsort in sortCommand().
文章目录 前言 一、链表简介 二、链表实现 1.链表节点实现 2.链表实现 3.链表迭代器实现 4.链表API 总结 前言 本文对Redis的底层数据结构链表做了简要介绍,涉及的文件是adlist.h Redis 使用的 C 语言并没有内置这种数据结构, 所以 Redis 构建了自己的链表实现。 链表在 Redis 中的应用非常广泛, 比如列表键的底层实现之一就是链表: 当一个列表键包含了数量比较多的元素, 又或者列表中包含的元素都是比较长的字符串时, Redis 就会使用链表作为列表键的底层实现 除了链表键之外, 发布与订阅、慢查询、监视器等功能也用到了链表, Redis 服务器本身还使用链表来保存多个客户端的状态信息, 以及使用链表来构建客户端输出缓冲区(output buffer),后续的部分文章将陆续对这些链表应用进行介绍 3.链表迭代器实现 Redis为了便于访问链表元素,还定义了链表的迭代器代码如下: /* Directions for iterators * * 迭代器进行迭代的方向 */ // 从表头向表尾进行迭代
简介 Redis服务器是典型的事件驱动程序,而事件又分为文件事件(socket的可读可写事件)与时间事件(定时任务)两大类。 Redis底层可以使用4种I/O多路复用模型(kqueue、epoll等), apidata是对这4种模型的进一步封装。 文件监听事件 Redis客户端通过TCP socket与服务端交互,文件事件指的就是socket的可读可写事件。socket读写操作有阻塞与非阻塞之分。 eventLoop:事件循环,与文件事件相关的最主要字段有3个, apidata指向I/O多路复用模型对象,注意4种I/O多路复用模型对象的类型不同,因此此字段是void*类型; events存储需要监控的事件数组 Redis创建时间事件节点的函数为aeCreateTimeEvent,内部实现非常简单,只是创建时间事件并添加到时间事件链表。
zipmap redis旧版小hash使用的数据结构,紧密数组存储结构 用1字节存储总节点数(如果1字节满了,代表需要遍历到底才知道有多少节点) 每个节点存储自己占用的内存空间,修改删除后,标记为闲置空间 adlist 环形双端链表,没啥好说的 dict 这里比较特别的是一个字典里会有最多两个hash表同时存在,目的是rehash的时候可以做渐进式hash table的结构是个数组,每个元素是一条链表,redis 把缩容一次后会聚拢到该bucket的bucket也遍历了,也就是idx与(idx + size/2) % size 比如size是8,缩容后就是4,所以对size为8的遍历就是 0->4 1->5 2->6 3- >7 基于idx与idx + size/2这个公式得到的bucket 源码里把这用一个数学公式体现(反序+1后再反序) //每次从高位进1 000 0 -》 100 4 001 1 -》 101 5 010 2 -》 110 6 011 3- 》 111 7
# 源码-调试Redis 在阅读源码的时候,通过debug调试的方式逐行去理解代码的意思,不免是一个好的方式。 第一步: 在src目录下新建一个文件learn.h,在这里面定义入口 #ifndef REDIS_LEARN_H #define REDIS_LEARN_H int learn(); #endif &ret); // 升级到int64 is = intsetAdd(is, INT32_MAX, &ret); // 中间插入 is = intsetAdd(is, 3, @1052b3e (github.com)open in new window,不一一描述 修改src/server.c,这里面包含了一个mian函数,程序的入口,其中有一段是这样子的 /* Check = NULL) redis_check_rdb_main(argc,argv,NULL); else if (strstr(argv[0],"redis-check-aof")
而redis的底层实现是十分简单的,核心源码也仅有几万行。本文就带大家来领略,小小的redis是如何实现这些复杂功能的。 *注:本文介绍的源码为redis 5.0.14版本 * 二、字符串 C语言存储字符串的问题: 二进制安全 C语言中表示字符串结尾的符号是'\0',如果字符串本身就具有'\0'字符,就会被截断,即非二进制安全 即多浪费了30%的空间,redis的跳表使用了较低的空间成本,实现了时间复杂度的大减少 3.3.3 插入节点 插入节点总的来说一共四步 查找插入位置 调整高度 插入节点 调整backward 源码如下 源码注解的例子。 工作中我们也常常使用redis进行各种逻辑的处理,而了解其源码可以避免踩很多坑。
bin的目录,里面包括了以下文件: redis-benchmark redis-check-aof redis-check-dump redis-cli redis-server redis-server :Redis服务器的daemon启动程序 redis-cli:Redis命令行操作工具。 redis #将报以下错误: redis服务不支持chkconfig #为此,我们需要更改redis脚本。 /redis/bin/redis-cli #将redis配置文件拷贝到/etc/redis/${REDISPORT}.conf mkdir /etc/redis cp /data/tgz/redis -3.0.7/redis.conf /etc/redis/6379.conf cp /data/tgz/redis-3.0.7/redis.conf /data/apps/redis/bin/redis.conf
如果entry是字符串,使用高两位表示编码类型,紧接着是实际长度; 如果entry是整数,最高两位均设置成1,第3、4位表示使用哪种整型编码。 * |11110000| - 1 byte * Integer encoded as 24 bit signed (3 bytes). entry的数量 ZIPLIST_LENGTH(zl) = 0; // 结束字节 zl[bytes-1] = ZIP_END; return zl; } resize的源码 case ZIP_INT_24B: return 3; // 1101 0000 4字节无符号整形 case ZIP_INT_32B: return 4; // 1110 0000 case ZIP_INT_24B: return 3; // 1101 0000 4字节无符号整形 case ZIP_INT_32B: return 4; // 1110 0000
简介 需要了解Redis命令执行过程,请先了解Redis启动过程和Redis事件监听。 Redis启动过程分析 Redis事件监听 在Redis事件监听中我们了解到在创建文件监听事件的时候 acceptTcpHandler就是的执行函数。 创建Redis连接。 listLength(server.ready_keys)) handleClientsBlockedOnKeys(); } return C_OK; } 命令表详见:《Redis
我们知道,Redis在解析命令行参数时,会将各个参数解析成robj类型,当expire值不为NULL则表示需要设置key的超时时间。 //标识key的超时时间被设置为单位毫秒 在知道了这3个变量的意义之后,再来看解析参数的具体过程。 由set命令的参数格式得知,前3个参数为set、key、value,这3个参数是通用参数,我们暂时先不考虑,先从第4个参数开始依次向后通过 for循环解析: for (j = 3; j < c->argc Redis将所有含有超时时间的key存储到redisDb的expire字典内,ttl命令可以快速确定key的超时秒数,就是通过查找这个字典实现的。 通过以上4个步骤已经成功地将一个key-value设置到Redis的数据库中。
简介 由于本人目前是华为FusionInsight HD 中Redis组件的Owner,所以要对Redis进行深入的了解,这对于C语言水平不咋地的我来讲还是有点难度的,于是我决定先从Redis的启动开始看 初始化ACL 权限信息 主要是通过加载redis.conf配置文件里面的配置信息,用于控制登录用户执行命令的权限,仔细详见:Redis 6 ACL源码详解 初始化命令表 在函数populateCommandTable set as fast, since it may perform an * implicit DEL of a large key. */ {"set",setCommand,-3, "write use-memory @string", 0,NULL,1,1,1,0,0,0}, {"setnx",setnxCommand,3, "write punsubscribe",punsubscribeCommand,-1,"",0,NULL,0,0,0,0,0}, {"publish",sentinelPublishCommand,3,
文章目录 redis集群概述 客户端重定向 槽位迁移 redis cluster 的运行流程 redis集群概述 哨兵、主从、集群,一串下来。 所以本文的重心也就很明确了:redis集群是如何实现通信及数据分片、流量分发的 关于实操:【redis】闲得无聊,来聊聊当下爆火的 redis集群,顺便搭一个玩玩呗 客户端重定向 如果cluster中的某个节点收到客户端请求 ; /* To support the KEYS option we need the following additional state. */ int first_key = 3; strcasecmp(c->argv[j]->ptr,"keys")) { if (sdslen(c->argv[3]->ptr) ! 1、节点启动 2、节点握手,参见主从握手 3、指派槽位 4、建立主从关系 5、节点通信:Gossip算法 6、故障转移,故障转移机制与哨兵基本一致
与append命令一样,原key在Redis中不存在时,Redis会创建一个robj对象,并将robj先设置到数据库;当key在Redis中存在时,会要求原值必须为string类型,并且由于Redis的限制
我的目标定位,这个项目是资深程序猿阅读和理解redis源码最优质的中文材料。 我这个项目预期做到 源码+中文注释+系列博文 三位一体,全方位帮大家深入理解redis的原理。 另外github上我源码库不是redis的copy,而是直接fork出来的,所以会定期和redis当前源码保持一致,时更时新。 这里放上相关链接,欢迎关注 Redis中文注解版仓库:https://github.com/xindoo/redis Redis源码剖析专栏:https://blog.csdn.net/xindoo 基础 [ ] 初识Redis [ ] redis的日常使用 [ ] 搭建redis源码环境(单步调试) [ ] 了解redis的启动过程 各种数据结构 [ ] SDS(simple dynamic
byte = bitoffset >> 3;//一个字节是8位,现在需要除以8,以定位到第byte个字节上 byteval = ((uint8_t*)o->ptr)[byte];//取出第byte个字节
使用的是redis6.0.6版本,因为我第一次接触 redis 时它就是这个最新稳定版。 文章目录 robj 数据类型 编码类型 随机应变的对象编码 回到robj robj redis中的数据对象 server.h/redisObject 是redis内部存储的数据定义的抽象类型。 define OBJ_LIST 1 /* List object. */ #define OBJ_SET 2 /* Set object. */ #define OBJ_ZSET 3 integer 整数*/ #define OBJ_ENCODING_HT 2 /* Encoded as hash table 字典*/ #define OBJ_ENCODING_ZIPMAP 3 = OBJ_SHARED_REFCOUNT) o->refcount--; } } 3)lru,缓存淘汰策略(不一定就是LRU哈,不要被事物的表面现象所迷惑,也有可能是LFU,在配置文件中设定)
[Redis 源码解析 1:字符串 SDS ] Redis 中字符串都用自定义的结构**简单动态字符串(Simple Dynamic Strings,SDS),而不是C语言的字符串。 Redis 中使用到的字符串都是用 SDS,例如 key、string 类型的值、sorted set 的 member、hash 的 field 等等等等 数据结构 旧版本的结构 在 3.2 版本之前 在 Redis 3.2 版本之后,Redis 将 SDS 划分为 5 种类型: 类型 字节 位 sdshdr5 < 1 <8 sdshdr8 1 8 sdshdr16 2 16 sdshdr32 4 32 类型只占用了前 3 位。在 sdshdr5 中,后 5 位用来保存字符串的长度。其他类型后 5 位没有用。 ` struct attribute ((packed)) sdshdr5 { unsigned char flags; /* 前 3 位保存类型,后 5 位保存字符串长度 */ char buf[]
1:SDS介绍 我们在redis中执行命令 set key name 的时候,key和name都是字符串类型,而且字符串(string)在redis中是会经常用到的类型,那redis是如何保存字符串的呢 我们接下来往下看 众所周知,redis是c写的,在c中使用char来保存字符串,并且用\0作为字符串的结尾,但是redis不是这样保存的,redis是使用一种叫SDS的结构来保存字符串的。 结构如下(redis3.2以前) struct sdshdr{ int len; int free; char buf[]; } 那么问题来了,redis为什么 会用SDS的结构 源码如下 void sdsclear(sds s) { //重置sds的buf空间,懒惰释放 struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr 其余的sdshdr16以上的都是以此类推,判断方式源码如下 static inline char sdsReqType(size_t string_size) { if (string_size
在Linux下安装Redis非常简单,具体步骤如下(官网有说明): 1、下载源码,解压缩后编译源码。 mkdir /usr/redis cp ./src/redis-server /usr/redis cp ./src/redis-benchmark /usr/redis cp . /src/redis-cli /usr/redis cp ./src/redis-check-aof /usr/redis cp . /src/redis-check-rdb /usr/redis cp ./src/redis-sentinel /usr/redis cp . /src/redis.conf /usr/redis cd /usr/redis 3、启动Redis服务。 $ redis-server redis.conf 4、然后用客户端测试一下是否启动成功。