Redis
简介
nosql的一种,k-v类型,支持string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类
型),常被用于缓存,所有数据都存储与内存,支持事务,使用单线程+epoll i/o多路复用+纯内存来保证性能
安装
配置文件
登录
指定配置文件登录,如果不指定则使用默认
redis-server /etc/redis.conf
客户端登录
redis-cli
关闭服务
SHUTDOWN
操作
全局操作
读取所有键,生产慎用
keys *
查看当前库中键的数量
dbsize
查看某个键是否存在
exists keyname
删除/批量删除键
del keyname
设置键过期时间
expire keyname seconds
查看键距离过期的时间
ttl keyname
查看键的数据结构类型
type keyname
字符串
设置键值
SET key value [EX seconds] [PX milliseconds] [NX|XX]
EX seconds:超时时间
PX milliseconds:设置毫秒级过期时间
nx:键必须不存在才能被创建,用于新建
xx:键必须存在才能被创建,用于更新
获取键值
get keyname
127.0.0.1:6379> set hello world EX 30 NX
OK
#创建键值对
127.0.0.1:6379> dbsize
(integer) 1
#查看库中键的数量
127.0.0.1:6379> EXISTS hello
(integer) 1
#查看键是否存在
127.0.0.1:6379> set hello world EX 30 NX
OK
127.0.0.1:6379> get hello
"world"
#查看键值
127.0.0.1:6379> ttl hello
(integer) 15
#查看键的到期时间
127.0.0.1:6379> type hello
string
#查看键的类型
127.0.0.1:6379> ttl hello
(integer) -2
127.0.0.1:6379> EXISTS hello
(integer) 0
#到期后查看键是否存在
批量设置/获取键值对
mset
mget
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379> mget k1 k2 k3
1) "v1"
2) "v2"
3) "v3"
自增
incr keyname
incr命令用于对值做自增操作,返回结果分为三种情况:
·值不是整数,返回错误。
·值是整数,返回自增后的结果。
·键不存在,按照值为0自增,返回结果为1。
例如对一个不存在的键执行incr操作后,返回结果是1:
127.0.0.1:6379> EXISTS key1
(integer) 0
127.0.0.1:6379> incr key1
(integer) 1
127.0.0.1:6379> incr key1
(integer) 2
127.0.0.1:6379> EXISTS key1
(integer) 1
127.0.0.1:6379> get key1
"2"
向字符串尾部增加值
append keyname value
查看字符串长度
strlen keyname
设置值,并成功后返回原值
getset keyname value
从指定位置开始修改字符串的值
127.0.0.1:6379> SET key helloworld
OK
127.0.0.1:6379> SETRANGE key 5 redis
(integer) 10
127.0.0.1:6379> get key
"helloredis"
获取字符串的部分值
getrange key start end
列表
从右插入元素
rpush keylist v1 v2 v3
从左侧插入元素
lpush keylist v1 v2
在某个值(pivot)的前后插入元素
linsert key BEFORE|AFTER pivot value
列出范围内的值,0 -1表示全部
lrange keylist start end
查看列表长度
llen listkey
删:
从列表的右/左弹出元素
lpop/rpop
删除指定元素
lrem key count value
lrem命令会从列表中找到等于value的元素进行删除
count>0,从左到右,删除最多count个元素。
count<0,从右到左,删除最多count绝对值个元素。
·count=0,删除所有。
裁剪保留区域内的列表值
ltrim key start stop
改
修改对应坐标的值
lset key index value
127.0.0.1:6379> lpush listkey v1 v2 v3 v4 v5
(integer) 5
127.0.0.1:6379> lpop listkey
"v5"
127.0.0.1:6379> lrem listkey 2 v3
(integer) 1
127.0.0.1:6379> lrange listkey 0 -1
1) "v4"
2) "v2"
3) "v1"
127.0.0.1:6379> ltrim listkey 0 1
OK
127.0.0.1:6379> lrange listkey 0 -1
1) "v4"
2) "v2"
127.0.0.1:6379> lset listkey 0 v5
OK
127.0.0.1:6379> lrange listkey 0 -1
1) "v5"
2) "v2"
哈希
类似python中的字典
设置/批量值
hset/hmset key field value
获取/批量获取
hget/hmget key field
测量长度
hlen key
判断field是否存在
hexists key field
获取所有的fields
hkeys key
获取所有fields-values
hgetall key
127.0.0.1:6379> hset sethash username foo
(integer) 1
127.0.0.1:6379> hset sethash age 18
(integer) 1
127.0.0.1:6379> hget sethash username
"foo"
127.0.0.1:6379> hlen sethash
(integer) 2
127.0.0.1:6379> hmget sethash username age
1) "foo"
2) "18"
127.0.0.1:6379> HEXISTS sethash username
(integer) 1
127.0.0.1:6379> hkeys sethash
1) "username"
2) "age"
127.0.0.1:6379> hgetall sethash
1) "username"
2) "foo"
3) "age"
4) "18"
集合
无序不可重复
添加元素
sadd key member [member ...]
删除元素
srem key member [member ...]
计算元素个数,直接调用内部变量,时间复杂度为O(1)
scard key
查看元素是否在集合内
sismember key member
随机返回n个集合内的元素
srandmember key [count]
随机弹出元素
spop key [count]
获取所有元素
smembers key
交集
sinter key [key ...]
并集
sunion key [key ...]
差集
sdiff key [key ...]
保存交并差集结果到新的集合中
sinterstore destination key [key ...]
suionstore destination key [key ...]
sdiffstore destination key [key ...]
127.0.0.1:6379> sadd myset v1 v2 v3
(integer) 3
127.0.0.1:6379> srem myset v2
(integer) 1
127.0.0.1:6379> scard myset
(integer) 2
127.0.0.1:6379> sismember myset v6
(integer) 0
127.0.0.1:6379> sismember myset v1
(integer) 1
127.0.0.1:6379> srandmember myset 2
1) "v3"
2) "v1"
127.0.0.1:6379> spop myset 1
1) "v3"
127.0.0.1:6379> sadd myset v2 b4 sdcd wer t3
(integer) 5
127.0.0.1:6379> smembers myset
1) "sdcd"
2) "v1"
3) "t3"
4) "v2"
5) "b4"
6) "wer"
127.0.0.1:6379> sadd testset v3 t3 sad iti hap
(integer) 5
127.0.0.1:6379> sinter myset testset
1) "t3"
127.0.0.1:6379> sunion myset testset
1) "v1"
2) "iti"
3) "v2"
4) "b4"
5) "wer"
6) "sdcd"
7) "sad"
8) "t3"
9) "hap"
10) "v3"
127.0.0.1:6379> sdiff myset testset
1) "b4"
2) "v2"
3) "sdcd"
4) "v1"
5) "wer"
127.0.0.1:6379> sdiffstore my_test_diff myset testset
(integer) 5
127.0.0.1:6379> smember my_test_diff
(error) ERR unknown command `smember`, with args beginning with: `my_test_diff`,
127.0.0.1:6379> smembers my_test_diff
1) "b4"
2) "v2"
3) "sdcd"
4) "v1"
5) "wer"
有序集合
有序不重复,它给每个元素设置一个分数(score)作为排序的依据
添加元素
zadd key [NX|XX] [CH] [INCR] score member [score member ...]
nx:member必须不存在,才可以设置成功,用于添加。
xx:member必须存在,才可以设置成功,用于更新。
ch:返回此次操作后,有序集合元素和分数发生变化的个数
incr:对score做增加,相当于后面介绍的zincrby。
计算成员个数
zcard key
计算某个成员的分数
zscore key member
计算成员的排名(从高到低/从低到高)
zrank key member
zrevrank key member
删除成员
zrem key member [member ...]
给成员加分
zincrby key n member
返回指定排名范围的成员,加上withscores同时附上分数
zrange key start end [withscores]
zrevrange key start end [withscores]
返回指定分数范围的成员
zrangebyscore key min max [withscores] [limit offset count]
zrevrangebyscore key max min [withscores] [limit offset count]
其中zrangebyscore按照分数从低到高返回,zrevrangebyscore反之。例如
下面操作从低到高返回200到221分的成员,withscores选项会同时返回每个
成员的分数。[limit offset count]选项可以限制输出的起始位置和个数
返回指定分数范围成员个数
zcount key min max
删除指定排名范围内的成员
zremrangebyrank key start end
删除指定分数范围的成员
zremrangebyscore key min max
交/并集
zinterstore/zunionstore destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]
destination:交集计算结果保存到这个键。
numkeys:需要做交集计算键的个数。
key[key...]:需要做交集计算的键。
weights weight[weight...]:每个键的权重,在做交集计算时,每个键中
的每个member会将自己分数乘以这个权重,每个键的权重默认是1。
aggregate sum|min|max:计算成员交集后,分值可以按照sum(和)、
min(最小值)、max(最大值)做汇总,默认值是sum。
慢查询
使用命令修改配置
config set slowlog-log-slower-than 20000 # 单位为微秒
config set slowlog-max-len 1000
config rewrite
查询慢sql,返回的结果包含慢查询日志的标识
id、发生时间戳、命令耗时、执行命令和参数
slowlog get
慢sql列表长度
slowlog len
慢sql日志重置
slowlog reset
redis shell
-r n :重复n次
-i n :间隔多少秒,需要和-r一起使用
redis-cli -r 5 -i 1 ping
-x :把stdin的数值作为最后一个参数
下面的操作会将字符串world作为set hello的值
echo "world" | redis-cli -x set hello
内存检测:检测当前服务器是否可以提供对应的内存给redis(M)
耗时很长
redis-server --test-memory 1024
持久化/高可用
持久化
RDB
默认的持久化方案,没AOF的情况下执行shutdown时会执行
RDB持久是把当前数据生成快照保存到硬盘的过程
触发RDB持久化过程为手动触发和自动触发
优点
RDB是一个非常紧凑(compact)的文件,它保存了redis 在某个时间点上的数据集。这种文件非常适合用于进 行备份和灾难恢复。
RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
缺点
RDB方式数据没办法做到实时持久化/秒级持久化。因为bgsave每次运行都要执行fork操作创建子进程,属于 重量级操作(内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑),频繁执行成本过高(影响性能)
RDB文件使用特定二进制格式保存,Redis版本演进过程中有多个格式的RDB版本,存在老版本Redis服务无 法兼容新版RDB格式的问题(版本不兼容)
在一定间隔时间做一次备份,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改(数据有 丢失)
触发方式为修改主配置中的save字段
分别表示每900秒数据发生一次改变、每300秒数据发生10次改变、每60秒数据发生10000
次改变会自动触发rdb持久化机制
save 900 1
save 300 10
save 60 10000
当遇到坏盘或磁盘写满等情况时,可以通过config set dir{newDir}在线 修改文件路径到可用的磁盘路径,之后执行bgsave进行磁盘切换,同样适用 于AOF持久化文件。
Redis默认采用LZF算法对生成的RDB文件做压缩处理,压缩后的 文件远远小于内存大小,默认开启,可以通过参数config set rdbcompression{yes|no}动态修改。
如果想要恢复相关数据,只需要将相关的RDB文件拷贝到相关的目录下面即可,redis启动时会自动将rdb文件里的内容加载到内存中
AOF
AOF以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中的命令以恢复数据
AOF 持久化的方法提供了多种的同步频率,即使使用默认的同步频率每秒同步一次,Redis 最多也就丢失 1 秒的数据而已。
AOF 文件使用 Redis 命令追加的形式来构造,因此,即使 Redis 只能向 AOF 文件写入命令的片断,使用 redis-check-aof 工具也很容易修正 AOF 文件。
AOF 文件的格式可读性较强,这也为使用者提供了更灵活的处理方式。例如,如果我们不小心错用了 FLUSHALL 命令,在重写还没进行时,我们可以手工将最后的 FLUSHALL 命令去掉,然后再使用 AOF 来恢 复数据。
缺点
对于具有相同数据的的 Redis,AOF 文件通常会比 RDB 文件体积更大。
虽然 AOF 提供了多种同步的频率,默认情况下,每秒同步一次的频率也具有较高的性能。但在 Redis 的负载 较高时,RDB 比 AOF 具好更好的性能保证。
RDB 使用快照的形式来持久化整个 Redis 数据,而 AOF 只是将每次执行的命令追加到 AOF文件中,因此从 理论上说,RDB 比 AOF 方式更健壮。官方文档也指出,AOF 的确也存在一些 BUG,这些 BUG 在 RDB 没有 存在
配置方法为修改配置文件中的配置项
appendonly yes
数据闪回flashback
一种基于AOF的数据恢复机制,可以以秒级速度随时恢复到数据保存期限里面的任一时间的数据
阿里云 redis 闪回
https://www.alibabacloud.com/help/zh/apsaradb-for-redis/latest/use-data-flashback-to-restore-data-by-point-in-time
高可用
主从
把数据复制到别的副本,master宕机无法自动选举
全量同步
Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份。
步骤如下:
从服务器连接主服务器,发送SYNC命令;
主服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所有写命令;
主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令;
从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;
从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;
增量同步
Redis增量复制是指Slave初始化后开始正常工作时主服务器发生的写操作同步到从服务器的过程。
增量复制的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令。
同步策略
主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。当然,如果有需要,slave在任何时候都可 以发起全量同步。redis 策略是,无论如何,首先会尝试进行增量同步,如不成功,要求从机进行全量同步。
配置
主
#/bin/bash
mkdir /usr/local/redis/{data,conf,log} -pv
cat << EOF > /usr/local/redis/conf/redis6380.conf
bind 127.0.0.1
port 6380
daemonize yes
pidfile /usr/local/redis/redis_6380.pid
loglevel notice
logfile /usr/local/redis/log/redis_6380.log
dir /usr/local/redis/data/
EOF
从
cat << EOF > /usr/local/redis/conf/redis6381.conf
bind 127.0.0.1
port 6381
daemonize yes
pidfile /usr/local/redis/redis_6381.pid
loglevel notice
logfile /usr/local/redis/redis_6381.log
dir /usr/local/redis/data/
slaveof 127.0.0.1 6380
EOF
cat << EOF > /usr/local/redis/conf/redis6382.conf
bind 127.0.0.1
port 6382
daemonize yes
pidfile /usr/local/redis/redis_6382.pid
loglevel notice
logfile /usr/local/redis/redis_6382.log
dir /usr/local/redis/data/
slaveof 127.0.0.1 6380
EOF
redis-server指定配置文件启动后,使用info replication验证
哨兵
带自动选举的主从
哨兵会去定期ping主,如果主不回复,则标记为SDOWN,当标记主不可用的哨兵数量达到一定程度的时候,就会从从服务器中选取一个新的主服务器,并同时修改其余从服务器的配置文件,将新的主节点作为数据同步的来源,然后重新启动服务,完成切换。
集群
分布式存储,每个node上都存储不一样的数据
对象保存到Redis之前先经过CRC16哈希到一个指定的Node上。
每个Node被平均分配了一个Slot段,对应着0-16384,Slot不能重复也不能缺失,否则会导致对象重复存储或无法存储。
Node之间也互相监听,一旦有Node退出或者加入,会按照Slot为单位做数据的迁移。例如Node1如果掉线了,0- 5640这些Slot将会平均分摊到Node2和Node3上,由于Node2和Node3本身维护的Slot还会在自己身上不会被重新 分配,所以迁移过程中不会影响到5641-16384Slot段的使用。
备份方案
预定方案为每周日晚上10-12点全备一次,每天晚上10-12点增量备份一次,每隔两小时备份一次日志
数据闪回功能只有部分云厂商有直接提供,直接根据厂商文档开启就行
方案实施(由gpt自动生成,未验证)
要按照您的备份方案配置Redis,可以参考以下步骤:
- 确保您已经安装并正确配置了Redis服务器。
- 创建一个用于存储备份文件和日志的目录。例如,您可以在服务器上创建一个名为"/redis-backup"的目录。
编辑Redis服务器的配置文件(redis.conf)并进行以下设置:
save "" # 禁用Redis的自动快照功能。 appendonly yes # 启用AOF持久化机制,支持增量备份。 dir /redis-backup # 设置备份文件和日志文件存储的目录路径。
请注意,通过将save
参数设置为空字符串,们禁用了Redis的自动快照功能。(save会导致堵塞,不推荐使用)- 保存并关闭Redis配置文件。
创建全备份脚本(full_backup.sh):
#!/bin/bash redis-cli bgsave # 创建Redis快照(全备份) backup_dir="/redis-backup/full_backup" mkdir -p $backup_dir # 创建备份目录(如果不存在) cp /var/lib/redis/dump.rdb $backup_dir/$(date +\%Y\%m\%d-\%H\%M).rdb # 将快照文件移动到备份目录并添加时间戳 # 删除一个月前的备份文件 find $backup_dir -type f -name "*.rdb" -mtime +30 -exec rm {} \;
这个脚本使用Redis命令bgsave
创建一个新的Redis快照(全备份),然后将快照文件复制到备份目录,并为备份文件添加了时间戳。
请注意,上面的示例假设Redis的快照文件默认存储在"/var/lib/redis/dump.rdb"。如果您的Redis配置使用了不同的路径,请相应地修改脚本。创建增量备份脚本(incremental_backup.sh):
#!/bin/bash redis-cli bgsave # 创建Redis快照(增量备份) cp /var/lib/redis/dump.rdb /redis-backup/redis-incremental-backup-$(date +\%Y\%m\%d-\%H\%M).rdb # 将快照文件移动到备份目录并添加时间戳
这个脚本与全备份脚本类似,不同之处在于它创建了Redis的增量备份。
请注意,上面的示例假设Redis的快照文件默认存储在"/var/lib/redis/dump.rdb"。如果您的Redis配置使用了不同的路径,请相应地修改脚本。备份日志文件脚本(log_backup.sh):
#!/bin/bash backup_dir="/redis-backup/log_backup" mkdir -p $backup_dir # 创建备份目录(如果不存在) cp /var/lib/redis/appendonly.aof $backup_dir/$(date +\%Y\%m\%d-\%H\%M).aof # 将当前的日志文件移动到备份目录并添加时间戳 # 删除一个月前的备份文件 find $backup_dir -type f -name "*.aof" -mtime +30 -exec rm {} \;
请注意,上面的示例假设Redis的日志文件默认存储在"/var/lib/redis/appendonly.aof"。如果您的Redis配置使用了不同的路径,请相应地修改脚本。
使用cron工具来安排定期运行备份脚本。运行
crontab -e
命令并添加以下行:- 22 0 /bin/bash /path/to/full_backup.sh
22 * /bin/bash /path/to/incremental_backup.sh
/2 * /bin/bash /path/to/log_backup.sh<br />上面的cron表达式表示每周日的22:00运行全备份脚本,每天的22:00运行增量备份脚本,以及每隔两小时运行日志备份脚本。
配置完成后,您的Redis服务器将按计划执行全备份、增量备份和日志备份,并将备份文件存储在指定的目录中。请根据您的实际路径和需求进行调整。