NOSQL
NOSQL
什么是nosql?
NoSQL(Not Only SQL):非关系型数据库;
包括:
- Redis:基于内存的KV结构的数据库;
- MongoDB:文档型数据库,擅长存储JSON(BSON)数据;
- HBase:列存储数据库,大数据存储;
特点:
- 存储半结构化、非结构化数据;
- 海量存储;
- 高并发场景;
Redis
Redis(Remote Dictionary Server )远程字典服务。
内存型数据库:数据存储到内存中的,读写速度快(GB级);
支持高并发,查询11万次 / 秒,写入8万次 / 秒。
支持持久化(将数据定期存储到磁盘中);
常用于缓存,存储热点数据、临时数据;
通过加缓存,可以提高并发,减少成本。
Redis常用的数据类型:
- 字符串
- hash
- 集合
- 列表
- 有序集合
- 空间结构
Redis安装
1.编译安装脚本
#1.编译安装脚本
vim redis_install.sh
#内容如下:
#!/bin/bash
# 检查系统类型
if [ -f /etc/os-release ]; then
. /etc/os-release
OS_NAME=$NAME
OS_VERSION=$VERSION_ID
else
echo "无法识别操作系统"
exit 1
fi
echo "当前操作系统: $OS_NAME $OS_VERSION"
# 根据操作系统选择安装命令
if [[ "$OS_NAME" == "Ubuntu" ]]; then
# 更新包列表并安装依赖
apt update
apt -y install build-essential tcl wget
elif [[ "$OS_NAME" == "CentOS Linux" ]] || [[ "$OS_NAME" == "Red Hat" ]]; then
yum -y install gcc gcc-c++ make tcl wget
else
echo "不支持的操作系统"
exit 1
fi
cd /usr/local/src
# 下载Redis源码包
if [ -f redis-6.2.14.tar.gz ]; then
echo "redis-6.2.14.tar.gz已存在不需要下载!"
else
# wget http://download.redis.io/releases/redis-6.2.14.tar.gz
wget http://192.168.56.200/Software/redis-6.2.14.tar.gz
fi
# 解压源码包
tar -xvf redis-6.2.14.tar.gz
# 进入解压后的目录
cd redis-6.2.14
# Redis编译安装
make
make PREFIX=/usr/local/redis install
# Redis基础配置
mkdir -p /usr/local/redis/{etc,logs,data}
egrep -v "^$|^#" redis.conf > /usr/local/redis/etc/redis.conf
sed -i "s/bind 127.0.0.1/bind 0.0.0.0/g" /usr/local/redis/etc/redis.conf
sed -i "s/protected-mode yes/protected-mode no/g" /usr/local/redis/etc/redis.conf
sed -i "s/daemonize no/daemonize yes/g" /usr/local/redis/etc/redis.conf
sed -i "s/pidfile \/var\/run\/redis_6379.pid/pidfile \/usr\/local\/redis\/redis.pid/g" /usr/local/redis/etc/redis.conf
sed -i "s/dir \.\//dir \/usr\/local\/redis\/data/g" /usr/local/redis/etc/redis.conf
sed -i "s/logfile \"\"/logfile \"\/usr\/local\/redis\/logs\/redis.log\"/g" /usr/local/redis/etc/redis.conf
# 将配置文件复制到/etc下
mkdir -p /etc/redis/
cp /usr/local/redis/etc/redis.conf /etc/redis/
# 启动redis
/usr/local/redis/bin/redis-server /etc/redis/redis.conf
# 更新PATH环境变量
echo 'export PATH=$PATH:/usr/local/redis/bin/' >> /etc/profile
. /etc/profile
# 查看redis监听端口
echo "查看redis监听端口:"
netstat -tanp | grep redis
-----------------------------------------------------
#给脚本一个执行权限
chmod +x redis_install.sh
#执行脚本,进行安装
bash redis_install.sh
#2.编写一个Redis启动、关闭和重启的Shell脚本
vim redis.sh
#内容如下
#!/bin/bash
REDIS_PATH="/usr/local/redis"
REDIS_CONF="/etc/redis/redis.conf"
PID_FILE="$REDIS_PATH/redis.pid"
start() {
if [ -f $PID_FILE ]; then
echo "Redis is already running."
exit 1
fi
echo "Starting Redis..."
$REDIS_PATH/bin/redis-server $REDIS_CONF &
echo $! > $PID_FILE
echo "Redis started."
}
stop() {
if [ ! -f $PID_FILE ]; then
echo "Redis is not running."
exit 1
fi
echo "Stopping Redis..."
kill $(cat $PID_FILE)
rm $PID_FILE
echo "Redis stopped."
}
restart() {
stop
sleep 1
start
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
;;
esac
------------------------------------------------------
#给脚本一个执行权限
chmod +x redis.sh
#使用方法
/etc/init.d/redis start # 启动Redis服务器
/etc/init.d/redis stop # 停止Redis服务器
/etc/init.d/redis restart # 重启Redis服务器
## 习惯上会把启动脚本放置在/etc/init.d/目录下,方便使用
cp redis.sh /etc/init.d/redis
#配置文件在 //etc/init.d/redis
#启动redis端
redis-cli
缓存失败问题:
- 缓存击穿:一个热点的key失效,直接访问到数据库,导致数据库访问量激增。
- 加锁,从数据库中读取数据写入缓存后,返回给用户;
- 通过异步的⽅式不断的刷新过期时间;
- 缓存穿透:大量用户访问不存在的数据,导致请求直接访问数据库,占用数据库大量的资源;
- 缓存空值/默认值;
- 布隆过滤器做一层过滤;
- 缓存雪崩:最严重的缓存问题,缓存自身崩溃或者有大量的key都过期,后端数据库压力剧增,或直接崩溃。
- 缓存增加备份、高可用;
- 缓存集群;
- 过期时间设置均匀一些;
- 多级缓存;
Redis基础配置
| 配置项名称 | 配置项值范围 | 说明 |
|---|---|---|
| daemonize | yes、no | yes表示启用守护进程,默认是no即不以守护进程方式运行。其中Windows系统下不支持启用守护进程方式运行 |
| port | 指定 Redis 监听端口,默认端口为 6379 | |
| bind | 绑定的主机地址,如果需要设置远程访问则直接将这个属性备注下或者改为bind * 即可,这个属性和下面的protected-mode控制了是否可以远程访问 | |
| protected-mode | yes 、no | 保护模式,该模式控制外部网是否可以连接redis服务,默认是yes,所以默认我们外网是无法访问的,如需外网连接rendis服务则需要将此属性改为no |
| loglevel | debug、verbose、notice、warning | 日志级别,默认为 notice |
| databases | 16 | 设置数据库的数量,默认的数据库是0。整个通过客户端工具可以看得到 |
| rdbcompression | yes、no | 指定存储至本地数据库时是否压缩数据,默认为 yes,Redis 采用 LZF 压缩,如果为了节省 CPU 时间,可以关闭该选项,但会导致数据库文件变得巨大 |
| dbfilename | dump.rdb | 指定本地数据库文件名,默认值为 dump.rdb |
| dir | 指定本地数据库存放目录 | |
| requirepass | 设置 Redis 连接密码,如果配置了连接密码,客户端在连接 Redis 时需要通过 AUTH命令提供密码,默认关闭 | |
| maxclients | 0 | 设置同一时间最大客户端连接数,默认无限制,Redis 可以同时打开的客户端连接数为 Redis 进程可以打开的最大文件描述符数,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis 会关闭新的连接并向客户端返回 max number of clients reached 错误信息 |
| maxmemory | XXX | 指定 Redis 最大内存限制,Redis 在启动时会把数据加载到内存中,达到最大内存后,Redis 会先尝试清除已到期或即将到期的 Key,当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis 新的 vm 机制,会把 Key 存放内存,Value 会存放在 swap 区。配置项值范围列里XXX为数值 |
#服务器端
#查看是否启动
[root@localhost redis]# ps -ef|grep redis
或
[root@localhost redis]# ./bin/redis-cli ping
#前台启动
[root@localhost redis]# ./bin/redis-server
#后台启动
#修改/usr/local/redis/etc/redis.conf文件
daemonize yes #前台启动,改后台启动
#指定配置文件,启动
[root@localhost redis]# ./bin/redis-server ./etc/redis.conf
#关闭
[root@localhost redis]# ./bin/redis-cli shutdown
#客户端
#启动
[root@localhost redis]# ./bin/redis-cli
127.0.0.1:6379>
#关闭
方式一:指令ctrl+c
方式二:执行指令quit
方式三:执行指令exit
#设置远程访问
修改/usr/local/redis/etc/redis.conf文件
#bind 127.0.0.1 #注释掉允许本地连接
protected-mode no #允许远程访问
Redis客户端应用
#下载地址:
(局域网)http://192.168.56.200/Software/RedisDesktopManager.exe
#安装
next -> IAgree -> 选择安装路径 -> Install -> next -> √ Finssh
Redis基础命令
1.连接命令
ping 通常用于测试与服务器的连接是否仍然生效,或者用于测量延迟值。
127.0.0.1:6379> ping
PONG
echo m 打印一个特定的信息 m ,测试时使用。
127.0.0.1:6379> echo 'hello world'
"hello world"
select i 切换到指定的数据库,数据库索引号 i 用数字值指定,以 0 作为起始索引值。默认使用 0号数据库。Redis 默认包含 16 个独立的数据库(编号 0-15)
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]>
set 存储键值对
SET 键名(Key) 键值(Value)
127.0.0.1:6379> set a 'hello world'
OK
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> get a
(nil)
get 读取键值对
GET 键名(Key)
# 读取存在的 Key(0 号库中你存储的 a)
127.0.0.1:6379> GET a
"hello world" # 返回存储的 Value
# 读取不存在的 Key(比如 Key = "x")
127.0.0.1:6379> GET x
(nil) # 无此 Key,返回空
# 切换到 1 号库后读取 a(你之前的操作)
127.0.0.1:6379[1]> GET a
(nil) # 1 号库中未存储 a,返回空
auth pword
开启了密码保护,在每次连接 Redis 服务器之后,就要使用auth命令解锁,解锁之后才能使用其他 Redis 命令。密码匹配时返回 OK ,否则返回一个错误。
设置密码
127.0.0.1:6379> config set requirepass redis123456
OK #requirepass的值就是密码
127.0.0.1:6379> quit
在次登录
[root@localhost redis]# ./src/redis-cli
127.0.0.1:6379> ping
(error) NOAUTH Authentication required.
127.0.0.1:6379> auth redis123456
OK
127.0.0.1:6379> ping
PONG
清空密码
127.0.0.1:6379> config set requirepass “”
OK #requirepass的值就是密码
127.0.0.1:6379> quit
quit
请求服务器关闭与当前客户端的连接。总是返回 OK (但是不会被打印显示,因为当时 Redis-cli 已经退出)。
127.0.0.1:6379[1]> quit
[root@localhost redis]#
2.键命令
set key value
将字符串值 value关联到 key 。
127.0.0.1:6379> set key1 1 #传入的都是字符串
OK
get key
返回 key所关联的字符串值。如果 key 不存在那么返回特殊值 nil 。
127.0.0.1:6379> get key1
"1"
del key1 [key2 … keyn]
删除给定的一个或多个 key 。没有的key忽略,返回被删除 key 的数量。
127.0.0.1:6379> del key1
(integer) 1
案例:
声明key1,key2,key3,删除key1,key2,key4
127.0.0.1:6379> set key1 1
OK
127.0.0.1:6379> set key2 1
OK
127.0.0.1:6379> set key3 1
OK
127.0.0.1:6379> del key1 key2 key4
(integer) 2
exists key
检查给定 key 是否存在。若 key 存在,返回 1 ,否则返回 0 。
127.0.0.1:6379> exists key3
(integer) 1
type key
返回 key 所储存的值的类型。none (key不存在)、string (字符串)、list (列表)、set (集合)、zset (有序集)、hash (哈希表)
127.0.0.1:6379> type key1
string
expire key seconds
为给定 key 设置生存时间,以秒为单位,当 key 过期时(生存时间为 0 ),它会被自动删除。设置成功返回 1 。其他为0。
127.0.0.1:6379> expire key3 30
(integer) 1
127.0.0.1:6379> ttl key3 #查看有效时间
(integer) 24
127.0.0.1:6379> exists key3 #验证是否存在
(integer) 0
pexpire key mseconds
这个命令和 EXPIRE 命令的作用类似,但是它以毫秒为单位设置 key 的生存时间,而不像 EXPIRE 命令那样,以秒为单位。设置成功,返回 1。key不存在或设置失败,返回0
127.0.0.1:6379> set key1 abc
OK
127.0.0.1:6379> pexpire key1 10000
(integer) 1
127.0.0.1:6379> ttl key1
(integer) 5
127.0.0.1:6379> pttl key1
(integer) 746
persist key
移除给定 key 的生存时间,将这个 key 从易失的转换成持久的。当生存时间移除成功时,返回 1 .如果 key 不存在或 key 没有设置生存时间,返回 0 。
127.0.0.1:6379> set zhangwu 1
OK
127.0.0.1:6379> persist zhangwu
(integer) 0
127.0.0.1:6379> expire zhangwu 30
(integer) 1
127.0.0.1:6379> persist zhangwu
(integer) 1
127.0.0.1:6379> ttl zhangwu
(integer) -1
ttl key
以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。当 key 不存在时,返回 -2 。当 key 存在但没有设置剩余生存时间时,返回 -1 。
127.0.0.1:6379> set key1 helloworld
OK
127.0.0.1:6379> ttl key1
(integer) -1
127.0.0.1:6379> expire key1 50
(integer) 1
127.0.0.1:6379> ttl key1
(integer) 44
127.0.0.1:6379> ttl key1
(integer) -2
pttl key
这个命令类似于 TTL 命令,但它以毫秒为单位返回 key 的剩余生存时间,而不是像 TTL 命令那样,以秒为单位。当 key 不存在时,返回 -2 。当 key 存在但没有设置剩余生存时间时,返回 -1 。
127.0.0.1:6379> pttl key1
(integer) -2
127.0.0.1:6379> set key1 abc
OK
127.0.0.1:6379> pexpire key1 30000
(integer) 1
127.0.0.1:6379> pttl key1
(integer) 27345
keys pattern
查找所有符合给定模式 pattern 的 key 。符合给定模式的 key 列表。
通配符
* 表示多个字符
? 表示一个字符
[] 表示只能是[]里面的字符
\ 表示指定特殊字符
127.0.0.1:6379> mset zhangsan 1 zhangsi 2 zhangwu 3
OK
127.0.0.1:6379> keys *
1) "zhangwu"
2) "zhangsan"
3) "zhangsi"
127.0.0.1:6379> keys ng*
(empty list or set)
127.0.0.1:6379> keys *ng*
1) "zhangwu"
2) "zhangsan"
3) "zhangsi"
127.0.0.1:6379> keys zhang??
1) "zhangwu"
2) "zhangsi"
127.0.0.1:6379> keys zha[ng]si
(empty list or set)
127.0.0.1:6379> keys zhan[ng]si
1) "zhangsi"
move key db
将当前数据库的 key 移动到给定的数据库 db 当中。移动成功返回 1 ,失败则返回 0 。
127.0.0.1:6379> keys *
1) "zhangwu"
2) "zhangsan"
3) "zhangsi"
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]> select 0
OK
127.0.0.1:6379> move zhangsan 1
(integer) 1
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> keys *
1) "zhangsan"
127.0.0.1:6379[1]> select 0
OK
127.0.0.1:6379> keys *
1) "zhangwu"
2) "zhangsi"
注意:
key不存在时,移动失败
key移动到1库时,1库中出现同名的key,移动失败
random key
从当前数据库中随机返回(不删除)一个 key 。当数据库不为空时,返回一个 key 。当数据库为空时,返回 nil 。
127.0.0.1:6379> randomkey
"zhangwu"
127.0.0.1:6379> randomkey
"key"
127.0.0.1:6379> randomkey
"key"
127.0.0.1:6379> randomkey
"zhangwu"
rename key newkey
将 key 改名为 newkey 。改名成功时提示 OK ,失败时候返回一个错误。
127.0.0.1:6379> rename key key1
OK
127.0.0.1:6379> keys *
1) "key1"
2) "zhangwu"
3) "zhangsi"
注意:
当 key 和 newkey 相同,或者 key 不存在时,返回一个错误。
当 newkey 已经存在时, RENAME 命令将覆盖旧值。
renamenx key newkey
当且仅当 newkey 不存在时,将 key 改名为 newkey 。修改成功时,返回 1 。如果 newkey 已经存在,返回 0 。
127.0.0.1:6379> renamenx zhangsi zhangwu
(integer) 0
127.0.0.1:6379> renamenx zhangsi zhangsan
(integer) 1
127.0.0.1:6379> keys *
1) "zhangsan"
2) "key1"
3) "zhangwu"
Redis数据类型
Redis常用的数据类型:
-
字符串
Redis 最基础的数据类型,以 “键值对(Key-Value)” 形式存储,Value 可以是字符串、数字(整数 / 浮点数)或二进制数据(如图片),最大容量 512MB。
**核心命令**:
SET key value:存储键值对(覆盖旧值);
GET key:获取值;INCR key:对数值型 Value 自增 1(如计数器);APPEND key value:在原有 Value 后追加字符串。
应用场景:- 缓存(如用户信息、商品详情);
- 计数器(如文章阅读量、接口调用次数);
- 分布式锁(利用
SET key value NX EX命令); - 存储二进制数据(如短链接映射、Token)
-
哈希hash
类似 “字典” 或 “对象”,Value 是一个键值对集合(field-value),适合存储结构化数据(如用户信息、商品属性)。
HSET key field value:设置哈希中某个字段的值;HGET key field:获取哈希中某个字段的值;HGETALL key:获取哈希中所有字段和值;HDEL key field:删除哈希中的某个字段。
应用场景:- 存储对象(如
user:1001作为 key,name/age/email作为 field); - 精简键名(避免
user:1001:name这类冗余键); - 部分更新(只需修改某个字段,无需操作整个对象)。
-
集合
无序、唯一的字符串集合(不允许重复元素),支持交集、并集、差集等集合运算。
核心命令:
SADD key member1 member2:向集合添加元素;SMEMBERS key:获取集合中所有元素;SISMEMBER key member:判断元素是否在集合中;SINTER key1 key2:求两个集合的交集(如共同好友);SUNION key1 key2:求两个集合的并集。
应用场景:- 去重存储(如用户标签、商品分类);
- 关系计算(如共同好友、粉丝交集);
- 抽奖系统(
SRANDMEMBER key随机取元素)
-
列表
有序、可重复的字符串列表(类似链表),支持从两端插入 / 删除元素,底层是 “双向链表” 结构,适合高频的首尾操作。
核心命令:
LPUSH key value:从列表左侧(头部)添加元素;RPUSH key value:从列表右侧(尾部)添加元素;LPOP key:移除并返回列表左侧第一个元素;RPOP key:移除并返回列表右侧第一个元素;LRANGE key start end:获取列表中指定范围的元素(如LRANGE list 0 9取前 10 个)。
应用场景:- 消息队列(
LPUSH生产消息,RPOP消费消息); - 最新列表(如 “最近浏览商品”“最新评论”,用
LPUSH加LRANGE取前 N 条); - 栈 / 队列模拟(
LPUSH+LPOP实现栈,LPUSH+RPOP实现队列)。
-
有序集合
类似 “带分数的集合”,每个元素(member)关联一个分数(score,浮点数),元素唯一,但分数可重复;集合按分数自动排序(升序 / 降序)。
核心命令:
ZADD key score1 member1 score2 member2:添加元素及分数;ZRANGE key start end [WITHSCORES]:按分数升序取指定范围的元素(带WITHSCORES显示分数);ZREVRANGE key start end:按分数降序取元素(如排行榜);ZSCORE key member:获取元素的分数;ZINCRBY key increment member:给元素的分数增加指定值(如投票加 1 分)。
应用场景:- 排行榜(如 “游戏得分榜”“销量排行榜”,用
ZREVRANGE取前 N 名); - 范围查询(如 “分数在 80-100 之间的用户”);
- 延迟队列(用时间戳作为分数,按分数顺序消费)。
-
空间结构
专门用于存储地理位置信息(经纬度),支持距离计算、范围查询等地理空间操作,底层基于有序集合(Sorted Set)实现。
核心命令:
GEOADD key longitude latitude member:添加地理位置(经度、纬度、名称);GEODIST key member1 member2 [unit]:计算两个位置的距离(单位:m/km/mi/ft);GEORADIUS key longitude latitude radius unit:查询指定经纬度范围内的位置(如 “附近 1km 的商店”);GEOPOS key member:获取位置的经纬度。
应用场景:- LBS 服务(如 “附近的人”“周边商家”);
- 地理位置排序(如按距离远近展示门店);
- 地理围栏(如 “用户进入某区域时触发通知”)。
总结
Redis 不同数据类型的核心区别在于 存储结构和适用场景:
- 简单键值用 String;
- 结构化对象用 Hash;
- 无序去重用 Set;
- 有序可重用 List;
- 带排序需求用 Sorted Set;
- 地理信息用 Geo。
Redis数据持久化
数据持久化:将内存中的数据保持到磁盘中。
作用:让redis服务重启后可以恢复之前的数据。
- Redis数据持久化的方式:
- RDB(快照):将内存中Redis缓存的所有数据,都以二进制字符串的方式保存为一个 .rdb 文件。特点:占用存储小,当恢复所有数据时,速度快。不建议频繁生成快照。每次重启自动加载快照。
- AOF(追加日志):将每次增、删、改的操作添加到 .aof 日志中,默认明文存储(可压缩),占据更大的存储空间,保存数据时,运行资源占用少。追加日志可以实时添加。
RDB的触发
- 手动触发:save 【前台保存,使 Redis 处于阻塞状态】和 bgsave【后台保存,整个过程中只有在 fork() 子进程时有短暂的阻塞】
- 自动触发:save m n 在配置文件中修改 /etc/redis/redis.conf
- 表示的是在 m 秒内,如果有 n 个键发生改变,则自动触发持久化。
vim /etc/redis/redis.conf
#RDB持久化自动触发条件
save 900 1
save 300 10
save 60 10000
#bgsave持久化失败,是否停止持久化数据到磁盘,yes 表示停止持久化,no 表示忽略错误继续写文件
stop-writes-on-bgsave-error yes
#rdb文件是否压缩
rdbcompression yes
#写入文件和读取文件时是否开启rdb文件检查,检查是否有无损坏,如果在启动是检查发现损坏,则停止启动。
rdbchecksum yes
#rdb持久化后存放的文件名
dbfilename dump.rdb
#rdb持久化后文件的存放路径
dir ./
AOF持久化
#修改配置
#修改配置文件/usr/local/redis/redis.conf
appendonly yes #表示开启AOF持久化,默认是no表示关闭
appendfilename "appendonly.aof" #AOF持久化文件名
appendfsync everysec #缓冲同步策略,默认值
no-appendfsync-on-rewrite no #是否重写,默认不重写
#开启之后,Redis每执行一条写命令就会将该命令写入硬盘中的AOF文件。AOF文件保存路径和RDB文件路径是一致的,都是通过dir参数配置 , 默 认文 件 名 是 : appendonly.aof
AOF重写
为什么要重写:
随着aof文件越来越大,需要定期对aof文件进行重写,达到压缩的目的。
重写方式
AOF重写过程可以手动触发和自动触发:
手动触发:直接调用bgrewriteaof命令。
#直接在命令行输入
127.0.0.1:6379> bgrewriteaof
Background append only file rewriting started
自动触发:根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定自动触发时机。
#修改配置文件/etc/redis/redis.conf
auto-aof-rewrite-percentage 100 #AOF文件增长率(当前AOF文件大小超过上一次重写的AOF文件大小的百分之多少才会重写)
auto-aof-rewrite-min-size 64mb #表示运行AOF重写时文件最小体积,默认为64MB。
aof文件恢复
在写入aof日志文件时,如果Redis服务器宕机,则aof日志文件文件会出格式错误,在重启Redis服务器时,Redis服务器会拒绝载入这个aof文件,可以通过以下步骤修复aof并恢复数据。
备份现在aof文件,以防万一。
出现以下提示:
(https://img2024.cnblogs.com/blog/3672404/202508/3672404-20250826143358495-1372562543.png)
使用redis-check-aof命令修复aof文件,该命令格式如下:
# 修复aof日志文件
$ redis-check-aof -fix file.aof
重启Redis服务器,加载已经修复的aof文件,恢复数据。
Redis集群
- redis 主从模式:一主一从或一主多从,自带读写分离,负载均衡。
- redis 哨兵模式:高可用,主服务器宕机,从服务器变为主服务器。
- redis 集群模式(分片):将数据拆分存储到多个Redis 主从集群中;从而实现高扩展。
Redis主从模式
原理:第一次同步时,使用RDB(快照),在同步时,主服务器产生的数据,会记录偏移量,在同步完成后,再进行偏移量的同步。
全量复制完成后,主从节点进入增量复制阶段,此时的数据同步依赖于 “命令传播” 机制。
- 当slave启动后,主动向master发送SYNC命令;
- master接受到SYNC命令后在后台保存快照(RDB持久化)和缓存保存快照这段时间的命令;
- 然后将保存的快照文件和缓存的命令发送给slave;
- slave收到快照文件和命令后加载快照文件和缓存的执行命令;
- 复制初始化后,master每次收到的写命令都会同步发送给slave,保证主从数据一致性;
缺点:只有主服务器能写入数据,从服务器只能读,主服务器一但宕机,导致无法写入数据。
Redis哨兵模式
- 1.监控所有Redis 服务器,重点监控主服务器,1秒ping一次主;
- 2.主服务器宕机主观下线,10秒后未恢复,客观下线,选举新的主服务器,根据条件(数据完整性,服务器性能);
- 3.通知其他从服务器,主从变更,让其他从服务器连接新的主服务器;
多哨兵模式:
- 哨兵监控主从的同时,也监控其他哨兵;
- 当主服务器宕机,哨兵中选出一个哨兵,这个哨兵再从其他从服务器中选出新的主服务器;
Cluster模式
cluster可以说是sentinal和主从模式的结合体,通过=可以实现主从和master重选功能,所以如果配置两个副本三个分片的话,就需要六个Redis实例。因为Redis的数据是根据一定规则分配到cluster的不同机器的,当数据量过大时,可以新增机器进行扩容。
使用集群,只要将redis配置文件中的cluster-enable配置打开即可。每个集群中至少需要3个主数据库才能正常运行,新增节点非常方便。
实验:一主两从三哨兵
- 192.168.25.26 redis(主)
- 192.168.25.27 redis(从)
- 192.168.25.28 redis(从)
#1.在三台服务器上都安装好redis
#包含一件安装脚本和启动脚本
#2.修改从服务器配置文件
vim /etc/redis/redis.conf
# 主服务器ip 端口
replicaof 192.168.25.26 6379
#3.分别启动三台redis服务器
redis-cli
#4.查看主从信息
info replication
手动临时修改主从
#从服务器上输入 让当前 Redis 节点从 “从节点(slave/replica)” 变为 “主节点(master)
slaveof no one
#从服务器切换主节点
# 新主服务器ip 端口
slaveof 192.168.25.27 6379
配置哨兵
#在主服务器上先配置哨兵配置文件
#1.把模板复制出来
#复制或替换 sentinel.conf
grep -Ev "^$|^#" /usr/local/src/redis-6.2.14/sentinel.conf > /etc/redis/sentinel.conf
#修改配置文件 /etc/redis/sentinel.conf
-------------------------------------------------------
#指定哨兵进程的 PID 文件路径,用于记录哨兵进程的 ID,方便管理
pidfile "/var/run/redis-sentinel.pid"
#设置哨兵的日志文件路径
logfile "/usr/local/redis/logs/sentinel.log"
#指定哨兵的工作目录,用于存储临时文件
dir "/usr/local/redis/data"
# 两个哨兵主观下线,才能客观下线
#单哨兵后面数字是1,三哨兵后面数字是2,哨兵数量是单数
sentinel monitor mymaster 192.168.8.11 6379 2
#“主观下线” 的判断时间 10秒
sentinel down-after-milliseconds mymaster 10000
#故障转移的超时时间 15秒
sentinel failover-timeout mymaster 15000
--------------------------------------------------------
#2.把修改后的哨兵配置文件发给从服务器
scp /etc/redis/sentinel.conf root@192.168.25.27://etc/redis/sentinel.conf
scp /etc/redis/sentinel.conf root@192.168.25.28://etc/redis/sentinel.conf
#3.重新启动服务器上的redis
/etc/init.d/redis restart
#再启动哨兵日志
redis-sentinel /etc/redis/sentinel.conf
#主服务器上查看哨兵日志 是否有误
cd /usr/local/redis/logs
#实时监控 日志
tail -f sentinel.log
#4.进行测哨兵
#手动关闭主服务器,查看是否会切换
搭建集群
单机搭建集群
#集群搭建:至少要三个master 三对主从
#1.创建一个文件夹redis-cluster,然后在其下面分别创建6个文件夹
[root@zuolaoshi /]# cd /usr/local/redis
[root@zuolaoshi redis]# mkdir redis-cluster
[root@zuolaoshi redis]# cd redis-cluster/
[root@zuolaoshi redis-cluster]# mkdir 7001
[root@zuolaoshi redis-cluster]# mkdir 7002
[root@zuolaoshi redis-cluster]# mkdir 7003
[root@zuolaoshi redis-cluster]# mkdir 7004
[root@zuolaoshi redis-cluster]# mkdir 7005
[root@zuolaoshi redis-cluster]# mkdir 7006
#把之前的redis.conf配置文件分别copy到700*下
[root@zuolaoshi redis]# cp ./etc/redis.conf ./redis-cluster/7001/redis.conf
[root@zuolaoshi redis]# cp ./etc/redis.conf ./redis-cluster/7002/redis.conf
[root@zuolaoshi redis]# cp ./etc/redis.conf ./redis-cluster/7003/redis.conf
[root@zuolaoshi redis]# cp ./etc/redis.conf ./redis-cluster/7004/redis.conf
[root@zuolaoshi redis]# cp ./etc/redis.conf ./redis-cluster/7005/redis.conf
[root@zuolaoshi redis]# cp ./etc/redis.conf ./redis-cluster/7006/redis.conf
------------------------------------------------------
#2. Redis 5.0 及以上版本:无需依赖 Ruby,直接用 redis-cli --cluster 管理集群 可直接跳过这一步
#查看redis版本
redis-server --version
#5.0 以下旧版本:必须安装 Ruby 及 redis gem
# CentOS7
yum install ruby
yum install rubygems
gem install redis #(安装redis和ruby的接口)
---------------------------------------------------------
#3.修改每个节点的配置文件
[root@zuolaoshi redis]# vim ./redis-cluster/7001/redis.conf
#需要修改的配置
daemonize yes
port 700* #(分别对每个机器的端口号进行设置)
bind 192.168.25.26 #(必须要绑定当前机器的ip,不然会无限悲剧下去哇..深坑勿入!!!)
dir /usr/local/redis-cluster/700*/ #(指定数据文件存放位置,必须要指定不同的目录位置,不然会丢失数据,深坑勿入!!!)
pidfile /usr/local/redis/redis_700*.pid
appendonly yes
cluster-enabled yes #(启动集群模式,开始玩耍)
cluster-config-file nodes700*.conf#(这里700x最好和port对应上)
cluster-node-timeout 5000 #redis节点宕机被发现的时间
--------------------------------------------------------
#配置文件写好后需要手动创建没有的目录dir /usr/local/redis-cluster/700*/
cd /usr/local
mkdir redis-cluster
cd redis-cluster
mkdir 7001-6
#4.启动redis服务
[root@zuolaoshi redis]# ./bin/redis-server ./redis-cluster/7001/redis.conf
[root@zuolaoshi redis]# ./bin/redis-server ./redis-cluster/7002/redis.conf
[root@zuolaoshi redis]# ./bin/redis-server ./redis-cluster/7003/redis.conf
[root@zuolaoshi redis]# ./bin/redis-server ./redis-cluster/7004/redis.conf
[root@zuolaoshi redis]# ./bin/redis-server ./redis-cluster/7005/redis.conf
[root@zuolaoshi redis]# ./bin/redis-server ./redis-cluster/7006/redis.conf
---------------------------------------------------------
#5.创建集群
#执行redis-cli --cluster create命令
[root@zuolaoshi redis]# ./bin/redis-cli --cluster create 192.168.25.26:7001 192.168.25.26:7002 192.168.25.26:7003 192.168.25.26:7004 192.168.25.26:7005 192.168.25.26:7006 --cluster-replicas 1
#说明
#create
#表示创建一个redis集群。
#--cluster-replicas 1
#表示为集群中的每一个主节点指定一个从节点,即一比一的复制。

#6.集群搭建完成后,查看redis服务状态
[root@zuolaoshi redis]# ps -ef|grep redis
---------------------------------------------------------
#7.进入一个节点
[root@zuolaoshi redis]# ./bin/redis-cli -c -h 192.168.25.26 -p 7001
192.168.25.26:7001> info cluster
# Cluster
cluster_enabled:1 #节点是否为cluster模式 。1是0否
---------------------------------------------------------
#8.进行测试集群功能是否成功
[root@zuolaoshi redis]# ./bin/redis-cli -c -h 192.168.25.26 -p 7005
192.168.25.26:7005> set b fdfsfsd
-> Redirected to slot [3300] located at 192.168.25.26:7001
OK
192.168.25.26:7001> get b
"fdfsfsd"
192.168.25.26:7001> set c fdsfdfdsfds
-> Redirected to slot [7365] located at 192.168.25.26:7002
OK
192.168.25.26:7002> get c
"fdsfdfdsfds"
192.168.25.26:7002> set x fdsfdsfsdf
-> Redirected to slot [16287] located at 192.168.25.26:7003
OK
192.168.25.26:7003> keys *
1) "x"
2) "a"
192.168.25.26:7003> get b
-> Redirected to slot [3300] located at 192.168.25.26:7001
"fdfsfsd"
192.168.25.26:7001> keys *
1) "b"
192.168.25.26:7001> set d fdsfdsfsd
-> Redirected to slot [11298] located at 192.168.25.26:7003
OK
192.168.25.26:7003> get d
"fdsfdsfsd"
192.168.25.26:7003> set x zhangsan
OK
192.168.25.26:7003> get x
"zhangsan"
添加新的主节点
#将7007设置为7006的主节点
#保证7007服务是启动的
[root@zuolaoshi redis]# ./bin/redis-cli --cluster add-node 192.168.1.121:7007 192.168.1.121:7006
#查看节点信息,未分配槽位不能存储数据
[root@zuolaoshi redis]# ./bin/redis-cli -c -h 192.168.1.121 -p 7005
192.168.1.121:7005> cluster nodes
#如果有未分配槽位的主节点,则重新分配槽位
[root@zuolaoshi redis]# ./bin/redis-cli --cluster reshard 192.168.1.121:7007
#查看节点信息
[root@zuolaoshi redis]# ./bin/redis-cli -c -h 192.168.1.121 -p 7005
192.168.1.121:7005> cluster nodes
给主节点加从节点
#准备一个新的Redis,7008
[root@zuolaoshi redis]#cd redis-cluster/
[root@zuolaoshi redis-cluster]# ls
7001 7002 7003 7004 7005 7006 7007
[root@zuolaoshi redis-cluster]# mkdir 7008
[root@zuolaoshi redis-cluster]# cp ./7007/redis.conf ./7008/redis.conf
[root@zuolaoshi redis-cluster]# vim ./7008/redis.conf
[root@zuolaoshi redis-cluster]# cd ..
[root@zuolaoshi redis]# ./bin/redis-server ./redis-cluster/7008/redis.conf
[root@zuolaoshi local]#cd redis-cluster
[root@zuolaoshi redis-cluster]# mkdir 7008
#为7007添加从节点7008
[root@zuolaoshi redis]# ./bin/redis-cli --cluster add-node 192.168.1.121:7008 192.168.1.121:7007 --cluster-slave
#查看节点信息
[root@zuolaoshi redis]# ./bin/redis-cli -c -h 192.168.1.121 -p 7005
192.168.1.121:7005> cluster nodes
删除节点
#删除从节点
[root@zuolaoshi redis]# ./bin/redis-cli --cluster del-node 192.168.1.121:7008 8e52c94dafa72df26b1eddf94363a4780bed9339
>>> Removing node 8e52c94dafa72df26b1eddf94363a4780bed9339 from cluster 192.168.1.121:7008
>>> Sending CLUSTER FORGET messages to the cluster...
>>> SHUTDOWN the node.
#移动数据将7007移动到7001节点
[root@zuolaoshi redis]# ./bin/redis-cli --cluster reshard 192.168.1.121:7007
#查看节点信息
[root@zuolaoshi redis]# ./bin/redis-cli -c -h 192.168.1.121 -p 7005
192.168.1.121:7005> cluster nodes
#删除主节点
[root@zuolaoshi redis]# ./bin/redis-cli --cluster del-node 192.168.1.121:7007 d7a3e48cd142dce6566023fce21e31669e9fa3d5
>>> Removing node d7a3e48cd142dce6566023fce21e31669e9fa3d5 from cluster 192.168.1.121:7007
>>> Sending CLUSTER FORGET messages to the cluster...
>>> SHUTDOWN the node.
#查看节点信息
[root@zuolaoshi redis]# ./bin/redis-cli -c -h 192.168.1.121 -p 7005
192.168.1.121:7005> cluster nodes
浙公网安备 33010602011771号