200字
Redis配置
2026-03-21
2026-03-21

Redis 配置管理

Redis 配置文件说明

bind 0.0.0.0 #指定监听地址,支持用空格隔开的多个监听IP

protected-mode yes #redis3.2之后加入的新特性,在没有设置bind IP和密码的时候,redis只允许访问127.0.0.1:6379,可以远程连接,但当访问将提示警告信息并拒绝远程访问,redis-7版本后,只要没有密码就不能远程访问

port 6379 #监听端口,默认6379/tcp

tcp-backlog 511 #三次握手的时候server端收到client ack确认号之后的队列值,即全连接队列长度

timeout 0 #客户端和Redis服务端的连接超时时间,默认是0,表示永不超时

tcp-keepalive 300 #tcp 会话保持时间300s

daemonize no #默认no,即直接运行redis-server程序时,不作为守护进程运行,而是以前台方式运行,如果想在后台运行需改成yes,当redis作为守护进程运行的时候,它会写一个 pid 到/var/run/redis.pid 文件

supervised no #和OS相关参数,可设置通过upstart和systemd管理Redis守护进程,centos7后都使用systemd

pidfile /var/run/redis_6379.pid #pid文件路径,可以修改为/apps/redis/run/redis_6379.pid

loglevel notice #日志级别

logfile "/path/redis.log" #日志路径,示例:logfile "/apps/redis/log/redis_6379.log"

databases 16 #设置数据库数量,默认:0-15,共16个库

always-show-logo yes #在启动redis 时是否显示或在日志中记录记录redis的logo

save 900 1 #在900秒内有1个key内容发生更改,就执行快照机制
save 300 10 #在300秒内有10个key内容发生更改,就执行快照机制
save 60 10000 #60秒内如果有10000个key以上的变化,就自动快照备份

stop-writes-on-bgsave-error yes #默认为yes时,可能会因空间满等原因快照无法保存出错时,会禁止redis写入操作,生产建议为no

	#此项只针对配置文件中的自动save有效
	
rdbcompression yes #持久化到RDB文件时,是否压缩,"yes"为压缩,"no"则反之

rdbchecksum yes #是否对备份文件开启RC64校验,默认是开启

dbfilename dump.rdb #快照文件名

dir ./ #快照文件保存路径,示例:dir "/apps/redis/data"

#主从复制相关
# replicaof <masterip> <masterport> #指定复制的master主机地址和端口,5.0版之前的指令为slaveof
# masterauth <master-password> #指定复制的master主机的密码

replica-serve-stale-data yes #当从库同主库失去连接或者复制正在进行,从机库有两种运行方式:
1、设置为yes(默认设置),从库会继续响应客户端的读请求,此为建议值
2、设置为no,除去特定命令外的任何请求都会返回一个错误"SYNC with master in progress"。

replica-read-only yes #是否设置从库只读,建议值为yes,否则主库同步从库时可能会覆盖数据,造成数据丢失

repl-diskless-sync no #是否使用socket方式复制数据(无盘同步),新slave第一次连接master时需要做数据的全量同步,redis server就要从内存dump出新的RDB文件,然后从master传到slave,有两种方式把RDB文件传输给客户端:
1、基于硬盘(disk-backed):为no时,master创建一个新进程dump生成RDB磁盘文件,RDB完成之后由父进程(即主进程)将RDB文件发送给slaves,此为默认值
2、基于socket(diskless):master创建一个新进程直接dump RDB至slave的网络socket,不经过主进程和硬盘
#推荐使用基于硬盘(为no),是因为RDB文件创建后,可以同时传输给更多的slave,但是基于socket(为yes), 新slave连接到master之后得逐个同步数据。只有当磁盘I/O较慢且网络较快时,可用diskless(yes),否则一般建议使用磁盘(no)

repl-diskless-sync-delay 5 #diskless时复制的服务器等待的延迟时间,设置0为关闭,在延迟时间内到达的客户端,会一起通过diskless方式同步数据,但是一旦复制开始,master节点不会再接收新slave的复制请求,直到下一次同步开始才再接收新请求。即无法为延迟时间后到达的新副本提供服务,新副本将排队等待下一次RDB传输,因此服务器会等待一段时间才能让更多副本到达。推荐值:30-60

repl-ping-replica-period 10 #slave根据master指定的时间进行周期性的PING master,用于监测master状态,默认10s

repl-timeout 60 #复制连接的超时时间,需要大于repl-ping-slave-period,否则会经常报超时

repl-disable-tcp-nodelay no #是否在slave套接字发送SYNC之后禁用 TCP_NODELAY,如果选择"yes",Redis将合并多个报文为一个大的报文,从而使用更少数量的包向slaves发送数据,但是将使数据传输到slave上有延迟,Linux内核的默认配置会达到40毫秒,如果 "no" ,数据传输到slave的延迟将会减少,但要使用更多的带宽

repl-backlog-size 512mb #复制缓冲区内存大小,当slave断开连接一段时间后,该缓冲区会累积复制副本数据,因此当slave 重新连接时,通常不需要完全重新同步,只需传递在副本中的断开连接后没有同步的部分数据即可。只有在至少有一个slave连接之后才分配此内存空间,建议建立主从时此值要调大一些或在低峰期配置,否则会导致同步到slave失败

repl-backlog-ttl 3600 #多长时间内master没有slave连接,就清空backlog缓冲区

replica-priority 100 #当master不可用,哨兵Sentinel会根据slave的优先级选举一个master,此值最低的slave会优先当选master,而配置成0,永远不会被选举,一般多个slave都设为一样的值,让其自动选择

#min-replicas-to-write 3 #至少有3个可连接的slave,mater才接受写操作
#min-replicas-max-lag 10 #和上面至少3个slave的ping延迟不能超过10秒,否则master也将停止写操作

requirepass foobared #设置redis连接密码,之后需要AUTH pass,如果有特殊符号,用" "引起来,生产建议设置

rename-command #重命名一些高危命令,示例:rename-command FLUSHALL "" 禁用命令
	#示例: rename-command del aya
	
maxclients 10000 #Redis最大连接客户端

maxmemory <bytes> #redis使用的最大内存,单位为bytes字节,0为不限制,建议设为物理内存一半,8G内存的计算方式8(G)*1024(MB)1024(KB)*1024(Kbyte),需要注意的是缓冲区是不计算在maxmemory内,生产中如果不设置此项,可能会导致OOM

maxmemory-policy
# MAXMEMORY POLICY:当达到最大内存时,Redis 将如何选择要删除的内容。您可以从以下行为中选择一种:
#
# volatile-lru -> Evict 使用近似 LRU,只有设置了过期时间的键。
# allkeys-lru -> 使用近似 LRU 驱逐任何键。
# volatile-lfu -> 使用近似 LFU 驱逐,只有设置了过期时间的键。
# allkeys-lfu -> 使用近似 LFU 驱逐任何键。
# volatile-random -> 删除设置了过期时间的随机密钥。
# allkeys-random -> 删除一个随机密钥,任何密钥。
# volatile-ttl -> 删除过期时间最近的key(次TTL)
# noeviction -> 不要驱逐任何东西,只是在写操作时返回一个错误。此为默认值
#
# LRU 表示最近最少使用
# LFU 表示最不常用
#
# LRU、LFU 和 volatile-ttl 都是使用近似随机算法实现的。
#
# 注意:使用上述任何一种策略,当没有合适的键用于驱逐时,Redis 将在需要更多内存的写操作时返回错误。这些通常是创建新密钥、添加数据或修改现有密钥的命令。一些示例是:SET、INCR、HSET、LPUSH、SUNIONSTORE、SORT(由于 STORE 参数)和 EXEC(如果事务包括任何需要内存的命令)。

appendonly no #是否开启AOF日志记录,默认redis使用的是rdb方式持久化,这种方式在许多应用中已经足够用了,但是redis如果中途宕机,会导致可能有几分钟的数据丢失(取决于dump数据的间隔时间),根据save来策略进行持久化,Append Only File是另一种持久化方式,可以提供更好的持久化特性,Redis会把每次写入的数据在接收后都写入 appendonly.aof 文件,每次启动时Redis都会先把这个文件的数据读入内存里,先忽略RDB文件。默认不启用此功能

appendfilename "appendonly.aof" #文本文件AOF的文件名,存放在dir指令指定的目录中

appendfsync everysec #aof持久化策略的配置
#no表示由操作系统保证数据同步到磁盘,Linux的默认fsync策略是30秒,最多会丢失30s的数据
#always表示每次写入都执行fsync,以保证数据同步到磁盘,安全性高,性能较差
#everysec表示每秒执行一次fsync,可能会导致丢失这1s数据,此为默认值,也生产建议值

#同时在执行bgrewriteaof操作和主进程写aof文件的操作,两者都会操作磁盘,而bgrewriteaof往往会涉及大量磁盘操作,这样就会造成主进程在写aof文件的时候出现阻塞的情形,以下参数实现控制

no-appendfsync-on-rewrite no #在aof rewrite期间,是否对aof新记录的append暂缓使用文件同步策略,主要考虑磁盘IO开支和请求阻塞时间。
#默认为no,表示"不暂缓",新的aof记录仍然会被立即同步到磁盘,是最安全的方式,不会丢失数据,但是要忍受阻塞的问题
#为yes,相当于将appendfsync设置为no,这说明并没有执行磁盘操作,只是写入了缓冲区,因此这样并不会造成阻塞(因为没有竞争磁盘),但是如果这个时候redis挂掉,就会丢失数据。丢失多少数据呢?Linux的默认fsync策略是30秒,最多会丢失30s的数据,但由于yes性能较好而且会避免出现阻塞因此比较推荐

#rewrite 即对aof文件进行整理,将空闲空间回收,从而可以减少恢复数据时间

auto-aof-rewrite-percentage 100 #当Aof log增长超过指定百分比例时,重写AOF文件,设置为0表示不自动重写Aof日志,重写是为了使aof体积保持最小,但是还可以确保保存最完整的数据

auto-aof-rewrite-min-size 64mb #触发aof rewrite的最小文件大小

aof-load-truncated yes #是否加载由于某些原因导致的末尾异常的AOF文件(主进程被kill/断电等),建议yes

aof-use-rdb-preamble no #redis4.0新增RDB-AOF混合持久化格式,在开启了这个功能之后,AOF重写产生的文件将同时包含RDB格式的内容和AOF格式的内容,其中RDB格式的内容用于记录已有的数据,而AOF格式的内容则用于记录最近发生了变化的数据,这样Redis就可以同时兼有RDB持久化和AOF持久化的优点(既能够快速地生成重写文件,也能够在出现问题时,快速地载入数据),默认为no,即不启用此功能

lua-time-limit 5000 #lua脚本的最大执行时间,单位为毫秒

cluster-enabled yes #是否开启集群模式,默认不开启,即单机模式

cluster-config-file nodes-6379.conf #由node节点自动生成的集群配置文件名称

cluster-node-timeout 15000 #集群中node节点连接超时时间,单位ms,超过此时间,会踢出集群

cluster-replica-validity-factor 10 #单位为次,在执行故障转移的时候可能有些节点和master断开一段时间导致数据比较旧,这些节点就不适用于选举为master,超过这个时间的就不会被进行故障转移,不能当选master,计算公式:(node-timeout * replica-validity-factor) + repl-ping-replica-period

cluster-migration-barrier 1 #集群迁移屏障,一个主节点至少拥有1个正常工作的从节点,即如果主节点的slave节点故障后会将多余的从节点分配到当前主节点成为其新的从节点。

cluster-require-full-coverage yes #集群请求槽位全部覆盖,如果一个主库宕机且没有备库就会出现集群槽位不全,那么yes时redis集群槽位验证不全,就不再对外提供服务(对key赋值时,会出现CLUSTERDOWN The cluster is down的提示,cluster_state:fail,但ping 仍PONG),而no则可以继续使用,但是会出现查询数据查不到的情况(因为有数据丢失)。生产建议为no

cluster-replica-no-failover no #如果为yes,此选项阻止在主服务器发生故障时尝试对其主服务器进行故障转移。 但是,主服务器仍然可以执行手动强制故障转移,一般为no

#Slow log 是 Redis 用来记录超过指定执行时间的日志系统,执行时间不包括与客户端交谈,发送回复等I/O操作,而是实际执行命令所需的时间(在该阶段线程被阻塞并且不能同时为其它请求提供服务),由于slow log 保存在内存里面,读写速度非常快,因此可放心地使用,不必担心因为开启 slow log 而影响Redis 的速度

slowlog-log-slower-than 10000 #以微秒为单位的慢日志记录,为负数会禁用慢日志,为0会记录每个命令操作。默认值为10ms,一般一条命令执行都在微秒级,生产建议设为1ms-10ms之间

slowlog-max-len 128 #最多记录多少条慢日志的保存队列长度,达到此长度后,记录新命令会将最旧的命令从命令队列中删除,以此滚动删除,即,先进先出,队列固定长度,默认128,值偏小,生产建议设为1000以上

config 命令实现动态修改配置

config 命令用于查看当前redis配置、以及不重启redis服务实现动态更改redis配置等

注意:不是所有配置都可以动态修改,且此方式无法持久保存

CONFIG SET parameter value
时间复杂度:O(1)
CONFIG SET 命令可以动态地调整 Redis 服务器的配置(configuration)而无须重启。

可以使用它修改配置参数,或者改变 Redis 的持久化(Persistence)方式。
CONFIG SET 可以修改的配置参数可以使用命令 CONFIG GET * 来列出,所有被 CONFIG SET 修改的配置参数都会立即生效。

CONFIG GET parameter
时间复杂度: O(N),其中 N 为命令返回的配置选项数量。
CONFIG GET 命令用于取得运行中的 Redis 服务器的配置参数(configuration parameters),在Redis 2.4 版本中, 有部分参数没有办法用 CONFIG GET 访问,但是在最新的 Redis 2.6 版本中,所有配置参数都已经可以用 CONFIG GET 访问了。


CONFIG GET 接受单个参数 parameter 作为搜索关键字,查找所有匹配的配置参数,其中参数和值以“键-值对”(key-value pairs)的方式排列。
比如执行 CONFIG GET s* 命令,服务器就会返回所有以 s 开头的配置参数及参数的值:

范例:版本差异

#redis-7支持动态修改端口
127.0.0.1:6379> config set port 8888
OK

#redis-5不支持动态修改端口
127.0.0.1:6379> config set port 8888
(error) ERR Unsupported CONFIG parameter: port

设置客户端连接密码

#设置连接密码
127.0.0.1:6379> CONFIG SET requirepass 123456
OK

#查看连接密码
127.0.0.1:6379> CONFIG GET requirepass
1) "requirepass"
2) "123456"

获取当前配置

#奇数行为键,偶数行为值
127.0.0.1:6379> CONFIG GET *
1) "dbfilename"
2) "dump.rdb"
3) "requirepass"
4) ""
5) "masterauth"
6) ""
7) "cluster-announce-ip"
8) ""
9) "unixsocket"
10) ""
11) "logfile"
12) "/var/log/redis/redis.log"
13) "pidfile"
14) "/var/run/redis_6379.pid"
15) "slave-announce-ip"
16) ""
17) "replica-announce-ip"
18) ""
19) "maxmemory"
20) "0"
......

#查看bind
127.0.0.1:6379> CONFIG GET bind
1) "bind"
2) "0.0.0.0"

#Redis5.0有些设置无法修改,Redis6.2.6版本支持修改bind
127.0.0.1:6379> CONFIG SET bind 127.0.0.1
(error) ERR Unsupported CONFIG parameter: bind

设置 Redis 使用的最大内存量

127.0.0.1:6379> CONFIG SET maxmemory 8589934592 或 1g|G # 默认以字节为单位

127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "8589934592

慢查询

iayaka-20260320175038917

范例: SLOW LOG

[root@centos8 ~]#vim /etc/redis.conf
slowlog-log-slower-than 1 #单位为us,指定超过1us即为慢的指令,默认值为10000us
slowlog-max-len 1024 #指定只保存最近的1024条慢记录,默认值为128

127.0.0.1:6379> SLOWLOG LEN #查看慢日志的记录条数
(integer) 14
127.0.0.1:6379> SLOWLOG GET [n] #查看慢日志的最近n条记录,默认为10
1) 1) (integer) 14
2) (integer) 1544690617 #第2)行表示命令执行的时间戳,距离1970-1-1的秒数,date -d +@1544690617 可以转换
3) (integer) 4 #第3)行表示每条指令的执行时长
4) 1) "slowlog"
127.0.0.1:6379> SLOWLOG GET 3
1) 1) (integer) 7
2) (integer) 1602901545
3) (integer) 26
4) 1) "SLOWLOG"
2) "get"
5) "127.0.0.1:38258"
6) ""
2) 1) (integer) 6
2) (integer) 1602901540
3) (integer) 22
4) 1) "SLOWLOG"
2) "get"
3) "2"
5) "127.0.0.1:38258"
6) ""
3) 1) (integer) 5
2) (integer) 1602901497
3) (integer) 22
4) 1) "SLOWLOG"
2) "GET"
5) "127.0.0.1:38258"
6) ""
127.0.0.1:6379> SLOWLOG RESET #清空慢日志
OK

Redis 持久化

Redis 是基于内存型的NoSQL, 和MySQL是不同的,使用内存进行数据保存

如果想实现数据的持久化,Redis也也可支持将内存数据保存到硬盘文件中

Redis支持两种数据持久化保存方法

  • RDB:Redis DataBase
  • AOF:AppendOnlyFile

RDB

RDB 工作原理

redis持久化aof结合rdb redis持久化rdb和aof优缺点_数据

RDB(Redis DataBase):是基于某个时间点的快照,注意RDB只保留当前最新版本的一个快照

相当于MySQL中的完全备份

RDB 持久化功能所生成的 RDB 文件是一个经过压缩的二进制文件,通过该文件可以还原生成该 RDB 文件时数据库的状态。因为 RDB 文件是保存在磁盘中的,所以即便 Redis 服务进程甚至服务器宕机,只要磁盘中 RDB 文件存在,就能将数据恢复

RDB 支持save和bgsave两种命令实现数据文件的持久化

RDB bgsave 实现快照的具体过程

注意: save 指令使用主进程进行备份,而不生成新的子进程

java 非结构化数据 敏感词_服务器_04

首先从redis 主进程先fork生成一个新的子进程,此子进程负责将Redis内存数据保存为一个临时文件tmp-<子进程pid>.rdb,当数据保存完成后,再将此临时文件改名为RDB文件,如果有前一次保存的RDB文件则会被替换,最后关闭此子进程

由于Redis只保留最后一个版本的RDB文件,如果想实现保存多个版本的数据,需要人为实现

范例: save 执行过程会使用主进程进行快照

[root@centos7 data]#redis-cli -a 123456 save&
[1] 28684
[root@centos7 data]#pstree -p |grep redis ;ll /apps/redis/data
        |-redis-server(28650)-+-{redis-server}(28651)
        | 					|-{redis-server}(28652)
        | 					|-{redis-server}(28653)
        | 					`-{redis-server}(28654)
        | 	| 								`-redis-cli(28684)
        | 	`-sshd(23494)---bash(23496)---redis-cli(28601)
        total 251016
        -rw-r--r-- 1 redis redis 189855682 Nov 17 15:02 dump.rdb
        -rw-r--r-- 1 redis redis 45674498 Nov 17 15:02 temp-28650.rdb

RDB 相关配置

#在配置文件中的 save 选项设置多个保存条件,只有任何一个条件满足,服务器都会自动执行 BGSAVE 命令
#Redis7.0以后支持写在一行,如:save 3600 1 300 100 60 10000,此也为默认值
save 900 1 #900s内修改了1个key即触发保存RDB
save 300 10 #300s内修改了10个key即触发保存RDB
save 60 10000 #60s内修改了10000个key即触发保存RDB

dbfilename dump.rdb
dir ./ #编泽编译安装时默认RDB文件存放在Redis的工作目录,此配置可指定保存的数据目录

stop-writes-on-bgsave-error yes #当快照失败是否仍允许写入,yes为出错后禁止写入,建议为no
rdbcompression yes
rdbchecksum yes

范例:RDB 相关配置

[root@ubuntu2004 ~]#grep save /apps/redis/etc/redis.conf
# save <seconds> <changes>
# Redis will save the DB if both the given number of seconds and the given
# save ""
# Unless specified otherwise, by default Redis will save the DB:
# save 3600 1
# save 300 100
# save 60 10000
#以上是默认值

[root@ubuntu2004 ~]#redis-cli config get save
1) "save"
2) "3600 1 300 100 60 10000"

#禁用系统的自动快照
[root@ubuntu2004 ~]#vim /apps/redis/etc/redis.conf
save ""
# save 3600 1
# save 300 100
# save 60 10000

实现 RDB 方法

  • save: 同步,不推荐使用,使用主进程完成快照,因此会阻赛其它命令执行
  • bgsave: 异步后台执行,不影响其它命令的执行,会开启独立的子进程,因此不会阻赛其它命令执行
  • 配置文件实现自动保存: 在配置文件中制定规则,自动执行bgsave

RDB 模式的优缺点

RDB 模式优点
  • RDB快照只保存某个时间点的数据,恢复的时候直接加载到内存即可,不用做其他处理,这种文件适合用于做灾备处理.可以通过自定义时间点执行redis指令bgsave或者save保存快照,实现多个版本的备份

    • 比如: 可以在最近的24小时内,每小时备份一次RDB文件,并且在每个月的每一天,也备份一个RDB文件。这样的话,即使遇上问题,也可以随时将数据集还原到指定的不同的版本。
  • RDB在大数据集时恢复的速度比AOF方式要快

RDB 模式缺点
  • 不能实时保存数据,可能会丢失自上一次执行RDB备份到当前的内存数据
    • 如果需要尽量避免在服务器故障时丢失数据,那么RDB并不适合。虽然Redis允许设置不同的保存点(save point)来控制保存RDB文件的频率,但是,因为RDB文件需要保存整个数据集的状态,所以它可能并不是一个非常快速的操作。因此一般会超过5分钟以上才保存一次RDB文件。在这种情况下,一旦发生故障停机,就可能会丢失较长时间的数据。
  • 在数据集比较庞大时,fork()子进程可能会非常耗时,造成服务器在一定时间内停止处理客户端请求,如果数据集非常巨大,并且CPU时间非常紧张的话,那么这种停止时间甚至可能会长达整整一秒或更久。另外子进程完成生成RDB文件的时间也会花更长时间.

范例: 手动执行备份RDB

[root@rocky8 ~]#redis-cli
127.0.0.1:6379> debug populate 5000000
OK
(3.96s)
127.0.0.1:6379> dbsize
(integer) 5000000
127.0.0.1:6379> get key:0
"value:0"
127.0.0.1:6379> get key:1
"value:1"
127.0.0.1:6379> get key:2
"value:2"
127.0.0.1:6379> get key:499999
"value:499999"
127.0.0.1:6379> get key:5000000
nil)
127.0.0.1:6379> bgsave
Background saving started
[root@rocky8 ~]#ll /var/lib/redis/ -h
total 127M
-rw-r--r-- 1 redis redis 127M Jun 13 23:07 dump.rdb

范例: 手动备份RDB文件的脚本

#配置文件
[root@centos7 ~]#vim /apps/redis/etc/redis.conf
save ""
dbfilename dump_6379.rdb
dir "/data/redis"
appendonly no

#脚本
[root@centos8 ~]#cat redis_backup_rdb.sh
#!/bin/bash
#

BACKUP=/backup/redis-rdb
DIR=/data/redis
FILE=dump_6379.rdb
PASS=123456

color () {
    RES_COL=60
    MOVE_TO_COL="echo -en \\033[${RES_COL}G"
    SETCOLOR_SUCCESS="echo -en \\033[1;32m"
    SETCOLOR_FAILURE="echo -en \\033[1;31m"
    SETCOLOR_WARNING="echo -en \\033[1;33m"
    SETCOLOR_NORMAL="echo -en \E[0m"
    echo -n "$1" && $MOVE_TO_COL
    echo -n "["
    if [ $2 = "success" -o $2 = "0" ] ;then
        ${SETCOLOR_SUCCESS}
        echo -n $" OK "
    elif [ $2 = "failure" -o $2 = "1" ] ;then
        ${SETCOLOR_FAILURE}
        echo -n $"FAILED"
    else
        ${SETCOLOR_WARNING}
        echo -n $"WARNING"
    fi
        ${SETCOLOR_NORMAL}
        echo -n "]"
        echo
}
redis-cli -h 127.0.0.1 -a $PASS --no-auth-warning bgsave
result=`redis-cli -a $PASS --no-auth-warning info Persistence |grep rdb_bgsave_in_progress| sed -rn 's/.*:([0-9]+).*/\1/p'`
#result=`redis-cli -a $PASS --no-auth-warning info Persistence |awk -F: '/rdb_bgsave_in_progress/{print $2}'`
until [ $result -eq 0 ] ;do
	sleep 1
	result=`redis-cli -a $PASS --no-auth-warning info Persistence |awk -F: '/rdb_bgsave_in_progress/{print $2}'`
done
DATE=`date +%F_%H-%M-%S`

[ -e $BACKUP ] || { mkdir -p $BACKUP ; chown -R redis.redis $BACKUP; }
cp $DIR/$FILE $BACKUP/dump_6379-${DATE}.rdb
color "Backup redis RDB" 0       



#执行
[root@centos8 ~]#bash redis_backup_rdb.sh
Background saving started
Backup redis RDB [ OK ]
[root@centos8 ~]#ll /backup/redis-rdb/ -h
total 143M
-rw-r--r-- 1 redis redis 143M Oct 21 11:08 dump_6379-2020-10-21_11-08-47.rdb

范例: 观察save 和 bgsave的执行过程

#阻塞
#生成临时文件
[root@centos7 ~]#(redis-cli -a 123456 save &) ; echo save is finished; redis-cli -a 123456 get class

范例: 自动保存

[root@centos7 ~]#vim /apps/redis/etc/redis.conf
save 60 3
#测试60s内修改3个key,验证是否生成RDB文件

AOF

AOF 工作原理

java 非结构化数据 敏感词_缓存_05

AOF 即 AppendOnlyFile,AOF 和 RDB 都采有COW机制,AOF可以指定不同的保存策略,默认为每秒钟执行一次 fsync,按照操作的顺序地将变更命令追加至指定的AOF日志文件尾部

在第一次启用AOF功能时,会做一次完全备份,后续将执行增量性备份,相当于完全数据备份+增量变化

如果同时启用RDB和AOF,进行恢复时,默认AOF文件优先级高于RDB文件,即会使用AOF文件进行恢复

在第一次开启AOF功能时,会自动备份所有数据到AOF文件中,后续只会记录数据的更新指令

注意: AOF 模式默认是关闭的,第一次开启AOF后,并重启服务生效后,会因为AOF的优先级高于RDB,而AOF默认没有数据文件存在,从而导致所有数据丢失

范例: 错误开启AOF功能,会导致数据丢失

[root@ubuntu1804 ~]#redis-cli
127.0.0.1:6379> dbsize
(integer) 10010011

[root@ubuntu1804 ~]#vim /apps/redis/etc/redis.conf
appendonly yes #修改此行

[root@ubuntu1804 data]#systemctl restart redis

[root@ubuntu1804 ~]#redis-cli
127.0.0.1:6379> dbsize
(integer) 0

范例: 正确启用AOF功能,访止数据丢失

[root@centos8 ~]#ll /var/lib/redis/
total 314392
-rw-r--r-- 1 redis redis 187779391 Oct 17 14:23 dump.rdb
[root@centos8 ~]#redis-cli
127.0.0.1:6379> config get appendonly
1) "appendonly"
2) "no"
127.0.0.1:6379> config set appendonly yes #自动触发AOF重写,会自动备份所有数据到AOF文件
OK
[root@centos8 ~]#ll /var/lib/redis/
total 314392
-rw-r--r-- 1 redis redis 187779391 Oct 17 14:23 dump.rdb
-rw-r--r-- 1 redis redis 85196805 Oct 17 14:45 temp-rewriteaof-2146.aof
[root@centos8 ~]#ll /var/lib/redis/
total 366760
-rw-r--r-- 1 redis redis 187779391 Oct 17 14:45 appendonly.aof
-rw-r--r-- 1 redis redis 187779391 Oct 17 14:23 dump.rdb
[root@centos8 ~]#vim /etc/redis.conf
appendonly yes #改为yes

#config set appendonly yes 后可以同时看到下面显示

iayaka-20260321103301450

范例: Redis 7.0以上版本的AOF是多个文件,Redis6.0以前版本只有一个文件

# Redis 7.0以上版本
[root@ubuntu2204 ~]#file /apps/redis/data/appendonlydir/*
/apps/redis/data/appendonlydir/appendonly.aof.1.base.rdb: Redis RDB file, version
0010
/apps/redis/data/appendonlydir/appendonly.aof.1.incr.aof: ASCII text, with CRLF
line terminators
/apps/redis/data/appendonlydir/appendonly.aof.manifest: ASCII text

#Redis6.0以前版本只有一个文件
[root@ubuntu2204 ~]#file /var/lib/redis/appendonly.aof
/var/lib/redis/appendonly.aof: Redis RDB file, version 0009

AOF 相关配置

appendonly no #是否开启AOF日志记录,默认redis使用的是rdb方式持久化,这种方式在许多应用中已经足够用了,但是redis如果中途宕机,会导致可能有几分钟的数据丢失(取决于dump数据的间隔时间),根据save来策略进行持久化,Append Only File是另一种持久化方式,可以提供更好的持久化特性,Redis会把每次写入的数据在接收后都写入 appendonly.aof 文件,每次启动时Redis都会先把这个文件的数据读入内存里,先忽略RDB文件。默认不启用此功能

appendfilename "appendonly.aof" #文本文件AOF的文件名,存放在dir指令指定的目录中
appenddirname "appendonlydir" #7.X 版指定目录名称

appendfsync everysec #aof持久化策略的配置

#no表示由操作系统保证数据同步到磁盘,Linux的默认fsync策略是30秒,最多会丢失30s的数据
#always表示每次写入都执行fsync,以保证数据同步到磁盘,安全性高,性能较差
#everysec表示每秒执行一次fsync,可能会导致丢失这1s数据,此为默认值,也生产建议值
dir /path


#rewrite相关
no-appendfsync-on-rewrite yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes

范例: 动态修改配置自动生成appendonly.aof文件

127.0.0.1:6379> CONFIG set appendonly yes

AOF Rewrite 重写

将一些重复的,可以合并的,过期的数据重新写入一个新的AOF文件,从而节约AOF备份占用的硬盘空间,也能加速恢复过程

可以手动执行bgrewriteaof 触发AOF,第一次开启AOF功能,或定义自动rewrite 策略

AOF rewrite 过程

父进程生成一个新的子进程负责生成新的AOF文件,同时父进程将新的数据更新同时写入两个缓冲区aof_buf和aof_rewrite_buf

图片-UGvFfbpOlclQCFFXNWxbAkWsgIQqNNoS.png

AOF rewrite 重写相关配置

#同时在执行bgrewriteaof操作和主进程写aof文件的操作,两者都会操作磁盘,而bgrewriteaof往往会涉及大量磁盘操作,这样就会造成主进程在写aof文件的时候出现阻塞的情形,以下参数实现控制
no-appendfsync-on-rewrite no #在aof rewrite期间,是否对aof新记录的append暂缓使用文件同步策略,主要考虑磁盘IO开支和请求阻塞时间。
#默认为no,表示"不暂缓",新的aof记录仍然会被立即同步到磁盘,是最安全的方式,不会丢失数据,但是要忍受阻塞的问题
#为yes,相当于将appendfsync设置为no,这说明并没有执行磁盘操作,只是写入了缓冲区,因此这样并不会造成阻塞(因为没有竞争磁盘),但是如果这个时候redis挂掉,就会丢失数据。丢失多少数据呢?Linux的默认fsync策略是30秒,最多会丢失30s的数据,但由于yes性能较好而且会避免出现阻塞因此比较推荐

#rewrite 即对aof文件进行整理,将空闲空间回收,从而可以减少恢复数据时间
auto-aof-rewrite-percentage 100 #当Aof log增长超过指定百分比例时,重写AOF文件,设置为0表示不自动重写Aof日志,重写是为了使aof体积保持最小,但是还可以确保保存最完整的数据
auto-aof-rewrite-min-size 64mb #触发aof rewrite的最小文件大小
aof-load-truncated yes #是否加载由于某些原因导致的末尾异常的AOF文件(主进程被kill/断电等),建议yes

手动执行AOF重写 BGREWRITEAOF 命令

BGREWRITEAOF
时间复杂度: O(N), N 为要追加到 AOF 文件中的数据数量。
执行一个 AOF文件 重写操作。重写会创建一个当前 AOF 文件的体积优化版本。

即使 BGREWRITEAOF 执行失败,也不会有任何数据丢失,因为旧的 AOF 文件在 BGREWRITEAOF 成功之前不会被修改。

重写操作只会在没有其他持久化工作在后台执行时被触发,也就是说:
如果 Redis 的子进程正在执行快照的保存工作,那么 AOF 重写的操作会被预定(scheduled),等到保存工作完成之后再执行 AOF 重写。在这种情况下, BGREWRITEAOF 的返回值仍然是 OK ,但还会加上一条额外的信息,说明 BGREWRITEAOF 要等到保存操作完成之后才能执行。在 Redis 2.6 或以上的版本,以使用 INFO [section] 命令查看 BGREWRITEAOF 是否被预定。

如果已经有别的 AOF 文件重写在执行,那么 BGREWRITEAOF 返回一个错误,并且这个新的BGREWRITEAOF 请求也不会被预定到下次执行。

从 Redis 2.4 开始, AOF 重写由 Redis 自行触发, BGREWRITEAOF 仅仅用于手动触发重写操作。

范例: 手动 bgrewriteaof

127.0.0.1:6379> BGREWRITEAOF
Background append only file rewriting started

#7.X版本
[root@ubuntu2204 etc]#redis-cli -a 123456 BGREWRITEAOF ; pstree -p ; ls -l /apps/redis/data/appendonlydir/
├─redis-server(41173)─┬─redis-server(41192)
│ 		├─{redis-server}(41174)
│ 		├─{redis-server}(41175)
│ 		├─{redis-server}(41176)
│ 		├─{redis-server}(41177)
│ 		├─{redis-server}(41183)
│ 		└─{redis-server}(41194)

-rw-r--r-- 1 redis redis 189855694 6月 26 16:53 appendonly.aof.2.base.rdb
-rw-r--r-- 1 redis redis 267 6月 26 17:04 appendonly.aof.2.incr.aof
-rw-r--r-- 1 redis redis 0 6月 26 17:10 appendonly.aof.3.incr.aof
-rw-r--r-- 1 redis redis 132 6月 26 17:10 appendonly.aof.manifest

#执行完成后incr文件清空,合并到RDB文件中
[root@ubuntu2204 etc]#ll /apps/redis/data/appendonlydir/
总计 185420
drwxr-xr-x 2 redis redis 4096 6月 26 17:10 ./
drwxr-xr-x 3 redis redis 4096 6月 26 17:10 ../
-rw-r--r-- 1 redis redis 189855711 6月 26 17:10 appendonly.aof.3.base.rdb
-rw-r--r-- 1 redis redis 0 6月 26 17:10 appendonly.aof.3.incr.aof
-rw-r--r-- 1 redis redis 88 6月 26 17:10 appendonly.aof.manifest

AOF 模式优缺点

AOF 模式优点
  • 数据安全性相对较高,根据所使用的fsync策略(fsync是同步内存中redis所有已经修改的文件到存储设备),默认是appendfsync everysec,即每秒执行一次 fsync,在这种配置下,Redis 仍然可以保持良好的性能,并且就算发生故障停机,也最多只会丢失一秒钟的数据( fsync会在后台线程执行,所以主线程可以继续努力地处理命令请求)
  • 由于该机制对日志文件的写入操作采用的是append模式,因此在写入过程中不需要seek, 即使出现宕机现象,也不会破坏日志文件中已经存在的内容。然而如果本次操作只是写入了一半数据就出现系统崩溃问题,不用担心,在Redis下一次启动之前,可以通过 redis-check-aof 工具来解决数据一致性的问题
  • Redis可以在 AOF文件体积变得过大时,自动地在后台对AOF进行重写,重写后的新AOF文件包含了恢复当前数据集所需的最小命令集合。整个重写操作是绝对安全的,因为Redis在创建新 AOF文件的过程中,append模式不断的将修改数据追加到现有的 AOF文件里面,即使重写过程中发生停机,现有的 AOF文件也不会丢失。而一旦新AOF文件创建完毕,Redis就会从旧AOF文件切换到新AOF文件,并开始对新AOF文件进行追加操作。
  • AOF包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作。事实上,也可以通过该文件完成数据的重建

AOF文件有序地保存了对数据库执行的所有写入操作,这些写入操作以Redis协议的格式保存,因此 AOF文件的内容非常容易被人读懂,对文件进行分析(parse)也很轻松。导出(export)AOF文件也非常简单:举个例子,如果不小心执行了FLUSHALL.命令,但只要AOF文件未被重写,那么只要停止服务器,移除 AOF文件末尾的FLUSHAL命令,并重启Redis ,就可以将数据集恢复到FLUSHALL执行之前的状态。

AOF 模式缺点
  • 即使有些操作是重复的也会全部记录,AOF 的文件大小一般要大于 RDB 格式的文件
  • AOF 在恢复大数据集时的速度比 RDB 的恢复速度要慢
    如果 fsync 策略是appendfsync no, , AOF保存到磁盘的速度甚至会可能会慢于RDB
  • bug 出现的可能性更多

RDB和AOF 的选择

如果主要充当缓存功能,或者可以承受较长时间,比如数分钟数据的丢失, 通常生产环境一般只需启用RDB即可,此也是默认值

如果一点数据都不能丢失,可以选择同时开启RDB和AOF

一般不建议只开启AOF

Redis 常用命令

官方文档:

https://redis.io/docs/latest/commands/

参考链接:

http://redisdoc.com
http://doc.redisfans.com/

INFO

显示当前节点redis运行状态信息

127.0.0.1:6379> INFO
# Server
redis_version:5.0.3
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:8c0bf22bfba82c8f
redis_mode:standalone
os:Linux 4.18.0-147.el8.x86_64 x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:atomic-builtin
gcc_version:8.2.1
process_id:725
run_id:8af0d3fba2b7c5520e0981b125cc49c3ce4d2a2f
tcp_port:6379
uptime_in_seconds:18552
......

#只显示指定部分的内容
[root@ubuntu2004 ~]#redis-cli info server
# Server
redis_version:6.2.6
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:7559afb376c61733

[root@ubuntu2004 ~]#redis-cli info Cluster
# Cluster
cluster_enabled:0

SELECT

切换数据库,相当于在MySQL的 USE DBNAME 指令

[root@centos8 ~]#redis-cli
127.0.0.1:6379> info cluster
# Cluster
cluster_enabled:0
127.0.0.1:6379[15]> SELECT 0
OK
127.0.0.1:6379> SELECT 1
OK
127.0.0.1:6379[1]> SELECT 15
OK
127.0.0.1:6379[15]> SELECT 16
(error) ERR DB index is out of range
127.0.0.1:6379[15]>

注意: 在Redis cluster 模式下不支持多个数据库,会出现下面错误

[root@centos8 ~]#redis-cli
127.0.0.1:6379> info cluster
# Cluster
cluster_enabled:1
127.0.0.1:6379> select 0
OK
127.0.0.1:6379> select 1
(error) ERR SELECT is not allowed in cluster mode

KEYS

查看当前库下的所有key,此命令慎用!

127.0.0.1:6379[15]> SELECT 0
OK
127.0.0.1:6379> KEYS *
1) "9527"
2) "9526"
3) "course"
4) "list1"
127.0.0.1:6379> SELECT 1
OK
127.0.0.1:6379[1]> KEYS *
(empty list or set)
127.0.0.1:6379[1]>

redis>MSET one 1 two 2 three 3 four 4 # 一次设置 4 个 key
OK

redis> KEYS *o*
1) "four"
2) "two"
3) "one"
redis> KEYS t??
1) "two"
redis> KEYS t[w]*
1) "two"
redis> KEYS * # 匹配数据库内所有 key
1) "four"
2) "three"
3) "two"
4) "one"

BGSAVE

手动在后台执行RDB持久化操作

#交互式执行
127.0.0.1:6379[1]> BGSAVE
Background saving started

#非交互式执行
[root@centos8 ~]#ll /var/lib/redis/
total 4
-rw-r--r-- 1 redis redis 326 Feb 18 22:45 dump.rdb

[root@centos8 ~]#redis-cli -h 127.0.0.1 -a '123456' BGSAVE
Warning: Using a password with '-a' or '-u' option on the command line interface
may not be safe.
Background saving started
[root@centos8 ~]#ll /var/lib/redis/
total 4
-rw-r--r-- 1 redis redis 92 Feb 18 22:54 dump.rdb

DBSIZE

返回当前库下的所有key 数量

127.0.0.1:6379> DBSIZE
(integer) 4
127.0.0.1:6379> SELECT 1
OK
127.0.0.1:6379[1]> DBSIZE
(integer) 0

FLUSHDB

强制清空当前库中的所有key,此命令慎用!

127.0.0.1:6379[1]> SELECT 0
OK
127.0.0.1:6379> DBSIZE
(integer) 4
127.0.0.1:6379> FLUSHDB
OK
127.0.0.1:6379> DBSIZE
(integer) 0
127.0.0.1:6379>

FLUSHALL

强制清空当前Redis服务器所有数据库中的所有key,即删除所有数据,此命令慎用!

127.0.0.1:6379> FLUSHALL
OK

#生产建议修改配置使用rename-command禁用此命令
vim /etc/redis.conf
rename-command FLUSHALL "" #flushdb和flushall 配置和AOF功能冲突,需要设置 appendonly no,不区分命令大小写

SHUTDOWN

可用版本: >= 1.0.0
时间复杂度: O(N),其中 N 为关机时需要保存的数据库键数量。
SHUTDOWN 命令执行以下操作:

关闭Redis服务,停止所有客户端连接

如果有至少一个保存点在等待,执行 SAVE 命令

如果 AOF 选项被打开,更新 AOF 文件

关闭 redis 服务器(server)

如果持久化被打开的话, SHUTDOWN 命令会保证服务器正常关闭而不丢失任何数据。

另一方面,假如只是单纯地执行 SAVE 命令,然后再执行 QUIT 命令,则没有这一保证 —— 因为在执行SAVE 之后、执行 QUIT 之前的这段时间中间,其他客户端可能正在和服务器进行通讯,这时如果执行 QUIT就会造成数据丢失。

#建议禁用此指令
vim /etc/redis.conf
rename-command shutdown ""

Redis 数据类型

字符串 string

字符串是一种最基本的Redis值类型。Redis字符串是二进制安全的,这意味着一个Redis字符串能包含任意类型的数据,例如: 一张JPEG格式的图片或者一个序列化的Ruby对象。一个字符串类型的值最多能存储512M字节的内容。Redis 中所有 key 都是字符串类型的。此数据类型最为常用

创建一个key

set 指令可以创建一个key 并赋值, 使用格式

SET key value [EX seconds] [PX milliseconds] [NX|XX]
时间复杂度: O(1)
将字符串值 value 关联到 key 。

如果 key 已经持有其他值, SET 就覆写旧值, 无视类型。
当 SET 命令对一个带有生存时间(TTL)的键进行设置之后, 该键原有的 TTL 将被清除。

从 Redis 2.6.12 版本开始, SET 命令的行为可以通过一系列参数来修改:
EX seconds : 将键的过期时间设置为 seconds 秒。 执行 SET key value EX seconds 同于执行 SETEX key seconds value 。

PX milliseconds : 将键的过期时间设置为 milliseconds 毫秒。 执行 SET key value milliseconds 的效果等同于执行 PSETEX key milliseconds value 。

NX : 只在键不存在时, 才对键进行设置操作。 执行 SET key value NX 的效果等同于执行 SETNX key value 。

XX : 只在键已经存在时, 才对键进行设置操作。

范例

#不论key是否存在.都设置
127.0.0.1:6379> set key1 value1
OK
127.0.0.1:6379> get key1
"value1"
127.0.0.1:6379> TYPE key1 #判断类型
string
127.0.0.1:6379> SET title ceo ex 3 #设置自动过期时间3s
OK
127.0.0.1:6379> set NAME aya
OK
127.0.0.1:6379> get NAME
"aya"

#Key大小写敏感
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> set name ayaka
OK
127.0.0.1:6379> get name
"ayaka"
127.0.0.1:6379> get NAME
"aya"

#key不存在,才设置,相当于add
127.0.0.1:6379> get title
"ceo"
127.0.0.1:6379> setnx title coo #set key value nx
(integer) 0
127.0.0.1:6379> get title
"ceo"

#key存在,才设置,相当于update
127.0.0.1:6379> get title
"ceo"
127.0.0.1:6379> set title coo xx
OK
127.0.0.1:6379> get title
"coo"
127.0.0.1:6379> get age
(nil)
127.0.0.1:6379> set age 20 xx
(nil)
127.0.0.1:6379> get age
(nil)

查看一个key的值

27.0.0.1:6379> get key1
"value1"

#get只能查看一个key的值
127.0.0.1:6379> get name age
(error) ERR wrong number of arguments for 'get' command

删除key

127.0.0.1:6379> DEL key1
(integer) 1

127.0.0.1:6379> DEL key1 key2
(integer) 2

批量设置多个key

127.0.0.1:6379> MSET key1 value1 key2 value2
OK

批量获取多个key

127.0.0.1:6379> MGET key1 key2
1) "value1"
2) "value2"

127.0.0.1:6379> KEYS n*
1) "n1"
2) "name"

127.0.0.1:6379> KEYS *
1) "k2"
2) "k1"
3) "key1"
4) "key2"
5) "n1"
6) "name"
7) "k3"
8) "title"

追加key的数据

127.0.0.1:6379> APPEND key1 " append new value"
(integer) 12 #添加数据后,key1总共9个字节

127.0.0.1:6379> get key1
"value1 append new value"

设置新值并返回旧值

127.0.0.1:6379> set name wang
OK
#set key newvalue并返回旧的value
127.0.0.1:6379> getset name wange
"wang"
127.0.0.1:6379> get name
"wange"

返回字符串 key 对应值的字节数

127.0.0.1:6379> SET name wang
OK
127.0.0.1:6379> STRLEN name
(integer) 5
127.0.0.1:6379> APPEND name " okada"
(integer) 10
127.0.0.1:6379> GET name
"ayaka okada"
127.0.0.1:6379> STRLEN name #返回字节数
(integer) 10

判断 key 是否存在

127.0.0.1:6379> SET name wang ex 10
OK
127.0.0.1:6379> set age 20
OK
127.0.0.1:6379> EXISTS NAME #key的大小写敏感
(integer) 0
127.0.0.1:6379> EXISTS name age #返回值为1,表示存在2个key,0表示不存在
(integer) 2
127.0.0.1:6379> EXISTS name #过几秒再看
(integer) 0

获取 key 的过期时长

ttl key #查看key的剩余生存时间,如果key过期后,会自动删除
-1 #返回值表示永不过期,默认创建的key是永不过期,重新对key赋值,也会从有剩余生命周期变成永不过期
-2 #返回值表示没有此key
num #key的剩余有效期

127.0.0.1:6379> TTL key1
(integer) -1
127.0.0.1:6379> SET name aer EX 100
OK
127.0.0.1:6379> TTL name
(integer) 96
127.0.0.1:6379> TTL name
(integer) 93
127.0.0.1:6379> SET name ayaka #重新设置,默认永不过期
OK
127.0.0.1:6379> TTL name
(integer) -1
127.0.0.1:6379> SET name aya EX 200
OK
127.0.0.1:6379> TTL name
(integer) 198
127.0.0.1:6379> GET name
"aya"

重置key的过期时长

127.0.0.1:6379> TTL name
(integer) 148
127.0.0.1:6379> EXPIRE name 1000
(integer) 1
127.0.0.1:6379> TTL name
(integer) 999
127.0.0.1:6379>

取消key的期限

即永不过期

127.0.0.1:6379> TTL name
(integer) 999
127.0.0.1:6379> PERSIST name
(integer) 1
127.0.0.1:6379> TTL name
(integer) -1

数字递增

利用INCR命令簇(INCR, DECR, INCRBY,DECRBY)来把字符串当作原子计数器使用

127.0.0.1:6379> set num 10 #设置初始值
OK
127.0.0.1:6379> INCR num
(integer) 11
127.0.0.1:6379> get num
"11

数字递减

127.0.0.1:6379> set num 10
OK
127.0.0.1:6379> DECR num
(integer) 9
127.0.0.1:6379> get num
"9"

数字增加

将key对应的数字加decrement(可以是负数)。如果key不存在,操作之前,key就会被置为0。如果key的value类型错误或者是个不能表示成数字的字符串,就返回错误。这个操作最多支持64位有符号的正型数字。

redis> SET mykey 10
OK
redis> INCRBY mykey 5
(integer) 15
127.0.0.1:6379> get mykey
"15"
127.0.0.1:6379> INCRBY mykey -10
(integer) 5
127.0.0.1:6379> get mykey
"5"

127.0.0.1:6379> INCRBY nokey 5
(integer) 5
127.0.0.1:6379> get nokey
"5"

数字减少

decrby 可以减小数值(也可以增加)

127.0.0.1:6379> SET mykey 10
OK
127.0.0.1:6379> DECRBY mykey 8
(integer) 2
127.0.0.1:6379> get mykey
"2"
127.0.0.1:6379> DECRBY mykey -20
(integer) 22
127.0.0.1:6379> get mykey
"22"

127.0.0.1:6379> DECRBY nokey 3
(integer) -3
127.0.0.1:6379> get nokey
"-3"

列表 lis

Redis列表实际就是简单的字符串数组,按照插入顺序进行排序.

支持双向读写,可以添加一个元素到列表的头部(左边)或者尾部(右边),一个列表最多可以包含2^32-1=4294967295个元素

每个列表元素用下标来标识,下标 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。

也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,元素值可以重复,常用于存入日志等场景,此数据类型比较常用

列表特点

  • 有序
  • 可重复
  • 左右都可以操作

创建列表和数据

LPUSH和RPUSH都可以插入列表

LPUSH key value [value …]
时间复杂度: O(1)
将一个或多个值 value 插入到列表 key 的表头

如果有多个 value 值,那么各个 value 值按从左到右的顺序依次插入到表头: 比如说,对空列表mylist 执行命令 LPUSH mylist a b c ,列表的值将是 c b a ,这等同于原子性地执行 LPUSH mylist a 、 LPUSH mylist b 和 LPUSH mylist c 三个命令。

如果 key 不存在,一个空列表会被创建并执行 LPUSH 操作。
当 key 存在但不是列表类型时,返回一个错误。

RPUSH key value [value …]
时间复杂度: O(1)
将一个或多个值 value 插入到列表 key 的表尾(最右边)。

如果有多个 value 值,那么各个 value 值按从左到右的顺序依次插入到表尾:比如对一个空列表 mylist执行 RPUSH mylist a b c ,得出的结果列表为 a b c ,等同于执行命令 RPUSH mylist a 、RPUSH mylist b 、 RPUSH mylist c 。

如果 key 不存在,一个空列表会被创建并执行 RPUSH 操作。
当 key 存在但不是列表类型时,返回一个错误。

范例:

#从左边添加数据,已添加的需向右移
127.0.0.1:6379> LPUSH name ayaka wang zhang #根据顺序逐个写入name,最后的zhang会在列表的最左侧。
(integer) 3
127.0.0.1:6379> TYPE name
list

#从右边添加数据
127.0.0.1:6379> RPUSH course linux python go
(integer) 3
127.0.0.1:6379> type course
list

列表追加新数据

127.0.0.1:6379> LPUSH list1 tom
(integer) 2
#从右边添加数据,已添加的向左移
127.0.0.1:6379> RPUSH list1 jack
(integer) 3

获取列表长度(元素个数)

127.0.0.1:6379> LLEN list1
(integer) 3

获取列表指定位置元素数据

127.0.0.1:6379> LPUSH list1 a b c d
(integer) 4
127.0.0.1:6379> LINDEX list1 0 #获取0编号的元素
"d"
127.0.0.1:6379> LINDEX list1 3 #获取3编号的元素
"a"
127.0.0.1:6379> LINDEX list1 -1 #获取最后一个的元素
"a"

#元素从0开始编号
127.0.0.1:6379> LPUSH list1 a b c d
(integer) 4
127.0.0.1:6379> LRANGE list1 1 2
1) "c"
2) "b"
127.0.0.1:6379> LRANGE list1 0 3 #所有元素
1) "d"
2) "c"
3) "b"
4) "a"

127.0.0.1:6379> RPUSH list2 zhang wang li zhao
(integer) 4
127.0.0.1:6379> LRANGE list2 1 2 #指定范围
1) "wang"
2) "li"
127.0.0.1:6379> LRANGE list2 2 2 #指定位置
1) "li"
127.0.0.1:6379> LRANGE list2 0 -1 #所有元素
1) "zhang"
2) "wang"
3) "li"
4) "zhao"

修改列表指定索引值

127.0.0.1:6379> RPUSH listkey a b c d e f
(integer) 6
127.0.0.1:6379> lrange listkey 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
5) "e"
6) "f"

127.0.0.1:6379> lset listkey 2 java
OK
127.0.0.1:6379> lrange listkey 0 -1
1) "a"
2) "b"
3) "java"
4) "d"
5) "e"
6) "f"
127.0.0.1:6379>

删除列表数据

127.0.0.1:6379> LPUSH list1 a b c d
(integer) 4
127.0.0.1:6379> LRANGE list1 0 3
1) "d"
2) "c"
3) "b"
4) "a"

127.0.0.1:6379> LPOP list1 #弹出左边第一个元素,即删除第一个
"d"
127.0.0.1:6379> LLEN list1
(integer) 3
127.0.0.1:6379> LRANGE list1 0 2
1) "c"
2) "b"
3) "a"

127.0.0.1:6379> RPOP list1 #弹出右边第一个元素,即删除最后一个
"a"
127.0.0.1:6379> LLEN list1
(integer) 2
127.0.0.1:6379> LRANGE list1 0 1
1) "c"
2) "b"

#LTRIM 对一个列表进行修剪(trim),让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除

127.0.0.1:6379> LLEN list1
(integer) 4
127.0.0.1:6379> LRANGE list1 0 3
1) "d"
2) "c"
3) "b"
4) "a"
127.0.0.1:6379> LTRIM list1 1 2 #只保留1,2号元素
OK
127.0.0.1:6379> LLEN list1
(integer) 2
127.0.0.1:6379> LRANGE list1 0 1
1) "c"
2) "b"


#删除list
127.0.0.1:6379> DEL list1
(integer) 1
127.0.0.1:6379> EXISTS list1
(integer) 0

集合 set

Set 是一个无序的字符串合集

同一个集合中的每个元素是唯一无重复的

支持在两个不同的集合中对数据进行逻辑处理,常用于取交集,并集,统计等场景,例如: 实现共同的朋友

集合特点

  • 无重复
  • 无序
  • 集合间操作

创建集合

127.0.0.1:6379> SADD set1 v1
(integer) 1
127.0.0.1:6379> SADD set2 v2 v4
(integer) 2
127.0.0.1:6379> TYPE set1
set
127.0.0.1:6379> TYPE set2
set

集合中追加数据

#追加时,只能追加不存在的数据,不能追加已经存在的数值
127.0.0.1:6379> SADD set1 v2 v3 v4
(integer) 3
127.0.0.1:6379> SADD set1 v2 #已存在的value,无法再次添加
(integer) 0
127.0.0.1:6379> TYPE set1
set
127.0.0.1:6379> TYPE set2
set

获取集合的所有数据

127.0.0.1:6379> SMEMBERS set1
1) "v4"
2) "v1"
3) "v3"
4) "v2"
27.0.0.1:6379> SMEMBERS set2
1) "v4"
2) "v2"

删除集合中的元素

127.0.0.1:6379> sadd goods mobile laptop car
(integer) 3
127.0.0.1:6379> srem goods car
(integer) 1
127.0.0.1:6379> SMEMBERS goods
1) "mobile"
2) "laptop"
127.0.0.1:6379>

集合间操作

取集合的交集

交集:同时属于集合A且属于集合B的元素

可以实现共同的朋友

127.0.0.1:6379> SINTER set1 set2
1) "v4"
2) "v2"

取集合的并集

并集:属于集合A或者属于集合B的元素

127.0.0.1:6379> SUNION set1 set2
1) "v2"
2) "v4"
3) "v1"
4) "v3"

取集合的差集

差集:属于集合A但不属于集合B的元素

可以实现我的朋友的朋友

127.0.0.1:6379> SDIFF set1 set2
1) "v1"
2) "v3"

有序集合 sorted set

Redis有序集合和Redis集合类似,是不包含相同字符串的合集。

它们的差别是,每个有序集合的成员都关联着一个双精度浮点型的评分

这个评分用于把有序集合中的成员按最低分到最高分排序。

有序集合的成员不能重复,但评分可以重复,一个有序集合中最多的成员数为 2^32 - 1=4294967295个,经常用于排行榜的场景

图片-JgidgoRnvpbolUngUxmfMEYyGLYYBgIo.png

有序集合特点

  • 有序
  • 无重复元素
  • 每个元素是由score和value组成
  • score 可以重复
  • value 不可以重复

创建有序集合

127.0.0.1:6379> ZADD zset1 1 v1 #分数为1
(integer) 1
127.0.0.1:6379> ZADD zset1 2 v2
(integer) 1
127.0.0.1:6379> ZADD zset1 2 v3 #分数可重复,元素值不可以重复
(integer) 1
127.0.0.1:6379> ZADD zset1 3 v4
(integer) 1
127.0.0.1:6379> TYPE zset1
zset
127.0.0.1:6379> TYPE zset2
zset

#一次生成多个数据:
127.0.0.1:6379> ZADD zset2 1 v1 2 v2 3 v3 4 v4 5 v5
(integer) 5

实现排名

127.0.0.1:6379> ZADD course 90 linux 99 go 60 python 50 cloud
(integer) 4
127.0.0.1:6379> ZRANGE course 0 -1 #正序排序后显示集合内所有的key,按score从小到大显示
1) "cloud"
2) "python"
3) "linux"
4) "go"

127.0.0.1:6379> ZREVRANGE course 0 -1 #倒序排序后显示集合内所有的key,score从大到小显示
1) "go"
2) "linux"
3) "python"
4) "cloud"

27.0.0.1:6379> ZRANGE course 0 -1 WITHSCORES #正序显示指定集合内所有key和得分情况
1) "cloud"
2) "50"
3) "python"
4) "60"
5) "linux"
6) "90"
7) "go"
8) "99"

127.0.0.1:6379> ZREVRANGE course 0 -1 WITHSCORES #倒序显示指定集合内所有key和得分情况
1) "go"
2) "99"
3) "linux"
4) "90"
5) "python"
6) "60"
7) "cloud"
8) "50"
127.0.0.1:6379>

查看集合的成员个数

127.0.0.1:6379> ZCARD course
(integer) 4
127.0.0.1:6379> ZCARD zset1
(integer) 4
127.0.0.1:6379> ZCARD zset2
(integer) 4

基于索引查找数据

127.0.0.1:6379> ZRANGE course 0 2
1) "cloud"
2) "python"
3) "linux"
127.0.0.1:6379> ZRANGE course 0 10 #超出范围不报错
1) "cloud"
2) "python"
3) "linux"
4) "go"
127.0.0.1:6379> ZRANGE zset1 1 3
1) "v2"
2) "v3"
3) "v4"
127.0.0.1:6379> ZRANGE zset1 0 2
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> ZRANGE zset1 2 2
1) "v3"

查询指定数据的排名

127.0.0.1:6379> ZADD course 90 linux 99 go 60 python 50 cloud
(integer) 4
127.0.0.1:6379> ZRANK course go
(integer) 3 #第4个
127.0.0.1:6379> ZRANK course python
(integer) 1 #第2个

获取分数

127.0.0.1:6379> zscore course cloud
"50"

删除元素

127.0.0.1:6379> ZADD course 90 linux 199 go 60 python 30 cloud
(integer) 4
127.0.0.1:6379> ZRANGE course 0 -1
1) "cloud"
2) "python"
3) "linux"
4) "go"

127.0.0.1:6379> ZREM course python go
(integer) 2
127.0.0.1:6379> ZRANGE course 0 -1
1) "cloud"
2) "linux"

哈希 hash

hash 即字典, 用于保存字符串字段field和字符串值value之间的映射,即key/value做为数据部分

hash特别适合用于存储对象场景.

一个hash最多可以包含2^32-1 个key/value键值对

哈希特点

  • 无序
  • K/V 对
  • 适用于存放相关的数据

创建 hash

格式:

HSET hash field value
时间复杂度: O(1)
将哈希表 hash 中域 field 的值设置为 value 。

如果给定的哈希表并不存在, 那么一个新的哈希表将被创建并执行 HSET 操作。
如果域 field 已经存在于哈希表中, 那么它的旧值将被新值 value 覆盖。

范例

127.0.0.1:6379> HSET 9527 name zhouxingxing age 20
(integer) 2
127.0.0.1:6379> TYPE 9527
hash

#查看所有字段的值
127.0.0.1:6379> hgetall 9527
1) "name"
2) "zhouxingxing"
3) "age"
4) "20"

#增加字段
127.0.0.1:6379> HSET 9527 gender male
(integer) 1
127.0.0.1:6379> hgetall 9527
1) "name"
2) "zhouxingxing"
3) "age"
4) "20"
5) "gender"
6) "male"

查看hash的指定field的value

127.0.0.1:6379> HGET 9527 name
"zhouxingxing"
127.0.0.1:6379> HGET 9527 age
"20"

127.0.0.1:6379> HMGET 9527 name age #获取多个值
1) "zhouxingxing"
2) "20"
127.0.0.1:6379>

删除hash 的指定的 field/value

127.0.0.1:6379> HDEL 9527 age
(integer) 1
127.0.0.1:6379> HGET 9527 age
(nil)

127.0.0.1:6379> hgetall 9527
1) "name"
2) "zhouxingxing"

127.0.0.1:6379> HGET 9527 name
"zhouxingxing"

批量设置hash key的多个field和value

127.0.0.1:6379> HMSET 9527 name zhouxingxing age 50 city hongkong
OK
127.0.0.1:6379> HGETALL 9527
1) "name"
2) "zhouxingxing"
3) "age"
4) "50"
5) "city"
6) "hongkong"

查看hash指定field的value

127.0.0.1:6379> HMSET 9527 name zhouxingxing age 50 city hongkong
OK
127.0.0.1:6379> HMGET 9527 name age
1) "zhouxingxing"
2) "50"
127.0.0.1:6379>

查看hash的所有field

127.0.0.1:6379> HMSET 9527 name zhouxingxing age 50 city hongkong #重新设置
OK
127.0.0.1:6379> HKEYS 9527
1) "name"
2) "age"
3) "city"

查看hash 所有value

127.0.0.1:6379> HMSET 9527 name zhouxingxing age 50 city hongkong
OK
127.0.0.1:6379> HVALS 9527
1) "zhouxingxing"
2) "50"
3) "hongkong"

查看指定 hash的所有field及value

127.0.0.1:6379> HGETALL 9527
1) "name"
2) "zhouxingxing"
3) "age"
4) "50"
5) "city"
6) "hongkong"
127.0.0.1:6379>

删除 hash

127.0.0.1:6379> DEL 9527
(integer) 1
127.0.0.1:6379> HMGET 9527 name city
1) (nil)
2) (nil)
127.0.0.1:6379> EXISTS 9527
(integer) 0

消息队列

消息队列: 把要传输的数据放在队列中,从而实现应用之间的数据交换

常用功能: 可以实现多个应用系统之间的解耦,异步,削峰/限流等

常用的消息队列应用: Kafka,RabbitMQ,Redis

消息队列分为两种

  • 生产者/消费者模式: Producer/Consumer
  • 发布者/订阅者模式: Publisher/Subscriber

生产者消费者模式

模式说明

生产者消费者模式下,多个消费者同时监听一个频道(redis用队列实现),但是生产者产生的一个消息只能被最先抢到消息的一个消费者消费一次,队列中的消息由可以多个生产者写入,也可以有不同的消费者取出进行消费处理.此模式应用广泛

图片-wwftvxwheQgyBvHLGvtUoDLEYlQcgicM.png

图片-OJEbZXnYNwPWNGEwCAWnEfQjPafiwkfA.png

生产者生成消息

[root@redis ~]# redis-cli
127.0.0.1:6379> AUTH 123456
OK
127.0.0.1:6379> LPUSH channel1 message1 #从管道的左侧写入
(integer) 1
127.0.0.1:6379> LPUSH channel1 message2
(integer) 2
127.0.0.1:6379> LPUSH channel1 message3
(integer) 3
127.0.0.1:6379> LPUSH channel1 message4
(integer) 4
127.0.0.1:6379> LPUSH channel1 message5
(integer) 5

获取所有消息

127.0.0.1:6379> LRANGE channel1 0 -1
1) "message5"
2) "message4"
3) "message3"
4) "message2"
5) "message1"

消费者消费消息

127.0.0.1:6379> RPOP channel1 #基于实现消息队列的先进先出原则,从管道的右侧消费
"message1"
127.0.0.1:6379> RPOP channel1
"message2"
127.0.0.1:6379> RPOP channel1
"message3"
127.0.0.1:6379> RPOP channel1
"message4"
127.0.0.1:6379> RPOP channel1
"message5"
127.0.0.1:6379> RPOP channel1
(nil)

验证队列消息消费完成

127.0.0.1:6379> LRANGE channel1 0 -1
(empty list or set) #验证队列中的消息全部消费完成

发布者订阅模式

模式说明

在发布者订阅者Publisher/Subscriber模式下,发布者Publisher将消息发布到指定的频道channel,事先监听此channel的一个或多个订阅者Subscriber都会收到相同的消息。即一个消息可以由多个订阅者获取到. 对于社交应用中的群聊、群发、群公告等场景适用于此模式

订阅者订阅频道

[root@redis ~]# redis-cli
127.0.0.1:6379> AUTH 123456
OK
127.0.0.1:6379> SUBSCRIBE channel01 #订阅者事先订阅指定的频道,之后发布的消
息才能收到
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel01"
3) (integer) 1

发布者发布消息

127.0.0.1:6379> PUBLISH channel01 message1 #发布者发布信息到指定频道
(integer) 2 #订阅者个数
127.0.0.1:6379> PUBLISH channel01 message2
(integer) 2

各个订阅者都能收到消息

[root@redis ~]#redis-cli
127.0.0.1:6379> AUTH 123456
OK
127.0.0.1:6379> SUBSCRIBE channel01
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel01"
3) (integer) 1
1) "message"
2) "channel01"
3) "message1"
1) "message"
2) "channel01"
3) "message2"

订阅多个频道

#订阅指定的多个频道
127.0.0.1:6379> SUBSCRIBE channel01 channel02

订阅所有频道

127.0.0.1:6379> PSUBSCRIBE * #支持通配符*

订阅匹配的频道

127.0.0.1:6379> PSUBSCRIBE chann* #匹配订阅多个频道

取消订阅频道

127.0.0.1:6379> unsubscribe channel01
1) "unsubscribe"
2) "channel01"
3) (integer) 0

评论