1 Redis持久化策略
1.1 什么是持久化
说明:Redis运行环境在内存中,如果redis服务器关闭,则内存数据将会丢失
需求:如何保存内存数据呢?
解决方案: 可以定期将内存数据持久化到磁盘中
持久化策略规则:
当Redis正常运行时,定期的将数据保存到磁盘中,当redis服务器重启时,则根据配置文件中指定的持久化的方式,实现数的恢复(读取数据,之后恢复数据)
1.2 RDB模式
1.2.1 特点说明
1).RDB模式是Redis默认的策略
2).RDB模式能够定期(时间间隔)持久化. 影响:可能导致数据的丢失
3).RDB模式 记录的是内存数据的快照,持久化效率较高,快照只保留最新的记录
1.2.2 RDB模式命令
1.save命令: 将内存数据持久化到磁盘中 主动的操作 会造成线程阻塞
2.bgsave命令: 将内存数据采用后台运行的方式,持久化到文件中.不会造成阻塞
3.默认的持久化的机制
save 900 1 如果在900秒内,执行了1次更新操作,则持久化一次
save 300 10 如果在300秒内,执行了10次更新操作,则持久化一次
save 60 10000 如果在60秒内,执行了10000次更新操作,则持久化一次
1.2.3 持久化文件配置
1).指定持久化文件
2).指定持久化文件目录
1.3 AOF模式
1.3.1 AOF模式特点
1).AOF模式默认条件下是关闭的,需要手动开启
2).AOF模式记录的是用户的操作过程,所以可以实现实时持久化操作
3).AOF模式由于记录的是实时的操作过程,所以持久化文件较大,需要定期维护
1.3.2 启动AOF
说明: 如果一旦开启AOF模式.则以AOF模式为准
1.4 关于持久化操作总结
1.当内存数据少量丢失时,采用RDB模式(快)
2.当内存数不允许丢失时,采用AOF模式(定期维护持久化文件)
3.一般在工作中采用RDB+AOF模式共同作用,保证数据的有效性
1.5 面试题
问题: 如果小李(漂亮妹子)在公司服务器中执行了flushALL命令,问怎么办?
答: 需要找到aof文件之后,删除flushAll命令 之后重启redis,执行save命令即可.
2 内存优化策略
2.1 为什么需要内存优化
说明: 由于redis在内存中保存数据.如果一直存储,则内存数据必然溢出,所以需要定期维护内存数据的大小
维护策略: 删除旧的不用的数据,保留新的常用的数据
2.2 LRU算法
LRU是Least Recently Used的缩写,即最近最少使用,是一种常用的页面置换算法,选择最近最久未使用的页面予以淘汰。该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间 t,当须淘汰一个页面时,选择现有页面中其 t 值最大的,即最近最少使用的页面予以淘汰。
计算维度: 时间T
注意事项: LRU算法是迄今为止内存中最好用的数据置换算法
2.3 LFU算法
LFU(least frequently used (LFU) page-replacement algorithm)。即最不经常使用页置换算法,要求在页置换时置换引用计数最小的页,因为经常使用的页应该有一个较大的引用次数。但是有些页在开始时使用次数很多,但以后就不再使用,这类页将会长时间留在内存中,因此可以将引用计数寄存器定时右移一位,形成指数衰减的平均使用次数。
维度: 使用次数
2.4 随机算法
随机算法
2.5 TTL算法
根据剩余的存活时间,将马上要超时的数据提前删除
2.6 配置内存优化策略
1.volatile-lru 在设定了超时时间的数据中,采用lru算法
2.allkeys-lru 在所有的数据中,采用lru算法
1.volatile-lru 在设定了超时时间的数据中,采用lru算法
2.allkeys-lru 在所有的数据中,采用lru算法
3.volatile-lfu 在设定了超时时间的数据中,采用lfu算法
4.allkeys-lfu 所有数据采用lfu算法
5.volatitle-random 设置超时时间数据的随机算法
6.allkeys-random 所有数据的随机
7.volatitle-ttl 将设定了超时时间的数据,提前删除
8.noeviction 默认规则,如果设定noeviction 则不删除数据,直接报错返回
手动修改redis内存优化策略
3 关于缓存面试问题
问题出发点:
由于缓存失效,导致大量的用户的请求,直接访问数据库服务器,导致负载过高,从而引发整体岩机的风险
3.1 缓存穿透
说明: 用户频繁访问数据库中不存在的数据时,可能出现缓存穿透的现象,如果该操作是高并发操作,则可能直接威胁数据库服务器
解决方案:
1.采用IP限流的方式,降低用户访问服务器次数 IP动态代理(一分钟变一次)
2.微服务的处理方式: 利用断路器返回执行的业务数据即可不执行数据库操作 从而保护了数据库
3.微服务处理方式:API网关设计. 不允许进行非法操作
3.2 缓存击穿
说明: 由于redis中某个热点数据由于超时/删除等操作造成数据失效,同时用户高并发访问该数据,则可能导致数据库岩机,该操作称之为 缓存击穿
解决方案: 可以采用多级缓存的设计,同时数据的超时时间采用随机数的方式
3.3 缓存雪崩
说明: 由于redis内存数据大量失效,导致用户的访问命中率太低,大量的用户直接访问数据库,可能导致数据库服务器宕机,这种现象称之为缓存雪崩
解决:
1.采用多级缓存]
2.设定不同的超时时间
3.禁止执行flashall等敏感操作
4 Redis分片机制
4.1 Redis分片说明
说明: 如果需要Redis存储海量的内存数据,使用单台redis不能满足用户需求,所以可以采用Redis分片机制实现数据存储
注意事项:
如果有多台redis,则其中的数据都是不一样的…
4.2 Redis部署
搭建端口号: 6379/6380/6381
4.2.1 准备配置文件
6379.conf / 6380.conf / 6381.conf
4.2.2 修改端口号
只修改80和81的端口即可
4.3 Redis分片测试
@Test
public void testShards(){
List<JedisShardInfo> shards = new ArrayList<>();
shards.add(new JedisShardInfo("192.168.126.129", 6379));
shards.add(new JedisShardInfo("192.168.126.129", 6380));
shards.add(new JedisShardInfo("192.168.126.129", 6381));
ShardedJedis shardedJedis = new ShardedJedis(shards);
shardedJedis.set("shards", "redis分片操作!!!");
System.out.println(shardedJedis.get("shards"));
}
4.4 一致性HASH算法
4.4.1 概念
一致性哈希算法在1997年由麻省理工学院提出,是一种特殊的哈希算法,目的是解决分布式缓存的问题
[1] 咋移除或者添加一个服务器时,能够尽可能小的改变已存在的服务请求与处理请求服务器之间的映射关系.一致性哈希解决了简单哈希算法在分布式哈希表( Distributed Hash Table , DHT)中存在的动态伸缩等问题
4.4.2 原理说明
知识复习:
1.常规hash由多少位16进制数组成?8位16进制数组成2^32次方
2.如果对相同的数据进行hash计算问结果是否相同???结果必然相同
4.4.3 特性一平衡性
①平衡性是指hash的结果应该平均分配到各个节点,这样从算法上解决了负载均衡问题
实现平衡性的方案: 引入虚拟节点
4.4.3 特性二单调性
②单调性是指在新增或者删减节点时,不影响系统正常运行
特点: 在进行数据迁移时,要求尽可能小的改变数据
4.4.4 特性三分散性
③分散性是指数据应该分散地存放在分布式集群中的各个节点(节点自己可以有备份),不必每个节点都存储所有的数据
俗语:鸡蛋不要放到一个篮子里
4.5 SpringBoot整合Redis分片
4.5.1 编辑properties配置文件
# 配置单台redis服务器
#redis.host=192.168.126.129
#redis.port=6379
##配置redis分片
redis.nodes=192.168.126.129:6379,192.168.126.129:6380,192.168.126.129:6381
4.5.2 编辑配置类
package com.jt.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import java.util.ArrayList;
import java.util.List;
@Configuration //标识我是配置类
@PropertySource("classpath:/properties/redis.properties")
public class RedisConfig {
/**
* SpringBoot整合Redis分片,实质:ShardedJedis对象,交给容器管理
*/
@Value("${redis.nodes}")
private String nodes; //node,node,node
@Bean
public ShardedJedis shardedJedis(){
List<JedisShardInfo> shards = new ArrayList<>();
String[] nodeArray = nodes.split(",");
for (String node : nodeArray){ //node=ip:port
String host = node.split(":")[0];
int port = Integer.parseInt(node.split(":")[1]);
//准备分片节点信息
JedisShardInfo info = new JedisShardInfo(host, port);
shards.add(info);
}
return new ShardedJedis(shards);
}
/* @Value("${redis.host}")
private String host;
@Value("${redis.port}")
private Integer port;
@Bean
public Jedis jedis(){
return new Jedis(host, port);
}*/
}
4.5.3 修改AOP缓存注入
说明: 将AOP中的注入对象切换为分片对象
5 Redis哨兵机制
5.1 分片机制存在的问题
说明: redis分片主要的作用是实现内存数据的扩容,但是如果redis分片中有一个节点岩机,则直接影响所有节点的运行.能否优化?
实现策略: 采用Redis哨兵机制实现Redis节点高可用
5.2 Redis节点主从配置
5.2.1 准备主从节点
1).关闭redis分片的节点,之后复制配置文件准备哨兵的配置
2).复制分片的目录,改名为sentinel
3).删除多余的持久化文件,保存redis配置文件
4).启动3台Redis服务器
5.2.2 实现redis主从
命令:
info replication 检查redis节点的状态信息
节点划分: 6379 当主机 6380/6381当从机
命令2: 实现主从挂载
slaveof host port
3).检查6379主机的状态
结论: redis所有节点都可以相互通信,并且路径当前主从的状态
数据主从同步的状态
5.3 哨兵机制工作原理
1).当哨兵启动时,会链接redis主节点,同时获取所有节点的状态信息
2).当哨兵连续3次通过心跳检测机制(PINC-PONG),如果发现主机岩机,则开始选举
3).哨兵内部通过随机算法筛选一台从机单选新的主机,其他的节点应该当新主机的从机
5.4 哨兵机制配置
5.4.1 关闭保护模式
5.4.2 开启后台运行
5.4.3 配置投票机制
5.4.4 修改投票时间
主机岩机3秒之后开始选举
5.5 哨兵高可用测试
1.启动哨兵 redis-sentinel sentinel.conf
2).检查哨兵配置
3).将主机岩机,之后检查从机是否当选主机
4).启动之前的主机,检查是否当选新主机的从机
5).如果搭建异常 则删除重做
关闭所有redis服务器