zoukankan      html  css  js  c++  java
  • redis07

    redis的整合

    引入依赖

    1 <dependency>
    2     <groupId>redis.clients</groupId>
    3     <artifactId>jedis</artifactId>
    4 </dependency>

    redis的工具类,将redis的池初始化到spring容器中

     1 public class RedisUtil {
     2 
     3     private JedisPool jedisPool;
     4 
     5     public void initPool(String host,int port ,int database){
     6         JedisPoolConfig poolConfig = new JedisPoolConfig();
     7         poolConfig.setMaxTotal(200);
     8         poolConfig.setMaxIdle(30);
     9         poolConfig.setBlockWhenExhausted(true);
    10         poolConfig.setMaxWaitMillis(10*1000);
    11         poolConfig.setTestOnBorrow(true);
    12         jedisPool=new JedisPool(poolConfig,host,port,20*1000);
    13     }
    14 
    15     public Jedis getJedis(){
    16         Jedis jedis = jedisPool.getResource();
    17         return jedis;
    18     }
    19 
    20 }

    spring整合redis的配置类

     1 @Configuration
     2 public class RedisConfig {
     3     //读取配置文件中的redis的ip地址
     4     @Value("${spring.redis.host:disabled}")
     5     private String host;
     6     @Value("${spring.redis.port:0}")
     7     private int port ;
     8     @Value("${spring.redis.database:0}")
     9     private int database;
    10     @Bean
    11     public RedisUtil getRedisUtil(){
    12         if(host.equals("disabled")){
    13             return null;
    14         }
    15         RedisUtil redisUtil=new RedisUtil();
    16         redisUtil.initPool(host,port,database);
    17         return redisUtil;
    18     }
    19 }

    application.properties

    spring.redis.host=192.168.239.139
    
    spring.redis.port=6379
    
    spring.redis.database=0

    缓存击穿

    是某一个热点key在高并发访问的情况下,突然失效,导致大量的并发,引起mysql数据库压力瞬间增大,造成过大压力

    击穿:在正常的访问情况下,如果缓存失效,如果保护mysql,重启缓存的过程,使用redis数据库的分布式锁,解决mysql的访问压力问题。

    第一种分布式锁:redis自带一个分布式锁,set px nx

    set sku:108:lock 1 px 600000 nx 

    px 600000   过期时间

    nx    分布式锁参数,只有不存在才能返回成功

    第二种分布式锁:redisson框架,一个redis的带有juc的lock功能的客户端的实现(既有jedis的功能,又有juc的锁功能)

    例:通过skuId查询skuInfo

     1  @Override
     2     public PmsSkuInfo getSkuById(String skuId) {
     3 
     4         PmsSkuInfo pmsSkuInfo = new PmsSkuInfo();
     5 
     6 
     7         //连接缓存,查询缓存
     8         Jedis jedis = redisUtil.getJedis();
     9 
    10 
    11         //没有缓存,查询mysql
    12         String skuKey = "sku:"+skuId+":info";
    13         String skuJson = jedis.get(skuKey);
    14 
    15         if (StringUtils.isNotBlank(skuJson)){
    16             pmsSkuInfo = JSON.parseObject(skuJson, PmsSkuInfo.class);
    17         }else {
    18 
    19             //设置分布式锁
    20             String token = UUID.randomUUID().toString();
    21             String OK = jedis.set("sku:" + skuId + ":lock", token, "nx", "px", 10*1000);
    22             if (StringUtils.isNotBlank(OK)&&OK.equals("OK")){
    23                 //设置成功,有权在10s内访问数据库
    24                 pmsSkuInfo = getSkuByIdFromDb(skuId);
    25 
    26                 try {
    27                     Thread.sleep(2000);
    28                 } catch (InterruptedException e) {
    29                     e.printStackTrace();
    30                 }
    31 
    32                 if (pmsSkuInfo != null){
    33                     //mysql存入redis
    34                     jedis.set("sku:"+skuId+":info",JSON.toJSONString(pmsSkuInfo));
    35                 }else {
                  //数据库不存在该sku
    36 //防止缓存穿透,值设为空字符串或null 37 jedis.setex("sku:"+skuId+":info",60*3,JSON.toJSONString("")); 38 } 39 40 String lockToken = jedis.get("sku:" + skuId + ":lock"); 41 if(StringUtils.isNotBlank(lockToken)&&lockToken.equals(token)){ //用token确认删除的是自己的锁 42 43 //在访问mysql后,将mysql的分布式锁删除 44 jedis.del("sku:" + skuId + ":lock"); 45 46 } 47 48 }else { 49 //设置失败,自旋(该线程在睡眠几秒后,重新尝试本方法) 50 return getSkuById(skuId); 51 } 52 53 } 54 jedis.close(); 55 56 return pmsSkuInfo; 57 58 }

    49行中,如改为,则是错误的自旋

    1                 //设置失败,自旋(该线程在睡眠几秒后,重新尝试本方法)
    2                 try {
    3                     Thread.sleep(3000);
    4                 } catch (InterruptedException e) {
    5                     e.printStackTrace();
    6                 }
    7                 
    8                 getSkuById(skuId);

    getSkuId(skuId) 表示又开新辟的线程重新进行访问,与原线程形成父子线程,

    加入 return 后 ,return getSkuById(skuId) 表原线程重新进行访问

  • 相关阅读:
    [转载]「服务」WCF中NetNamedPipeBinding的应用实例
    [转载] ABP框架理论学习之后台工作(Jobs)和后台工作者(Workers)
    .NET Core use NLog
    把.netcore console 安装到Windows 系统服务。
    利用Linq Skip() Take()分页
    C#访问Java的WebService添加SOAPHeader验证的问题
    马丁福勒 关于微服务特点的描述
    转载 springboot 配置读取
    luajit与NYI
    lua启用lua-resty-core
  • 原文地址:https://www.cnblogs.com/quyangyang/p/11618725.html
Copyright © 2011-2022 走看看