集群数据结构 3.CLUSTER MEET 命令的实现 二、槽指派 1.记录节点的槽指派信息 2.传播节点的槽指派信息 3.记录集群中所有槽的指派信息 三、在集群中执行命令 四、重新分片 总结 前言 集群是Redis 握手示意图如下: 1.节点启动 一个节点就是一个运行在集群模式下的 Redis 服务器, Redis 服务器在启动时会根据 cluster-enabled 配置选项的是否为 yes 来决定是否开启服务器的集群模式 二、槽指派 Redis集群通过分片的方式来保存数据库中的键值对,整个数据库会被分为16384个槽。当所有的槽都有集群节点在处理时,集群处于上线状态,否则处于下线状态。 集群管理软件redis-trib负责执行,在此不多做介绍。 总结 本文对redis集群进行了简要介绍,方便对集群进行一个简单的初步了解。
一、同步实现 1.完整重同步 2.部分重同步 a.复制偏移量 b.复制积压缓冲区 c.服务器运行id 二、复制的完整过程 1.设置主服务器的地址和断开 2.建立套接字连接 3.发送ping命令 4. 身份认证 5.发送端口信息 6.同步 7.命令传播 总结 前言 Redis中用户可以执行slaveof命令让一个服务器去复制另一个服务器,被复制的服务器称为主服务器,另一个服务器称为从服务器。 1.完整重同步 在从服务器首次复制主服务器或者从服务器和主服务器数据相差过多时,redis采用完整重同步。 4.身份认证 ping命令返回pong后,若从服务器设置了masterauth选项,将会进行身份验证。 总结 本文对redis的复制内容进行了简要介绍,如有不当,请指正。
简介 本文主要是讲解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信息。
文章目录 前言 一、Redis哨兵简介 二、初始化哨兵节点 1.初始化服务器 2.使用哨兵专用代码 3.初始化哨兵状态 4.初始化 Sentinel 状态的 masters 属性 5.创建连向主服务器的网络连接 2.将普通 Redis 服务器使用的代码替换成 Sentinel 专用代码。 3.初始化 Sentinel 状态。 4.根据给定的配置文件, 初始化 Sentinel 的监视主服务器列表。 不过, 因为 哨兵执行的工作和普通 Redis 服务器执行的工作不同, 所以 哨兵的初始化过程和普通 Redis 服务器的初始化过程并不完全相同。 ras",0,NULL,0,0,0,0,0}, {"time",timeCommand,1,"rR",0,NULL,0,0,0,0,0}, {"bitop",bitopCommand,-4, mstime_t previous_time; // 一个 FIFO 队列,包含了所有需要执行的用户脚本 list *scripts_queue; } sentinel; 4.
简介 Redis服务器是典型的事件驱动程序,而事件又分为文件事件(socket的可读可写事件)与时间事件(定时任务)两大类。 Redis底层可以使用4种I/O多路复用模型(kqueue、epoll等), apidata是对这4种模型的进一步封装。 *eventLoop, int fd, int delmask) static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp); 4个函数的输入参数含义如下 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的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 quicklistCreate(); // quicklistPushHead(list, "hello", 6); // quicklistPushHead(list, "xxx", 4) = NULL) redis_check_rdb_main(argc,argv,NULL); else if (strstr(argv[0],"redis-check-aof") = NULL) redis_check_rdb_main(argc,argv,NULL); else if (strstr(argv[0],"redis-check-aof")
存储(实现)原理 Redis用intset或hashtable存储set。如果元素都是整数类型,就用inset存储。如果不是整数类型,就用hashtable(数组+链表的存来储结构)。 redis.conf set-max-intset-entries 512 127.0.0.1:6379> sadd lset 1 2 3 3 4 5 6 7 (integer) 7 127.0.0.1
而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
在Redis中 可以对列表两端插入push 或者弹出pop,或者获取指定访问的元素列表,获取指定索引的下标的元素。 6379> linsert listkey after e n (integer) 8 127.0.0.1:6379> lrange listkey 0 -1 1) "e" 2) "n" 3) "d" 4) 会一直阻塞 127.0.0.1:6379> blpop emptylist 2 (nil) (2.08s) 127.0.0.1:6379> blpop emptylist 0 这个时候我们开启另外一个redis-cli ziplist 压缩列表:当列表类型元素个数小于list-max-ziplist-entries配置(默认512个),同时所有值都小于list-max-ziplist-value配置(默认64个字节)redis linkedlist链表当list类型无法满足ziplist的条件是,redis会使用linkedlist作为列表的内部实现。
命令master 上没有 rdb 文件[root@m1 ~]# lsanaconda-ks.cfg Downloads log Public redis.conf redis_slave_on_m1.conf VideosDesktop install.log Music redis-3.0.0 redis.log TemplatesDocuments install.log.syslog Pictures redis-3.0.0.tar.gz redis-new.conf tmp[root@m1 ~]# redis-cli 127.0.0.1:6379> keys * 1) "b"2) "a"3) "c"4) "8"5) "9"6) "d"127.0.0.1:6379
十条数据,算出各自的哈希值,(这里就不变了,实际上要经过一系列计算) 0 : 0 1 : 1 2 : 2 3 : 3 4 : 4 5 : 5 6 : 6 7 : 7 8 : 8 9 : 9 有三个节点, 算出各自的哈希值 node a: 3 node b: 5 node c: 7 这个时候比较两者的哈希值,5等于b,则归属b,4小于b,归属b,3等于a,则归属a,最后所有大于c的,归属于c(这里只是模拟 ) 相当于整个哈希值就是一个环,对应的映射结果: node a: 0,1,2,3 node b: 4,5 node c: 6,7,8,9 这个时候加入node d, 就可以算出node d的哈希值: node d: 9 这个时候对应的数据就会做迁移: node a: 0,1,2,3 node b: 4,5 node c: 6,7 node d: 8,9 只有最后8,9这2条数据被存储到新的节点,其他不变
/src/{redis-benchmark,redis-check-aof,redis-check-rdb,redis-cli,redis-sentinel,redis-server} /usr/local 0 1608532872000 4 connected 60bee426b74f78863ebde556ccdf3be318076e2a 192.168.1.31:6380@16380 slave 61a3730c0bc4f8dd0adc6cb8361468b111ae107f 0 1608532290000 4 connected 61a3730c0bc4f8dd0adc6cb8361468b111ae107f 192.168.1.33:6379@16379 master 0 1608533632330 4 connected 61a3730c0bc4f8dd0adc6cb8361468b111ae107f 192.168.1.33:6379@16379 master failove 1887:M 21 Dec 2020 16:57:07.822 # Setting secondary replication ID to fb19496140888dd50683a812b6f4dc4c6475a003
第一个字节设置成254表示,前一个条目的长度长度保存在后面4个字节内。 _64B (0xc0 | 2<<4) // 1111 0000, 24位有符号整数(3字节) #define ZIP_INT_24B (0xc0 | 3<<4) // 1111 1110 8位有符号整数 entry的数量 ZIPLIST_LENGTH(zl) = 0; // 结束字节 zl[bytes-1] = ZIP_END; return zl; } resize的源码 case ZIP_INT_32B: return 4; // 1110 0000 8字节无符号整形 case ZIP_INT_64B: return 8; // 4位无符号整形立即数 那就将p-4后面的数据偏移到p+reqlen nextdiff == -4:原先p节点需要5个字节来存储上一个节点的长度,现在只需要1个字节。
简介 需要了解Redis命令执行过程,请先了解Redis启动过程和Redis事件监听。 Redis启动过程分析 Redis事件监听 在Redis事件监听中我们了解到在创建文件监听事件的时候 acceptTcpHandler就是的执行函数。 创建Redis连接。 listLength(server.ready_keys)) handleClientsBlockedOnKeys(); } return C_OK; } 命令表详见:《Redis
命令行解析额外参数 set命令共支持NX、XX、EX、PX这4个额外参数,在执行set命令时,需要首先对这4个参数进行解析,此时需要3个局部变量来辅助实现: robj *expire = NULL; int 我们知道,Redis在解析命令行参数时,会将各个参数解析成robj类型,当expire值不为NULL则表示需要设置key的超时时间。 由set命令的参数格式得知,前3个参数为set、key、value,这3个参数是通用参数,我们暂时先不考虑,先从第4个参数开始依次向后通过 for循环解析: for (j = 3; j < c->argc Redis将所有含有超时时间的key存储到redisDb的expire字典内,ttl命令可以快速确定key的超时秒数,就是通过查找这个字典实现的。 通过以上4个步骤已经成功地将一个key-value设置到Redis的数据库中。
https://www.jianshu.com/p/0232236688c1 1、集群架构 Redis集群设计 总体架构 在这个图中,每一个蓝色的圈都代表着一个redis的服务器节点。 2、集群通信---- 2.1 集群发现:MEET 最开始时,每个Redis实例自己是一个集群,我们通过cluster meet让各个结点互相“握手”。 3、数据分布及槽信息 3.1槽(slot)概念 Redis Cluster中有一个16384长度的槽的概念,他们的编号为0、1、2、3……16382、16383。 ,这是可以由用户指定的,也可以在初始化的时候自动生成(redis-trib.rb脚本)。 3.2数据分片 在Redis Cluster中,拥有16384个slot,这个数是固定的,存储在Redis Cluster中的所有的键都会被映射到这些slot中。
spring源码4 强烈推介IDEA2020.2破解激活,IntelliJ IDEA
文章目录 redis集群概述 客户端重定向 槽位迁移 redis cluster 的运行流程 redis集群概述 哨兵、主从、集群,一串下来。 所以本文的重心也就很明确了:redis集群是如何实现通信及数据分片、流量分发的 关于实操:【redis】闲得无聊,来聊聊当下爆火的 redis集群,顺便搭一个玩玩呗 客户端重定向 如果cluster中的某个节点收到客户端请求 = C_OK || getLongFromObjectOrReply(c,c->argv[4],&dbid,NULL) ! 5 : 4)); if (server.cluster_enabled) serverAssertWithInfo(c,NULL, 1、节点启动 2、节点握手,参见主从握手 3、指派槽位 4、建立主从关系 5、节点通信:Gossip算法 6、故障转移,故障转移机制与哨兵基本一致