学习资源整理自:B站《狂神说》
书接上回
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,操作系统自己同步数据
Redis是内存数据库,数据属于断电既失的情况,所以需要持久化的能力。
redis有两种持久化策略 rdb 和 aof,默认使用rdb模式。
触发机制:
1、save规则,满足则执行rdb持久化
2、执行flushall
3、退出redis
数据恢复:
当redis启动的时候,会自动检查redis.conf中配置的持久化规则,去寻找是否有对应的持久化文件,如果有则会回复文件中的数据。
redis database
在指定持久化条件符合时,将内存中的数据集写入磁盘中。
redis会创建一个fork子进程来进行持久化操作:
1、首先将数据写入一个临时文件中;
2、等到全部数据都写入临时文件后,再用这个临时的rdb文件替代上一次持久化的rdb文件,成为正式rdb文件。
在整个持久化过程中,全部io操作都由fork进程完成,确保了主进程的高性能。
redis.conf
dbfilename dump.rdb # rdb文件名
dir ./ # rdb文件保存的目录
优点:高性能、适合大规模恢复数据
缺点:可能会丢失最后一次持久化的数据(持久化过程中宕机等情况)、fork进程会占用一定的系统资源
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
订阅端:
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
实时消息系统
实时聊天(频道当作聊天室,将信息回显给聊天的人)
订阅,关注系统
稍微复杂的场景使用消息队列实现。
主从复制是指将一台Redis服务器的数据,复制到其它的Redis服务器。前者称为主节点(Master/Leader),后者称为从节点(Slave/Follower)。数据的复制是单向的,只能由主节点到从节点(主从复制、读写分离)Master以写为主、Slave以读为主。
PS:默认情况下,每台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”
配置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
# masterauth
#主机写入
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
[root@localhost redis-5.0.8]# src/redis-server redis.conf
[root@localhost 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,就会完成一次全量复制。
这种模式下,当Master宕机之后,需要手动执行命令让Slave1成为老大:
slaveof on one
自动选取老大
主从切换技术的方法是:当主服务器宕机后,手动把一台从服务器切换为主服务器,需要人工干预,耗时费力并且会造成一段时间内服务不可用情况。这不是一种推荐的方法,更多时候我们优先考虑哨兵模式。Redis2.8开始正式提供Sentinel(哨兵)架构来解决这个问题。
谋朝篡位自动版,能够后台监控主机是否故障,如果故障了将根据投票决定自动将一台从机转换为主机。
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程。进程原理:哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。
目前集群结构为:一主二从
#sentinel monitor 监听名 host port 票数
sentinel monitor myredis 127.0.0.1 6379 2
后面的票数代表主机挂了之后,Slave投票让谁成为主机,票数多的成为主机。
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
Redis缓存的使用极大的提升了性能和效率,特别是数据查询方面。但是也带来了一些问题,其中最致命的是数据一致性问题,从严格意义上讲这个问题无解。如果对数据一致性要求较高,那么就不能使用缓存。
另外一些典型问题如:缓存穿透、缓存雪崩和缓存击穿。
(某类绕过缓存查询数据库的数据)
缓存穿透的意思是,当用户想要查询一个数据,然后Redis中并没有,于是缓存没有命中,那么就会进入持久层中去数据库查,发现也没有,于是本次查询失败。
然后当这类查询被无数次执行时(恶意攻击、秒杀等),一直无法存入缓存,一直向数据库进行查询,则会造成数据库被攻击的现象,这就叫做 缓存击穿。
布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询攻击。
当存储层不命中后,即使返回的空对象也将其缓存起来,同时设置一个过期时间,之后再访问这个数据会从缓存中获取,保护了后端数据源
存在两个问题:
(某个热点缓存持续高并发查询)
指的是一个key非常热门,一直在被大并发集中查询,然后当这个key瞬间过期失效时,持续的大并发就会穿透缓存,直接冲击到数据库(类似于一堵墙,在一个空被穿出一个洞)
从缓存层面来看,没有设置过期时间,所以不会出现热点key过期问题,避免了缓存击穿
分布式锁:使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务,其它线程没有获得分布式锁的权限不能去查询。这种实现方式将高并发的压力转移到分布式锁上,因此对分布式锁的考验较大。
指的是缓存在某一个时间点,集体失效。(Redis宕机、集体过期)
比如:双十一的时候,热门商品被放入缓存中,过期设置1小时,那么凌晨一点时,缓存集体过期,那么就会对数据库造成一个压力波峰,极有可能将持久层冲垮;
集中过期还不是非常危险,更为致命的是缓存服务器某个节点宕机断网,将全部压力直接卸到持久层上。
redis集群,当一台挂了还会有别的redis顶上。(异地多活)
意思是在正式启用之前,先把可能访问的数据预先访问一遍,让大部分数据先存入缓存中。
在即将发生大并发访问前,手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点分布均匀。