第04項目:淘淘商城(SpringMVC+Spring+Mybatis)【第七天】(redis緩存)

https://pan.baidu.com/s/1bptYGAb#list/path=%2F&parentPath=%2Fsharelink389619878-229862621083040html

第04項目:淘淘商城(SpringMVC+Spring+Mybatis) 的學習實踐總結【第五天】java

第04項目:淘淘商城(SpringMVC+Spring+Mybatis) 的學習實踐總結【第六天】node

第04項目:淘淘商城(SpringMVC+Spring+Mybatis)【第七天】(redis緩存)redis

第04項目:淘淘商城(SpringMVC+Spring+Mybatis)【第八天】(solr服務器搭建、搜索功能實現)spring

第04項目:淘淘商城(SpringMVC+Spring+Mybatis)【第七天】(redis緩存)


 課程計劃:數據庫

一、內容管理功能添加緩存。json

a)       使用redis作緩存工具緩存

b)       實現系統高可用,redis須要作主備。使用redis作分片集羣。Redis集羣的搭建。ruby

c)       向業務邏輯中添加緩存。服務器

2.1    訪問taotao-portal服務406問題

一、查看是否Jackson包是否存在。

二、若是後綴是html是不能響應json數據的。須要修改後綴名。

2.2    Post亂碼問題

produces=MediaType.TEXT_PLAIN_VALUE+";charset=utf-8"

 


 

使用redis作緩存安裝的步驟詳情見點擊跳轉

Redis 簡介

Redis 是徹底開源免費的,是一個高性能的key-value數據庫。

Redis 與其餘 key - value 緩存產品有如下三個特色:

  • Redis支持數據的持久化,能夠將內存中的數據保存在磁盤中,重啓的時候能夠再次加載進行使用。
  • Redis不單單支持簡單的key-value類型的數據,同時還提供list,set,zset,hash等數據結構的存儲。
  • Redis支持數據的備份,即master-slave模式的數據備份。

 


 

2.7.3   Jedis客戶端

使用前先引入依賴座標

版本能夠選用3.1.0

            <!-- Redis客戶端 -->
            <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
                <version>${jedis.version}</version>
            </dependency>

 

RedisDesktopManager的使用注意事項:

第一步:在redis的配置文件(redis.conf)裏面是否設置了requirepass  表示鏈接的密碼,若是沒有設置,則鏈接不上。或者關閉保護模式。

第二步:在redis的配置文件裏面,在第69行左右是要已經把bind 127.0.0.1 給註釋掉。若是沒有,鏈接不上,。

 

package com.taotao.rest.jedis;

import java.util.HashSet;

import org.junit.Test;

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPool;

public class JedisTest {
    @Test
    public void testJedisSingle() {
        //建立一個jedis的對象
        Jedis jedis = new Jedis("192.168.179.128",6379);
        jedis.auth("12345678");
        //調用jedis對象的方法,方法名稱和redis的命令一致
        jedis.set("key1", "testJedisSingle");
        String string = jedis.get("key1");
        System.out.println(string);
        //關閉jedis
        jedis.close();        
    }
    
    /**
     * 使用鏈接池
     */
    @Test
    public void testJedisPool() {
        //建立jedis鏈接池
        JedisPool pool = new JedisPool("192.168.179.128", 6379);
        //從鏈接池中得到Jedis對象
        Jedis jedis = pool.getResource();
        jedis.auth("12345678");
        String string = jedis.get("key1");
        System.out.println(string);
        //關閉jedis對象
        jedis.close();
        pool.close();
    }
    
    //測試集羣redis
    @Test
    public void testJedisCluster() throws Exception {
        HashSet<HostAndPort> nodes = new HashSet<>();
        nodes.add(new HostAndPort("192.168.179.128", 7001));
        nodes.add(new HostAndPort("192.168.179.128", 7002));
        nodes.add(new HostAndPort("192.168.179.128", 7003));
        nodes.add(new HostAndPort("192.168.179.128", 7004));
        nodes.add(new HostAndPort("192.168.179.128", 7005));
        nodes.add(new HostAndPort("192.168.179.128", 7006));
        
        JedisCluster cluster = new JedisCluster(nodes);
        cluster.set("key2", "kang");
        
        String string = cluster.get("key2");
        System.out.println(string);
        
        cluster.close();
    }


}
View Code JedisTest

 

利用spring的IOC自動注入jedis的bean(參考資料:redis設置密碼以及jedisPool設置密碼

redis.properties

#redis單機版JedisPool配置信息
redis.hostName=192.168.179.128
redis.port=6379
redis.timeout=60
redis.password=12345678
View Code

application-jedis.xml

<?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.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">

    <!-- 加載屬性文件 -->
    <context:property-placeholder location="classpath:redis.properties" ignore-unresolvable="true" />
    <!-- 鏈接池配置 -->
    <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="jedisPool" class="redis.clients.jedis.JedisPool">
        <constructor-arg name="poolConfig"
            ref="jedisPoolConfig"></constructor-arg>
        <constructor-arg name="host" value="${redis.hostName}"></constructor-arg>
        <constructor-arg name="port" value="${redis.port}"></constructor-arg>
        <constructor-arg name="timeout" value="${redis.timeout}" type="int"/>
        <constructor-arg name="password" value="${redis.password}"></constructor-arg>    
    </bean>

    <bean id="jedisClientSingle"
        class="com.taotao.rest.dao.impl.JedisClientSingle"/>

    <!-- jedis集羣版配置 -->
<!--     <bean id="redisClient" class="redis.clients.jedis.JedisCluster">
        <constructor-arg name="nodes">
            <set>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host"
                        value="192.168.179.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.179.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.179.128"></constructor-arg>
                    <constructor-arg name="port" value="7003"></constructor-arg>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host"
                        value="192.168.179.128"></constructor-arg>
                    <constructor-arg name="port" value="7004"></constructor-arg>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host"
                        value="192.168.179.128"></constructor-arg>
                    <constructor-arg name="port" value="7005"></constructor-arg>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host"
                        value="192.168.179.128"></constructor-arg>
                    <constructor-arg name="port" value="7006"></constructor-arg>
                </bean>
            </set>
        </constructor-arg>

        <constructor-arg name="poolConfig"
            ref="jedisPoolConfig"></constructor-arg>
    </bean>

    <bean id="jedisClientCluster"
        class="com.taotao.rest.dao.impl.JedisClientCluster" /> -->



</beans>
View Code

 

測試類的test方法

    @Test
    public void testSpringJedisCluster() throws IOException {
        //1.獲取spring的IOC容器對象
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
                "classpath:spring/applicationContext-*.xml");
        //2.從IOC容器對象中取出bean的id爲jedisCluster的那個
        JedisCluster jedisCluster = (JedisCluster) applicationContext.getBean("redisClient");

        jedisCluster.set("name", "kang");
        String value = jedisCluster.get("name");
        System.out.println(value); //console打印出kang就測試經過
        
        /* 最後要關閉jedis客戶端 */
        jedisCluster.close();
    }

 


 /taotao-rest/src/main/java/com/taotao/rest/dao/JedisClient.java

package com.taotao.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.taotao.rest.dao.impl;

import org.springframework.beans.factory.annotation.Autowired;

import com.taotao.rest.dao.JedisClient;

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;
    }
  

/taotao-rest/src/main/java/com/taotao/rest/dao/impl/JedisClientSingle.java

package com.taotao.rest.dao.impl;

import org.springframework.beans.factory.annotation.Autowired;

import com.taotao.rest.dao.JedisClient;

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;
    }
    
}
View Code

/taotao-rest/src/main/java/com/taotao/rest/dao/impl/JedisClientCluster.java

package com.taotao.rest.dao.impl;

import org.springframework.beans.factory.annotation.Autowired;

import com.taotao.rest.dao.JedisClient;

import redis.clients.jedis.JedisCluster;

public class JedisClientCluster implements JedisClient {

    @Autowired
    private JedisCluster jedisCluster;
    
    @Override
    public String get(String key) {
        return jedisCluster.get(key);
    }

    @Override
    public String set(String key, String value) {
        return jedisCluster.set(key, value);
    }

    @Override
    public String hget(String hkey, String key) {
        return jedisCluster.hget(hkey, key);
    }

    @Override
    public long hset(String hkey, String key, String value) {
        return jedisCluster.hset(hkey, key, value);
    }

    @Override
    public long incr(String key) {
        return jedisCluster.incr(key);
    }

    @Override
    public long expire(String key, int second) {
        return jedisCluster.expire(key, second);
    }

    @Override
    public long ttl(String key) {
        return jedisCluster.ttl(key);
    }

    @Override
    public long del(String key) {
        return jedisCluster.del(key);
    }
    
    @Override
    public long hdel(String hkey,String key) {
        return jedisCluster.hdel(hkey,key);
    }

}
View Code
package com.taotao.rest.dao.impl;

import org.springframework.beans.factory.annotation.Autowired;

import com.taotao.rest.dao.JedisClient;

import redis.clients.jedis.JedisCluster;

public class JedisClientCluster implements JedisClient {

    @Autowired
    private JedisCluster jedisCluster;
    
    @Override
    public String get(String key) {
        return jedisCluster.get(key);
    }

    @Override
    public String set(String key, String value) {
        return jedisCluster.set(key, value);
    }

    @Override
    public String hget(String hkey, String key) {
        return jedisCluster.hget(hkey, key);
    }

    @Override
    public long hset(String hkey, String key, String value) {
        return jedisCluster.hset(hkey, key, value);
    }

    @Override
    public long incr(String key) {
        return jedisCluster.incr(key);
    }

    @Override
    public long expire(String key, int second) {
        return jedisCluster.expire(key, second);
    }

    @Override
    public long ttl(String key) {
        return jedisCluster.ttl(key);
    }

    @Override
    public long del(String key) {
        return jedisCluster.del(key)

5.3    把緩存添加到業務邏輯

注意:緩存的添加不能影響正常的業務邏輯。

/**
 * 內容管理
 * @author kangy
 *
 */
@Service
public class ContentServiceImpl implements ContentService {
    @Autowired
    private TbContentMapper contentMapper;
    //在XML配置文件中注入了bean
    @Autowired
    private JedisClient JedisClient;
    //從.properties文件讀取常量
    @Value("${INDEX_CONTENT_REDIS_KEY}")
    private String INDEX_CONTENT_REDIS_KEY;

    @Override
    public List<TbContent> getContentList(long contentCid) {
        
        
        //b從緩存中取內容
        try {
            String result = JedisClient.hget(INDEX_CONTENT_REDIS_KEY, contentCid + "");
            if (!StringUtils.isBlank(result)) {
                //把字符串轉換成list
                List<TbContent> resultList = JsonUtils.jsonToList(result, TbContent.class);
                return resultList;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        
        //a根據內容分類id查詢內容列表
        TbContentExample example = new TbContentExample();
        TbContentExample.Criteria criteria = example.createCriteria();
        criteria.andCategoryIdEqualTo(contentCid);
        //a執行查詢
        List<TbContent> list = contentMapper.selectByExampleWithBLOBs(example);

        
        //b向緩存中添加內容
        try {
            //把list轉換成字符串
            String cacheString = JsonUtils.objectToJson(list);
            JedisClient.hset(INDEX_CONTENT_REDIS_KEY, contentCid + "", cacheString);
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        //a返回結果
        return list;
    }

}
View Code
 打開win10下的圖形化鏈接redis的工具軟件查看是否成功地添加了商品信息內容的緩存到默認的database0

課後做業:商品類目展現添加緩存

 


6 緩存同步

當後臺管理系統,修改內容以後須要通知redis把修改的內容對應的分類id的key刪除。

6.1    添加緩存後的系統架構

6.2    解決方案

在taotao-rest工程中發佈一個服務。當後臺管理系統修改內容後,調用此服務,同步緩存。

6.3    Dao層

使用JedisClient接口對應的實現類。

6.4    Service層

接收內容分類id,調用dao刪除redis中對應的hash中key爲分類id的項。

參數:內容分類id

返回值:TaotaoResult

com.taotao.rest.service.impl.RedisServiceImpl

package com.taotao.rest.service.impl;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.taotao.common.pojo.TaotaoResult;
import com.taotao.common.utils.ExceptionUtil;
import com.taotao.rest.dao.JedisClient;
import com.taotao.rest.service.RedisService;

@Service
public class RedisServiceImpl implements RedisService {
    
    @Autowired
    private JedisClient jedisClient;
    //從.properties文件讀取常量
    @Value("${INDEX_CONTENT_REDIS_KEY}")
    private String INDEX_CONTENT_REDIS_KEY;
    
    
    @Override
    public TaotaoResult syncContent(long contentCid) {
        try {
            jedisClient.hdel(INDEX_CONTENT_REDIS_KEY, contentCid + "");
        } catch (Exception e) {
            e.printStackTrace();
            return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
        }

        return TaotaoResult.ok();
    }

}
View Code

6.5  Controller層

接收內容分類id,調用Service返回taotaoResult。

com.taotao.rest.controller.RedisController

@RestController
@RequestMapping("/cache/sync")
public class RedisController {
    @Autowired
    private RedisService redisService;

    @RequestMapping("/content/{contentCid}")
    public TaotaoResult contentCacheSync(@PathVariable Long contentCid) {
        TaotaoResult result = redisService.syncContent(contentCid);
        return result;
    }

}
View Code

http://localhost:8081/rest/cache/sync/content/89

 

6.6 同步緩存服務的調用

須要在後臺管理系統中添加一個服務調用的邏輯。當修改內容信息後,須要調用此服務同步緩存。

 

com.taotao.service.impl.ContentServiceImpl

//內容管理
@Service
public class ContentServiceImpl implements ContentService {
    
    @Value("${REST_BASE_URL}")
    private String REST_BASE_URL;
    @Value("REST_CONTENT_SYNC_URL")
    private String REST_CONTENT_SYNC_URL;
    
    @Autowired
    private TbContentMapper contentMapper;
    
    @Override
    public TaotaoResult insertContent(TbContent content) {
        // 補全pojo內容
        content.setCreated(new Date());
        content.setUpdated(new Date());
        contentMapper.insert(content);

        // 添加緩存同步邏輯
        try {
            HttpClientUtil.doGet(REST_BASE_URL + REST_CONTENT_SYNC_URL + content.getCategoryId());
        } catch (Exception e) {
            // 通知管理員處理異常
            e.printStackTrace();
        }

        return TaotaoResult.ok();
    }

 

=======================================

參考資料:

redis 安裝及集羣部署

redis學習筆記(二)JedisCluster + redis 3.2.5集羣

redis-4.0.14.gem集羣建立用到的腳本 下載地址

Redis免費客戶端 Another Redis DeskTop Manager 下載地址

RedisDesktopManager鏈接不上redis的解決方法

redis.clients. NOAUTH Authentication required 解決辦法

end

相關文章
相關標籤/搜索