Redis :Remote Dictionary Server(远程字典服务)是完全开源的,使用ANSIC语言编写遵守BSD协议,是一个高性能的Key-Value数据库提供了丰富的数据结构,例如String、Hash、List、Set、SortedSet等等。数据是存在内存中的,同时Redis支持事务、持久化、LUA脚本、发布/订阅、缓存淘汰、流技术等多种功能特性提供了主从模式、Redis Sentinel和Redis Cluster集群架构方案
版本号命名规则:版本号第二位如果是偶数,才为稳定版本 如2.6、2.8、3.0、3.2
安装前需确保具备 gcc 编译环境,gcc -v
,如找不到命令,则可通过 yum -y install gcc-c++
安装 gcc 环境
/opt
目录解压 tar -zxvf redis-7.2.3.tar.gz
/opt/redis-7.2.3
目录,执行 make && make install
/usr/local/bin
,该路径类似于 windows 系统中的 C:\Program Files
该路径下查看有
redis-benchmark
:性能测试工具,服务器运行后运行该命令可以查看性能情况redis-check-aof
:用于修复有问题的 aof 文件redis-check-rdb
:用于修复有问题的 rdb 文件redis-cli
:客户端,操作路口redis-sentinel
:redis 集群使用redis-server
:redis 服务器启动命令/opt/redis-7.2.3/redis.conf
建议先备份,本人复制了一份到 /root/myopt/redis.conf
修改以下四个配置
daemonize
:改为 yes
,让 redis 以后台程序运行protected-mode
:改为 no
,如果设置为yes,那么只允许我们在本机的回环连接,其他机器无法连接,生产建议 yes
bind 127.0.0.1 -::1
:测试可注释掉该项,否则只能指定 ip 连接 redis。生产建议配置好requirepass 密码
:配置密码,在配置文件约 1045 行添加该配置/etc/sysctl.conf
启用内存过度分配,增加配置 vm.overcommit_memory=1
,并执行立即生效命令 sysctl vm.overcommit_memory=1
redis-server /root/myopt/redis.conf
redis-cli -a 密码
,会警告不安全,可忽略(在客户端用 auth 密码
登陆将不会有警告),测试连接输入 ping
,收到 PONG
则表示成功关闭 redis :单实例关闭 redis-cli -a 密码 shutdown
;多实例关闭 redis-cli -a 密码 -p 6379 shutdown
卸载 redis:停止 redis 服务后,删除 /usr/local/bin
目录下与 redis 相关的文件 rm -rf /usr/local/bin/redis-*
命令参考网址:
可以使用 help command
命令来查看命令帮助,如 help keys
或者使用 help @数据类型
名来来查看对应数据类型相关的函数
key 及 db 常用命令
命令 | 描述 |
---|---|
keys * | 查看当前库所有 key,也可将 * 改成 a* 表示查看 a 开头的 key |
exists key | 判断某个 key 是否存在 |
type key | 查看 key 的类型 |
del key | 删除指定 key 数据 |
unlink key | 异步删除 key,删除大key需要用此命令 |
ttl key | 查看过期时间,单位:秒。-1 永不过期,-2 已过期 |
expire key | 设置 key 过期时间,默认单位:秒 |
select dbindex【0~15】 | 切换数据库,默认 0 |
move key dbindex【0~15】 | 将对应 key 移动到指定数据库 |
dbsize | 查看当前数据库 key 的数量 |
flushdb | 清空当前库 |
flushall | 清空所有库 |
不同数据类型对应不同增删改查命令,建议直接看英文官网(最全),通过类型过滤即可,这里主要剖析不同数据类型特点
getset
),数值增减( incr
),截取( getrange
),不存在才设置( setnx
)等
2^31 -1 (约40亿)
个键值对
2^31 -1
个元素,底层结构为双端链表
2^31 -1
个元素,底层结构为哈希表
2^32
位,节省空间,且位运算效率高
hello
用位域存储时每个字母是用 8位组成的字节 ASCII 存储的,用位域可直接操作对应 ASCII 编码,对编码进行修改持久化即将数据持久化到硬盘上,redis 有 rdb 和 aop 两种持久化方式。如完全为了性能不做自动持久化,也可配置纯缓存模式。持久化相关配置在配置文件中 SNAPSHOTTING
模块,可根据该关键字检索。
该持久化方案默认开启,在指定的时间间隔,执行数据集的时间点快照,采集时进行全量快照。最终保存的格式是 dump.rdb
文件。
save 3600 1 300 100 60 10000
,表示 3600s(1小时)内至少有1次变更触发;300s(5分钟)内至少有100次变更触发;以及 60s (1分钟)内至少有 10000 此变更触发redis-check-rdb rdb文件
save
/ bgsave
命令,生产禁止使用 save
备份,会阻塞主进程flushdb
/ flushall
命令,产生的是空备份文件,无意义shutdown
且没有设置开启 AOF 持久化redis-cli config set save ""
,配置文件中也是设置 save ""
dir ./
;备份文件名: dbfilename dump.rdb
总结:
默认不开启,该备份方案是以日志的形式来记录每个写操作,恢复重启时根据日志内容将写操作从前到后执行一次以完成数据恢复
AOF 持久化流程:
1 | Client作为命令的来源,会有多个源头以及源源不断的请求命令。 |
---|---|
2 | 在这些命令到达Redis Server 以后并不是直接写入AOF文件,会将其这些命令先放入AOF缓存中进行保存。这里的AOF缓冲区实际上是内存中的一片区域,存在的目的是当这些命令达到一定量以后再写入磁盘,避免频繁的磁盘IO操作。 |
3 | AOF缓冲会根据AOF缓冲区同步文件的三种写回策略将命令写入磁盘上的AOF文件。 |
4 | 随着写入AOF内容的增加为避免文件膨胀,会根据规则进行命令的合并(又称AOF重写),从而起到AOF文件压缩的目的。 |
5 | 当Redis Server 服务器重启的时候会从AOF文件载入数据。 |
appendonly yes
;配置文件目录及名称 dir
+ appenddirname
配置写回策略:appendfsync
everysec
always
:同步写回,每个写操作执行完立刻同步到磁盘everysec
:每秒写回no
:由操作系统自行决定何时从缓存写到磁盘redis-check-aof --fix aof文件
auto-aof-rewrite-percentage 100
是否增长一倍和 auto-aof-rewrite-min-size 64 mb
是否达到 64 MB大小bgrewriteaof
总结:
RDB 和 AOF 方式是可以共存的,按是否开启混合模式有两种情况,如下:
aof-use-rdb-preamble yes
默认是开启的,不开启则将优先使用 AOF。同时必须开启 aof:appendonly yes
RDB + AOF 混合方式:这种方式会先使用 RDB 进行快照存储,然后使用 AOF 持久化记录所有的写操作,当重写策略满足或手动触发重写的时候,将最新的数据存储为新的 RDB 记录。这样的话,重启服务的时候会从 RDB 和 AOF 两部分恢复数据,既保证了数据完整性,又提高了恢复数据的性能。简单来说:混合持久化方式产生的文件一部分是RDB格式,一部分是AOF格式。在持久化方案中也推荐使用该方案。
为了追求极致性能采取的模式,同时关闭 RDB 和 AOF。
save ""
,禁用情况下仍然可以使用命令 save
和 bgsave
生成 rdb 文件appendonly no
,禁用情况下仍然可使用命令 bgrewriteaof
生成 aof 文件使用事务,可以一次执行多个命令,本质是一组命令的集合,一个事务中的所有命令都会序列化,按顺序串行化执行,不会被其他命令加塞。
Redis事务特点:
命令 | 描述 |
---|---|
MULTI | 标记一个事务块的开始 |
DISCARD | 取消事务,放弃执行事务块内的所有命令 |
EXEC | 执行所有事务块内的命令 |
WATCH key | 监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断,乐观锁定 |
UNWATCH | 取消 WATCH 命令对所有 key 的监视 |
在事务中,如果执行的语句不符合语法规则,则事务会被放弃;如果执行的语句符合语法规则,则执行会继续执行,异常也不会影响事务中其它命令的执行。
当使用 watch 监控了一个 key 时,别的客户端再修改该值,则 watch 监控处开启的事务中的语句将都不会执行,且事务执行时会返回 (nil)
,exec
后,所有监控锁都会被取消掉。
Pipeline 是批处理命令变种优化措施,类似于 Redis 的原生批处理命令( mget
和 mset
),主要用于解决频繁命令往返造成的性能瓶颈。
使用:首先编写 Redis 批处理文档 cmd.txt
,如下:
set k100 v100
set k200 v200
hset k300 name haha
hset k300 age 20
hset k300 gender male
使用管道参数执行,则 cmd.txt
的命令均会在 redis 中执行:
cat cmd.txt | redis-cli -a 密码 --pipe
注意:
主从复制,就是 master 以写为主,slave 以读为主,当 master 数据变化的时候,自动将新的数据异步同步到其它 slave 数据库。
作用:读写分离,容灾恢复,数据备份,水平扩容支撑高并发
配置小结:
requirepass
参数,那么 slave 就要配置 masterauth
来设置连接主库的密码info replication
:查看节点的主从关系和配置信息relicaof 主库IP 主库端口
:主从复制,配置文件,在从库服务器上配置主库slaveof 主库IP 主库端口
:改换门庭,运行期间,执行该命令,建立从库关系,如果已经是从库,则会停止和原数据的同步关系slaveof no one
:自立为王个人利用虚拟机进行主从复制配置步骤,配置前需确保主从机之间网络互通,且主机防火墙已放行对应端口:
daemonize yes
bind 127.0.0.1
protected-mode no
port 6379
,默认就是 6379dir ./
默认值,可修改。还有文件名: dbfilename dump.rdb
pidfile /var/run/redis_6379.pid
logfile "/root/myopt/redis7/6379redis.log"
requirepass 密码
appendonly yes
开启 aof ,文件名: appendfilename "appendonly.aof"
replicaof 主库IP 主库端口
,masterauth 主机密码
主机不需要配置
slaveof 主库IP 端口
:使用该命令也可临时配置,重启后关系会断开薪火相传:slave 也可以作为其他 slave 的 master,减轻主 master 的压力
复制原理及工作流程:
repl-ping-replica-period 10
缺点:后面的 Redis 哨兵及集群将会针对这两个痛点进行一定优化
俗称无人值守运维,可以解决主从复制中 master 挂了必须人工干预的痛点。哨兵监控 master 主机是否故障,如果故障了重新选举 master 继续对外服务。
特点:
哨兵配置:从安装时解压的解压目录中,复制 sentinel.conf
文件,按以下顺序配置
bind 0.0.0.0
:服务监听目录,用于客户端连接,默认无该项配置需自行添加(本人添加到配置文件第二行),但默认是本机地址protected-mode no
:默认即关闭,关闭保护模式,允许其他 redis 访问port 26379
:配置端口,默认 26379
daemonize yes
:开启后台运行,默认 no
pidfile /var/run/redis-sentinel26379.pid
:pid 文件路径,默认 /var/run/redis-sentinel.pid
logfile "/root/myopt/redis7/sentinel26379.log"
:配置日志目录,默认 ""
dir /root/myopt/redis7
:配置工作目录,默认 /tmp
sentinel monitor mymaster 192.168.115.129 6379 2
:设置要监控的 master 服务器,最后一个参数是 quorum
,表示最少哨兵认可的客观下线票数。默认为 sentinel monitor mymaster 127.0.0.1 6379 2
sentinel auth-pass mymaster 主机密码
:设置主机连接密码,默认无该项配置,可在 # sentinel auth-pass mymaster MySUPER--secret-0123passw0rd
该注释行下添加其他配置:可自行视情况调整
配置 | 描述 |
---|---|
sentinel down-after-milliseconds |
指定多少毫秒之后,主节点没有应答哨兵,此时哨兵主观上认为主节点下线 |
sentinel parallel-syncs |
表示允许并行同步的slave个数 |
sentinel failover-timeout |
故障转移的超时时间,故障转移时,如果超过设置的毫秒,表示故障转移失败 |
sentinel notification-script |
配置当某一事件发生时所需要执行的脚本 |
sentinel client-reconfig-script |
客户端重新配置主节点参数脚本 |
提供一份测试中可直接使用的 sentinel.conf
参考配置:
bind 0.0.0.0
daemonize yes
protected-mode no
port 26379
logfile "/root/myopt/redis7/sentinel26379.log"
pidfile /var/run/redis-sentinel26379.pid
dir /root/myopt/redis7/
sentinel monitor mymaster 192.168.115.129 6379 2
sentinel auth-pass mymaster 主机密码
做完以上哨兵配置后,哨兵启动命令:redis-sentinel sentinel26379.conf --sentinel
,哨兵启动后可以在 master 用 info sentinel
查看哨兵信息
哨兵运行流程:当一个主从配置的 master 失效后,sentinel 可以选举出一个新的 master 接替原 master 工作,其他从机配置自动指向新 master 并同步数据。
一般不建议 sentinel 采取1~2台,防止某一台 sentinel 无法连接到 master 导致误切换
Server closed the connection
或Broken pipe
主机失效后,从机处可能的报错,意思是对端的管道已经断开,再次执行可能就会好
sentinel down-after-milliseconds
可配置认定失效时间,默认 30 秒quorum
个 sentinel 认为这个 master 有故障才会对这个master进行下线以及故障转移slave-priority
或者 replica-priority
最高的从节点(数字越小优先级越高)slaveof no one
操作,将其提升为 master 节点上述 slave 切换 master 时都会执行一个同步操作,先将自身的数据清除,再同步新 master 的数据。
使用建议:
哨兵使用的最大优缺点:
后面的集群,将着手解决 master 失效问题,保证高可用。
Redis是一个提供在多个Redis节点间共享数据的程序集,Redis集群可以支持多个 master,每个 master 又可以挂载多个 slave,故可支持读写分离,数据的高可用,以及海量数据的读写存储操作。
特别注意:Redis 集群不保证强一致性,在特定条件下,Redis 集群可能会丢掉一些被系统收到的写入命令
Redis 集群没有使用一致性 hash,而是引入了哈希槽的概念,Redis 集群有 16384(2^14) 个哈希槽,每个 key 通过 CRC16 校验后对 16384 取模来决定槽位。集群的每个节点负责一部分槽位。比如集群有3个节点,那么如下:
分片:集群中的每个Redis实例都被认为是整个数据的一个分片。使用确定性哈希函数,这意味着给定的key将多次始终映射到同一个分片
hash(key) % 3
,增删节点会导致取模公式变化,会导致hash取模数据全部重新洗牌HashSlot = CRC16(key) mod 16384
,按槽分配,使得节点可均匀持有相同的槽位数,这即满足方便增删节点,又解决了数据倾斜问题首先,CRC16产生的 hash 值是 16 bit 即 2^16=65535 个值,有更大的65535为什么不用,而选择2^14=16384?
在消息头中最占空间的是 myslots[CLUSTER_SLOTS/8]
。 当槽位为65536时,这块的大小是: 65536÷8÷1024=8kb
在消息头中最占空间的是 myslots[CLUSTER_SLOTS/8]
。 当槽位为16384时,这块的大小是: 16384÷8÷1024=2kb
因为每秒钟,redis节点需要发送一定数量的ping消息作为心跳包,如果槽位为65536,这个ping消息的消息头太大了,浪费带宽。
集群节点越多,心跳包的消息体内携带的数据越多。如果节点过1000个,也会导致网络拥堵。因此redis作者不建议redis cluster节点数量超过1000个。 那么,对于节点数在1000以内的redis cluster集群,16384个槽位够用了。没有必要拓展到65536个。
Redis主节点的配置信息中它所负责的哈希槽是通过一张bitmap的形式来保存的,在传输过程中会对bitmap进行压缩,但是如果bitmap的填充率slots / N很高的话(N表示节点数),bitmap的压缩率就很低。 如果节点数很少,而哈希槽数量很多的话,bitmap的压缩率就很低
首先,模板配置文件即最初解压目录中的 redis.conf
,配置模块为 REDIS CLUSTER
,根据该内容搜索即可直接到配置文件对应模块,重点要求配置的有
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 5000
这里提供一份测试用的完整的配置文件
bind 0.0.0.0
daemonize yes
protected-mode no
port 6379
logfile "/root/myopt/redis7/cluster/cluster6379.log"
pidfile /root/myopt/redis7/cluster/cluster6379.pid
dir /root/myopt/redis7/cluster
dbfilename dump6379.rdb
appendonly yes
appendfilename "appendonly6379.aof"
requirepass redis
masterauth redis
# 集群配置
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 5000
redis-server /root/myopt/redis7/cluster/redisCluster6379.conf
redis-cli -a redis --cluster create --cluster-replicas 1 192.168.115.129:6379 192.168.115.129:6380 192.168.115.130:6379 192.168.115.130:6380 192.168.115.131:6379 192.168.115.131:6380
Could not connect to Redis at 192.168.115.130:6379: No route to host
可尝试关闭防火墙( systemctl stop firewalld
)再执行redis-cli -a redis -p 6379
info replication
,cluster info
,cluster nodes
当主机宕机时,从机便会上位成为主机(新主登基),且原主机恢复后将会成为新主机的从机(旧主拜服)。
Redis 集群有 16384 个哈希槽,每个 key 通过 CRC16 校验后对 16384 取模来决定放在哪个槽,集群中的每个节点负责一部分的hash槽。
-c
参数,则是以连接集群的方式连接,当操作不是本机管理的键值对就会自动转发路由进行操作,这样就可以对全部键值对进行管理,示例命令:redis-cli -a redis -c
cluster keysolt key
cluster failover
{}
来定义同一组的概念,同组内容将被放在同一槽位中
mset k1{x} 11 k2{x} 22 k3{x} 33
和 mget k1{x} k2{x} k3{x}
cluster-require-full-coverage
默认 yes
,即需要集群完整方可对外提供服务,如要求不完整集群也可提供服务可配置为 no
cluster countkeysinslot 槽位数字编号
:查看槽位占用情况。1表示被占用,0表示未占用cluster keyslot key
:查看键应占槽位号redis-cli -a 密码 --raw
:--raw
看 redis 中存储的中文将不再乱码redis-cli -a 密码 --cluster add-node 待加入节点IP:端口 集群中节点IP:端口
,后者相当于入群申请的介绍人redis-cli -a 密码 --cluster check 新加入节点IP:端口
,新加入节点暂未分配槽位redis-cli -a 密码 --cluster reshard 新加入节点IP:端口
,需填写新节点将管理槽位数,ID以及可供分配的槽位(一般填 all
即可)redis-cli -a 密码 --cluster check 新加入节点IP:端口
,新加入节点将被分配不连续的多段槽位redis-cli -a 密码 --cluster add-node 新slave的ip:端口 集群中主机IP:端口 --cluster-slave --cluster-master-id 主机节点ID
redis-cli -a 密码 --cluster check 主机IP:端口
,确认对应主机 slave 数增加,从节点成功加入redis-cli -a 密码 --cluster check 从节点IP:端口
redis-cli -a 密码 --cluster del-node 从节点IP:端口 从节点ID
redis-cli -a 密码 --cluster reshard 待删主节点IP:端口
Source node
填待删除主机IP,后填 Done
redis-cli -a 密码 --cluster check 待删主节点IP:端口
,如待删节点槽位未清0,则仍需继续执行第3步redis-cli -a 密码 --cluster del-node 待删主节点IP:端口 待删节点ID
redis-cli -a 密码 --cluster check 某个主机IP:端口
,检查对应节点是否已被删除这里使用的是 SpringBoot3,SpringBoot2中配置稍有不同,但这里不介绍,请自行了解。
Redis单机版,RedisTemplate配置及使用步骤:
在SpringBoot项目中导入依赖及添加配置
org.springframework.boot
spring-boot-starter-data-redis
spring:
data:
redis:
host: 192.168.115.129
password: redis
配置 RedisTemplate ,配置后可以解决一系列序列化问题
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory)
{
RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(lettuceConnectionFactory);
//设置key序列化方式string
redisTemplate.setKeySerializer(new StringRedisSerializer());
//设置value的序列化方式json,使用GenericJackson2JsonRedisSerializer替换默认序列化
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
测试
@SpringBootTest(classes = SpringBootApplicationMain.class)
public class MainTest {
@Autowired private RedisTemplate redisTemplate;
@Test
public void test1() {
System.out.println(redisTemplate.opsForValue().get("a"));
redisTemplate.opsForValue().set("c", "非常好");
System.out.println(redisTemplate.opsForValue().get("c"));
}
}
Redis集群版,相比单机版只需修改配置文件:
spring:
data:
redis:
lettuce:
cluster:
refresh:
# 支持集群拓扑动态感应刷新,自适应拓扑刷新是否使用所有可用的更新,默认false关闭
adaptive: true
# 定时刷新
period: 2000
cluster:
nodes: 192.168.115.129:6379,192.168.115.129:6380,192.168.115.131:6379,192.168.115.131:6380,192.168.115.132:6379,192.168.115.132:6380
password: redis