zoukankan      html  css  js  c++  java
  • 完成前台门户页面系统功能(十四)使用redis构建缓存以及缓存同步

    为什么要使用redis?有什么意义?

    使用redis可以加快页面加载的速度。

    在页面一打开的时候,首先去redis中找是否有对应的缓存的内容,要是有的话就直接加载缓存,然后再加载在页面上面,这样就可以加快页面加载的速度,而不用每次加载页面的时候都去数据库进行查询,当数据比较大的时候,那么加载的速度就会很慢。

    1 使用redis做缓存。

    1.1 在vm中安装redis服务

    安装的前提条件:

       需要安装 gcc:yum install gcc-c++

    1. 安装第三方库:  yum install epel-release
    2. 再安装 redis 即可:  yum install redis
    3. 使用 service redis start 命令启动 redis 服务端
    4. iptables -I INPUT 1 -p tcp --dport 6379 -j ACCEPT
    5. 使用 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层中调用这个服务即可

    例如添加的方法中:

  • 相关阅读:
    第四节 哈希类型
    第三节 string类型
    第二节 redis的数据类型和一些通用的键命令
    第一节 Redis的安装配置
    第三十二节 定时器
    第三十一节 sed命令
    第三十节 awk命令
    第二十九节 cut命令
    第二十八节 函数和脚本调试
    Gartner 如何看 RASP 和 WAF?
  • 原文地址:https://www.cnblogs.com/mumudechengzhang/p/7704118.html
Copyright © 2011-2022 走看看