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;
}
}
发表回复