目录
1.Redis持久化机制
1): 业务需求
Redis中的运行环境在内存中, 但是内存特点 断电即擦除.
想法:能否保存redis中的内存数据不丢失呢?
持久化: 将内存数据定期保存到磁盘中.
2): RDB模式
2.1 关于RDB模式说明
1.Redis定期, 将内存数据保存到RDB文件中.
2.RDB模式 redis默认的规则.
3.RDB模式记录的是内存数据的快照 ,持久化效率更高(只保留最新数据)
4.RDB模式由于定期持久化,可能导致数据丢失.
2.2 RDB命令
1: 持久化操作 save 同步操作 可能其他线程陷入阻塞
2: 后端持久化 bgsave 异步操作 用户操作不会陷入阻塞 该操作什么时候完成不清楚.
2.3 RDB模式配置
redis.conf中
save 900 1 900秒内用户更新1次 则持久化1次
save 300 10 300秒内用户更新10次 持久化 1次
save 60 10000 60秒内用户更新10000次 持久化1次
save 1 1 保证数据安全性 问题:效率极低 阻塞…
如果想让持久化性能更优,则需要通过监控的手段灵活运用.
用户操作越频繁,则持久化周期越短.
修改rdb文件名称
设置rdb文件生成位置
3):AOF模式
3.1 开启AOF模式
默认条件下AOF模式 默认关闭的.
开启AOF
appendfilename是aof文件的名字
3.2 AOF模式特点
说明: 当开启AOF策略之后,redis持久化以AOF为主.
特点:
- AOF文件默认关闭的,需要手动开启
- AOF文件记录的是用户的操作过程.则可以实现实时持久化操作.(几乎不丢数据)
- AOF文件做追加的操作,所有持久化文件较大.
- AOF持久化时,采用异步的方式进行.
- AOF文件需要定期清理.
3.3 AOF持久化原则
redis.conf中
appendfsync always 用户执行一次操作,持久化一次
appendfsync everysec 每秒持久化一次
appendfsync no 不主动持久化
3.4关于AOF与RDB如何选择
业务:
1.如果用户追求速度,允许少量的数据丢失 首选RDB模式. 快
2.如果用户追求数据的安全性. 首选AOF模式.
面试题:
如果你在redis中执行了flushAll命令,如何挽救??
答案: 修改AOF文件中,删除flushAll的命令.重启redis即可.
注意事项: 一般条件下 Redis会开启AOF与RDB 2种模式
常规用法: 一般会配置redis主从结构 主机开启RDB模式 从机开启AOF模式
3.5 一般redis会开启AOF与RDB两种模式,配置完aof之后会以aof为主 想要开始rdb要执行一下save , aof定期清理 清理时先save持久化 重启服务 删除旧的aof文件
2.Redis内存优化策略
2.1 关于内存优化的说明
Redis运行环境,在内存中. 但是内存资源有限的.不能一味的扩容.所以需要对内存数据优化.
Redis内存大小的设定:
最大内存设定:1G 1GB (可以自行设置内存大小)
2.2 LRU算法
LRU是Least Recently Used的缩写,即最近最少使用,是一种常用的页面置换算法,选择最近最久未使用的页面(数据)予以淘汰。该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间 t,当须淘汰一个页面时,选择现有页面中其 t 值最大的,即最近最少使用的页面予以淘汰。
维度: 时间T
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算法删除数据.
3.volatile-lfu 在设定了超时时间的数据中 采用LFU算法删除数据.
4.allkeys-lfu 在所有数据中. 采用LFU算法删除数据.
5.volatile-random 设定了超时时间数据,采用随机的方式删除数据
6.allkeys-random 所有数据采用随机算法.
7.volatile-ttl 设定超时时间的数据,采用TTl算法删除.
noeviction 默认不删除数据. 如果内存满了,则报错返回. 默认策略
3.redis缓存常见问题(穿透,击穿,雪崩,布隆过滤器)
3.1 什么是缓存穿透
说明: 在高并发的条件下,用户频繁访问一个不存在的数据.导致大量的请求直接发往数据库.导致服务器宕机.
解决方案
1. 只要能够保障用户访问的数据 数据库中一定存在. 布隆过滤器
2. IP限流 黑名单. 微服务中可以通过API网关进行控制
3.2 什么是缓存击穿
说明: 在高并发条件下 用户频繁访问一个热点数据. 但是该热点数据在缓存中失效.导致用户直接访问数据库.
俗语: 称它病,要它命
3.3 什么是缓存雪崩
说明: 在高并发的条件下, 有大量的缓存数据失效了. 导致redis缓存服务器命中率太低.从而导致用户直接访问数据库.
主要问题: 热点数据失效.
解决方案:
1.为热点数据设定超时时间时 采用随机数. 10秒+随机数 保障数据不会同时失效.
2. 设定多级缓存
3.4 布隆过滤器
3.4.1 介绍
布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。
3.4.2 计算机进制换算
1字节 = 8比特
1kb = 1024字节
1mb = 1024kb
3.4.3 业务场景
假设数据库中有1000万数据,每条记录大约2kb 如果该数据都是热点数据,则需要多大的内存空间进行存储? 19G数据!!!
问题: 能否优化内存数据的存储呢??? 尽可能少占用内存空间.
想法: 如果使用1个**bit(01)**代表一个数据, 问占用多大空间 1.19M
3.4.4 布隆过滤器原理
核心1: 很长的二进制向量
核心2: 多个hash函数
解决问题: 校验数据是否存在!!!
1).数据加载过程
2).数据校验
3).存在问题
好的布隆算法可以将误判率 降低到 < 0.03%
4.redis分片机制
4.1 为什么需要分片
说明: 如果有海量的内存数据需要保存,但是都把数据保存到1个redis中,查询的效率太低.如果这台redis服务器宕机,.则整个缓存将不能使用.
解决方案: 采用redis分片机制.
4.2 Redis分片搭建
4.2.1 准备配置文件
4.2.2 修改端口号
说明: 分别将6379/6380/6381的端口号进行配置
4.2.3 启动三台redis
[root@localhost shards]# redis-server 6379.conf &
redis-server 6380.conf & redis-server 6381.conf &
校验redis
4.2.4 redis分片入门案例
/**
* 3台redes key如何存储?? 79/80/81
*/
@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.3 一致性hash算法(3台redes key如何存储?? )
4.3.1 介绍
一致性哈希算法在1997年由麻省理工学院提出,是一种特殊的哈希算法,目的是解决分布式缓存的问题。 [1] 在移除或者添加一个服务器时,能够尽可能小地改变已存在的服务请求与处理请求服务器之间的映射关系。一致性哈希解决了简单哈希算法在分布式哈希表( Distributed Hash Table,DHT) 中存在的动态伸缩等问题 [2] 。
核心知识:
- 一致性hash解决了数据与节点的映射关系(数据归谁管理)
- 节点增加/减少时,数据可以弹性伸缩.
4.3.2 一致性hash算法原理
4.3.3 特性-平衡性
说明: 平衡性是指hash的结果应该平均分配到各个节点,这样从算法上解决了负载均衡问题
解决策略: 引入虚拟节点
4.3.4 特性-单调性
②单调性是指在新增或者删减节点时,不影响系统正常运行 [4] 。
说明: 无论节点增/减,数据都能找到与之匹配的node进行数据的挂载.
4.3.5 特性-分散性
③分散性是指数据应该分散地存放在分布式集群中的各个节点(节点自己可以有备份),不必每个节点都存储所有的数据 [4] 。
谚语: 鸡蛋不要放到一个篮子里.
百度原理图1:
百度原理图2:
4.4 SpringBoot整合Redis分片
4.4.1 编辑配置文件
#单台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.4.2 编辑配置类
package com.jt.config;
@Configuration //标识为一个配置类, 一般整合第三方
@PropertySource("classpath:/properties/redis.properties")
public class RedisConfig {
@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=host: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);
}
4.4.3 修改RedisAOP
5.redis哨兵机制
5.1 关于Redis分片特点
Redis分片可以实现内存数据的扩容,但是如果节点宕机则直接影响程序的运行.
问题关键: 如果节点宕机,需要实现高可用.
5.2 Redis数据同步配置
5.2.1 复制目录
说明: 将shards目录复制 并且改名为sentinel
5.2.2 启动3台redis
说明: 1.删除原有的持久化文件
2.启动3台redis
5.2.3 主从结构搭建
1.6379 主机
2.6380/6381 从机
2.主从挂载命令
slaveof 192.168.126.129 6379
5.3 Redis哨兵实现
5.3.1 哨兵原理
说明:
1.当哨兵启动时,会链接redis主节点,获取所有节点的相关信息.
2.当哨兵通过心跳检测机制 PING -PONG 命令校验服务器是否正常.
3.如果哨兵连续3次发现服务器没有响应,则断定当前主机宕机.
4.之后由哨兵采用随机算法挑选其中的一个从机当选主机.并且其他的节点当做新主机的从.
5.3.2 配置哨兵服务
1).复制文件
cp sentinel.conf sentinel/
2).关闭保护模式
3).开启后台运行
4).哨兵监控
5).修改宕机时间
5.3.3 哨兵命令
1.启动 redis-sentinel sentinel.conf
2.关闭哨兵 ps -ef |grep redis kill -9 PID号
5.3.4 哨兵高可用测试
1).关闭6379主机,检查从机是否当选主机
2).检查从机的配置文件 是否以后关联了主机
如果搭建错误,.则需要删除最后一条主从关系.,之后重启服务器.重新搭建.
5.4 SpringBoot整合哨兵
5.4.1 入门案例
/**
* 测试哨兵API
*/
@Test
public void testSentinel(){
Set<String> sets = new HashSet<>();
sets.add("192.168.126.129:26379");
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMinIdle(10);
poolConfig.setMaxIdle(40);
poolConfig.setMaxTotal(1000);
JedisSentinelPool pool = new JedisSentinelPool("mymaster",sets,poolConfig);
Jedis jedis = pool.getResource();
jedis.set("AAA", "您好Redis");
System.out.println(jedis.get("AAA"));
jedis.close();
}
5.5 关于Redis分片/哨兵总结
1.分片作用: 扩大内存实现海量数据数据的存储. 缺点: 没有实现高可用
2.哨兵作用: 实现了节点的高可用. 缺点: 1.哨兵不能实现扩容 2.哨兵本身没有高可用
想法: 能否有一种机制 既可以实现内存扩容,又可以实现高可用(不需要第三方)