Java项目中使用Redis缓存案例
缓存的目的是为了提高系统的性能,缓存中的数据主要有两种:
1.热点数据。我们将经常访问到的数据放在缓存中,降低数据库I/O,同时因为缓存的数据的高速查询,加快整个系统的响应速度,也在一定程度上提高并发量。
2.查询耗时的数据。如果有一些数据查询十分耗时,那么每次请求这些数据时,都去数据库查询的话,会使得系统响应速度特别低,数据库cpu 100%。将这些数据放缓存,会极大提高系统响应速度,但同时数据实时性较差。
最近工作中有碰到需要使用缓存的情况,场景如下:app端看板统计数据汇总,在打开app时加载看板数据,汇总数据来源于不同的库,各个数据的生成接口已经写好,只需要去调用接口整合数据返回即可。
具体我们来看看是怎么实现的吧。
第一步,取mysql中查询各个接口的信息:
getPanelInfo.java
/* service代码略*/
List<PanelDto> panels = panelService.getAllPanels(); //得到接口的名称,接口的url
第二步,根据拿到的信息生成请求参数:
getPanelInfo.java
WrapResponseModel resonseModel = new WrapResponseModel();
Map<String, String> headers = new HashMap<>();
headers.put("username", username);
headers.put("token",token);
List<String> content = new ArrayList<String>();
for(PanelDto panelDto:panel){
//发送http请求
content.add(HttpRequestUtils.get(panelDto.getUrl(), headers));
}
// 返回格式
responseModel.setCode(SUCCESS_CODE);
responseModel.setData(content);
第三步,发送http请求调用接口:
HttpRequestUtils.java
public static String get(String url, Map<String, String> headers) {
RequestConfig config = RequestConfig.custom().setConnectTimeout(TIME_OUT).setConnectionRequestTimeout(TIME_OUT).setSocketTimeout(TIME_OUT).build();
String ret = null;
//创建HttpClient对象
CloseableHttpClient closeHttpClient = HttpClients.createDefault();
CloseableHttpResponse httpResponse = null;
//发送get请求
HttpGet httpGet = new HttpGet(url);
try {
// add header
if (Objects.nonNull(headers)) {
Set<String> keys = headers.keySet();
for (Iterator<String> i = keys.iterator(); i.hasNext(); ) {
String key = i.next();
httpGet.addHeader(key, headers.get(key));
}
}
httpGet.setConfig(config);
//执行Get请求 得到Response对象
httpResponse = closeHttpClient.execute(httpGet);
//httpResponse.getStatusLine() 响应头信息
int httpResponseCode = httpResponse.getStatusLine().getStatusCode();
if (200 != httpResponseCode) {
logger.error("http返回值异常, httpResponseCode = " + httpResponseCode);
}
//返回对象
HttpEntity httpEntity = httpResponse.getEntity();
ret = EntityUtils.toString(httpEntity, "UTF-8");
} catch (UnsupportedEncodingException e) {
logger.error(e.getMessage(), e);
} catch (ClientProtocolException e) {
logger.error(e.getMessage(), e);
} catch (IOException e) {
//logger.error(e.getMessage(), e);
} finally {
if (httpResponse != null) {
try {
httpResponse.close();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
if (closeHttpClient != null) {
try {
closeHttpClient.close();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
}
return ret;
}
第四步,查询数据set进redis,之后返回查询的数据:
getPanelInfo.java
if (!Objects.equals(redisCache, "false")) {
2 //redisttl过期时间
3 redisProxyHandler.set(redisKey, JSON.toJSONString(responseModel), REDIS_TTL);
4 logger.error("set succeed!!!!!!!!!!!!!!!!");
5 }
redisHandler.java
public void set(String key, String value, int seconds) {
redisCacheProvider.set(key, value, seconds);
}
redisProvider.java
@Autowired
private JedisPool jedisPool; public Jedis getJedis() {
Jedis jedis = this.jedisPool.getResource();
// 使用index为2的database
jedis.select(2);
return jedis;
} public void set(String key, String value, int seconds) {
Jedis jedis = null;
try {
jedis = getJedis();
jedis.setex(key, seconds, value);
Long exp = jedis.ttl(key);
if (exp < 0) {
throw new RuntimeException("data time out!"); }
} catch (Throwable e) {
logger.error(e.getMessage(), e);
throw new TokenException(e.getMessage());
} finally {
if(jedis != null){jedis.close;}
}
}
第五步,请求接口的时候,先请求redis缓存,如果命中则返回命中数据,否则,将执行上面的发送http请求在拼凑数据返回的代码:
getPanelInfo.java
String panelInfo = redisProxyHandler.get(redisKey);
Long expire = redisProxyHandler.getExpire(redisKey);
//命中才返回,否则会去发http请求
if (Objects.nonNull(panelInfo) && (expire > 0) && expire <REDIS_TTL) {
responseModel = JSON.parseObject(panelInfo, WrapResponseModel.class);
6 return responseModel;
7 }
redisHandler.java
public String get(String key)
return redisCacheProvider.get(key);
}
redisProvider.java
public String get(String key) {
String value = null;
Jedis jedis = null;
try {
jedis = getJedis();
value = jedis.get(key);
} catch (Throwable e) {
logger.error(e.getMessage(), e);
throw new TokenException(e.getMessage());
} finally {
if(jedis != null){
jedis.close();
}
}
return value;
}
redis相关配置文件如下
applicationContext.xml
<!-- 读取配置文件信息 -->
<context:property-placeholder location="classpath:redis.properties" file-encoding="UTF-8" ignore-unresolvable="true"/> <!-- Jedis 连接池配置 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="${redis.pool.maxTotal}"/>
<property name="maxIdle" value="${redis.pool.maxIdle}"/>
<property name="maxWaitMillis" value="${redis.pool.maxWaitMillis}"/>
<property name="testOnBorrow" value="${redis.pool.testOnBorrow}"/>
</bean> <bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg ref="jedisPoolConfig"/>
<constructor-arg value="${jedis.host}" type="java.lang.String"/>
<constructor-arg type="int" value="${jedis.port}"/>
</bean>
redis.properties
# 控制一个pool可分配多少个jedis实例
redis.pool.maxTotal=1000
# 控制一个pool最多有多少个状态为idle(空闲)的jedis实例
redis.pool.maxIdle=200
# 表示当borrow一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛出JedisConnectionException
redis.pool.maxWaitMillis=2000
#在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的
redis.pool.testOnBorrow=true
# redis 单机
# 单机 host
jedis.host=127.0.0.1
# 单机 port
jedis.port=6379
看了上面的代码,我们知道一般的缓存是怎么使用的,在这个案例中,每个redisKey是根据请求的用户名拼接特定的字符串生成的,每个请求用户对应的key只在redis中保存一定的时间,过了指定的过期时间REDIS_TTL,数据将会被清除掉。
Java项目中使用Redis缓存案例的更多相关文章
- Redis学习笔记之二 :在Java项目中使用Redis
成功配置redis之后,便来学习使用redis.首先了解下redis的数据类型. Redis的数据类型 Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set( ...
- java项目中,针对缓存问题的处理方式【接口中的处理方式】
1.在service包中,分别建立了关于缓存的一系列的接口.类等,封装到一个工具包中: 临时缓存的接口(代码部分): package com.tools; import java.util.Date; ...
- Redis的安装以及在项目中使用Redis的一些总结和体会
第一部分:为什么我的项目中要使用Redis 我知道有些地方没说到位,希望大神们提出来,我会吸取教训,大家共同进步! 注册时邮件激活的部分使用Redis 发送邮件时使用Redis的消息队列,减轻网站压力 ...
- redis在java项目中的使用
在上一篇文章中已经讲了redis的spring配置,这篇将会描述redis在java项目中的使用. redis存储形式都是key-value(键值对),按照存储的内容分为两种,一种是存简单数据,即数字 ...
- 实战派 | Java项目中玩转Redis6.0客户端缓存!
原创:微信公众号 码农参上,欢迎分享,转载请保留出处. 哈喽大家好啊,我是Hydra. 在前面的文章中,我们介绍了Redis6.0中的新特性客户端缓存client-side caching,通过tel ...
- java项目中ehcache缓存最简单用法
java项目中ehcache缓存最简单用法: 1.下载ehcache-core-2.4.3.jar复制到项目的lib目录下 2.新建ehcache.xml文件,放置在项目src目录下的resour ...
- Spring-Boot项目中配置redis注解缓存
Spring-Boot项目中配置redis注解缓存 在pom中添加redis缓存支持依赖 <dependency> <groupId>org.springframework.b ...
- Django项目中使用Redis
Django项目中使用Redis DjangoRedis 1 redis Redis 是一个 key-value 存储系统,常用于缓存的存储.django-redis 基于 BSD 许可, 是一个使 ...
- eclipse java项目中明明引入了jar包 为什么项目启动的时候不能找到jar包 项目中已经 引入了 com.branchitech.app 包 ,但时tomcat启动的时候还是报错? java.lang.ClassNotFoundException: com.branchitech.app.startup.AppStartupContextListener java.lang.ClassN
eclipse java项目中明明引入了jar包 为什么项目启动的时候不能找到jar包 项目中已经 引入了 com.branchitech.app 包 ,但时tomcat启动的时候还是报错?java. ...
随机推荐
- C# 使用正则表达式去掉字符串中的数字
/// <summary>/// 去掉字符串中的数字/// </summary>/// <param name="key"></param ...
- 比较DataTable中新旧数据
内容不写了,代码上都做了写注释. 1 /**//// <summary> 2 /// 比较两个数据表,并返回比较结果表 3 /// 比较条件: 4 ...
- window下安装Apache+PHP
本地系统为windows 10,Apache选择httpd-2.4.25-x64-vc14-r1,PHP选择php7.1_x64线程安全版. 1.安装Apache 将apache解压到c:/serve ...
- 用JAVA中BufferedImage画出漂亮的验证码点击变化
如果我们想用JAVA中BufferedImage画出漂亮的验证码点击变化怎么实现呢,类似这样: 点击变化,以下是实现过程,直接上代码: 首先前台:<i><img style=&quo ...
- JS 三目运算符和RETURN
以前写的博客,现在搬过来 首先三目运算符和return的正确用法是这样的: (function test(){ var foo = []; return typeof foo === 'object' ...
- 已知前序(后序)遍历序列和中序遍历序列构建二叉树(Leetcode相关题目)
1.文字描述: 已知一颗二叉树的前序(后序)遍历序列和中序遍历序列,如何构建这棵二叉树? 以前序为例子: 前序遍历序列:ABCDEF 中序遍历序列:CBDAEF 前序遍历先访问根节点,因此前序遍历序列 ...
- 邻里街坊 golang入坑系列
如果要追新或者怀旧,就点击https://andy-zhangtao.gitbooks.io/golang/content/ . 博客园里面的文章基本和gitbook上面是保持同步的. 这几天看了几集 ...
- 【SSM之旅】Spring+SpringMVC+MyBatis+Bootstrap整合基础篇(一)项目简介及技术选型相关介绍
试水 一直想去搭建个自己的个人博客,苦于自己的技术有限,然后也个人也比较懒散.想动而不能动,想动而懒得动,就这么一直拖到了现在.总觉得应该把这几年来的所学总结一番,这样才能有所成长. 不知在何时,那就 ...
- Play-With-Docker在chrome上的插件
一键使用PWD 在chrome扩展中,找到"Play With Docker"插件,并安装在chrome浏览器中 进入hub.docker.com网站,搜索熟悉的docker镜像. ...
- poj2524 解题报告
基于并查集的一道简单题目 Ubiquitous Religions Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 22334 ...