Redis【进阶】

Redis持久化机制

  • RDB快照(Redis DataBase)
    在指定时间间隔执行数据集的时间点快照,将当前Redis的数据生成一个快照"dump.rdb"二进制文件

如下配置

save 60 1000 // 在60秒内有1000个key被改动,则触发RDB快照,生成文件

RDB缺点
RDB并不是时时刻刻都在执行的,因为RDB记录的是整个Redis的数据,执行RDB时会很消耗性能。
如果在执行完RDB之后的真空期发生了Redis服务器的宕机,就会导致,这期间的数据丢失

  • AOF(append-only file)
    将修改key的每一条指令存进 "appendonly.aof"文件中
    比如 在执行 “set k1 v1” 时,AOF会记录数据
*3
$3
set
$2
k1
$2
v1

这是一种 resp 协议格式数据,每当Redis执行一个改变数据的命令时,这个命令就会被记录在AOF文件的末尾
当Redis服务重启时,会一个个执行AOF里的命令,达到还原数据的目的

  1. AOF缺点
    如果Redis的数据量大,执行的命令过多,那么服务重启时,会花费很长的时间

Redis 发布订阅

什么是发布订阅,发布订阅(pub/sub)是一种消息通信模式:发送者发送消息,订阅者接收消息

Redis 的subscribe 命令可以让客户端订阅任意数量的频道
Redis的List双端链表也可以实现消息队列机制,但是不能支持一对多的消息分发,并且如果消息的生产速度大于订阅者的接收速度,那么就会造成消息堆积。

  • 基于channel的发布/订阅
127.0.0.1:6379> SUBSCRIBE qq     # 订阅名为"qq"的频道,可同时订阅多个
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "qq"
3) (integer) 1

我是Windows,没法开启另一个客户端,所以用java代替发布者

publicstatic void main(String[] args) {
    Jedis jedis = new Jedis("127.0.0.1", 6379);
    jedis.publish("qq", "hello");    // 往”qq“的频道发送"hello"消息
}

执行java代码后,订阅者收到,来自发布者的消息

127.0.0.1:6379> SUBSCRIBE qq
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "qq"
3) (integer) 1
1) "message"
2) "qq"
3) "hello"
  • 基于pattern的发布/订阅
127.0.0.1:6379> PSUBSCRIBE q?      # 订阅”q“?是个占位符
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "q?"
3) (integer) 1
publicstatic void main(String[] args) {
    Jedis jedis = new Jedis("127.0.0.1", 6379);
    jedis.publish("qq", "hello");    // 往”qq“的频道发送"hello"消息
}
127.0.0.1:6379> PSUBSCRIBE q?
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "q?"
3) (integer) 1
1) "pmessage"  
2) "q?"      # 信息匹配的模式:q?
3) "qq"      # 信息本身的目标频道:qq信息本身的目标频道:qq 
4) "hello"

主从复制

主从复制,是指将一台Redis服务器的数据复制到另一台Redis服务器,前者为主服务器,后者为从服务器,且数据的复制是单向的,只能主–>从,主服务器主要进行写操作,从服务器进行读操作

在这里插入图片描述

  • 主从复制好处
    1. 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
    2. 故障恢复:如果主服务器宕机了,哨兵模式可以将一个从服务器升级为主服务器
    3. 负载均衡:redis 80%都是读操作,读写分离可以减缓redis服务器压力。
  • 缺点:
    由于所有的写操作都是先在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave服务器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重

info replication命令查看当前服务器信息

127.0.0.1:6379> info replication
# Replication
role:master       # 主服务器
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

主从复制只需要配置从服务器,从服务器配置文件更改:

slaveof <masterip> <masterport>   # 配置主服务器ip,端口号
masterauth <master-password>   # 主机的密码
slave-read-only yes    # 从服务器,只读

复制原理

  • 全量复制
    1. 从机 启动成功连接到 主机后会发送一个sync同步命令
    2. 主机接到命令,执行bgsave命令生成RDB快照文件记录所有写命令
    3. 在后台进程执行完毕之后,主机将向所有从机发送快照文件
    4. 从机收到并处理RDB快照,将数据载入缓存。
  • 增量复制
    从机在初始化完全量复制并正常工作后,主机会将发生的写命令都发给从机,从机接受并处理命令的过程

哨兵模式(Sentinel)

在主从复制模式下,如果主机宕机了,我们需要手动配置将一台从机升级为主机,而启动哨兵模式,可以帮我们自动完成这项操作

  1. 首先在redis目录下添加Sentinel.conf配置文件,添加配置
###普通配置
#哨兵端口号
port 6385 
# 保护模式关闭,这样其他服务起就可以访问此台redis
protected-mode no
# 哨兵模式是后台启动
daemonize yes

###核心配置
# 最后一个参数:哨兵的数量。1表示,当只要有1个哨兵发现master断线了,就会标记master为down
#sentinel monitor [被监控的主机名称] [主机ip] [主机端口]
sentinel monitor mymaster 127.0.0.1 6379 1
# master中redis的密码
sentinel auth-pass mymaster 123456
# 哨兵从master节点宕机后,等待多少时间(毫秒),认定master不可用,默认30s。
sentinel down-after-milliseconds mymaster 10000

linux命令redis-sentinel sentinel.conf 启动哨兵
windows命令redis-server sentinel.conf --sentinel启动哨兵
在这里插入图片描述
之后启动主机和从机,哨兵模式就搭建好了
如果主机宕机超过一定时间(默认30s)后,这时就会从从机中随机选择一个服务器,升级为主机。之后如果主机重新启动后,这台主机会自动降将为从机。

缓存穿透

正常的环境下,用户请求数据会优先访问Redis缓存,如果缓存中没有,再去数据库中找,数据库有,就会写到缓存中并返回给用户,但是如果数据库中也没有,并且这时大量请求这个没有的数据,那么会给数据库带来很大的压力,甚至崩溃。这就是缓存穿透

  • 解决方案
    1. 缓存空对象,在数据库哪怕没找到对象,也生成一个空的值存入缓存中,并且设置一个较短的过期时间。
    2. 使用布隆过滤器
    3. 一般这种请求都是遭到攻击引起的,所以可以过滤过于频繁查询无效数据的请求

缓存击穿

缓存中的某个key过于频繁的被搜索,是一种非常“热点”的数据,这时这个key刚好过期,在过期的一瞬间,所有的请求都会去请求数据库,造成数据库的压力,这就叫缓存击穿。

  • 解决方案:
    1. 将“热点”key设为永不过期,但什么是“热点数据”?
    2. 加分布式锁,redis可以用setnx命令来实现分布式锁,为防止出现死锁,要在互斥锁上加过期时间
public String get(key) {
      String value = redis.get(key);
      if (value == null) { //代表缓存值过期
          //设置3min的超时,防止del操作失败的时候,下次缓存过期一直不能load db
		  if (redis.setnx(key_mutex, 1, 3 * 60) == 1) {  //代表设置成功
            value = db.get(key);
            redis.set(key, value, expire_secs);
            redis.del(key_mutex);
           } else {  //这个时候代表同时候的其他线程已经load db并回设到缓存了,这时候重试获取缓存值即可
             sleep(50);
             get(key);  //重试
           }
       } else {
           return value;      
       }
 }

缓存雪崩

当Redis服务器宕机重启,或者是缓存中大量的key一起失效,这时大量请求就会直接访问数据库,造成缓存雪崩

  • 解决方案
    1. 将key的过期时间分散开来,避免同时过期大量的key
    2. 缓存集群,主从复制
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值