1. Redis算法
1.1 一致性hash算法
一致性哈希算法在1997年由麻省理工学院提出,是一种特殊的哈希算法,目的是解决分布式缓存的问题
- 新增/删除节点,要求尽可能小的改变原有的映射关系
- 解决了分布式环境下的存储动态伸缩性(弹性)问题
一致性算法的特点
- 平衡性
平衡性是指hash的结果应该平均分配到各个节点,这样从算法上解决了负载不均问题
由于节点是通过hash计算得到的结果.所以可能出现如下的情况,发现数据分配严重不平衡
- 单调性
单调性是指在新增或者删减节点时,不影响系统正常运行,其中的数据可以自动的实现迁移
- 分散性
分散性是指数据应该分散地存放在分布式集群中的各个节点(节点自己可以有备份),不必每个节点都存储所有的数据
1.2. hash槽算法
说明: RedisCluster(redis分区)采用此分区,所有的键根据哈希函数(CRC16[key]%16384)映射到0-16383槽内,共16384个槽位,每个节点维护部分槽及槽所映射的键值数据.根据主节点的个数,均衡划分区间.
算法:哈希函数: Hash()=CRC16[key]%16384
当向redis集群中插入数据时,首先将key进行计算.之后将计算结果匹配到具体的某一个槽的区间内,之后再将数据set到管理该槽的节点中
SpringBoot整合reids分片
redis.shards=192.168.126.129:6379,192.168.126.129:6380,192.168.126.129:6381
package com.jt.redisConfig;
import java.util.ArrayList;
import java.util.List;
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 lombok.Data;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
@Configuration
@PropertySource("classpath:/properties/redis.properties")
@Data
public class RedisConfig {
@Value("${redis.shards}")
private String redis;
@Bean
public ShardedJedis shardedJedis() {
List<JedisShardInfo> list = new ArrayList<>();
String[] str = redis.split(",");
for (String string : str) {
String ip = string.split(":")[0];
int port =Integer.parseInt(string.split(":")[1]);
list.add(new JedisShardInfo(ip,port));
}
return new ShardedJedis(list);
}
}
2. Redis持久化策略
redis的运行环境是内存中,其特点是断电或者宕机即数据清空.为了保证数据的有效性,提高用户的查询效率.所以内存的数据必须持久化.定期将内存中的数据写入到执行的文件中(磁盘中).如果redis服务器宕机了.如果下次重启时,则先读取持久化文件实现数据的恢复
2.1. RDB模式
- RDB模式是redis的默认的持久化策略
- Redis会定期的将数据以快照的形式保存的RDB文件中
风险:RDB模式由于定期保存数据,所以可以会丢失数据. - RDB模式由于记录的是内存数据的快照所以持久化的效率较高
新的快照会覆盖旧的快照.每次保留的都是最新的数据. 持久化文件的大小,相对固定
快照,顾名思义可以理解为拍照一样,把整个内存数据映射到硬盘中,保存一份到硬盘,因此恢复数据起来比较快,把数据映射回去即可
=============================================================================
命令
save指令: 表示告诉redis立即将内存数据进行持久化操作.(同步) 可能造成线程的阻塞
bgsave指令 以异步的形式执行持久化操作
2.3. AOF模式
- AOF模式默认条件下是关闭状态,需要手动开启
- AOF模式可以实现实时持久化操作.可以有效的解决数据丢失问题
- AOF模式做持久化操作时,记录的是用户的操作过程
- AOF的持久化文件相对较大,恢复数据的速度较慢
2.4. 关于持久化操作的总结
1.如果内存数据可以允许少量的数据丢失,则首选rdb
2.如果内存数据存储的是业务数据不允许丢失,则选用aof模式.(AOF文件相对较大,所以定期维护.
3.redis中所有的操作都是单进程单线程操作.(串行的)所以不会造成线程并发性问题
============================================================================================
4. Redis内存策略
redis的数据保存在内存中,但是内存资源是有限的.如果需要存储海量的数据,则将之前的旧的数据应该先删除,之后再新增
内存优化算法介绍
============================================================================================
4.1. LRU算法
最近最少使用算法,是一种常用的页面置换算法,选择最近最久未使用的页面予以淘汰。该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间 t,当须淘汰一个页面时,选择现有页面中其 t 值最大的,即最近最少使用的页面予以淘汰。
判断维度:时间T
4.2. LFU算法
即最不经常使用数据置换算法,要求在页置换时置换引用计数最小的页,因为经常使用的页应该有一个较大的引用次数。但是有些页在开始时使用次数很多,但以后就不再使用,这类页将会长时间留在内存中,因此可以将引用计数寄存器定时右移一位,形成指数衰减的平均使用次数
判断维度: 使用次数
4.3. RANDOM
随机算法
4.4. ttl
根据剩余的存活时间,挑选时间最少的删除
============================================================================================
4.5 缓存穿透、缓存击穿、缓存雪崩
1. 缓存穿透
访问数据库中压根不存在的数据,则导致缓存失效.所有的请求都访问数据库.导致数据库有宕机的风险.称之为缓存穿透
解决方案: 一般做数据的有效性的校验
2. 缓存击穿
某个热点数据(1个数据)由于超时/删除,导致大量的用户请求在同一时间访问数据库
解决方案:
1.将热点数据永久保存.
2.添加互斥(排它)锁(每次只能有一个用户访问数据库/第二次走缓存) lock操作
3. 缓存雪崩
在redis内存中的数据,在一定的时间内,有大量的缓存数据失效(多个),这时用户大量的访问缓存服务器,但是缓存中没有指定数据,则访问数据库.容易出现数据库宕机的现象
如何解决:
1.让热点数据永久有效
2.设定超时时间采用随机数. 让超时的数据不要在同一时间发生
3.设定多级缓存
5. 分片、哨兵、集群
5.1. 分片
分片环境的问题
根据测试 redis如果采用分片的机制,如果将来有1台redis宕机,则直接影响程序正常的执行。我们希望当redis服务器宕机可以自动的实现主从的切换
需要配置缓存数据同步,数据的同步是实现高可用的前提条件,如果没有数据同步 即使实现了高可用,则也可能由于从服务器中没有数据而导致缓存雪崩效应
Redis分片特点
- Redis分片机制可以实现Redis内存数据的扩容.
- Redis分片机制中,是业务服务器进行一致性hash的计算.而redis服务器只需要负责数据的存储即可.所以redis分片机制性能更高.
- Redis分片机制本身没有实现高可用的效果.如果redis节点缺失,则直接影响用户的使用.
==================================================================================================
5.2. 哨兵(集群前提)
哨兵主要作用: 实现了redis节点的高可用(HA)
Redis哨兵特点
- redis哨兵实现了redis节点的高可用
- redis哨兵机制不能实现内存数据的扩容
- 哨兵本身没有实现高可用.哨兵如何宕机,则直接影响用户使用
==================================================================================================
工作流程:
-
当哨兵启动时,首先要监控当前redis的主机.并且从主机中获取所有的从机信息.
-
当redis主机宕机之后,哨兵通过心跳检测机制检验主机是否宕机.如果连续3次都没有获取主机的反馈,则断定主机宕机.之后根据算法筛选出新的主机.
-
当哨兵选举出新的主机之后,则为了保证主从的关系,则会动态的修改各自的redis.conf配置文件.并且将其他的节点标识为新主机的从
5.3. 集群
==================================================================================================
Redis的所有节点都会保存当前redis集群中的全部主从状态信息.并且每个节点都能够相互通信.当一个节点发生宕机现象.则集群中的其他节点通过PING-PONG检测机制检查Redis节点是否宕机.当有半数以上的节点认为宕机.则认为主节点宕机.同时由Redis剩余的主节点进入选举机制.投票选举链接宕机的主节点的从机.实现故障迁移
6. 总结
- 分片只能实现内存扩容 不能高可用
- 哨兵可以高可用 但是不能实现内存扩容
- 集群相当于就是一个终极体 只能用hash槽算法