目录
aof重写,过程(重写不是持久化,aof的持久化是自动,重写是对持久化文件进行优化减少文件体积)
redis集群搭建
redis集群搭建参考:https://blog.csdn.net/yang_zzu/article/details/107583581
redis 升级到6.0 版本后,新增的功能:
acl
多线程io
cluster proxy
resp3协议
redis配置文件
redis 6.0.6 ,容器里面是找不到 redis.conf 配置文件
redis 6.0.1,redis.conf 文件 在 /redis/redis.conf
建议使用6.0.1,功能有了,6.0.6是一个优化,没有大的功能改变
虽说没有找到 6.0.6 版本的配置文件,但是在进入到redis 服务器里面,可以查到配置信息,
有厉害的大佬,可以指导一下疑惑。
redis版本选择
版本环境: redis
docker pull redis
下载的redis 镜像的 版本为 6.0.6
版本环境: grokzen/redis-cluster
docker pull grokzen/redis-cluster
下载的镜像版本为 6.0.1
docker 镜像打包
https://blog.csdn.net/qq_26235847/article/details/84635250
redisCluster集群镜像安装:
查找redis 集群镜像文件
下载镜像
docker pull grokzen/redis-cluster
创建文件夹:
cd
mkdir /redis
mkdir /redis/rediscluster
启动容器:
docker run -i -t -d --name redis-171 -p 6379:6379 grokzen/redis-cluster
这次启动容器,是为了拷贝出来 redis.conf 的配置文件到宿主机上面,然后做文件映射,后面在对容器的配置文件进行修改的时候直接修改宿主机上面的配置文件就可以了。
配置文件的映射可以不用做,但是data 文件的映射是必须要做的。
1.配置文件的映射
将 redis-171容器中的 /redis/redis.conf 文件 拷贝到 宿主机 /redis/rediscluster 中
docker cp redis-171:/redis/redis.conf /redis/rediscluster/
该文件是一个1784 行的文件(我就不贴出来)想要做配置文件映射的还是自己动手麻烦一点吧。
关闭redis 容器:
docker stop redis-171
移除 reids 容器:
docker rm redis-171
再次启动容器:
docker run -i -t -d --name redis-171 -v /redis/rediscluster/redis.conf:/redis/redis.conf -v /redis/rediscluster/data/:/data -p 6379:6378 grokzen/redis-cluster redis-server /redis/redis.conf
docker run
-i 运行容器
-t 前台启动,分配一个伪终端
-d 后台启动
--name redis-171 自定义容器的名称
-v /redis/rediscluster/redis.conf:/redis/redis.conf 文件映射,宿主机:容器,宿主机的文件会覆盖容器里面的文件
-v /redis/rediscluster/data/:/data 文件夹映射,宿主机:容器,宿主机文件夹文件覆盖容器里面的文件
-p 6379:6378 端口映射,宿主机端口:容器端口
grokzen/redis-cluster 镜像文件
redis-server /redis/redis.conf 指定使用 redis.conf 配置文件启动该容器(一定要加上,否则redis无法正常使用,在本地使用redis-cli 连接的时候会出现 error: connection reset by peer)
配置文件
端口
如果修改了配置文件中端口,则必须必须使用 -p 进行端口的映射,否则无法连接到redis服务器
-p 宿主端口:容器端口
在进行连接的时候使用的是 宿主机端口 进行连接,和容器端口没有关系,容器端口只是和宿主机端口进行通信。
远程连接
bind 0.0.0.0 允许任何一个ip 进行远程连接
本地保护模式
protected-mode yes 是否开启本保护模式(只监听本地)
网上有很多介绍说将 protected-mode 修改为no 其实没有必要,
从注释来看,说的是,
如果没有配置bind 或者 requirepass 则 protected默认是开启的,也就是说,如果配置了 bind 或者 requirepass 则会忽略掉protected-mode yes 的配置(当然手动禁用也是可以的)
登录
使用 6378 端口是连接不上的
使用宿主机的 6379 端口正常连接,由于我开启了 requirepass 密码验证,需要登录才能正常使用里面的功能
登录后正常使用
开启aof
1.使用命令行开启(方法一)
2.修改配置文件(方法二)
使用命令行开启 aof 不会修改 redis.conf 文件中的具体信息(使用这种方式有好有坏)
aof 只会记录 set 和 del 操作,get 操作不进行记录
*3 表示这条命令有3段
$3 第一段有3个字符
set 第一段的值
$2 第二段有2个字符
a1 第二段的值
$2 第三段有2个字符
a1 第三段的值
持久化分为 rdb 和 aof
rdb | aof | |
持久化方式 | 内存数据全部添加到xxx.rdb文件中(非追加方式,覆盖形式) | 命令追加到xxx.aof文件中 |
子进程 | 只要进行持久化,就会fock子进程 | 重写会fock子进程 |
文件大小 | xxx.rdb文件占用空间小 | xxx.aof文件占用空间大 |
阻塞 | 只要持久化,就会发生阻塞 | 重写,才会发生阻塞 |
消耗资源 | 多 | 少 |
aof
aof重写,过程(重写不是持久化,aof的持久化是自动,重写是对持久化文件进行优化减少文件体积)
1. fork 子进程,进行文件的重写(子进程进行重写的时候,主线程能够正常的工作)
2. 在重写过程中,新的命令会写入到 AOF重写缓冲区(aof_rewrite_buf) 和 aof缓冲区(aof_buf)(主线程能够正常的进行工作)
3. 重写结束后,将 AOF重写缓冲区的内容 写入到新的 aof 文件中 并且 替换旧的 aof 文件(主线程会出现阻塞)
no-appendfsync-on-rewrite yes
设置为 yes , 在重写期间,会将命令写入到 aof缓冲区 和 aof重写缓冲区,不会追加到aof文件
no-appendfsync-on-rewrite no 0
设置为 0, 禁止自动重写,虽然 aof 重写不会造成太大的阻塞时间,但是尽量还是手动的进行重写比较好
手动重写:
bgrewriteaof
将内存中存储的命令进行整合,将对同一个 key 值的新增 与 删除,抵消掉(将这两条命令都剔除掉),生成一个新的xxx.aof 文件,但是文件中数据的存储方式是以 xxx.rdb 的格式进行存储的。
重写后的文件内容为:
之后再插入数据,还以原来的方式进行内容的追加
aof自动重写的触发条件:
第一次重写当xxx.aof文件大小达到 64mb 的时候会进行一次重写,
后面第二次第三次的重写一次按照:
上一次文件的大小 + 上一次重写文件的大小 * percentage 的大小 为这一次重写的触发条件(类似于递归)
假设 percentage = 60,min-size=64mb
第一次触发需要文件需要达到的大小为:64
第 2 次触发需要文件需要达到的大小为:64 + 64 * 0.6
第 3 次触发需要文件需要达到的大小为:(64 + 64 * 0.6) + (64 + 64 * 0.6)*0.6
第 3 次触发需要文件需要达到的大小为:((64 + 64 * 0.6) + (64 + 64 * 0.6)*0.6 ) + ((64 + 64 * 0.6) + (64 + 64 * 0.6)*0.6 )*0.6
aof 方式丢失数据的情况:
目前常见的操作系统中,执行系统调用write函数,将一些内容写入到某个文件里面时,为了提高效率,系统通常不会直接将内容写入硬盘里面,而是先将内容放入一个内存缓冲区(buffer)里面,等到缓冲区被填满,或者用户执行fsync调用和fdatasync调用时才将储存在缓冲区里的内容真正的写入到硬盘里,未写入磁盘之前,数据可能会丢失
一般情况下,设置 aof 是一秒钟进行一次持久化(这种方式为Everysec(默认))(将这1秒中产生的set, del 语句添加到 xxx.aof 文件中),如果在一秒钟之间进行了10次数据的改变,这个时候服务器宕机,就会造成这10条数据的丢失。
rdb(fork 子进程是为了进行持久化)
rdb持久化:
1. SAVE 方式(完全阻塞,使用主进程执行该命令,无法响应请求)
2. BGSAVE 方式( fork子进程的时候发生阻塞,无法响应请求,在子进程进行持久化的时候,能够正常的响应请求 )
优点:
完全备份,不同时间的数据集备份可以做到多版本恢复
紧凑的单一文件,方便网络传输,适合灾难恢复
恢复大数据集速度较AOF快
缺点:
会丢失最近写入、修改的而未能持久化的数据
fork过程非常耗时,会造成毫秒级不能响应客户端请求
rdb 方式丢失数据的情况:
save 900 1
save 300 10
save 60 10000
如果在300 到 900 秒之间,数据改变了 8 次,这个时候没有达到 900 秒进行持久化的条件,服务器宕机了,这个时候就会丢失这8条数据。
redis 优化
提高redis的可靠性,可用性,减少数据的丢失与阻塞:
1.使用混合方式进行持久化(rdb(辅)+aof(主)),减少数据的丢失
2.使用rediscluster集群的方式,减少阻塞(集群至少要有3个节点才能正常的工作)
cluster 集群的工作方式:
当有key值传入的时候,redis会根据crc16的算法得出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作。
开启混合持久化
4.0之后默认开启混合持久化
开启aof
开启aof以后,redis 启动的时候会以 xxx.aof 日志文件进行数据的加载,xxx.rdb 文件无效,这样会造成数据的丢失
解决方式;
1. 先启动redis 服务,
2. 命令行开启 aof (不会改变配置文件中的配置信息)
修改rdb配置:
保留rdb, 900 秒,进行一次持久化操作
rdb持久化频率解析:
在900秒(15分钟)后,如果至少有一个键被改变,会进行持久化
300秒后(5分钟)如果至少有10个键被改变,会进行持久化
60秒后,如果至少改变了10000个键,会进行持久化
aof持久化频率解析:
always 只要改变就进行aof持久化
everysec 一秒钟进行一次aof持久化,不管在这一秒钟出现多少次的改变,都进行一次aof持久化,(不管你风吹雨打我该怎么干就怎么干,有点这么个意思)服务器每写入一个命令,就调用一次fdatasync,将缓冲区里面的命令写入到硬盘。这种模式下,服务器出现故障,也不会丢失任何已经成功执行的命令数据
no 表示操作系统进行数据缓存同步到磁盘(相比前两种方式总体消耗的资源要小,持久化没办法保证)。服务器不主动调用fdatasync,由操作系统决定何时将缓冲区里面的命令写入到硬盘。这种模式下,服务器遭遇意外停机时,丢失命令的数量是不确定的
redis-cli 工具
容器中复制:不能正常的执行命令
不可取,还是从redis 安装包里面编译获得吧。
或者不用安装,直接到容器里面使用 redis-cli 命令,
编译redis安装包获取:
官网下载 redis
http://www.redis.cn/download.html
解压文件
tar -xvzf redis-5.0.5.tar.gz
解压后该命令是无法进行使用的
进入到目录里面进行编译 make
最开始目录下的 redis-cli.c 文件是不可执行的
make 编译结束后:会生成一个可以运行的 redis-cli 文件
可以使用使用全路径运行,如果想方便的使用,需要将该 可运行文件拷贝到 /usr/local/bin 目录下
将 redis-cli 拷贝到 /usr/local/bin 目录下:
不跟参数 -h 默认连接的是本机的 redis,端口默认 6379
----------------------------------------------------
也可使用
make && make install
编译 + 安装
这样的话会直接在 /usr/local/bin 里面产生好几个可运行文件
不需要手动的将 redis-cli 可运行文件拷贝到 /usr/local/bin 目录下
-----------------------------------------------------------
redis.conf 文件的差异5.0.5 和 6.0.1
在redis的解压文件夹里面,也存在 redis.conf 文件,不过这个文件的大小和 grokzen/redis-cluster 文件不太一样
diff --context redis.conf /redis/rediscluster/redis.conf > /app/diff_redis.txt
有兴趣的可以将文件导出来看看
在容器中安装软件:
更新apt-get
apt-get update
安装 vim
vim /redis/redis.conf