redis分片缺点及特点,redis主从,哨兵原理,哨兵特点,redis集群及失效情况,redis配置文件

redis分片:
redis如果采用分片机制,将来如果有一台宕机,则直接影响程序的正常运行

如何解决分片缺点:
1.实现高可用,当redis服务器宕机时可以自动的实现主从切换
2.缓存数据同步是实现高可用的前提
3. 如果没有数据同步,即使实现了高可用,则也可能由于从服务器中没有数据而导致缓存雪崩效应

redis分片特点:
1.redis分片机制可以实现redis内存数据的扩容
2.redis分片机制中,是业务服务器进行一致性hash的`计算,而reids服务器只需要负责数据的存储即可,所以redis分片机制性能更高
3.redis分片机制本身没有实现高可用的效果,如果redis节点缺失,则直接影响用户的使用

redis主从搭建
要求:实现主从同步

主从测试
1.当搭建主从结构之后,用户操作主机,从机可以自动实现数据同步
2.搭建主从结构后,从机只读操作,不能写入
3.不要使用主从结构,测试分片API

主从配置有效期
1.默认条件下通过slaveof指令,制定主从结构只能在内存中有效,如果服务器关机重启,则该结构失效,需要手动修改
2.如需要指定永久配置,则需要修改配置文件redis.conf,但是该文件不能由用户自己操作,最好由哨兵/集群的策略完成

redis哨兵工作原理
1.哨兵启动启动后,首先监控当前redis的主机,并且从主机中其获得从机的信息
2.当redis主机宕机之后,哨兵通过心跳检测机制检测主机是否宕机,如果连续3次都没有获取主机的反馈,则断定主机宕机,之前根据算法筛选出 新的主机
3.当哨兵选举出新的主机后,为了保证主从的关系,则会动态的修改各自的redis.conf文件,并且将其他节点标识为新主机的从机

redis哨兵特点:
1.实现redis节点的高可用
2.redis哨兵机制不能实现内存数据的扩容
3.哨兵本身没有实现高可用,哨兵如果宕机,则直接影响用户使用

为什么要使用redis集群??
1.为了提高网站响应速度,总是把热点数据保存在内存中而不是直接从后端数据库中读取
2.由于内存大小的限制,使用一台 Redis 实例显然无法满足需求,这时就需要使用多台 Redis作为缓存数据库。但是如何保证数据存储的一致性呢,这时就需要搭建redis集群.采用合理的机制,保证用户的正常的访问需求.
3.采用redis集群,可以保证数据分散存储,同时保证数据存储的一致性.并且在内部实现高可用的机制.实现了服务故障的自动迁移.

如何进行redis集群高可用测试?
将主机宕机,等待15秒后检查是否有从机当选主机,然后重启主机,检查是否成为新主机的从机

如果redis集群搭建失败该怎么操作?
1.关闭redis的所有服务器
2.删除所有的文件,只保留redis.conf文件

[root@localhost cluster]# rm -rf 700*/dump.rdb
[root@localhost cluster]# rm -rf 700*/nodes.conf

3.重启redis
sh start.sh

4.重新搭建集群的指令

redis-cli --cluster create --cluster-replicas 1 
192.168.126.129:7000 192.168.126.129:7001 
192.168.126.129:7002 192.168.126.129:7003 
192.168.126.129:7004 192.168.126.129:7005

面试题
1.redis集群中最多存储16384个 错误
解释:redis的hash槽算法,只能判断某个数据属于哪台管理,至于数据存储多少个,取决于redis的内存决定
crc16(“key1”)%16384=1000
crc16(“key2”)%16384=1000
计算只能哪块存储,

2.redis集群中最多有多少台主机??? 16384台主机
一块区域由一个redis管理. 一般工作中使用30-80 够用即可.

编辑redis的properties文件

#配置redis单台
#redis.host=192.168.126.129
#redis.port=6379
​
#配置redis分片机制
#redis.shards=192.168.126.129:6379,192.168.126.129:6380,192.168.126.129:6381

#配置redis集群
redis.cluster=192.168.126.129:7000,192.168.126.129:7001,192.168.126.129:7002,192.168.126.129:7003,192.168.126.129:7004,192.168.126.129:7005

编辑配置类(redis集群)

@Configuration  //标识配置类  一般和@Bean注解联用
@PropertySource("classpath:/properties/redis.properties")
public class RedisConfig {
    
    @Value("${redis.cluster}")
    private String nodes;   //node,node,node
    
    //配置redis集群
    @Bean
    public JedisCluster   jedisCluster() {
        //1.定义redis链接池
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(1000);  //线程存活时间
        poolConfig.setMaxIdle(20);  //最大空闲数量
        
        //2.准备redis节点信息
        Set<HostAndPort> set = new HashSet<>();
        String[] nodeArray = nodes.split(","); //分割节点信息
        for (String node : nodeArray) {   //host:port
            String host = node.split(":")[0];  //[0] 指的是分隔符之前
            int port = Integer.parseInt(node.split(":")[1]); //[1]指的是分隔符之后
            set.add(new HostAndPort(host, port));
        }
        return new JedisCluster(set, poolConfig);
    }

编辑CacheAOP(redis集群)

@Aspect   //使该类成为切面类
@Component  //把切面类加入到IOC容器中 
public class CacheAOP {

	@Autowired(required = false)  //  使用到该依赖注入才起效
	private JedisCluster jedis;  //集群
	//private ShardedJedis jedis;  //引入分片机制
	//private Jedis jedis;  //单台

	/**
	 * 规定:ProceedingJoinPoint  参数必须位于第一位
	 * 1,利用切入点表达式拦截@CacheFind注解,同时获取CacheFind注解对象
	 * 2.自定义key
	 * 3.根据key查询缓存
	 *   有数据,则返回对象
	 *   没有数据,则查询数据库,之后保存到缓存
	 *   
	 *   反射相关:
	 * 
	 *  Method method = 
                joinPoint.getTarget()   //获取目标对象
                         .getClass()    //目标对象的class
                         .getMethod("findItemCatList", Long.class); //方法
                //从方法对象中获取返回值类型
                Class returnClass = method.getReturnType();
	 * @throws Throwable 
	 */
	@SuppressAjWarnings("unchecked")  //压制警告注解  unchecked行了未检查的转换时的警告
	//@Around("@annoation(com.jt.anno.cacheFind)")
	@Around("@annotation(cacheFind)")
	public Object around(ProceedingJoinPoint joinPoint,CacheFind cacheFind){
		Object result = null;
		System.out.println("环绕通知开始");
		try {
			Object[] ages = joinPoint.getArgs(); //目标方法参数
			String key = cacheFind.prekey()+"::"+Arrays.toString(ages);
			//根据key查询redis
			if(!jedis.exists(key)) {
				//如果key不存在,则执行目标方法

				result = joinPoint.proceed();
				System.out.println("查数据库");

				//调用业务方法
				//将数据存入缓存中redis
				String json = ObjectMapperUtil.toJSON(result);

				int seconds = cacheFind.seconds();
				if (seconds>0)
					//表示用户需要设置超时时间
					jedis.setex(key, seconds, json);
				else
					//表示用户不需要设置超时时间
					jedis.setnx(key, json);
			}else {
				//如果redis中有缓存,则将json串转化为对象之后返回
				String json = jedis.get(key);//获取json
				//如何获取方法的返回值类型?先获取方法对象
				MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();//获取对象的方法
				result = ObjectMapperUtil.toObj(json, methodSignature.getReturnType());		
				System.out.println("AOP缓存");
			}
		}catch(Throwable e) {
			e.printStackTrace();
		}
		System.out.println("环绕通知结束");
		return result;
	}
	@Around("@annotation(cacheUpdate)")
	//@Around("@annoation(com.jt.anno.cacheUpdate)")
	public Object updateAround(ProceedingJoinPoint joinPoint,CacheUpdate cacheUpdate) {
		/**
		 * 缓存更新AOP实现 首选环绕通知
		 * 要求:
		 * 执行目标方法
		 * 将返回值更新redis缓存
		 */
		try {
			//暂时写死
			ItemCat itemCat = (ItemCat)joinPoint.proceed();
			String key = cacheUpdate.prekey()+"::+["+itemCat.getId()+"]";
			String json = ObjectMapperUtil.toJSON(itemCat);
			if (cacheUpdate.seconds()>0) {
				//表示用户需要设置超时时间
				jedis.setex(key, cacheUpdate.seconds(), json);
			}else {
				jedis.set(key, json);
			}
			return itemCat;
		} catch (Throwable e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值