需求:
商城首页广告位的广告,更新不算频繁,但是用户经常从首页访问进来,查询操作比较频繁。如果将广告位信息加入到缓存中使用redis进行存储,就可以提高性能,增加用户的体验度。
使用步骤:
- 1.引用jedisjar
- 2.编写工具类JedisClient和两个具体的实现单机版和集群版
- 3.spring整合redis
- 4.向业务中加入缓存
- 5.缓存同步
代码实现:
1.引入jar包,版本在聚合工程中统一管理了
<!-- Redis客户端 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
2.接口声明,两个实现类
接口:
package cn.e3mall.common.jedis;
import java.util.List;
public interface JedisClient {
String set(String key, String value);
String get(String key);
Boolean exists(String key);
Long expire(String key, int seconds);
Long ttl(String key);
Long incr(String key);
Long hset(String key, String field, String value);
String hget(String key, String field);
Long hdel(String key, String... field);
Boolean hexists(String key, String field);
List<String> hvals(String key);
Long del(String key);
}
package cn.e3mall.common.jedis;
import java.util.List;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
public class JedisClientPool implements JedisClient {
private JedisPool jedisPool;
public JedisPool getJedisPool() {
return jedisPool;
}
public void setJedisPool(JedisPool jedisPool) {
this.jedisPool = jedisPool;
}
@Override
public String set(String key, String value) {
Jedis jedis = jedisPool.getResource();
String result = jedis.set(key, value);
jedis.close();
return result;
}
@Override
public String get(String key) {
Jedis jedis = jedisPool.getResource();
String result = jedis.get(key);
jedis.close();
return result;
}
@Override
public Boolean exists(String key) {
Jedis jedis = jedisPool.getResource();
Boolean result = jedis.exists(key);
jedis.close();
return result;
}
@Override
public Long expire(String key, int seconds) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.expire(key, seconds);
jedis.close();
return result;
}
@Override
public Long ttl(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.ttl(key);
jedis.close();
return result;
}
@Override
public Long incr(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.incr(key);
jedis.close();
return result;
}
@Override
public Long hset(String key, String field, String value) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.hset(key, field, value);
jedis.close();
return result;
}
@Override
public String hget(String key, String field) {
Jedis jedis = jedisPool.getResource();
String result = jedis.hget(key, field);
jedis.close();
return result;
}
@Override
public Long hdel(String key, String... field) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.hdel(key, field);
jedis.close();
return result;
}
@Override
public Boolean hexists(String key, String field) {
Jedis jedis = jedisPool.getResource();
Boolean result = jedis.hexists(key, field);
jedis.close();
return result;
}
@Override
public List<String> hvals(String key) {
Jedis jedis = jedisPool.getResource();
List<String> result = jedis.hvals(key);
jedis.close();
return result;
}
@Override
public Long del(String key) {
Jedis jedis = jedisPool.getResource();
Long result = jedis.del(key);
jedis.close();
return result;
}
}
集群版:
package cn.e3mall.common.jedis;
import java.util.List;
import redis.clients.jedis.JedisCluster;
public class JedisClientCluster implements JedisClient {
private JedisCluster jedisCluster;
public JedisCluster getJedisCluster() {
return jedisCluster;
}
public void setJedisCluster(JedisCluster jedisCluster) {
this.jedisCluster = jedisCluster;
}
@Override
public String set(String key, String value) {
return jedisCluster.set(key, value);
}
@Override
public String get(String key) {
return jedisCluster.get(key);
}
@Override
public Boolean exists(String key) {
return jedisCluster.exists(key);
}
@Override
public Long expire(String key, int seconds) {
return jedisCluster.expire(key, seconds);
}
@Override
public Long ttl(String key) {
return jedisCluster.ttl(key);
}
@Override
public Long incr(String key) {
return jedisCluster.incr(key);
}
@Override
public Long hset(String key, String field, String value) {
return jedisCluster.hset(key, field, value);
}
@Override
public String hget(String key, String field) {
return jedisCluster.hget(key, field);
}
@Override
public Long hdel(String key, String... field) {
return jedisCluster.hdel(key, field);
}
@Override
public Boolean hexists(String key, String field) {
return jedisCluster.hexists(key, field);
}
@Override
public List<String> hvals(String key) {
return jedisCluster.hvals(key);
}
@Override
public Long del(String key) {
return jedisCluster.del(key);
}
}
3.spring的xml配置文件中装配jedis对象
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
<!-- 连接redis单机版 -->
<bean id="jedisClientPool" class="cn.e3mall.common.jedis.JedisClientPool">
<property name="jedisPool" ref="jedisPool"></property>
</bean>
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg name="host" value="192.168.139.128"/>
<constructor-arg name="port" value="6379"/>
</bean>
<!-- 连接redis集群 -->
<!-- <bean id="jedisClientCluster" class="cn.e3mall.common.jedis.JedisClientCluster"> -->
<!-- <property name="jedisCluster" ref="jedisCluster"/> -->
<!-- </bean> -->
<!-- <bean id="jedisCluster" class="redis.clients.jedis.JedisCluster"> -->
<!-- <constructor-arg name="nodes"> -->
<!-- <set> -->
<!-- <bean class="redis.clients.jedis.HostAndPort"> -->
<!-- <constructor-arg name="host" value="192.168.139.128"></constructor-arg> -->
<!-- <constructor-arg name="port" value="7001"></constructor-arg> -->
<!-- </bean> -->
<!-- <bean class="redis.clients.jedis.HostAndPort"> -->
<!-- <constructor-arg name="host" value="192.168.139.128"></constructor-arg> -->
<!-- <constructor-arg name="port" value="7002"></constructor-arg> -->
<!-- </bean> -->
<!-- <bean class="redis.clients.jedis.HostAndPort"> -->
<!-- <constructor-arg name="host" value="192.168.139.128"></constructor-arg> -->
<!-- <constructor-arg name="port" value="7003"></constructor-arg> -->
<!-- </bean> -->
<!-- </set> -->
<!-- </constructor-arg> -->
<!-- </bean> -->
</beans>
4.向业务中加入缓存
具体代码的思路:
1、查询数据库之前先查询缓存。
2、查询到结果,直接响应结果。
3、查询不到,缓存中没有需要查询数据库。
4、把查询结果添加到缓存中。
5、返回结果。
@Override
public List<TbContent> getContentListByCid(long cid) {
//查询缓存
String jsonString=jedisClient.hget(CONTENT_LIST, cid+"");
try {
if (StringUtils.isNotBlank(jsonString)) {
//如果缓存中有直接响应结果
List<TbContent> list=JsonUtils.jsonToList(jsonString, TbContent.class);
return list;
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//如果没有查询数据库
TbContentExample example=new TbContentExample();
Criteria criteria=example.createCriteria();
criteria.andCategoryIdEqualTo(cid);
List<TbContent> list=contentMapper.selectByExampleWithBLOBs(example);
try {
//将数据添加到redis中
jedisClient.hset(CONTENT_LIST, cid+"", JsonUtils.objectToJson(list));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return list;
}
5.缓存同步,在发生修改和删除的时候,将缓存内容删除。
@Value("${CONTENT_LIST}")
private String CONTENT_LIST;
@Override
public E3Result addContent(TbContent content) {
//将内容数据插入到内容表
content.setCreated(new Date());
content.setUpdated(new Date());
//插入到数据库
contentMapper.insert(content);
//删除缓存中的数据
jedisClient.hdel(CONTENT_LIST, content.getCategoryId().toString());
return E3Result.ok();
}
总结:
相对于Memcached来说,redis的数据类型更多。同时,redis支持持久化,可以将数据保存到硬盘中。memcached只能保存到内存中,如果出现宕机的意外,数据就丢掉了。在电商项目中,一些商品信息用户信息适合放到缓存中,但是订单信息这样需要及时反馈,及时更新的。就不适合了。