当前位置:   article > 正文

spring整合redis以及优化和内存问题解决_spring-boot-redis-starter 参数优化

spring-boot-redis-starter 参数优化

引入

一、单体架构缓存

1.1、使用Map map = new HashMap<k,v>()做本地缓存

1、可以使用Map作为处理缓存问题,因为Map本身就是吧信息存储到内存中的
2、不足之处是当应用是分布式服务,多个微服务,用本地缓存就会出现bug,在某个微服务缓存了数据,负载均衡后可能会切换到别的微服务,这就导致了缓存数据的不一致性
引出了分布式缓存

二、分布式缓存redis

2.1、安装

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  • 1
  • 2
  • 3
  • 4

2.2、yml

spring:
  redis:
    port: 6379
    host: 192.168.182.130
  • 1
  • 2
  • 3
  • 4

2.3、测试

@Slf4j
@SpringBootTest
@RunWith(SpringRunner.class)
public class GuliMallApplicationTest {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Test
    public void test1(){
        Integer append = stringRedisTemplate.opsForValue().append("k1", "hello world");
        log.info("redis append:{}",append);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

2.4、内存移除问题解决

如:

io.netty.util.internal.OutOfDirectMemoryError: failed to allocate 482344960 byte(s) of direct memory (used: 528482304, max: 1006632960)

这样的问题是spring2.0下,redis使用的是letture客户端,手动换成jedis客户端

修改
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
   <exclusions>
       <exclusion>
           <groupId>io.lettuce</groupId>
           <artifactId>lettuce-core</artifactId>
       </exclusion>
   </exclusions>
</dependency>
<dependency>
   <groupId>redis.clients</groupId>
   <artifactId>jedis</artifactId>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

三、缓存穿透、雪崩、击穿

缓存穿透

大量并发访问一个不存在的数据,解决:对查询的数据为null也储存到redis中。

缓存雪崩

大量并发同时发访问多个数据,多个数据并且都过期了,解决:对放入redis中的数据设置随机过期时间。

缓存击穿

大量并发访问某个热点数据,且这个热点数据正好过期了,解决:对访问这个数据的服务或者业务加锁lock。

四、解决缓存击穿问题

本地一台机器微服务大量并发情况下

对需要做缓存的业务加锁如: synchronized 、JUC(lock)等
伪代码:

public class ThreadLoclTest{
  public Object method(){
	  synchronized(this){
		  数据 = 查缓存
		  if(有缓存数据){
		  	return 数据;
		  }
		  数据 = 去db查;
		  把db查到的数据存到redis中;
		  return 数据
		  }
  }  
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

这里一定注意一定要把db中查到的数据写到锁里面,否则并发会有问题,由于redis存储有网络波动问题,会导致大量并发访问时,可能还没存到redis中,线程就去访问db了

分布式并发

原生StringRedisTemplate使用分布式锁
//伪代码
//1.查询是否缓存命中
//2.没有命中则进行分布式锁业务开发
//2.1 分布式锁开发模板
	  //每个线程唯一的uuid
	  String uuid = UUID.randomUUID().toString();
	  //redis加锁命令 set lock uuid ex <时间> nx 要满足原子性
	  Boolean lock1 = stringRedisTemplate.opsForValue().setIfAbsent("lock", uuid, 30, TimeUnit.SECONDS);
	  if (lock1) {
	  //true则抢分布式锁成功
	      System.out.println("抢占分布式锁成功。。。。。。");
	      try {
	         //业务
	      } finally {
	          //lua脚本 释放分布式锁  解锁要满足原子性
	          String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
	          Long lock = stringRedisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class), Arrays.asList("lock"), uuid);
	          
	      }
	  } else {
	      //没抢到锁继续自选抢锁
	      //todo设置睡眠时间
	      return 当前方法
	  }
//3.命中直接返回数据
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

使用Redisson结局分布式缓存击穿问题

见引用博文:

https://blog.csdn.net/weixin_45031570/article/details/126002868?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22126002868%22%2C%22source%22%3A%22weixin_45031570%22%7D&ctrtid=mkGrK

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/721943
推荐阅读
相关标签
  

闽ICP备14008679号