zoukankan      html  css  js  c++  java
  • Java项目中使用Redis缓存案例

       缓存的目的是为了提高系统的性能,缓存中的数据主要有两种: 

                    1.热点数据。我们将经常访问到的数据放在缓存中,降低数据库I/O,同时因为缓存的数据的高速查询,加快整个系统的响应速度,也在一定程度上提高并发量。

                    2.查询耗时的数据。如果有一些数据查询十分耗时,那么每次请求这些数据时,都去数据库查询的话,会使得系统响应速度特别低,数据库cpu 100%。将这些数据放缓存,会极大提高系统响应速度,但同时数据实时性较差。

      最近工作中有碰到需要使用缓存的情况,场景如下:app端看板统计数据汇总,在打开app时加载看板数据,汇总数据来源于不同的库,各个数据的生成接口已经写好,只需要去调用接口整合数据返回即可。

      具体我们来看看是怎么实现的吧。

     第一步,取mysql中查询各个接口的信息:

     getPanelInfo.java

    1 /* service代码略*/
    2 List<PanelDto> panels = panelService.getAllPanels();   //得到接口的名称,接口的url

    第二步,根据拿到的信息生成请求参数:

     getPanelInfo.java

     1   WrapResponseModel resonseModel = new WrapResponseModel();
     2   Map<String, String> headers = new HashMap<>();
     3   headers.put("username", username);
     4   headers.put("token",token);
     5   List<String> content = new ArrayList<String>();
     6   for(PanelDto panelDto:panel){
     7   //发送http请求
     8        content.add(HttpRequestUtils.get(panelDto.getUrl(), headers));
     9 }
    10 // 返回格式
    11   responseModel.setCode(SUCCESS_CODE);
    12   responseModel.setData(content);

    第三步,发送http请求调用接口:

    HttpRequestUtils.java

     1 public static String get(String url, Map<String, String> headers) {
     2         RequestConfig config = RequestConfig.custom().setConnectTimeout(TIME_OUT).setConnectionRequestTimeout(TIME_OUT).setSocketTimeout(TIME_OUT).build();
     3         String ret = null;
     4         //创建HttpClient对象
     5         CloseableHttpClient closeHttpClient = HttpClients.createDefault();
     6         CloseableHttpResponse httpResponse = null;
     7         //发送get请求
     8         HttpGet httpGet = new HttpGet(url);
     9         try {
    10             // add header
    11             if (Objects.nonNull(headers)) {
    12                 Set<String> keys = headers.keySet();
    13                 for (Iterator<String> i = keys.iterator(); i.hasNext(); ) {
    14                     String key = i.next();
    15                     httpGet.addHeader(key, headers.get(key));
    16                 }
    17             }
    18 
    19             httpGet.setConfig(config);
    20             //执行Get请求 得到Response对象
    21             httpResponse = closeHttpClient.execute(httpGet);
    22             //httpResponse.getStatusLine() 响应头信息
    23             int httpResponseCode = httpResponse.getStatusLine().getStatusCode();
    24 
    25             if (200 != httpResponseCode) {
    26                 logger.error("http返回值异常, httpResponseCode = " + httpResponseCode);
    27             }
    28 
    29             //返回对象
    30             HttpEntity httpEntity = httpResponse.getEntity();
    31             ret = EntityUtils.toString(httpEntity, "UTF-8");
    32         } catch (UnsupportedEncodingException e) {
    33             logger.error(e.getMessage(), e);
    34         } catch (ClientProtocolException e) {
    35             logger.error(e.getMessage(), e);
    36         } catch (IOException e) {
    37             //logger.error(e.getMessage(), e);
    38         } finally {
    39             if (httpResponse != null) {
    40                 try {
    41                     httpResponse.close();
    42                 } catch (IOException e) {
    43                     logger.error(e.getMessage(), e);
    44                 }
    45             }
    46             if (closeHttpClient != null) {
    47                 try {
    48                     closeHttpClient.close();
    49                 } catch (IOException e) {
    50                     logger.error(e.getMessage(), e);
    51                 }
    52             }
    53         }
    54         return ret;
    55     }

    第四步,查询数据set进redis,之后返回查询的数据:

     getPanelInfo.java

    1  if (!Objects.equals(redisCache, "false")) {
    2 //redisttl过期时间
    3 redisProxyHandler.set(redisKey, JSON.toJSONString(responseModel), REDIS_TTL); 4 logger.error("set succeed!!!!!!!!!!!!!!!!"); 5 }

     redisHandler.java

    1   public void set(String key, String value, int seconds) {
    2             redisCacheProvider.set(key, value, seconds);
    3     }

     redisProvider.java

     1     @Autowired
     2     private JedisPool jedisPool;
     3 
     4     public Jedis getJedis() {
     5         Jedis jedis = this.jedisPool.getResource();
     6         // 使用index为2的database
     7         jedis.select(2);
     8         return jedis;
     9     }
    10 
    11     public void set(String key, String value, int seconds) {
    12         Jedis jedis = null;
    13         try {
    14             jedis = getJedis();
    15             jedis.setex(key, seconds, value);
    16             Long exp = jedis.ttl(key);
    17             if (exp < 0) {
    18                 throw new RuntimeException("data time out!");19             }
    20         } catch (Throwable e) {
    21             logger.error(e.getMessage(), e);
    22             throw new TokenException(e.getMessage());
    23         } finally {
    24             if(jedis != null){jedis.close;}
    25         }
    26     }

    第五步,请求接口的时候,先请求redis缓存,如果命中则返回命中数据,否则,将执行上面的发送http请求在拼凑数据返回的代码:

    getPanelInfo.java

    1                 String panelInfo = redisProxyHandler.get(redisKey);
    2                 Long expire = redisProxyHandler.getExpire(redisKey);
    3                //命中才返回,否则会去发http请求
    4                 if (Objects.nonNull(panelInfo) && (expire > 0) && expire <REDIS_TTL) {
    5 responseModel = JSON.parseObject(panelInfo, WrapResponseModel.class);
    6 return responseModel;
    7 }

    redisHandler.java

    1    public String get(String key) 
    2             return redisCacheProvider.get(key);
    3    }

    redisProvider.java

     1       public String get(String key) {
     2         String value = null;
     3         Jedis jedis = null;
     4         try {
     5             jedis = getJedis();
     6             value = jedis.get(key);
     7         } catch (Throwable e) {
     8             logger.error(e.getMessage(), e);
     9             throw new TokenException(e.getMessage());
    10         } finally {
    11             if(jedis != null){
    12                 jedis.close();
    13            }
    14         }
    15         return value;
    16     }

     redis相关配置文件如下

    applicationContext.xml

     1  <!-- 读取配置文件信息 -->
     2     <context:property-placeholder location="classpath:redis.properties" file-encoding="UTF-8" ignore-unresolvable="true"/>
     3 
     4     <!-- Jedis 连接池配置 -->
     5     <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
     6         <property name="maxTotal" value="${redis.pool.maxTotal}"/>
     7         <property name="maxIdle" value="${redis.pool.maxIdle}"/>
     8         <property name="maxWaitMillis" value="${redis.pool.maxWaitMillis}"/>
     9         <property name="testOnBorrow" value="${redis.pool.testOnBorrow}"/>
    10     </bean>
    11 
    12     <bean id="jedisPool" class="redis.clients.jedis.JedisPool">
    13         <constructor-arg ref="jedisPoolConfig"/>
    14         <constructor-arg value="${jedis.host}" type="java.lang.String"/>
    15         <constructor-arg type="int" value="${jedis.port}"/>
    16     </bean>

    redis.properties

     1 # 控制一个pool可分配多少个jedis实例
     2 redis.pool.maxTotal=1000
     3 # 控制一个pool最多有多少个状态为idle(空闲)的jedis实例
     4 redis.pool.maxIdle=200
     5 # 表示当borrow一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛出JedisConnectionException
     6 redis.pool.maxWaitMillis=2000
     7 #在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的
     8 redis.pool.testOnBorrow=true
     9 # redis 单机
    10 # 单机 host
    11 jedis.host=127.0.0.1
    12 # 单机 port
    13 jedis.port=6379

    看了上面的代码,我们知道一般的缓存是怎么使用的,在这个案例中,每个redisKey是根据请求的用户名拼接特定的字符串生成的,每个请求用户对应的key只在redis中保存一定的时间,过了指定的过期时间REDIS_TTL,数据将会被清除掉。

  • 相关阅读:
    mvc多级views目录
    JSP中文乱码总结
    sql查询指定表外键约束
    eclipse设置汉化
    c#序列化json字符串及处理
    获取需要登录认证的远程数据
    vs2013 括号自动配对样式设置
    c#中事物使用
    ListView遍历每个Item出现NullPointerException的异常
    gen目录无法更新,或者gen目录下的R.JAVA文件无法生成
  • 原文地址:https://www.cnblogs.com/jy107600/p/8110173.html
Copyright © 2011-2022 走看看