爬梯:Redis全解析(二)
学习资源整理自:B站《狂神说》
书接上回
11、Redis配置文件详解
redis.conf以下都是默认配置
######### INCLUDES #########
# 包含,可以想properties一样包含其他配置文件
# include /path/to/local.conf
# include /path/to/other.conf
######### NETWORK ##########
# 绑定地址,可以接收请求的链接,改成 0.0.0.0 或者 * 表示通配
bind 127.0.0.1
# 保护模式,非本机访问需要将其关闭
protected-mode yes
port 6379 # 监听端口
######### GENERAL ########
# 以守护进程的方式运行,默认no,意思是是否可以后台运行redis
daemonize no
# 如果以后台方式运行,我们需要制定一个pid文件
pidfile /var/run/redis_6379.pid
# 日志级别
# Specify the server verbosity level.
# This can be one of:
# debug (a lot of information, useful for development/testing)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably) 生产环境适用
# warning (only very important / critical messages are logged)
loglevel notice
logfile "" # 日志文件名
databases 16 # 数据库数量,默认16个
#是否显示logo,就是运行redis-server的时候那个redis logo
always-show-logo yes
########## SNAPSHOTTING ########
# 快照
# 持久化的执行规则,复合条件则执行一次数据持久化 .rdb .aof
# 如果900秒内,有至少1个key修改过
# 如果300秒内,有至少10个key修改过
# 如果60秒内,至少有10000个key修改过
save 900 1
save 300 10
save 60 10000
# 持久化出错,是否继续工作
stop-writes-on-bgsave-error yes
rdbcompression yes # 是否压缩rdb文件(压缩会消耗cpu资源)
rdbchecksum yes # 保存rdb文件的时候,进行错误的检查校验
dbfilename dump.rdb # rdb文件名
dir ./ # rdb文件保存的目录
########## SECURITY #########
# 密码,默认是注释掉,没有密码的
# requirepass foobared
# 也可以通过命令修改密码:config set requirepass 123
######### CLIENTS ##########
# 最大连接数,默认不限制,指的是同时存活的redis客户端
# maxclients 10000
######## MEMORY MANAGEMENT ########
# 最大内存容量
# maxmemory <bytes>
# 内存满了之后的处理策略
# maxmemory-policy 六种方式
# 1、volatile-lru:只对设置了过期时间的key进行LRU(默认值)
# 2、allkeys-lru : 删除lru算法的key
# 3、volatile-random:随机删除即将过期key
# 4、allkeys-random:随机删除
# 5、volatile-ttl : 删除即将过期的
# 6、noeviction : 永不过期,返回错误
# maxmemory-policy noeviction
####### APPEND ONLY MODE #######
# aof
# 默认不开启aof模式,默认使用rdb模式
appendonly no
# aof持久化文件名
appendfilename "appendonly.aof"
# aof同步模式
# appendfsync always # 每次修改都会 sync,比较消耗性能
appendfsync everysec # 每秒执行一次sync,可能会丢失1秒的数据
# appendfsync no # 不执行 sync,操作系统自己同步数据
12、Redis持久化
概念
Redis是内存数据库,数据属于断电既失的情况,所以需要持久化的能力。
redis有两种持久化策略 rdb 和 aof,默认使用rdb模式。
触发机制:
1、save规则,满足则执行rdb持久化
2、执行flushall
3、退出redis
数据恢复:
当redis启动的时候,会自动检查redis.conf中配置的持久化规则,去寻找是否有对应的持久化文件,如果有则会回复文件中的数据。
rdb
redis database
在指定持久化条件符合时,将内存中的数据集写入磁盘中。
redis会创建一个fork子进程来进行持久化操作:
1、首先将数据写入一个临时文件中;
2、等到全部数据都写入临时文件后,再用这个临时的rdb文件替代上一次持久化的rdb文件,成为正式rdb文件。
在整个持久化过程中,全部io操作都由fork进程完成,确保了主进程的高性能。
redis.conf
dbfilename dump.rdb # rdb文件名
dir ./ # rdb文件保存的目录
优点:高性能、适合大规模恢复数据
缺点:可能会丢失最后一次持久化的数据(持久化过程中宕机等情况)、fork进程会占用一定的系统资源
aof
append only file 将命令追加到文件
aof策略是指,将每一条写指令以日志的形式存入aof文件,在需要恢复时redis会将aof文件中的写指令逐行执行
aof文件修复:
如果aof文件遭到破坏,aof模式的redis将无法启动。使用redis-check-aof工具修复:
redis-check-aof --fix appendonly.aof
redis.conf
##### APPEND ONLY MODE #####
# 默认不开启,修改为yes重启生效
appendonly no
appendfilename "appendonly.aof"
# appendfsync always
appendfsync everysec
# appendfsync no
# 是否不需要重写aof文件
no-appendfsync-on-rewrite no
# 当aof文记达到64兆的100%时,重写一个新的文件来继续存储指令
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
优点:
1、数据的完整性会更好
2、最多丢失1秒的数据
3、不需要同步则不需要fork进程周期进行持久化
缺点:
1、aof的文件远大于rdb的文件大小
2、数据恢复的速度慢于rdb
持久化总结扩展
- RDB持久化方式能够在指定的时间间隔内对数据进行快照存储
- AOF持久化方式记录每次对服务器的写操作,当服务器重启的时候会重新执行这些命令来恢复原始数据,AOF命令以Redis协议追加保存命令到文件末尾,Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大;
- 制作缓存,如果你只希望你的数据在服务器运行的时候存在,你也可以不做任何持久化
- 同时开启两种缓存的方式
- 在这种情况下,当Redis重启的时候会优先载入AOF文件来恢复原始数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的更完整;
- RDB的数据不实时,同事使用两者时服务器重启也只会找AOF文件,即便如此,也不是说仅仅只开启AOF模式就可以,因为RDB更适合用于备份数据库(AOF在不断变化不好备份),快速重启,而且不能保证AOF不会出现语句错误,留一个后手;
- 性能建议
- 因为RDB文件只用作后备用途,建议只在Slave上持久化RDB文件,而且只要15分钟备份一次即可,只保留900 1的规则;
- 如果开启AOF,好处是在恶劣情况下也只会丢失不超过两秒的数据,启动脚本较简单只load AOF文件就可以,代价是:1.带来持续的IO 2、AOF rewrite的最后将rewrite过程中产生的新数据写到新文件造成阻塞几乎是不可避免的,所以只要硬盘大小允许,应该尽量减少AOF rewrite的频率,AOF重写的基础大小默认为64m太小了,可以设置到5G以上,默认超过原始大小100%时重写可以改到适当值;
- 如果不启动AOF,仅靠Master-Slave Replication 实现 高可用也可以,能节省大部分IO,也减少了rewrite时带来的系统波动。代价是如果Master/Slave同事崩掉,会丢失十几分钟的数据,启动脚本也要比较两个Master/Slave中的RDB文件,载入较新的那个(微博使用这种架构)。
14、Redis发布订阅
引用菜鸟资料
订阅/发布消息图
演示
订阅端:
127.0.0.1:6379> subscribe ssxChennel
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "ssxChennel"
3) (integer) 1
#进入等待阶段,等待频道消息推送
1) "message" #消息
2) "ssxChennel" #频道名
3) "helloCust" #消息内容
发送端:
127.0.0.1:6379> publish ssxChennel helloCust
(integer) 1
应用场景
-
实时消息系统
-
实时聊天(频道当作聊天室,将信息回显给聊天的人)
-
订阅,关注系统
稍微复杂的场景使用消息队列实现。
15、Redis主从复制
概念
主从复制是指将一台Redis服务器的数据,复制到其它的Redis服务器。前者称为主节点(Master/Leader),后者称为从节点(Slave/Follower)。数据的复制是单向的,只能由主节点到从节点(主从复制、读写分离)Master以写为主、Slave以读为主。
PS:默认情况下,每台Redis服务器都是主节点,且一个主节点可以有多个从节点(或没有),而一个从节点只能由一个主节点。
主从复制的作用主要包括:
- 数据冗余:主从复制实现了数据的热备份,是持久化之外的数据冗余方式;
- 故障恢复:当主节点出问题时,可以由从节点提供服务,实现快速的故障恢复(服务冗余);
- 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务,分担服务器负载;一般系统是读的压力更大可以通过多个从节点分担“读”的压力;
- 高可用:主从复制还是哨兵和集群能够实现的基础,因此说主从复制是Redis高可用的基础。
一般生产环境是不可以使用单台Redis;
环境配置
默认情况下,每台Redis服务器都是主节点
127.0.0.1:6379> info replication
# Replication
role:master #主节点
connected_slaves:0
master_replid:d1ca96e10d765ebb85d9db44475211bade81534d
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
配置集群:
三份配置文件:实例:6379 6380 6381
-
端口:port 6379
-
后台服务:daemonize yes
-
pid文件 :pidfile /var/run/redis_6379.pid
-
rdb文件:dbfilename dump.rdb
-
日志文件:logfile “6379.log”
-
分别启动三个redis
集群配置:一主二从
让从机去认老大
使用命令配置主从集群
配置6380:
127.0.0.1:6380> slaveof 127.0.0.1 6379 #配置主机的host和port (我使用localhost能连接成功,但主机没找到从机....)
OK
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:2
master_sync_in_progress:0
slave_repl_offset:0
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:d507237df1352cd264dfe399b439c2872dca4977
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:0
主机6379:
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=14,lag=1
master_replid:d507237df1352cd264dfe399b439c2872dca4977
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:14
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:14
一般生产环境直接在配置文件中配置,永久配置
# replicaof <masterip> <masterport>
# masterauth <master-password>
主写 从读
#主机写入
127.0.0.1:6379> set key1 v1
OK
#从机读取
127.0.0.1:6380> get key1
"v1"
127.0.0.1:6380> set key2 v2
(error) READONLY You can't write against a read only replica. #从机不能进行写操作
主机宕机重连
127.0.0.1:6379> shutdown
not connected> exit
此时关闭了主机
然后主机重启 设值
[aaa@qq.com redis-5.0.8]# src/redis-server redis.conf
[aaa@qq.com redis-5.0.8]# src/redis-cli -p 6379
127.0.0.1:6379> set key2 v2
OK
从机读取值
127.0.0.1:6380> get key2
"v2" #还是可以读取到,意味着恢复了主从链接关系
从机宕机重连
如果使用命令配置的主从关系,从机重启会失去关联主机(重启不能恢复主从结构)
但如果再使用命令关联到主机 slaveof,此时会将主机中的数据全部恢复过来从机。
复制原理
Slave启动成功连接到Master后会发送一个sync同步命令。
Master接到命令后,启动后台存盘进程,收集所有接收到的写命令,在后台进程执行完毕之后,Master将传送整个文件到Slave完成一次数据同步;
官方名词:
- 全量复制:Slave服务器接收到数据文件后,将其存盘并全数加载到内存中;
- 增量复制:Master在接收到写命令时,依次将命令发送给Slave完成同步;
只有Slave重新连接到Master,就会完成一次全量复制。
集群配置:链路集群
这种模式下,当Master宕机之后,需要手动执行命令让Slave1成为老大:
slaveof on one
此时如果Master回来了,需要手动配置集群结构。
16、Redis哨兵模式
自动选取老大
概述
主从切换技术的方法是:当主服务器宕机后,手动把一台从服务器切换为主服务器,需要人工干预,耗时费力并且会造成一段时间内服务不可用情况。这不是一种推荐的方法,更多时候我们优先考虑哨兵模式。Redis2.8开始正式提供Sentinel(哨兵)架构来解决这个问题。
谋朝篡位自动版,能够后台监控主机是否故障,如果故障了将根据投票决定自动将一台从机转换为主机。
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程。进程原理:哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。
单哨兵模式
多哨兵模式
- 当主服务器宕机后,假设哨兵1先检测到这个结果,此时这个主服务会被判定为“主观下线”,不会立刻进行failover(故障转移)操作。
- 当另外的哨兵都检测到主服务器宕机并且数量达到一定值后,那么哨兵之间就会进行一次投票,投票的行为由其中一台哨兵发起,即进行failover操作。
- 切换成功后,会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机操作,这个过程成为“客观下线”。
实操
目前集群结构为:一主二从
- 配置哨兵文件 sentinel.conf
#sentinel monitor 监听名 host port 票数
sentinel monitor myredis 127.0.0.1 6379 2
后面的票数代表主机挂了之后,Slave投票让谁成为主机,票数多的成为主机。
- 启动哨兵进程
当主机宕机,一定时间后会由哨兵进行选举另外一台作为主机。
优点
- 哨兵集群,基于主从复制模式,所有的主从配置优点
- 主从可以自动切换,故障自动转移,Redis实现高可用
- 从手动模式的主从模式升级,更加健壮实时
缺点
- Redis不好进行在线扩容,集群容量一旦达到上限后,在线扩容十分麻烦
- 实现哨兵模式的全套配置较为麻烦
哨兵模式全套配置:
bind 172.31.11.235
port 26380
daemonize yes
logfile "/usr/local/redis-4.0.9/sentinel.log.26380"
#master1
# 哨兵监控这个master,在至少1个哨兵实例都认为master down后把master标记为odown
sentinel monitor master1 172.31.11.235 6380 1#多少毫秒后,sentinel 认定redis master 服务器已掉线sentinel down-after-milliseconds master1 5000
# 若sentinel在该配置值内未能完成failover操作(即故障时master/slave自动切换),则认为本次failover失败
sentinel failover-timeout master1 10000
#sentinel can-failover master1 yes
sentinel parallel-syncs master1 2
# Generated by CONFIG REWRITE
dir "/usr/local/redis-4.0.9"
sentinel auth-pass master1 xxxxx
17、Redis缓存穿透、击穿和雪崩
Redis缓存的使用极大的提升了性能和效率,特别是数据查询方面。但是也带来了一些问题,其中最致命的是数据一致性问题,从严格意义上讲这个问题无解。如果对数据一致性要求较高,那么就不能使用缓存。
另外一些典型问题如:缓存穿透、缓存雪崩和缓存击穿。
缓存穿透
(某类绕过缓存查询数据库的数据)
缓存穿透的意思是,当用户想要查询一个数据,然后Redis中并没有,于是缓存没有命中,那么就会进入持久层中去数据库查,发现也没有,于是本次查询失败。
然后当这类查询被无数次执行时(恶意攻击、秒杀等),一直无法存入缓存,一直向数据库进行查询,则会造成数据库被攻击的现象,这就叫做 缓存击穿。
布隆过滤器
布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询攻击。
缓存空对象
当存储层不命中后,即使返回的空对象也将其缓存起来,同时设置一个过期时间,之后再访问这个数据会从缓存中获取,保护了后端数据源
存在两个问题:
- 如果空值被存储存储起来,也意味着使用了更多的内存空间;
- 虽然对空值设置了过期时间,还是会存在缓存层和存储层会有一段时间数据不一致问题,此时业务对一致性要求较高时则会造成不必要的影响。
缓存击穿
(某个热点缓存持续高并发查询)
指的是一个key非常热门,一直在被大并发集中查询,然后当这个key瞬间过期失效时,持续的大并发就会穿透缓存,直接冲击到数据库(类似于一堵墙,在一个空被穿出一个洞)
设置热点数据不过期
从缓存层面来看,没有设置过期时间,所以不会出现热点key过期问题,避免了缓存击穿
加互斥锁
分布式锁:使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务,其它线程没有获得分布式锁的权限不能去查询。这种实现方式将高并发的压力转移到分布式锁上,因此对分布式锁的考验较大。
缓存雪崩
指的是缓存在某一个时间点,集体失效。(Redis宕机、集体过期)
比如:双十一的时候,热门商品被放入缓存中,过期设置1小时,那么凌晨一点时,缓存集体过期,那么就会对数据库造成一个压力波峰,极有可能将持久层冲垮;
集中过期还不是非常危险,更为致命的是缓存服务器某个节点宕机断网,将全部压力直接卸到持久层上。
Redis高可用
redis集群,当一台挂了还会有别的redis顶上。(异地多活)
限流降级
- 分布式锁限流,控制只能有一个或几个线程可以访问后台;
- 降级:临时关闭其他不紧急的服务,来为主服务让出服务器资源;
数据预热
意思是在正式启用之前,先把可能访问的数据预先访问一遍,让大部分数据先存入缓存中。
在即将发生大并发访问前,手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点分布均匀。
上一篇: 爬梯:Maven全解析