Redis

Redis

1 介绍

Redis(Remote Dictionary Server)是一个开源的内存数据存储系统,它可以用作数据库、缓存和消息中间件。Redis支持多种数据结构,包括字符串、哈希表、列表、集合、有序集合等。它提供了丰富的命令集合,使得开发者可以方便地对这些数据结构进行操作。

以下是Redis的一些关键特性和优势:

  1. 内存存储: Redis数据完全存储在内存中,因此读写速度非常快。同时,Redis也可以将数据持久化到磁盘,以防止数据丢失。

  2. 丰富的数据结构: Redis支持多种数据结构,包括字符串、列表、集合、有序集合、哈希表等,每种数据结构都支持丰富的操作。

  3. 持久化: Redis支持将数据持久化到磁盘,可以选择使用RDB快照或者AOF(Append-Only File)日志文件的方式进行持久化。

  4. 高可用性: Redis支持主从复制,可以创建多个Redis副本来提供高可用性和容错性。

  5. 分布式: Redis Cluster是Redis的分布式解决方案,它可以将数据分布到多个节点上,提供横向扩展性。

  6. 事务支持: Redis支持事务,可以批量执行一系列命令,保证这些命令的原子性。

  7. 发布/订阅模式: Redis支持发布/订阅模式,可以用于消息传递和事件通知。

  8. 灵活性: Redis非常灵活,可以用于多种用途,包括缓存、计数器、消息队列等。

  9. 社区和生态系统: Redis拥有庞大的开发者社区和丰富的生态系统,有很多客户端库、工具和扩展可以使用。

2 Redis数据类型

2.1 String类型

字符串是Redis最简单的数据类型,可以存储文本、整数或者浮点数。字符串类型是二进制安全的,意味着它可以包含任意数据,比如图片或者序列化的对象。

使用场景

  • 视频的播放量统计
  • 共享session

常用命令

  • set key value:设置String类型的键key的值为value
  • get key:获取String类型的键key中的值value
  • 例如:
    在这里插入图片描述
  • incr key:对键key进行递增操作
  • decr key:对键key进行递减操作
  • 例如:
    在这里插入图片描述
  • setex key timeout value:设置键key在指定的时间后过期,单位是秒(s)
  • ttl key:获取键key剩余时间
  • 例如:设置age的时间为10s,10s之后自动清空
    在这里插入图片描述
    例如:设置age的时间为20s,获取剩余时间为12s
    在这里插入图片描述

2.2 hash类型

Hash类型是一种键值对的集合,适用于存储对象(例如用户信息、商品信息等)的属性和属性值。每个Hash类型的键可以包含多个字段和字段值,类似于关联数组。

在java中的比喻:

Map<String,Map<String,?>> map 

使用场景
开发中不建议使用hash类型,如果一定要用它,使用对象转换为json类型

常用命令

  • hset key field value: 设置Hash类型的键key中字段field的值为value

  • hget key field: 获取Hash类型的键key中字段field的值。

  • 例如:
    在这里插入图片描述

  • hdel key field1 field2 ...: 删除Hash类型的键key中的一个或多个字段。

  • hexists key field: 判断Hash类型的键key中是否存在字段field

  • 例如:
    在这里插入图片描述

  • hkeys key: 获取Hash类型的键key中所有的字段名。

  • havls key: 获取Hash类型的键key中所有的字段值。

  • hlen key: 获取Hash类型的键key中字段的数量。

2.3 list类型

在Redis中,List(列表)是一种有序的字符串元素集合,它可以包含字符串、数字等类型的元素。List数据类型支持在头部(左侧)和尾部(右侧)快速添加、删除元素,因此常用来实现队列、栈等数据结构,也可以用来存储有序的元素集合。

使用场景:收藏文章列表

常用命令

  • lpush key value [value ...] :在列表头部(左侧)插入一个或多个值。
  • rpush key value [value ...]: 在列表尾部(右侧)插入一个或多个值。
  • lpop key :移除并返回列表头部(左侧)的元素。
  • rpop key :移除并返回列表尾部(右侧)的元素。
  • lrange key start stop :获取列表指定范围内的所有元素。
  • llen key:获取列表的长度。
  • 例如:
    在这里插入图片描述

2.4 set类型

Set是一个无序的、不重复的元素集合。以下是关于Redis中Set类型的一些重要特点:

  1. 无序性: Set中的元素是无序的,不像列表(List)类型那样有顺序。

  2. 不重复性: Set中不允许重复的元素,每个元素都是唯一的。

  3. 集合操作: Redis提供了丰富的集合操作,如求交集、并集、差集等,可以方便地对集合进行操作。

常用命令

  • sadd key member [member ...]:将一个或多个元素添加到集合中。

  • srem key member [member ...]:从集合中移除一个或多个元素。

  • smembers key:返回集合中的所有元素。

  • scard key:返回集合中的元素个数。

  • 例如:
    在这里插入图片描述

2.5 zset类型

ZSET 是 Redis 提供的一种有序集合数据类型。ZSET 中的每个成员都关联着一个分值(score),Redis 使用分值来对集合中的成员进行排序。ZSET 是有序的,这意味着你可以按照分值的范围或者按照成员来查询元素。

在 ZSET 中,每个成员都是唯一的,但是分值(score)可以重复。ZSET 中的成员按照分值从小到大进行排序,分值相同的成员按照字典序进行排序。

常用命令

  • zadd key score member [score member ...]:向有序集合中添加一个或多个成员,或者更新已存在成员的分值。

  • zrem key member [member ...]:从有序集合中移除一个或多个成员。

  • zscore key member:获取有序集合中指定成员的分值。

  • zrank key member:获取有序集合中指定成员的排名(按照分值从小到大排序)。

  • zrevrank key member:获取有序集合中指定成员的排名(按照分值从大到小排序)。

  • zrange key min max:按照分值范围获取成员列表,可以指定返回结果的数量和起始位置。

  • zrevrank key max min:按照分值范围从大到小获取成员列表。

  • zcard key:获取有序集合中的成员数量。

在这里插入图片描述

3 Redis 安装(Linux环境)

1.安装redis所需要的依赖

yum install -y gcc tcl

2.上传 redis 压缩包到 tmp 目录下
3.解压缩redis压缩包

tar -xvf redis-6.2.4.tar.gz

4.进入解压缩目录,执行安装操作

make && make install 

5.编辑 redis.confg

bind 127.0.0.1 #本地访问 
bind 0.0.0.0   #任意ip都能访问

更改任意一个即可
6.启动 redis

redis-server redis.conf

结果如下:
在这里插入图片描述
安装成功!

7.停止 Redis 服务

redis-cli shutdown 

或者 ctrl + C

4 Redis 持久化

Redis提供了两种主要的持久化方式,分别是RDB快照(Snapshotting)和AOF(Append-Only File)日志。

4.1 RDB 持久化

RDB(Redis DataBase Backup file)快照是一种周期性将内存中的数据保存到磁盘上的持久化方式。它的工作原理是在指定的时间间隔内,将整个数据集的快照保存到一个压缩的二进制文件(.rdb)中。

  • 配置: RDB快照的配置在Redis的配置文件 redis.conf 中,通过以下配置项进行设置:

    save 900 1         # 在900秒内如果至少有1个key被修改,则触发快照
    save 300 10        # 在300秒内如果至少有10个key被修改,则触发快照
    save 60 10000      # 在60秒内如果至少有10000个key被修改,则触发快照
    save ""           # 表示禁用RDB
    
  • 其他配置: RDB的其它配置也可以在 redis.conf 文件中设置:

    rdbcompression yes 		#是否压缩 ,建议不开启,压缩也会消耗cpu,磁盘的话不值钱
    dbfilename dump .rdb  	#RDB文件名称
    dir ./					#文件保存的路径目录
    
  • 手动触发: 可以通过savebgsave命令手动触发RDB快照。

    • save: 由Redis的主进程执行RDB,会阻塞所有命令
    • bfsave: 开启子进程执行RDB,避免主进程受到影响
  • 恢复: 使用redis-server启动时,如果存在RDB文件,则会自动加载并恢复数据。

  • RDB原理:
    在这里插入图片描述
    bgsave命令一开始 就会 fork 主进程得到子进程 ,子进程会共享主进程的内存数据。完成 fork 之后读取内存中的数据并写入 RDB 文件。

    fork采用的是 copy-on-write 技术
    当主进程执行读操作的时候,访问共享内存。
    当主进程执行写的操作,则会拷贝一份数据,执行写操作。

  • RDB方式中的bgsave的基本流程
    fork主进程得到一个子进程,共享内存空间。子进程读取内存数据并写入新的RDB文件。然后用新的RDB文件替换旧的RDB文件。

  • RDB会在什么时候执行?
    服务停止的时候执行

  • RDB缺点:
    RDB执行时间间隔长,两次RDB之间写入数据会有丢失数据的风险 。
    fork子进程、压缩、写入RDB都比较耗时。

4.2 AOF 持久化

AOF( Append Only File)是一种以追加的方式记录每个写操作的持久化方式。它将写命令追加到一个日志文件中,以保持对数据修改的完整记录。AOF文件是一个文本文件,可以通过查看它来了解数据修改的历史。

  • 配置: AOF默认是关闭的,需要修改 redis.conf 配置文件来开启 AOF:

    #是否开启AOF功能,默认是no
    appendonly yes          		 # 开启AOF持久化
    appendfilename "appendonly.aof"  # AOF文件的名字
    
  • AOF的命令记录的频率也可以通过 redis.conf 文件来配:

    #表示每执行一次写命令,立即记录到AOF文件
    appendfsync always
    #写命令执行完先放入AOF缓冲区,然后表示每隔1秒将缓冲区数据写到AOF文件,是默认方案
    appendfsync everysec
    #写命令执行完先放入AOF缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
    appendfsync no
    
  • 重写: 因为是记录命令,AOF文件会比RDB文件大的多。而且AOF会记录对同一个key的多次写操作,但只有最后一次写操作才有意义。通过执行bgrewriteaof命令,可以让AOF文件执行重写功能,用最少的命令达到相同效果。

  • Redis也会在触发阈值时自动去重写AOF文件。阈值也可以在 redis.conf 中配置:

    #AOF文件比上次文件增长超过多少百分比则触发重写
    auto-aof-rewrite-percentage 100
    #AOF文件体积最小多大以上才触发重写
    auto-aof-rewrite-min-size 64mb
    
  • 实验:
    前提:禁用RDB,启用AOF
    在这里插入图片描述
    查看 AOF 文件:
    在这里插入图片描述

RDB 和 AOF 对比:

RDBAOF
使用场景容忍分钟数据的丢失,追求更快的启动速度对数据安全性要求较高
持久化方式定时对整个内存做快照记录每一次执行的命令
数据完整性不完整,两次备份之间会丢失数据相对完整,取决于刷盘策略
文件大小会有压缩,文件体积小记录命令,体积大
宕机恢复速度很快
数据恢复的优先级低,数据完整性不如AOF高,数据完整性高
系统资源占用高,大量CPU和内存消耗低,主要是磁盘IO资源

5 Redis 主从 (一主二从 )

Redis集群是将多个Redis节点组合在一起,以提供高可用性、横向扩展性和负载均衡。在Redis集群中,数据被分片存储到多个节点上,每个节点负责其中一部分数据。

5.1 搭建主从架构

节点操作作用
master写操作主节点
slave1读操作从节点
slave2读操作从节点

关系如图所示:
在这里插入图片描述

要搭建的主从

ip端口角色
192.168.64.1287001master
192.168.64.1287002slave
192.168.64.1287003slave

1.修改 redis.confg 文件:关闭AOF, 开启RDB

# 关闭AOF
appendonly no
# 开启RDB
save 3600 1
save 300 100
save 60 10000

2.在 tmp 目录下创建三个文件夹

mkdir 7001  7002  7003

3.将刚刚修改的 redis.conf 文件拷贝到7001、7002、7003三个文件中

cp redis-6.2.4/redis.conf 7001
cp redis-6.2.4/redis.conf 7002
cp redis-6.2.4/redis.conf 7003

4.使用 sed 命令将 redis.conf 文件中的端口和 dir 保存路径进行更改

sed -i -e  's/6379/7001/g' -e 's/dir .\//dir \/tmp\/7001\//g' 7001/redis.conf
sed -i -e  's/6379/7002/g' -e 's/dir .\//dir \/tmp\/7002\//g' 7002/redis.conf
sed -i -e  's/6379/7003/g' -e 's/dir .\//dir \/tmp\/7003\//g' 7003/redis.conf

5.修改实例 ip

sed -i '1a replica-announce-ip 192.168.64.128' 7001/redis.conf
sed -i '1a replica-announce-ip 192.168.64.128' 7002/redis.conf
sed -i '1a replica-announce-ip 192.168.64.128' 7003/redis.conf

6.分别启动三个 redis

redis-server /tmp/7001/redis.conf
redis-server /tmp/7002/redis.conf
redis-server /tmp/7003/redis.conf

7.开启主从
连接 7002

redis-cli -p 7002  

执行

slaveof 192.168.64.128 7001

结果:
在这里插入图片描述

连接 7003

redis-cli -p 7003

执行

slaveof 192.168.64.128 7001

8.查看集群状态
连接 master 7001

 redis-cli -p 7001

查看状态

info replication

结果如下:
在这里插入图片描述
此时主从搭建完成!

主从测试:
在 master 执行 set
在这里插入图片描述
在 slave 执行 get
在这里插入图片描述
在这里插入图片描述

5.2 主从数据同步原理

5.2.1 全量同步

主从第一次建立连接时,会执行全量同步,将master节点的所有数据都拷贝给slave节点,流程:

在这里插入图片描述

这里有一个问题,master如何得知salve是第一次来连接呢??

有几个概念,可以作为判断依据:

  • Replication Id:简称replid,是数据集的标记,id一致则说明是同一数据集。每一个master都有唯一的replid,slave则会继承master节点的replid
  • offset:偏移量,随着记录在repl_baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的offset。如果slave的offset小于master的offset,说明slave数据落后于master,需要更新。

因此slave做数据同步,必须向master声明自己的replication id 和offset,master才可以判断到底需要同步哪些数据。

因为slave原本也是一个master,有自己的replid和offset,当第一次变成slave,与master建立连接时,发送的replid和offset是自己的replid和offset。

master判断发现slave发送来的replid与自己的不一致,说明这是一个全新的slave,就知道要做全量同步了。

master会将自己的replid和offset都发送给这个slave,slave保存这些信息。以后slave的replid就与master一致了。

因此,master判断一个节点是否是第一次同步的依据,就是看replid是否一致

完整流程描述:

  • slave节点请求增量同步
  • master节点判断replid,发现不一致,拒绝增量同步
  • master将完整内存数据生成RDB,发送RDB到slave
  • slave清空本地数据,加载master的RDB
  • master将RDB期间的命令记录在repl_baklog,并持续将log中的命令发送给slave
  • slave执行接收到的命令,保持与master之间的同步

5.2.2 增量同步

全量同步需要先做RDB,然后将RDB文件通过网络传输个slave,成本太高了。因此除了第一次做全量同步,其它大多数时候slave与master都是做增量同步

什么是增量同步?就是只更新slave与master存在差异的部分数据。如图:

在这里插入图片描述

5.2.3 repl_backlog原理

master怎么知道slave与自己的数据差异在哪里呢?

这就要说到全量同步时的repl_baklog文件了。

这个文件是一个固定大小的数组,只不过数组是环形,也就是说角标到达数组末尾后,会再次从0开始读写,这样数组头部的数据就会被覆盖。

repl_baklog中会记录Redis处理过的命令日志及offset,包括master当前的offset,和slave已经拷贝到的offset:

在这里插入图片描述

slave与master的offset之间的差异,就是salve需要增量拷贝的数据了。

随着不断有数据写入,master的offset逐渐变大,slave也不断的拷贝,追赶master的offset:

在这里插入图片描述

直到数组被填满:

在这里插入图片描述

此时,如果有新的数据写入,就会覆盖数组中的旧数据。不过,旧的数据只要是绿色的,说明是已经被同步到slave的数据,即便被覆盖了也没什么影响。因为未同步的仅仅是红色部分。

但是,如果slave出现网络阻塞,导致master的offset远远超过了slave的offset:

在这里插入图片描述

如果master继续写入新数据,其offset就会覆盖旧的数据,直到将slave现在的offset也覆盖:

在这里插入图片描述

棕色框中的红色部分,就是尚未同步,但是却已经被覆盖的数据。此时如果slave恢复,需要同步,却发现自己的offset都没有了,无法完成增量同步了。只能做全量同步。

注意:repl_ baklog大小有上限,写满后会覆盖最早的数据。如果slave断开时间过久,导致尚未备份的数据被覆盖,则无法基于log做增量同步,只能再次全量同步。

5.2.4 主从同步优化

主从同步可以保证主从数据的一致性,非常重要。可以从以下几个方面来优化Redis主从就集群:

  • 在master中配置repl-diskless-sync yes启用无磁盘复制,避免全量同步时的磁盘IO。
  • Redis单节点上的内存占用不要太大,减少RDB导致的过多磁盘IO
  • 适当提高repl_baklog的大小,发现slave宕机时尽快实现故障恢复,尽可能避免全量同步
  • 限制一个master上的slave节点数量,如果实在是太多slave,则可以采用主-从-从链式结构,减少master压力

6 Redis 哨兵

Redis提供了哨兵(Sentinel)机制来实现主从集群的自动故障恢复。

6.1 哨兵原理

6.1.1 集群结构和作用

哨兵的结构如图:
在这里插入图片描述

哨兵的作用如下:

  • 监控:Sentinel 会不断检查您的master和slave是否按预期工作
  • 自动故障恢复:如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主
  • 通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis的客户端

6.1.2 集群监控原理

Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个实例发送ping命令:

•主观下线:如果某sentinel节点发现某实例未在规定时间响应,则认为该实例主观下线

•客观下线:若超过指定数量(quorum)的sentinel都认为该实例主观下线,则该实例客观下线。quorum值最好超过Sentinel实例数量的一半。

在这里插入图片描述

6.1.3 集群故障恢复原理

一旦发现master故障,sentinel需要在salve中选择一个作为新的master,选择依据是这样的:

  • 首先会判断slave节点与master节点断开时间长短,如果超过指定值(down-after-milliseconds * 10)则会排除该slave节点
  • 然后判断slave节点的slave-priority值,越小优先级越高,如果是0则永不参与选举
  • 如果slave-prority一样,则判断slave节点的offset值,越大说明数据越新,优先级越高
  • 最后是判断slave节点的运行id大小,越小优先级越高。

当选出一个新的master后,该如何实现切换呢?

流程如下:

  • sentinel给备选的slave1节点发送slaveof no one命令,让该节点成为master
  • sentinel给所有其它slave发送slaveof 192.168.150.101 7002 命令,让这些slave成为新master的从节点,开始从新的master上同步数据。
  • 最后,sentinel将故障节点标记为slave,当故障节点恢复后会自动成为新的master的slave节点

在这里插入图片描述

6.1.4 小结

Sentinel的三个作用是什么?

  • 监控
  • 故障转移
  • 通知

Sentinel如何判断一个redis实例是否健康?

  • 每隔1秒发送一次ping命令,如果超过一定时间没有相向则认为是主观下线
  • 如果大多数sentinel都认为实例主观下线,则判定服务下线

故障转移步骤有哪些?

  • 首先选定一个slave作为新的master,执行slaveof no one
  • 然后让所有节点都执行slaveof 新master
  • 修改故障节点配置,添加slaveof 新master

6.2 搭建哨兵集群

6.2.1 集群结构

这里我们搭建一个三节点形成的Sentinel集群,来监管之前的Redis主从集群。如图:

在这里插入图片描述

三个sentinel实例信息如下:

节点IPPORT
s1192.168.150.10127001
s2192.168.150.10127002
s3192.168.150.10127003

6.2.2 准备实例和配置

要在同一台虚拟机开启3个实例,必须准备三份不同的配置文件和目录,配置文件所在目录也就是工作目录。

我们创建三个文件夹,名字分别叫s1、s2、s3:

# 进入/tmp目录
cd /tmp
# 创建目录
mkdir s1 s2 s3

如图:

在这里插入图片描述

然后我们在s1目录创建一个sentinel.conf文件,添加下面的内容:

port 27001
sentinel announce-ip 192.168.150.101
sentinel monitor mymaster 192.168.150.101 7001 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
dir "/tmp/s1"

解读:

  • port 27001:是当前sentinel实例的端口
  • sentinel monitor mymaster 192.168.150.101 7001 2:指定主节点信息
    • mymaster:主节点名称,自定义,任意写
    • 192.168.150.101 7001:主节点的ip和端口
    • 2:选举master时的quorum值

然后将s1/sentinel.conf文件拷贝到s2、s3两个目录中(在/tmp目录执行下列命令):

# 方式一:逐个拷贝
cp s1/sentinel.conf s2
cp s1/sentinel.conf s3
# 方式二:管道组合命令,一键拷贝
echo s2 s3 | xargs -t -n 1 cp s1/sentinel.conf

修改s2、s3两个文件夹内的配置文件,将端口分别修改为27002、27003:

sed -i -e 's/27001/27002/g' -e 's/s1/s2/g' s2/sentinel.conf
sed -i -e 's/27001/27003/g' -e 's/s1/s3/g' s3/sentinel.conf

6.2.3 启动

为了方便查看日志,我们打开3个ssh窗口,分别启动3个redis实例,启动命令:

# 第1个
redis-sentinel s1/sentinel.conf
# 第2个
redis-sentinel s2/sentinel.conf
# 第3个
redis-sentinel s3/sentinel.conf

启动后:

在这里插入图片描述

6.2.4 测试

尝试让master节点7001宕机,查看sentinel日志:

在这里插入图片描述

查看7003的日志:

在这里插入图片描述

查看7002的日志:

在这里插入图片描述

7 Redis 分片集群

7.1 搭建分片集群

主从和哨兵可以解决高可用、高并发读的问题。但是依然有两个问题没有解决:

  • 海量数据存储问题

  • 高并发写的问题

使用分片集群可以解决上述问题,如图:

在这里插入图片描述

分片集群特征:

  • 集群中有多个master,每个master保存不同数据

  • 每个master都可以有多个slave节点

  • master之间通过ping监测彼此健康状态

  • 客户端请求可以访问集群任意节点,最终都会被转发到正确节点

7.1.1 集群结构

分片集群需要的节点数量较多,这里我们搭建一个最小的分片集群,包含3个master节点,每个master包含一个slave节点,结构如下:

在这里插入图片描述

这里我们会在同一台虚拟机中开启6个redis实例,模拟分片集群,信息如下:

IPPORT角色
192.168.64.1288001master
192.168.64.1288002master
192.168.64.1288003master
192.168.64.1289001slave
192.168.64.1289002slave
192.168.64.1289003slave

7.1.2 准备实例和配置

创建出8001、8002、 8003、 9001 、9002、 9003这几个目录:

# 进入/tmp目录
cd /tmp
# 创建目录
mkdir 8001 8002 8003 9001 9002 9003

在/tmp下准备一个新的redis.conf文件,内容如下:

port 6379
# 开启集群功能
cluster-enabled yes
# 集群的配置文件名称,不需要我们创建,由redis自己维护
cluster-config-file /tmp/6379/nodes.conf
# 节点心跳失败的超时时间
cluster-node-timeout 5000
# 持久化文件存放目录
dir /tmp/6379
# 绑定地址
bind 0.0.0.0
# 让redis后台运行
daemonize yes
# 注册的实例ip
replica-announce-ip 192.168.64.128
# 保护模式
protected-mode no
# 数据库数量
databases 1
# 日志
logfile /tmp/6379/run.log

将这个文件拷贝到每个目录下:

# 进入/tmp目录
cd /tmp
# 执行拷贝
echo 8001 8002 8003 9001 9002 9003 | xargs -t -n 1 cp redis.conf

修改每个目录下的redis.conf,将其中的6379修改为与所在目录一致:

# 进入/tmp目录
cd /tmp
# 修改配置文件
printf '%s\n' 8001 8002 8003 9001 9002 9003 | xargs -I{} -t sed -i 's/6379/{}/g' {}/redis.conf

7.1.3 启动

因为已经配置了后台启动模式,所以可以直接启动服务:

# 进入/tmp目录
cd /tmp
# 一键启动所有服务
printf '%s\n' 8001 8002 8003 9001 9002 9003 | xargs -I{} -t redis-server {}/redis.conf

通过ps查看状态:

ps -ef | grep redis

发现服务都已经正常启动:

在这里插入图片描述

如果要关闭所有进程,可以执行命令:

ps -ef | grep redis | awk '{print $2}' | xargs kill

或者(推荐这种方式):

printf '%s\n' 8001 8002 8003 9001 9002 9003 | xargs -I{} -t redis-cli -p {} shutdown

7.1.4 创建集群

虽然服务启动了,但是目前每个服务之间都是独立的,没有任何关联。

我们需要执行命令来创建集群,在Redis5.0之前创建集群比较麻烦,5.0之后集群管理命令都集成到了redis-cli中。

1)Redis5.0之前

Redis5.0之前集群命令都是用redis安装包下的src/redis-trib.rb来实现的。因为redis-trib.rb是有ruby语言编写的所以需要安装ruby环境。

# 安装依赖
yum -y install zlib ruby rubygems
gem install redis

然后通过命令来管理集群:

# 进入redis的src目录
cd /tmp/redis-6.2.4/src
# 创建集群
./redis-trib.rb create --replicas 1 192.168.64.128:8001 192.168.64.128:8002 192.168.64.128:8003 192.168.64.128:9001 192.168.64.128:9002 192.168.64.128:9003 

2)Redis5.0以后

我们使用的是Redis6.2.4版本,集群管理以及集成到了redis-cli中,格式如下:

redis-cli --cluster create --cluster-replicas 1 192.168.64.128:8001 192.168.64.128:8002 192.168.64.128:8003 192.168.64.128:9001 192.168.64.128:9002 192.168.64.128:9003 

命令说明:

  • redis-cli --cluster或者./redis-trib.rb:代表集群操作命令
  • create:代表是创建集群
  • --replicas 1或者--cluster-replicas 1 :指定集群中每个master的副本个数为1,此时节点总数 ÷ (replicas + 1) 得到的就是master的数量。因此节点列表中的前n个就是master,其它节点都是slave节点,随机分配到不同master

运行后的样子:

在这里插入图片描述

这里输入yes,则集群开始创建:

在这里插入图片描述

通过命令可以查看集群状态:

redis-cli -p 7001 cluster nodes

在这里插入图片描述

7.1.5 测试

尝试连接8001节点,存储一个数据:

# 连接
redis-cli -p 8001
# 存储数据
set nums 123

结果悲剧了:

在这里插入图片描述

集群操作时,需要给redis-cli加上-c参数才可以:

redis-cli -c -p 8001

这次可以了:

在这里插入图片描述

7.2 散列插槽

7.2.1 插槽原理

Redis会把每一个master节点映射到0~16383共16384个插槽(hash slot)上,查看集群信息时就能看到:

在这里插入图片描述

数据key不是与节点绑定,而是与插槽绑定。redis会根据key的有效部分计算插槽值,分两种情况:

  • key中包含"{}",且“{}”中至少包含1个字符,“{}”中的部分是有效部分
  • key中不包含“{}”,整个key都是有效部分

例如:key是num,那么就根据num计算,如果是{itcast}num,则根据itcast计算。计算方式是利用CRC16算法得到一个hash值,然后对16384取余,得到的结果就是slot值。

在这里插入图片描述

如图,在8001这个节点执行set c 1时,对c做hash运算,对16384取余,得到的结果是7365,因此要存储到103节点。

到了8002后,执行get num时,对num做hash运算,对16384取余,得到的结果是2765,因此需要切换到8001节点

7.2.2 小结

Redis如何判断某个key应该在哪个实例?

  • 将16384个插槽分配到不同的实例
  • 根据key的有效部分计算哈希值,对16384取余
  • 余数作为插槽,寻找插槽所在实例即可

如何将同一类数据固定的保存在同一个Redis实例?

  • 这一类数据使用相同的有效部分,例如key都以{typeId}为前缀
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值