共计 5585 个字符,预计需要花费 14 分钟才能阅读完成。
Redis 分片机制
三台 Redis 当做一台 Redis 来用,就叫做分片机制
如果须要存储海量的内存数据,如果只应用一台 Redis,无奈保障 Redis 工作的效率,大量的工夫都节约到了寻址当中,能够采纳分片机制
分片的搭建
创立新的文件夹
在文件夹中创立 3 个配置文件
更改端口号(三个端口号改成不一样)
启动 3 个 Redis 服务器
留神阐明
目前当启动多台服务器 多台之间是互不影响的,各自都是独立的实体
如果将分片通过程序的形式进行操作,要把 3 台 Redis 当做一台来用
分片入门案例
/**
* 测试 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","分片机制");
System.out.println(shardedJedis.get("shards"));
}
只存储到了其中一台
一致性 hash 算法
是一种非凡的算法,目标是在移除或增加一个服务器时,可能更小地扭转已存在的服务申请与解决申请服务器之间的映射关系
个别的 hash 是多少位的多少进制数?
8 位 16 进制数
如果对雷同的数据进行 hash 运算 问后果是否雷同?
后果雷同
一个数据 1M 与数据 1G 的 hash 运算的速度是否雷同?
雷同(任何数据用 hash 计算,不以它的量为规范,计算的速度简直都是雷同的)
个性 1 - 平衡性
概念: 平衡性是指 hash 的后果应该平均分配到各个节点,这样从算法上解决了负载平衡问题 [4]。(大抵均匀)
问题形容: 因为节点都是通过 hash 形式进行合计. 所以可能呈现如图中的景象., 导致负载重大不均衡
解决办法: 引入虚构节点
个性 2 - 枯燥性
特点: 枯燥性是指在 新增 或者 删减 节点时,不影响零碎失常运行
个性 3 - 分散性
谚语: 鸡蛋不要放到一个篮子里.
③分散性是指数据应该扩散地寄存在分布式集群中的各个节点(节点本人能够有备份),不用每个节点都存储所有的数据
SpringBoot 整合 Redis 分片
编写配置文件
@Configuration
@PropertySource("classpath:/properties/redis.properties")
public class JedisConfig {@Value("${redis.nodes}")
private String nodes;
@Bean
public ShardedJedis shardedJedis(){nodes=nodes.trim();// 去除多余空格
List<JedisShardInfo> shards=new ArrayList<>();
String[] strings = nodes.split(",");
for (String str:strings) {String host = str.split(":")[0];
Integer port= Integer.valueOf(str.split(":")[1]);
JedisShardInfo info=new JedisShardInfo(host,port);
shards.add(info);
}
return new ShardedJedis(shards);
}
}
自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CacheFind {public String preKey();// 用户标识 key 的前缀
public int seconds() default 0;// 如果用户不写示意不须要超时,如果写了以用户为准}
应用注解
AOP 代码切入
package com.cn.jt.aop;
import com.cn.jt.annotation.CacheFind;
import com.cn.jt.util.ObjectMapperUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.ShardedJedis;
import java.util.Arrays;
/**
* @program: jt
* @description:
* @author: zhu Xia
* @create: 2020-10-14 09:32
**/@Aspect // 我是一个 aop 的切面类
@Component// 将类交给 spring 容器治理
public class CacheAOP {
@Autowired
private ShardedJedis jedis;
/**
* 1. 动静生成 key preKey+ 用户参数数组
* @param joinPoint
* @return
*/
@Around("@annotation(cacheFind)")
public Object around(ProceedingJoinPoint joinPoint,CacheFind cacheFind){System.out.println("注解拦挡");
Object result=null;
try {
//1. 拼接 Redis 存储数据的 key
Object[] args = joinPoint.getArgs();
String key = cacheFind.preKey()+"::" + Arrays.toString(args);
//2. 查问 redis
if(jedis.exists(key)){
//redis 中有记录
String json=jedis.get(key);
// 将数据转化成须要的类型——办法的返回值类型
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Class type = signature.getReturnType();
result = ObjectMapperUtil.toObject(json,type);
}else{
// 不存在 查询数据库
result=joinPoint.proceed();// 执行指标办法
// 将查问后果保留到 Redis 中
String json= ObjectMapperUtil.toJson(result);
// 判断数据是否须要超时工夫
if(cacheFind.seconds()>0){jedis.setex(key,cacheFind.seconds(),json);
}else {jedis.set(key,json);
}
}
} catch (Throwable throwable) {throwable.printStackTrace();
}
return result;
}
}
Redis 哨兵机制
如果 Redis 分片中有一个节点呈现了问题,则整个 Redis 分片机制用户拜访必然有问题,间接影响用户的应用,那就须要实现 Redis 的高可用
配置 Redis 主从构造
实现从机挂载
查看主机状态
能够在主机写,同步到从机
从机只能读,不能写
哨兵机制
心跳检测机制
如果主机宕掉了,哨兵会在从外面选出主,主 修好的话,回来的话只能当从
用户未来连的是哨兵
哨兵原理阐明
1. 配置 redis 主从构造
2. 哨兵服务启动时,会监控以后的主机,同时获取主机的详情信息(主从的构造)
3. 当哨兵利用心跳检测机制(PING-PONG)间断 3 次都没有收到主机的反馈信息则断定主机宕机
4. 当哨兵发现主机宕机之后,则开启选举机制,在以后的从机中筛选一台 Redis 当做主机
5. 将其余的 Redis 节点设置为新主机的从
编辑哨兵配置文件
创立 sentinel 文件夹 并把 sentinel.conf 配置文件移至其下
1. 批改保护模式
2.
3. 其中的 1 示意投票失效的票数
启动哨兵
redis-sentinel sentinel.conf
测试哨兵
/**
* 测试 Redis 哨兵
*/
@Test
public void sentinel(){Set<String> set=new HashSet<>();
// 传递哨兵的配置信息
set.add("192.168.126.129:26379");
JedisSentinelPool jedisSentinelPool = new JedisSentinelPool("mymaster",set);
Jedis jedis=jedisSentinelPool.getResource();
jedis.set("aa","哨兵测试");
System.out.println(jedis.get("aa"));
}
SpringBoot 整合 Redis 哨兵
编辑配置文件
@Configuration
@PropertySource("classpath:/properties/redis.properties")
public class JedisConfig {@Value("${redis.sentinel}")
private String sentinel;
@Bean
public JedisSentinelPool sentinel(){Set<String> set=new HashSet<>();
set.add(sentinel);
JedisPoolConfig jedisPoolConfig=new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(100);
jedisPoolConfig.setMaxIdle(40);
jedisPoolConfig.setMinIdle(10);
return new JedisSentinelPool("mymaster",set,jedisPoolConfig);
}
}
自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CacheFind {public String preKey();// 用户标识 key 的前缀
public int seconds() default 0;// 如果用户不写示意不须要超时,如果写了以用户为准}
应用注解
AOP 切入
@Aspect // 我是一个 aop 的切面类
@Component// 将类交给 spring 容器治理
public class CacheAOP {
@Autowired
private JedisSentinelPool jedisSentinelPool;
/**
* 1. 动静生成 key preKey+ 用户参数数组
* @param joinPoint
* @return
*/
@Around("@annotation(cacheFind)")
public Object around(ProceedingJoinPoint joinPoint,CacheFind cacheFind){Jedis jedis = jedisSentinelPool.getResource();// 从池中取 Redis
System.out.println("注解拦挡");
Object result=null;
try {
//1. 拼接 Redis 存储数据的 key
Object[] args = joinPoint.getArgs();
String key = cacheFind.preKey()+"::" + Arrays.toString(args);
//2. 查问 redis
if(jedis.exists(key)){
//redis 中有记录
String json=jedis.get(key);
// 将数据转化成须要的类型——办法的返回值类型
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Class type = signature.getReturnType();
result = ObjectMapperUtil.toObject(json,type);
}else{
// 不存在 查询数据库
result=joinPoint.proceed();// 执行指标办法
// 将查问后果保留到 Redis 中
String json= ObjectMapperUtil.toJson(result);
// 判断数据是否须要超时工夫
if(cacheFind.seconds()>0){jedis.setex(key,cacheFind.seconds(),json);
}else {jedis.set(key,json);
}
}
} catch (Throwable throwable) {throwable.printStackTrace();
}
jedis.close();// 用完记得关掉
return result;
}
}