Redis高并发可能产生的问题即个人见解解决方案

1、  如果redis宕机了,或者链接不上,怎么办?

解决方法:

    ①配置主从复制,配置哨兵模式(相当于古代门派的长老级别可以选择掌门人的权利),一旦发现主机宕机,让下一个从机当做主机。

    ②如果最坏的情况,只能关闭Redis连接,去往数据库连接。但由于数据量大,这样SQL数据库也会宕掉的。

2、  如果redis缓存在高峰期到期失效,在这个时刻请求会向雪崩一样,直接访问数据库如何处理?

     设置条件查询判断,判断redis缓存里是否有数据,如果没有,则去往数据库连接。当然要加分布式锁,利用redis的单线程+多路IO复用技术,原子性原理,让其它的线程请求等待,假若第一个线程进去获取到分布式锁在查询数据的途中宕掉了,不能让其它线程一直等待,设置等待一定时间判断是否取回数据,如果没有,递归调用自己的方法让第二个线程继续拿分布式锁查询数据库。当第二个锁从数据库拿到数据时,把数据值设置到redis数据库缓存中,设置失效时间,避免占内存,方便使用提高效率。

3.   如果用户不停地查询一条不存在的数据,缓存没有,数据库也没有,那么会出现什么

    如果数据不存在,缓存中没有,数据库也没有,当然如果不设置判断,会一直调用数据库,使数据库效率降低,访问量大时甚至会宕机。

    解决方案:从数据库查询,如果数据库没有,则返回值为Null,判断数据库返回的值,如果为Null,则自定义把标识的字段存到Redis中,用key,value的方法,jedis.setex(key,"empty"),设置失效时间跟具体情况而定,然后调用String json=jedis.get(key),判断是否获取的值"empty".equal(json),如果相等,则抛出自定义异常,给用户提示,或者直接return null。这样用户再次查询的时候由于先从reids缓存中查询,redis会有对应的Key获取之前设置的value值,这样就不会再次调用数据库,影响效率等问题。

具体代码如下:

        

@Override
 public SkuInfo getSkuInfo(String skuId) {
  
 try {
 Thread.sleep(3*1000);
 //自定义从redis工具类中获取jedis对象
 Jedis jedis = redisUtil.getJedis();
 //拼接字符串创建Redis里面的Key值
 String skuInfoKey= JedisConst.SKU_PREFIX+skuId+JedisConst.SKU_SUFFIX;
 //根据key值获取value值
 String skuInfoJson = jedis.get(skuInfoKey);
 //如果返回为空,则调用本地数据库连接
 if (skuInfoJson==null || skuInfoJson.length()==0){
 System.out.println(Thread.currentThread().getName()+"当前缓存中未找到数据");
 //判断是否有人去取锁
 String skuLockKey=JedisConst.SKU_PREFIX+skuId+JedisConst.SKULOCK_SUFFIX;
 String result = jedis.set(skuLockKey, "OK", "NX", "PX", JedisConst.SKULOCK_EXPIRE_PX);
 if ("OK".equals(result)){
 System.out.println(Thread.currentThread().getName()+"获得分布式锁");
 SkuInfo skuInfo= getSkuInfoDB(skuId);
 //如果数据库里面没有值,别人恶意攻击的话,直接设置到redis缓存中
 if (skuInfo==null){
 jedis.setex(skuInfoKey,JedisConst.TIME_OUT,"empty");
 return null;
 }
 skuInfoJson = JSON.toJSONString(skuInfo);
 jedis.setex(skuInfoKey, JedisConst.TIME_OUT, skuInfoJson);
 jedis.close();
 return skuInfo;
  
  
 } else {
  
 //假设之后有人取锁后dang掉了,递归调用自己去寻找钥匙。
 System.out.println(Thread.currentThread().getName()+"未获得分布式锁,开启自旋模式俗称递归.");
 //等待1秒钟
 Thread.sleep(1*1000);
 jedis.close();
 return getSkuInfo(skuId);
 }
  
 }else if (skuInfoJson.equals("empty")){
 return null;
 }
 else {
 System.out.println(Thread.currentThread().getName()+"缓存中已有数据正在查询");
 SkuInfo skuInfo = JSON.parseObject(skuInfoJson, SkuInfo.class);
 jedis.close();
 return skuInfo;
 }
 }catch (JedisConnectionException e){
 e.printStackTrace();
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 return getSkuInfoDB(skuId);
  
 





  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值