1.发布订阅模式
例子:比如说你有一个收音机,你收听了xxxx频道,那么只要你你打开这个频道,你就能听到这个频道的所有内容
你的收音机 ----接收方(订阅方)
频道的内容发送方---内容的发布者
subscribe 订阅的频道的名称
publish 频道名称 内容
场景: 这个功能实际上就是MQ中的功能(消息中间件)
2.Redis中事务问题
事务是具有原子性的,要么同时成功,要么同时失败
但是Redis没有事务
multi 开启事务
exec 提交事务
3. rdb模式实现持久化
3.1 简介:
RDB:内存快照,保存的是数据某一个时刻的状态,类似于我们拍照,一张照片就是一瞬间的形象。
这个模式是将内存的数据内容直接保存到dump.rdb这样的一个二进制文件中 在/usr/local/redis/bin目录下
特点: 因为保存的是二进制文件,所以做数据的恢复是相当快的---适合做数据的备份
rdb到底是如何保存数据的,rdb每一次保存数据的时候,首先会清空原有的dump.rdb文件,然后将整个内存中的数据全部写入到这个文件中。
rdb保存的是redis某一时刻的数据(适合备份,不适合开发)
比如说。刚好清空rdb文件,此时出现断电,宕机---数据就会全部丢失
3.2 rdb触发时机
rdb不用我们开启,redis是默认开启的,redis中什么时候会触发rdb呢》有三种模式:
**save 900 1 ** 在900秒的时间内如果有一个key发生变化,那么将触发内存与硬盘同步
save 300 10 在300秒的时间内如果有10个key发生改变,那么将会触发内存和硬盘同步
save 60 10000 在60秒的时间内如果有10000个key发生改变,那么将会触发内存和硬盘同步
rdb执行的两个命令
save:在主线程中执⾏,会导致阻塞;
bgsave:创建⼀个⼦进程,专⻔⽤于写⼊ RDB ⽂件,避免了主线程的阻塞,这也是 RedisRDB ⽂件⽣成的默认配置。
3.3 rdb原理
rdb采用了写时复制的策略进行rdb
简单来说,bgsave ⼦进程是由主线程 fork ⽣成的,可以共享主线程的所有内存数据。 bgsave ⼦进程运⾏后,开始读取主线程的内存数据,并把它们写⼊ RDB ⽂件。
此时,如果主线程对这些数据也都是读操作(例如图中的键值对 A),那么,主线程和 bgsave ⼦进程相互不影响。但是,如果主线程要修改⼀块数据(例如图中的键值对 C),那么,这块数据就会被复制⼀份,⽣成该数据的副本(键值对 C’)。然后,主线程在这个数据副本上进⾏修改。同时,bgsave ⼦进程可以继续把原来的数据(键值对 C)写⼊ RDB ⽂件。
3.4 一个问题
我们使⽤⼀个 2 核 CPU、4GB 内存、500GB 磁盘的云主机运⾏ Redis,Redis 数据库的数据量⼤⼩差不多是 2GB,我们使⽤了 RDB 做持久化保证。当时 Redis 的运⾏负载以修改操作为主,写读⽐例差不多在 8:2 左右,也就是说,如果有 100 个 请求,80 个请求执⾏的是修改操作。你觉得,在这个场景下,⽤ RDB 做持久化有什么⻛险吗?
a、内存资源⻛险:Redis fork⼦进程做RDB持久化,由于写的⽐例为80%,那么在持久化过程中,“写实复制”会重新分配整个实例80%的内存副本,⼤约需要重新分配1.6GB内存空间,这样整个系统的内存使⽤接近饱和,如果此时⽗进程⼜有⼤量新key写⼊,很快机器内存就会被吃光,如果机器开启了Swap机制,那么Redis会有⼀部分数据被换到磁盘上,当Redis访问这部分在磁盘上的数据时,性能会急剧下降,已经达不到⾼性能的标准(可以理解为武功被废)。如果机器没有开启Swap,会直接触发OOM,⽗⼦进程会⾯临被系统kill掉的⻛险。
b、CPU资源⻛险:虽然⼦进程在做RDB持久化,但⽣成RDB快照过程会消耗⼤量的CPU资源,虽然Redis处理处理请求是单线程的,但Redis Server还有其他线程在后台⼯作,例如AOF每秒刷盘、异步关闭⽂件描述符这些操作。由于机器只有2核CPU,这也就意味着⽗进程占⽤了超过⼀半的CPU资源,此时⼦进程做RDB持久化,可能会产⽣CPU竞争,导致的结果就是⽗进程处理请求延迟增⼤,⼦进程⽣成RDB快照的时间也会变⻓,整个Redis Server性能下降。
c、另外,可以再延伸⼀下,⽼师的问题没有提到Redis进程是否绑定了CPU,如果绑定了CPU,那么⼦进程会继承⽗进程的CPU亲和性属性,⼦进程必然会与⽗进程争夺同⼀个CPU资源,整个Redis Server的性能必然会受到影响!所以如果Redis需要开启定时RDB和AOF重写,进程⼀定不要绑定CPU。
4.aof实现持久化
aof模式是在redis1.1的版本的时候,才增加的一种持久化模式
aof模式在使用的时候,保存的不是数据,是我们操作的时候的一条又一条的命令
只要调用了Redis,那么只要有命令的使用,都会被记录到aof文件中
aof---记录的是操作的命令,不记录实际的数据
aof模式如果是在数据恢复还原的时候,效率并不高,数据恢复一般采用rdb文件恢复是最快的
4.1 aof的使用
aof的使用
cd /usr/local/redis/etc/
vim redis.conf
appendonly no 改为 appendonly yes
重启redis服务器,在/usr/local/redis/bin目录下会生成一个appendonly.aof 文件
4.2 appendonly.aof文件解析
appendonly.aof文件解析
*3 *代表的是命令的开始 3 :这个表示的是命令中一共有3块内容
$3 $使用修饰命令中的每一个参数的 3代表的是下面的这个命令一共有3个字符
set
$5
email
$5
xxxxx
4.3 aof的触发策略
appendfsync always:只要有键发生改变,立马同步(每次都出发OI操作,速度就会慢下来,这种情况是不会丢数据)但是一般不用,因为效率太低了
appendfsync everysec:每一秒钟进行数据同步一次,(开发的时候,一般采用这个,速度也比较快,即使出现数据丢失,也只会丢失1秒钟的数据)
appendfsync no:永不同步,数据只是放到缓存里面,速度快,但是数据容易丢失
4.4 aof模式消息重写
如果aof文件越来越大,怎么办?这个时候,就需要aof的消息重写。
因为aof文件过大,往里写数据的速度也会变慢,如果发生宕机,如果aof文件过大,重启机器以后,恢复数据也需要很久的时间。
no-appendfsync-on-rewrite no :关闭自动重写
auto-aof-rewrite-percentage 100 (这个表示的是必须达到100%的增加才重写 64M+64M=128M )
auto-aof-rewrite-min-size 64mb aof文件(简单的说就是至少aof文件达到64M才重写)
手动重写:
bgrewriteaof :这个命令就是手动重写(需要关闭混合持久化的功能)
aof-use-rdb-preamble no
重写的好处就是对aof文件进行优化,最终的结果都是一样的
如果同时开启rdb模式和aof模式,会以aof优先
4.5 aof原理
为了防止主线程阻塞,redis会fork一个子进程进行aof的重写
- Redis 执行fork() ,现在同时拥有⽗进程和⼦进程。
- 子进程开始将新的aof文件的内容写入到临时文件。
- 对于所有新执行的命令,父进程一边将他们累积到一个内存缓存中,一边将这些改动追加到现有的aof文件的末尾,这样即使再重写的过程中发生宕机,现有的aof文件也是安全的。
- 当子进程完成重写工作时,他给父进程发送一个信号,父进程在接受到信号之后,将内存缓存中所有的数据追加到新的aof文件末尾。
- redis原子的用新文件替换旧文件,之后所有的命令都会直接追加到新aof文件的末尾。
5.混合持久化
我们在开发的时候,到底选择什么rdb还是aof?
如果关心的只是数据,但是仍然接受在一段时间内一些数据的丢失,那么使用rdb模式,速度快
如果在4.0版本以前,开发的时候,基本上都使用aof模式,在4.0以后,出现了一种新的持久化模式,混合持久化
混合持久化,具有rdb和aof的所有优点
aof-use-rdb-preamble yes
rdb:每一次出现重写的时候它会将aof的所有命令写成二进制
aof:每一次在追加的时候,他会直接写成命令的形式
6.Redis的缓存淘汰策略
maxmemory-policy volatile-lru :这个就是配置缓存淘汰策略
maxmemory <bytes> :这个是配置Redis的缓存的大小
noeviction: 只要缓存满了,那么就不会继续服务器里面的请求,读的请求是可以完成的,这种模式缓存里面的数据都不会丢失,但是会导致Redis的业务失败
volatile-lru (least recently used):最近最少使用算法:从设置了过期时间的key中选择空转时间最长的键值对清理掉
volatile-lfu(least frequently used):最近不经常使用算法:从设置了过期时间的key中,选中某一个时间段使用频率最小的键值对清理掉
volatile-ttl:从设置了过期时间的键中选择过期时间最早的键值对清除;
volatile-random:从设置了过期时间的键中,随机选择键进行清除;
allkeys-lru:最近最少使用算法,从所有的键中选择空转时间最长的键值对清除;
allkeys-lfu:最近最不经常使用算法,从所有的键中选择某段时间之内使用频次最少的键值对清除;
allkeys-random:所有的键中,随机选择键进行删除;
7 如何给Redis设置密码
打开redis.conf文件
requirepass foobared 修改foobared这个值
eg requirepass chaochao 那么密码就是chaochao
使用密码登录
auth chaochao
8.主从复制问题
场景: 一个redis服务器可以处理3000个请求,假设有5000个请求并发到来,这个服务器显然是不能承载的,这个时候,我们有这样一个思路:
就是将这5000个请求的读和写能够分离开,写的请求放到一台服务其上 ,读的请求放到另一台服务器上,也达到了解决问题的目的
读写分离:在进行写的操作的时候,在主服务器上进行,在执行读的操作的时候,在从服务器上进行
主从复制--就解决了读写分离的问题
1.主从复制的配置
1.准备两台或者更多的服务器
2.在两台服务器下的/usr/local/下创建一个文件夹
3.将redis解压目录的根目录下的redis.conf文件移动到创建的文件夹中
4.修改这个配置文件
主服务器 Master
daemonize yes //后台启动
bind 0.0.0.0 //表示的是允许所有人访问
从服务器 Slaver
daemonize yes //后台启动
bind 0.0.0.0 //表示的是允许所有人访问
添加一行配置
slaveof 主服务器的ip地址 主服务器端口
5.检查主从配置是否配置完成
./redis-server /usr/local/../redis.conf ..表示创建的文件夹名字
./redis-cli
info
9.哨兵模式
哨兵是安装在任意一台服务器上,跟主服务器没有任何关系
Redis2.0出现了哨兵模式,是为了解决单点问题
什么是单点问题:
在上面我们配置了主动复制,但是当主服务器崩溃,整个服务器就没办法访问的现象,就成为单点问题
哨兵具有监听程序的功能,简单来说,就是看监听主程序是否崩溃,如果主服务器在规定的时间内,没有给哨兵发送确认信息,那么哨兵就认为主服务器崩溃,哨兵就开始投票进行选举,选举一个从服务器作为新的主服务器,这样Redis依然可以正常提供功能
心跳信号:就是没过一段时间,就向服务器发送请求
哨兵的配置
1. 将Redis解压目录下的sentinal.xml文件复制到 /usr/local/../目录下 ..表示配置主从复制时放入redis.conf文件的目录
2.配置sentinal.xml文件
#配置的是配置文件的目录
dir /usr/local/../
#配置的是监听主服务器信息 最后一个参数很重要 一般设置为1 多少票通过
sentinel monitor mymaster 39.99.200.54(主服务器ip) 6379(端口号) 1
#配置的是意思是心跳信号发给你了 多久没回应就认为主服务器死了 单位(ms)...
sentinel down-after-milliseconds mymaster 5000
哨兵的启动命令
./redis-server /usr/local/../sentinel.conf --sentinel &
10.集群模式
场景:随着系统并发量不停的增加(写的请求达到了5000,服务器支持的并发访问量只有3000),这时候,主从复制架构模式已经不能满足要求,这时候,集群模式就应运而生
集群模式具有主从复制和哨兵模式的优点
10.1 集群的实操
1. 因为使用同一台服务器来模拟集群,因此,先创建一个文件夹,在/usr/local目录下
mkdir /usr/local/redis-clusterl
2.在redis-clusterl下创建6个文件夹,分别模拟六台服务器
[root@iz2ze3nurz2xyybhmzu6s6z redis-clusterl]# mkdir 7001
[root@iz2ze3nurz2xyybhmzu6s6z redis-clusterl]# mkdir 7002
[root@iz2ze3nurz2xyybhmzu6s6z redis-clusterl]# mkdir 7003
[root@iz2ze3nurz2xyybhmzu6s6z redis-clusterl]# mkdir 7004
[root@iz2ze3nurz2xyybhmzu6s6z redis-clusterl]# mkdir 7005
[root@iz2ze3nurz2xyybhmzu6s6z redis-clusterl]# mkdir 7006
//这里文件夹的名字表示我们六台服务器的端口号
3.将redis解压目录下的redis.conf文件复制到7001中
cd /usr/local/redis-5.0.7
cp redis.conf /usr/local/redis-clusterl/7001
4.修改配置文件
cd /usr/local/redis-clusterl/7001
vim redis.conf
daemonize yes //修改后台启动
port 7001 //修改redis的端口号为7001
bind 0.0.0.0 //允许所有机器访问
dir /usr/local/redis-clusterl/7001/ //修改配置文件的位置
appendonly yes // 开启aof持久化模式
cluster-enabled yes //开启集群模式
cluster-config-file nodes-7001.conf //集群的配置
cluster-node-timeout 15000 //超时时间
5.将修改后的配置文件分别给7002....7006复制一份
[root@iz2ze3nurz2xyybhmzu6s6z 7001]# cp redis.conf /usr/local/redis-clusterl/7002
[root@iz2ze3nurz2xyybhmzu6s6z 7001]# cp redis.conf /usr/local/redis-clusterl/7003
[root@iz2ze3nurz2xyybhmzu6s6z 7001]# cp redis.conf /usr/local/redis-clusterl/7004
[root@iz2ze3nurz2xyybhmzu6s6z 7001]# cp redis.conf /usr/local/redis-clusterl/7005
[root@iz2ze3nurz2xyybhmzu6s6z 7001]# cp redis.conf /usr/local/redis-clusterl/7006
6.将redis.conf文件中的7001修改为对应的端口号即可
cd /usr/local/redis-clusterl/7002
port 7002
cluster-config-file nodes-7002.conf
dir /usr/local/redis-clusterl/7002/
......
7、安装ruby的相关的工具(5.0的时候没有使用ruby去创建集群这个步骤可省略)
yum install ruby
yum install rubygems
gem install redis
安装最后一个工具就出错了....
(centos7 安装较高版本ruby2.2/2.3/2.4+)按照步骤玩一次就对了
8.开启每一个服务
cd /usr/local/redis/bin/
./redis-server /usr/local/redis-clusterl/7001/redis.conf
./redis-server /usr/local/redis-clusterl/7002/redis.conf
./redis-server /usr/local/redis-clusterl/7003/redis.conf
./redis-server /usr/local/redis-clusterl/7004/redis.conf
./redis-server /usr/local/redis-clusterl/7005/redis.conf
./redis-server /usr/local/redis-clusterl/7006/redis.conf
9.创建集群
5.0以上的版本
redis-cli --cluster create 101.200.149.246:7001 101.200.149.246:7002 101.200.149.246:7003 101.200.149.246:7004 101.200.149.246:7005 101.200.149.246:7006 --cluster-replicas 1
注意:询问的时候要输入yes
低版本
./redis-trib.rb ./redis-trib.rb create --replicas 1 101.200.149.246:7001 101.200.149.246:7002 101.200.149.246:7003 101.200.149.246:7004 101.200.149.246:7005 101.200.149.246:7006
101.200.149.246:服务器的ip
登录集群某一个客户端的命令
./redis-cli -c -h 101.200.149.246 -p 7001
10 .面试题
1、如果集群中一个主服务器死了 那么整个集群的数据是否是完整的?
肯定是、因为主服务器死了之后会选举他自己原来的从服务器来完成接班操作
2、当死了的服务器从新启动之后 主服务器会自动的将数据同步给从服务器
标签:aof,持久,clusterl,可用,redis,usr,服务器,local
From: https://www.cnblogs.com/wangchaochao/p/17201573.html