为什么要使用redis?有什么意义?
使用redis可以加快页面加载的速度。
在页面一打开的时候,首先去redis中找是否有对应的缓存的内容,要是有的话就直接加载缓存,然后再加载在页面上面,这样就可以加快页面加载的速度,而不用每次加载页面的时候都去数据库进行查询,当数据比较大的时候,那么加载的速度就会很慢。
1 使用redis做缓存。
1.1 在vm中安装redis服务
安装的前提条件:
需要安装 gcc:yum install gcc-c++
- 安装第三方库: yum install epel-release
- 再安装 redis 即可: yum install redis
- 使用 service redis start 命令启动 redis 服务端
- iptables -I INPUT 1 -p tcp --dport 6379 -j ACCEPT
- 使用 ps -ef | grep redis 查看 redis 进程
6. vi /etc/redis.conf 。直接/bind 回车,然后修改为你虚拟机的 ip 地址,不然无法访问。
使用 redis manager 连接:
1.2 通过使用jedis来对redis进行操作。
需要把 jedis 的 jar 包添加到工程中,如果是 maven 需要添加 jar 包的坐标,配置如下:
2.开发过程
2.1 jedis整合spring
<!-- 连接池配置 --> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <!-- 最大连接数 --> <property name="maxTotal" value="30" /> <!-- 最大空闲连接数 --> <property name="maxIdle" value="10" /> <!-- 每次释放连接的最大数目 --> <property name="numTestsPerEvictionRun" value="1024" /> <!-- 释放连接的扫描间隔(毫秒) --> <property name="timeBetweenEvictionRunsMillis" value="30000" /> <!-- 连接最小空闲时间 --> <property name="minEvictableIdleTimeMillis" value="1800000" /> <!-- 连接空闲多久后释放, 当空闲时间>该值 且 空闲连接>最大空闲连接数 时直接释放 --> <property name="softMinEvictableIdleTimeMillis" value="10000" /> <!-- 获取连接时的最大等待毫秒数,小于零:阻塞不确定的时间,默认-1 --> <property name="maxWaitMillis" value="1500" /> <!-- 在获取连接的时候检查有效性, 默认false --> <property name="testOnBorrow" value="true" /> <!-- 在空闲时检查有效性, 默认false --> <property name="testWhileIdle" value="true" /> <!-- 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true --> <property name="blockWhenExhausted" value="false" /> </bean> <!-- jedis客户端单机版 --> <bean id="redisClient" class="redis.clients.jedis.JedisPool"> <constructor-arg name="host" value="192.168.48.129"></constructor-arg> <constructor-arg name="port" value="6379"></constructor-arg> <constructor-arg name="poolConfig" ref="jedisPoolConfig"></constructor-arg> </bean>
测试:
/** * <p>Title: testSpringJedisSingle</p> * <p>Description: </p> */
@Test public void testSpringJedisSingle() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-*.xml"); JedisPool pool = (JedisPool) applicationContext.getBean("redisClient"); Jedis jedis = pool.getResource(); String string = jedis.get("key1"); System.out.println(string); jedis.close(); pool.close();
2.2 添加redis dao
package com.jingxi.rest.dao; public interface JedisClient { String get(String key); String set(String key,String value); String hget(String hkey,String key); long hset(String hkey,String key,String value); long incr(String key); long expire(String key,int second); long ttl(String key); long del(String key); long hdel(String hkey,String key); }
package com.jingxi.rest.dao; import org.springframework.beans.factory.annotation.Autowired; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; public class JedisClientSingle implements JedisClient { @Autowired private JedisPool jedisPool; @Override public String get(String key) { Jedis jedis= jedisPool.getResource(); String string= jedis.get(key); jedis.close(); return string; } @Override public String set(String key, String value) { Jedis jedis= jedisPool.getResource(); String string= jedis.set(key, value); jedis.close(); return string; } @Override public String hget(String hkey, String key) { Jedis jedis= jedisPool.getResource(); String string= jedis.hget(hkey, key); jedis.close(); return string; } @Override public long hset(String hkey, String key, String value) { Jedis jedis= jedisPool.getResource(); Long result= jedis.hset(hkey, key, value); 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 expire(String key, int second) { Jedis jedis= jedisPool.getResource(); Long result= jedis.expire(key, second); 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 del(String key) { Jedis jedis= jedisPool.getResource(); Long result= jedis.del(key); jedis.close(); return result; } @Override public long hdel(String hkey, String key) { Jedis jedis= jedisPool.getResource(); Long result= jedis.hdel(hkey,key); jedis.close(); return result; } }
2.3 在jingxi-rest中的获取内容列表的方法中加入缓存
注意:缓存的添加不能影响正常的业务逻辑。
正常的逻辑应该变成:调用这个方法的时候,首先去缓存中找是否存在缓存内容,如果有的话则直接return 内容。要是没有内容的话,那么就去数据库中进行查找,查找到内容后,先将查找到的内容保存在缓存中,然后再返回查找到的内容。
@Service public class ContentServiceImpl implements ContentService { @Autowired private TbContentMapper tbContentMapper; @Autowired private JedisClient jedisClient; private static final String INDEX_CONTENT_REDIS_KEY="INDEX_CONTENT_REDIS_KEY"; @Override public List<TbContent> getContentList(long contentCid) { //首先是取緩存中取内容 try{ String result=jedisClient.hget(INDEX_CONTENT_REDIS_KEY, contentCid+""); if(result!=null){ List<TbContent> resultList=JsonUtils.jsonToList(result, TbContent.class); return resultList; } }catch(Exception e){ e.printStackTrace(); } //根據内容分類的id查詢内容列表 TbContentExample example =new TbContentExample(); Criteria critria =example.createCriteria(); critria.andCategoryIdEqualTo(contentCid); List<TbContent> list=tbContentMapper.selectByExample(example); //向緩存中添加内容數據 try{ //把list轉換成字符串 String cacheString =JsonUtils.objectToJson(list); jedisClient.hset(INDEX_CONTENT_REDIS_KEY, contentCid+"", cacheString); }catch(Exception e){ e.printStackTrace(); } return list; } }
2.4 运行效果
测试结果:运行之前:
运行之后,缓存成功插入:
首页显示正常:
3.有关缓存同步的内容
3.1 需求分析
当在cms系统中对内容进行增加,修改,删除的时候,那么我们应该删除原本保存在缓存中的内容,这样在页面显示的内容才是最实时的内容,而不会出现说我改后的内容没有在首页展示出来,而是展示修改前的内容。
3.2 添加缓存后的架构
3.3 解决方案
在 jingxi-rest 工程中发布一个服务。当后台管理系统修改内容后,调用此服务,同步缓存。
3.3.1 dao层
3.3.2 service层
3.3.3 controller层
4 在jingxi-backend中调用jingxi-rest的服务
只要在对应的service层中调用这个服务即可
例如添加的方法中: