redis之20分钟轻松搞定springCache缓存(单机+集群)

redis之20分钟轻松搞定springCache缓存(单机+集群)

原文地址:https://m.baidu.com/from=1013843a/bd_page_type=1/ssid=0/uid=0/pu=sz%401321_1002%2Cta%40utouch_2_7.0_2_7.3%2Cusm%401/baiduid=9B4ABF6E3921A8D5A4D61ED28BC57185/w=0_10_/t=wap/l=3/tc?ref=www_utouch&lid=9194807654318041054&order=4&h5ad=0&tj=www_normal_4_0_10_1&vit=osres&m=8&srd=1&title=redis%E4%B9%8B20%E5%88%86%E9%92%9F%E8%BD%BB%E6%9D%BE%E6%90%9E%E5%AE%9AspringCache%E7%BC%93%E5%AD%98%28%E5%8D%95%E6%9C%BA%2B%E9%9B%86%E7%BE%A4%29&dict=32&wd=&eqid=7f9a84d86dab6800100000025ad3605a&w_qd=IlPT2AEptyoA_yiZH5_eIyYtvQbSq-dIoUlZ&tcplug=1&sec=29078&di=5624e693a16782a6&bdenc=1&nsrc=IlPT2AEptyoA_yixCFOxCGZb8c3JV3T5ABSULCRR1z_voo3-efnbFRhdXTqqAp7JZpLPvWL0sakExXyi_WYn7xpCqalhtWkg78XhgPrux14ACBVdv1Ex0tPUDXBu6u4gyKpOtQS

1. redis(单机版)实现spring缓存

redis之20分钟轻松搞定springCache缓存(单机+集群)_第1张图片

1.1. 环境准备

使用maven搭建一套ssm框架,并创建测试类查询emp表。测试代码如下:

/**

* @不开启springCache

*/

publicstaticvoid main(String[] args) {

ApplicationContext ac =new ClassPathXmlApplicationContext("applicationContext.xml");

EmpBiz empBiz=(EmpBiz) ac.getBean("empBizImpl");

Long begin=System.currentTimeMillis();

List empList = empBiz.findAllEmp();

System.out.println("员工数:"+empList.size());

Long end=System.currentTimeMillis();

System.out.println("花费时间:"+(end-begin));

}

结果截图:

redis之20分钟轻松搞定springCache缓存(单机+集群)_第2张图片

1.2. 配置spring缓存

1) 修改配置文件pom.xml

4.3.3.RELEASE

redis.clients

jedis

2.9.0

org.springframework.data

spring-data-redis

1.7.4.RELEASE

2) 修改配置文件applicationContext.xml,扫描service层

3) 添加配置文件spring-redis.xml

4) 创建spring cache接口的实现类SpringRedisCache

/**

* @author TeacherChen

* @description springcache的实现类

* @company AAA软件

* 2018-1-13下午2:07:15

*/

publicclass SpringRedisCache implements Cache {

private RedisTemplate redisTemplate;

private String name;

public RedisTemplate getRedisTemplate() {

return redisTemplate;

}

publicvoid setRedisTemplate(RedisTemplate redisTemplate) {

this.redisTemplate = redisTemplate;

}

publicvoid setName(String name) {

this.name = name;

}

@Override

public String getName() {

// TODO Auto-generated method stub

returnthis.name;

}

@Override

public Object getNativeCache() {

// TODO Auto-generated method stub

returnthis.redisTemplate;

}

@Override

public ValueWrapper get(Object key) {

// TODO Auto-generated method stub

System.out.println("get key");

final String keyf = key.toString();

Object object = null;

object = redisTemplate.execute(new RedisCallback() {

public Object doInRedis(RedisConnection connection)

throws DataAccessException {

byte[] key = keyf.getBytes();

byte[] value = connection.get(key);

if (value == null) {

returnnull;

}

return toObject(value);

}

});

return (object != null ? new SimpleValueWrapper(object) : null);

}

@Override

publicvoid put(Object key, Object value) {

// TODO Auto-generated method stub

System.out.println("put key");

final String keyf = key.toString();

final Object valuef = value;

finallong liveTime = 86400;

redisTemplate.execute(new RedisCallback() {

public Long doInRedis(RedisConnection connection)

throws DataAccessException {

byte[] keyb = keyf.getBytes();

byte[] valueb = toByteArray(valuef);

connection.set(keyb, valueb);

if (liveTime > 0) {

connection.expire(keyb, liveTime);

}

return 1L;

}

});

}

privatebyte[] toByteArray(Object obj) {

byte[] bytes = null;

ByteArrayOutputStream bos = new ByteArrayOutputStream();

try {

ObjectOutputStream oos = new ObjectOutputStream(bos);

oos.writeObject(obj);

oos.flush();

bytes = bos.toByteArray();

oos.close();

bos.close();

} catch (IOException ex) {

ex.printStackTrace();

}

return bytes;

}

private Object toObject(byte[] bytes) {

Object obj = null;

try {

ByteArrayInputStream bis = new ByteArrayInputStream(bytes);

ObjectInputStream ois = new ObjectInputStream(bis);

obj = ois.readObject();

ois.close();

bis.close();

} catch (IOException ex) {

ex.printStackTrace();

} catch (ClassNotFoundException ex) {

ex.printStackTrace();

}

return obj;

}

@Override

publicvoid evict(Object key) {

// TODO Auto-generated method stub

System.out.println("del key");

final String keyf = key.toString();

redisTemplate.execute(new RedisCallback() {

public Long doInRedis(RedisConnection connection)

throws DataAccessException {

return connection.del(keyf.getBytes());

}

});

}

@Override

publicvoid clear() {

// TODO Auto-generated method stub

System.out.println("clear key");

redisTemplate.execute(new RedisCallback() {

public String doInRedis(RedisConnection connection)

throws DataAccessException {

connection.flushDb();

return "ok";

}

});

}

@Override

public T get(Object key, Class type) {

// TODO Auto-generated method stub

returnnull;

5) }

6) 测试类

要在需要缓存的方法或者类上加缓存注解

@Cacheable

/**

* @开启springCache

*/

publicstaticvoid main(String[] args) {

ApplicationContext ac =new ClassPathXmlApplicationContext("applicationContext.xml","spring-redis.xml");

EmpBiz empBiz=(EmpBiz) ac.getBean("empBizImpl");

Long begin=System.currentTimeMillis();

List empList = empBiz.findAllEmp();

System.out.println("员工数:"+empList.size());

Long end=System.currentTimeMillis();

System.out.println("花费时间:"+(end-begin));

}

7) 测试效果

第一次查询

redis之20分钟轻松搞定springCache缓存(单机+集群)_第3张图片

第二次查询

redis之20分钟轻松搞定springCache缓存(单机+集群)_第4张图片

8) spring缓存注解@Cacheable

可以标记在一个方法上,也可以标记在一个类上。当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表示该类所有的方法都是支持缓存的(value key condition)

value属性是必须指定的,其表示当前方法的返回值是会被缓存在哪个Cache上的,对应Cache的名称。其可以是一个Cache也可以是多个Cache,当需要指定多个Cache时其是一个数组。

redis之20分钟轻松搞定springCache缓存(单机+集群)_第5张图片

key属性是用来指定Spring缓存方法的返回结果时对应的key的。该属性支持SpringEL表达式。当我们没有指定该属性时,Spring将使用默认策略生成key。

/**

* 按照员工编号查询员工信息,juan是缓存的名称,#empno是缓存的key,返回值Emp对象是缓存的值

* @param empno

* @return emp

*/

@Override

@Cacheable(value="juan",key="#empno")

public Emp selectByPrimaryKey(Short empno) {

return empMapper.selectByPrimaryKey(empno);

}

condition有的时候我们可能并不希望缓存一个方法所有的返回结果。通过condition属性可以实现这一功能。condition属性默认为空,表示将缓存所有的调用情形。其值是通过SpringEL表达式来指定的,当为true时表示进行缓存处理;当为false时表示不进行缓存处理,即每次调用该方法时该方法都会执行一次。如下示例表示只有当empno为偶数时才会进行缓存。

/**

* 按照员工编号查询员工信息,juan是缓存的名称,#empno是缓存的key,返回值Emp对象是缓存的值

* condition="#empno%2==0"缓存工号为偶数的员工信息,奇数不缓存

* @param empno

* @return emp

*/

@Override

@Cacheable(value="juan",key="#empno",condition="#empno%2==0")

public Emp selectByPrimaryKey(Short empno) {

return empMapper.selectByPrimaryKey(empno);

}

9) spring缓存注解@CacheEvict

是用来标注在需要清除缓存元素的方法或类上的。当标记在一个类上时表示其中所有的方法的执行都会触发缓存的清除操作

/**

* 按照员工编号删除员工,并清除对应的缓存

* @param empno

*/

@Override

@CacheEvict(value="juan",key="#empno")

publicvoid deleteByPrimaryKey(Short empno) {

empMapper.deleteByPrimaryKey(empno);

}

redis之20分钟轻松搞定springCache缓存(单机+集群)_第6张图片
redis之20分钟轻松搞定springCache缓存(单机+集群)_第7张图片

10) spring缓存注解@CachePut

CachePut也可以声明一个方法支持缓存功能。与@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。

/**

* 修改员工信息,并同步更新缓存中的员工信息

* @CachePut不管缓存中有没有,没有的话放入缓存,有的话替换缓存

*/

@Override

@CachePut(value="juan",key="#emp.empno")

public Emp updateByPrimaryKeySelective(Emp emp) {

empMapper.updateByPrimaryKey(emp);

return emp;

}

测试步骤,

首先不加@CachePut(value="juan",key="#emp.empno"),查询一条数据,这条数据自动缓存到redis,然后修改这条数据,再次查询数据库变化,缓存不变,查询的结果不对。

加上@CachePut(value="juan",key="#emp.empno"),再次修改同一条数据,查询发现数据库和缓存同步修改。

2. redis(集群版)实现spring缓存

2.1. 修改配置文件spring-redis.xml

2.2. 测试效果

1) 启动redis集群

redis-server /usr/local/redis_cluster/7001/redis.confredis-server /usr/local/redis_cluster/7002/redis.confredis-server /usr/local/redis_cluster/7003/redis.confredis-server /usr/local/redis_cluster/7004/redis.confredis-server /usr/local/redis_cluster/7005/redis.confredis-server /usr/local/redis_cluster/7006/redis.conf

2) 清空集群中的所有key,要在主节点上操作

使用FLUSHALL命令在所有的主节点

redis之20分钟轻松搞定springCache缓存(单机+集群)_第8张图片

3) 第一次查询

redis之20分钟轻松搞定springCache缓存(单机+集群)_第9张图片

查看redis集群发现缓存已经存在

4) 第二次查询

redis之20分钟轻松搞定springCache缓存(单机+集群)_第10张图片

后记:redis先讲这么多,后面会给大家介绍mysql数据库的主从复制和读写分离,敬请关注。

你可能感兴趣的:(NoSQL,JAVA)