Redis缓存热点数据案例
发布日期:2021-05-09 04:07:19 浏览次数:17 分类:博客文章

本文共 6238 字,大约阅读时间需要 20 分钟。

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

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

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

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

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

 

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

 getPanelInfo.java

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

 

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

 getPanelInfo.java

1   WrapResponseModel resonseModel = new WrapResponseModel(); 2   Map
headers = new HashMap<>(); 3 headers.put("username", username); 4 headers.put("token",token); 5 List
content = new ArrayList
(); 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
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 header11 if (Objects.nonNull(headers)) {12 Set
keys = headers.keySet();13 for (Iterator
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                 //redis过期时间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 

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
3 4
5
6
7
8
9
10
11 12
13
14
15
16

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 # 单机 host11 jedis.host=127.0.0.112 # 单机 port13 jedis.port=6379

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

上一篇:java中自定义注解的应用
下一篇:下拉框表单联动案例

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2025年03月28日 20时55分01秒