ssm項目_06_redis的持久化和集群

1. Redis的安裝和連接

1.1 redis的安裝

Redis是c語言開發(fā)的。
安裝redis需要c語言的編譯環(huán)境。如果沒有g(shù)cc需要在線安裝。yum install gcc-c++

安裝步驟:
第一步:redis的源碼包上傳到linux系統(tǒng)。
第二步:解壓縮redis。
第三步:編譯。進入redis源碼目錄。make
第四步:安裝。make install PREFIX=/usr/local/redis
PREFIX參數(shù)指定redis的安裝目錄。一般軟件安裝到/usr目錄下

1.2 連接redis

redis的啟動:
前端啟動:在redis的安裝目錄下直接啟動redis-server
[root@localhost bin]# ./redis-server

后臺啟動:
把/root/redis-3.0.0/redis.conf復(fù)制到/usr/local/redis/bin目錄下
[root@localhost redis-3.0.0]# cp redis.conf /usr/local/redis/bin/
修改配置文件:

Snip20180926_3.png

[root@localhost bin]# ./redis-server redis.conf
查看redis進程:
[root@localhost bin]# ps aux|grep redis
root 5190 0.1 0.3 33936 1712 ? Ssl 18:23 0:00 ./redis-server *:6379
root 5196 0.0 0.1 4356 728 pts/0 S+ 18:24 0:00 grep redis

[root@localhost bin]# ./redis-cli
默認連接localhost運行在6379端口的redis服務(wù)。
[root@localhost bin]# ./redis-cli -h 192.168.25.153 -p 6379
-h:連接的服務(wù)器的地址
-p:服務(wù)的端口號

2.Redis五種數(shù)據(jù)類型

String:key-value(做緩存)
Redis中所有的數(shù)據(jù)都是字符串。命令不區(qū)分大小寫,key是區(qū)分大小寫的。Redis是單線程的。Redis中不適合保存內(nèi)容大的數(shù)據(jù)。
get、set、
incr:加一(生成id)
Decr:減一

Hash:key-fields-values(做緩存)
相當(dāng)于一個key對應(yīng)一個map,map中還有key-value
使用hash對key進行歸類。

Hset:向hash中添加內(nèi)容
hash1是key,1是值
192.168.25.153:6379>hset hash1 field1 1
192.168.25.153:6379>hset hash1 field2 2
192.168.25.153:6379>hset hash1 field3 a
192.168.25.153:6379>hset hash1 field4 b

查看hashi1這個key中有多少個key
192.168.25.153:6379>hkeys hash1

查看hashi1這個對應(yīng)的map中有多少個值
192.168.25.153:6379>hvals hash1

查看全部
192.168.25.153:6379>hgetall hash1

刪除hash1這個key對應(yīng)的map中的某個值
192.168.25.153:6379>hdel hash1 field3

Hget:從hash中取內(nèi)容
192.168.25.153:6379>hget hash1 field1

List:有順序可重復(fù)
192.168.25.153:6379> lpush list1 a b c d
(integer) 4
192.168.25.153:6379> lrange list1 0 -1

  1. "d"
  2. "c"
  3. "b"
  4. "a"
    192.168.25.153:6379> rpush list1 1 2 3 4
    (integer) 8
    192.168.25.153:6379> lrange list1 0 -1
  5. "d"
  6. "c"
  7. "b"
  8. "a"
  9. "1"
  10. "2"
  11. "3"
  12. "4"
    192.168.25.153:6379>
    192.168.25.153:6379> lpop list1
    "d"
    192.168.25.153:6379> lrange list1 0 -1
  13. "c"
  14. "b"
  15. "a"
  16. "1"
  17. "2"
  18. "3"
  19. "4"
    192.168.25.153:6379> rpop list1
    "4"
    192.168.25.153:6379> lrange list1 0 -1
  20. "c"
  21. "b"
  22. "a"
  23. "1"
  24. "2"
  25. "3"

3. Key命令

設(shè)置key的過期時間。
Expire key second:設(shè)置key的過期時間
Ttl key:查看key的有效期
Persist key:清除key的過期時間。Key持久化。

192.168.25.153:6379> expire Hello 100
(integer) 1
192.168.25.153:6379> ttl Hello
(integer) 77

4. Redis的持久化方案

Redis的所有數(shù)據(jù)都是保存到內(nèi)存中的。
Rdb:快照形式,定期把內(nèi)存中當(dāng)前時刻的數(shù)據(jù)保存到磁盤。Redis默認支持的持久化方案。
aof形式:append only file。把所有對redis數(shù)據(jù)庫操作的命令,增刪改操作的命令。保存到文件中。數(shù)據(jù)庫恢復(fù)時把所有的命令執(zhí)行一遍即可。

在redis.conf配置文件中配置。

Rdb:

Snip20180926_5.png

Aof的配置:


Snip20180926_7.png

兩種持久化方案同時開啟使用aof文件來恢復(fù)數(shù)據(jù)庫。

5. Redis集群的搭建

5.1 redis-cluster架構(gòu)圖
Snip20180926_8.png
Snip20180926_9.png

架構(gòu)細節(jié):
(1)所有的redis節(jié)點彼此互聯(lián)(PING-PONG機制),內(nèi)部使用二進制協(xié)議優(yōu)化傳輸速度和帶寬.
(2)節(jié)點的fail是通過集群中超過半數(shù)的節(jié)點檢測失效時才生效.
(3)客戶端與redis節(jié)點直連,不需要中間proxy層.客戶端不需要連接集群所有節(jié)點,連接集群中任何一個可用節(jié)點即可
(4)redis-cluster把所有的物理節(jié)點映射到[0-16383]slot上,cluster 負責(zé)維護node<->slot<->value
Redis 集群中內(nèi)置了 16384 個哈希槽,當(dāng)需要在 Redis 集群中放置一個 key-value 時,redis 先對 key 使用 crc16 算法算出一個結(jié)果,然后把結(jié)果對 16384 求余數(shù),這樣每個 key 都會對應(yīng)一個編號在 0-16383 之間的哈希槽,redis 會根據(jù)節(jié)點數(shù)量大致均等的將哈希槽映射到不同的節(jié)點

Snip20180926_10.png
5.2. Redis集群的搭建

Redis集群中至少應(yīng)該有三個節(jié)點。要保證集群的高可用,需要每個節(jié)點有一個備份機。
Redis集群至少需要6臺服務(wù)器。
搭建偽分布式。可以使用一臺虛擬機運行6個redis實例。需要修改redis的端口號7001-7006

1、使用ruby腳本搭建集群。需要ruby的運行環(huán)境。
安裝ruby
yum install ruby
yum install rubygems

2、安裝ruby腳本運行使用的包。
[root@localhost ~]# gem install redis-3.0.0.gem
Successfully installed redis-3.0.0
1 gem installed
Installing ri documentation for redis-3.0.0...
Installing RDoc documentation for redis-3.0.0...
[root@localhost ~]#

[root@localhost ~]# cd redis-3.0.0/src
[root@localhost src]# ll *.rb
-rwxrwxr-x. 1 root root 48141 Apr 1 2015 redis-trib.rb

5.3搭建步驟

需要6臺redis服務(wù)器。搭建偽分布式。
需要6個redis實例。
需要運行在不同的端口7001-7006

第一步:創(chuàng)建6個redis實例,每個實例運行在不同的端口。需要修改redis.conf配置文件。配置文件中還需要把cluster-enabled yes前的注釋去掉。

Snip20180926_11.png

第二步:啟動每個redis實例。
第三步:使用ruby腳本搭建集群。

./redis-trib.rb create --replicas 1 192.168.25.153:7001 192.168.25.153:7002 192.168.25.153:7003 192.168.25.153:7004 192.168.25.153:7005 192.168.25.153:7006
[root@localhost redis-cluster]# ./redis-trib.rb create --replicas 1 192.168.25.153:7001 192.168.25.153:7002 192.168.25.153:7003 192.168.25.153:7004 192.168.25.153:7005  192.168.25.153:7006
>>> Creating cluster
Connecting to node 192.168.25.153:7001: OK
Connecting to node 192.168.25.153:7002: OK
Connecting to node 192.168.25.153:7003: OK
Connecting to node 192.168.25.153:7004: OK
Connecting to node 192.168.25.153:7005: OK
Connecting to node 192.168.25.153:7006: OK
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
192.168.25.153:7001
192.168.25.153:7002
192.168.25.153:7003
Adding replica 192.168.25.153:7004 to 192.168.25.153:7001
Adding replica 192.168.25.153:7005 to 192.168.25.153:7002
Adding replica 192.168.25.153:7006 to 192.168.25.153:7003
M: 2e48ae301e9c32b04a7d4d92e15e98e78de8c1f3 192.168.25.153:7001
   slots:0-5460 (5461 slots) master
M: 8cd93a9a943b4ef851af6a03edd699a6061ace01 192.168.25.153:7002
   slots:5461-10922 (5462 slots) master
M: 2935007902d83f20b1253d7f43dae32aab9744e6 192.168.25.153:7003
   slots:10923-16383 (5461 slots) master
S: 74f9d9706f848471583929fc8bbde3c8e99e211b 192.168.25.153:7004
   replicates 2e48ae301e9c32b04a7d4d92e15e98e78de8c1f3
S: 42cc9e25ebb19dda92591364c1df4b3a518b795b 192.168.25.153:7005
   replicates 8cd93a9a943b4ef851af6a03edd699a6061ace01
S: 8b1b11d509d29659c2831e7a9f6469c060dfcd39 192.168.25.153:7006
   replicates 2935007902d83f20b1253d7f43dae32aab9744e6
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join.....
>>> Performing Cluster Check (using node 192.168.25.153:7001)
M: 2e48ae301e9c32b04a7d4d92e15e98e78de8c1f3 192.168.25.153:7001
   slots:0-5460 (5461 slots) master
M: 8cd93a9a943b4ef851af6a03edd699a6061ace01 192.168.25.153:7002
   slots:5461-10922 (5462 slots) master
M: 2935007902d83f20b1253d7f43dae32aab9744e6 192.168.25.153:7003
   slots:10923-16383 (5461 slots) master
M: 74f9d9706f848471583929fc8bbde3c8e99e211b 192.168.25.153:7004
   slots: (0 slots) master
   replicates 2e48ae301e9c32b04a7d4d92e15e98e78de8c1f3
M: 42cc9e25ebb19dda92591364c1df4b3a518b795b 192.168.25.153:7005
   slots: (0 slots) master
   replicates 8cd93a9a943b4ef851af6a03edd699a6061ace01
M: 8b1b11d509d29659c2831e7a9f6469c060dfcd39 192.168.25.153:7006
   slots: (0 slots) master
   replicates 2935007902d83f20b1253d7f43dae32aab9744e6
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
[root@localhost redis-cluster]# 

6.Jedis

需要把jedis依賴的jar包添加到工程中。Maven工程中需要把jedis的坐標添加到依賴。
推薦添加到服務(wù)層。u-content-Service工程中。

6.1.連接單機版

第一步:創(chuàng)建一個Jedis對象。需要指定服務(wù)端的ip及端口。
第二步:使用Jedis對象操作數(shù)據(jù)庫,每個redis命令對應(yīng)一個方法。
第三步:打印結(jié)果。
第四步:關(guān)閉Jedis

    @Test
    public void testJedis() throws Exception {
        // 第一步:創(chuàng)建一個Jedis對象。需要指定服務(wù)端的ip及端口。
        Jedis jedis = new Jedis("192.168.25.153", 6379);
        // 第二步:使用Jedis對象操作數(shù)據(jù)庫,每個redis命令對應(yīng)一個方法。
        String result = jedis.get("hello");
        // 第三步:打印結(jié)果。
        System.out.println(result);
        // 第四步:關(guān)閉Jedis
        jedis.close();
    }

6.2.連接單機版使用連接池

第一步:創(chuàng)建一個JedisPool對象。需要指定服務(wù)端的ip及端口。
第二步:從JedisPool中獲得Jedis對象。
第三步:使用Jedis操作redis服務(wù)器。
第四步:操作完畢后關(guān)閉jedis對象,連接池回收資源。
第五步:關(guān)閉JedisPool對象。

    @Test
    public void testJedisPool() throws Exception {
        // 第一步:創(chuàng)建一個JedisPool對象。需要指定服務(wù)端的ip及端口。
        JedisPool jedisPool = new JedisPool("192.168.25.153", 6379);
        // 第二步:從JedisPool中獲得Jedis對象。
        Jedis jedis = jedisPool.getResource();
        // 第三步:使用Jedis操作redis服務(wù)器。
        jedis.set("jedis", "test");
        String result = jedis.get("jedis");
        System.out.println(result);
        // 第四步:操作完畢后關(guān)閉jedis對象,連接池回收資源。
        jedis.close();
        // 第五步:關(guān)閉JedisPool對象。
        jedisPool.close();
    }

6.3.連接集群版

第一步:使用JedisCluster對象。需要一個Set<HostAndPort>參數(shù)。Redis節(jié)點的列表。
第二步:直接使用JedisCluster對象操作redis。在系統(tǒng)中單例存在。
第三步:打印結(jié)果
第四步:系統(tǒng)關(guān)閉前,關(guān)閉JedisCluster對象。

@Test
    public void testJedisCluster() throws Exception {
        // 第一步:使用JedisCluster對象。需要一個Set<HostAndPort>參數(shù)。Redis節(jié)點的列表。
        Set<HostAndPort> nodes = new HashSet<>();
        nodes.add(new HostAndPort("192.168.25.153", 7001));
        nodes.add(new HostAndPort("192.168.25.153", 7002));
        nodes.add(new HostAndPort("192.168.25.153", 7003));
        nodes.add(new HostAndPort("192.168.25.153", 7004));
        nodes.add(new HostAndPort("192.168.25.153", 7005));
        nodes.add(new HostAndPort("192.168.25.153", 7006));
        JedisCluster jedisCluster = new JedisCluster(nodes);
        // 第二步:直接使用JedisCluster對象操作redis。在系統(tǒng)中單例存在。
        jedisCluster.set("hello", "100");
        String result = jedisCluster.get("hello");
        // 第三步:打印結(jié)果
        System.out.println(result);
        // 第四步:系統(tǒng)關(guān)閉前,關(guān)閉JedisCluster對象。
        jedisCluster.close();
    }

7. 通過面向接口的設(shè)計實現(xiàn)單機版和集群版的切換

在common中加入依賴

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

添加JedisClient接口

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

分別創(chuàng)建對接口的單機版和集群版的實現(xiàn)類
JedisClientPool單機版

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

}

JedisClientCluster集群版

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

}

為service層使用的時候,需要在配置文件中進行配置
applicationContext-redis.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.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="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.25.162"/>
        <constructor-arg name="port" value="6379"/>
    </bean>
    <!-- 連接redis集群 -->
    <!-- <bean id="jedisClientCluster" class="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.25.162"></constructor-arg>
                    <constructor-arg name="port" value="7001"></constructor-arg>
                </bean> 
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.25.162"></constructor-arg>
                    <constructor-arg name="port" value="7002"></constructor-arg>
                </bean> 
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.25.162"></constructor-arg>
                    <constructor-arg name="port" value="7003"></constructor-arg>
                </bean> 
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.25.162"></constructor-arg>
                    <constructor-arg name="port" value="7004"></constructor-arg>
                </bean> 
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.25.162"></constructor-arg>
                    <constructor-arg name="port" value="7005"></constructor-arg>
                </bean> 
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.25.162"></constructor-arg>
                    <constructor-arg name="port" value="7006"></constructor-arg>
                </bean> 
            </set>
        </constructor-arg>
    </bean> -->
</beans>

在測試模塊進行測試
創(chuàng)建JedisClientTest

package jedis;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import common.jedis.JedisClient;

public class JedisClientTest {

    @Test
    public void testJedisClient() throws Exception {
        //初始化spring容器
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-redis.xml");
        //從容器中獲得JedisClient對象
        JedisClient jedisClient = applicationContext.getBean(JedisClient.class);
        jedisClient.set("mytest", "jedisClient");
        String string = jedisClient.get("mytest");
        System.out.println(string);
        
        
    }
}

8. 將緩存添加到服務(wù)層

將緩存對應(yīng)的key存放到properties中
resource.properties

#內(nèi)容列表在redis中緩存的key
CONTENT_LIST=CONTENT_LIST

在applicationContext-dao.xml中統(tǒng)一加載所有資源文件

<!-- 加載配置文件 -->
    <context:property-placeholder location="classpath:conf/*.properties" />

服務(wù)層實現(xiàn)緩存

package content.service.impl;

import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import common.jedis.JedisClient;
import common.utils.E3Result;
import common.utils.JsonUtils;
import content.service.ContentService;
import mapper.TbContentMapper;
import pojo.TbContent;
import pojo.TbContentExample;
import pojo.TbContentExample.Criteria;

/**
 * 內(nèi)容管理Service
 * <p>Title: ContentServiceImpl</p>
 * <p>Description: </p>
 * <p>Company: www.itcast.cn</p> 
 * @version 1.0
 */
@Service
public class ContentServiceImpl implements ContentService {

    @Autowired
    private TbContentMapper contentMapper;
    @Autowired
    private JedisClient jedisClient;
    
    @Value("${CONTENT_LIST}")
    private String CONTENT_LIST;
    

    /**
     * 根據(jù)內(nèi)容分類id查詢內(nèi)容列表
     * <p>Title: getContentListByCid</p>
     * <p>Description: </p>
     * @param cid
     * @return
     * @see content.service.ContentService#getContentListByCid(long)
     */
    @Override
    public List<TbContent> getContentListByCid(long cid) {
        //查詢緩存
        try {
            //如果緩存中有直接響應(yīng)結(jié)果
            String json = jedisClient.hget(CONTENT_LIST, cid + "");
            if (StringUtils.isNotBlank(json)) {
                List<TbContent> list = JsonUtils.jsonToList(json, TbContent.class);
                return list;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //如果沒有查詢數(shù)據(jù)庫
        TbContentExample example = new TbContentExample();
        Criteria criteria = example.createCriteria();
        //設(shè)置查詢條件
        criteria.andCategoryIdEqualTo(cid);
        //執(zhí)行查詢
        List<TbContent> list = contentMapper.selectByExampleWithBLOBs(example);
        //把結(jié)果添加到緩存
        try {
            jedisClient.hset(CONTENT_LIST, cid + "", JsonUtils.objectToJson(list));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

}

9. 緩存同步

在增刪改數(shù)據(jù)庫操作的時候,將對應(yīng)的key的緩存刪掉,這樣redis就只能去查數(shù)據(jù)庫中最新的數(shù)據(jù)了,解決緩存同步的問題

package cn.e3mall.content.service.impl;

import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import common.jedis.JedisClient;
import common.utils.UjpResult;
import common.utils.JsonUtils;
import content.service.ContentService;
import mapper.TbContentMapper;
import pojo.TbContent;
import pojo.TbContentExample;
import pojo.TbContentExample.Criteria;

/**
 * 內(nèi)容管理Service
 * <p>Title: ContentServiceImpl</p>
 * <p>Description: </p>
 * <p>Company: www.itcast.cn</p> 
 * @version 1.0
 */
@Service
public class ContentServiceImpl implements ContentService {

    @Autowired
    private TbContentMapper contentMapper;
    @Autowired
    private JedisClient jedisClient;
    
    @Value("${CONTENT_LIST}")
    private String CONTENT_LIST;
    
    @Override
    public UjpResult addContent(TbContent content) {
        //將內(nèi)容數(shù)據(jù)插入到內(nèi)容表
        content.setCreated(new Date());
        content.setUpdated(new Date());
        //插入到數(shù)據(jù)庫
        contentMapper.insert(content);
        //緩存同步,刪除緩存中對應(yīng)的數(shù)據(jù)。
        jedisClient.hdel(CONTENT_LIST, content.getCategoryId().toString());
        return UjpResult.ok();
    }

    /**
     * 根據(jù)內(nèi)容分類id查詢內(nèi)容列表
     * <p>Title: getContentListByCid</p>
     * <p>Description: </p>
     * @param cid
     * @return
     * @see content.service.ContentService#getContentListByCid(long)
     */
    @Override
    public List<TbContent> getContentListByCid(long cid) {
        //查詢緩存
        try {
            //如果緩存中有直接響應(yīng)結(jié)果
            String json = jedisClient.hget(CONTENT_LIST, cid + "");
            if (StringUtils.isNotBlank(json)) {
                List<TbContent> list = JsonUtils.jsonToList(json, TbContent.class);
                return list;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //如果沒有查詢數(shù)據(jù)庫
        TbContentExample example = new TbContentExample();
        Criteria criteria = example.createCriteria();
        //設(shè)置查詢條件
        criteria.andCategoryIdEqualTo(cid);
        //執(zhí)行查詢
        List<TbContent> list = contentMapper.selectByExampleWithBLOBs(example);
        //把結(jié)果添加到緩存
        try {
            jedisClient.hset(CONTENT_LIST, cid + "", JsonUtils.objectToJson(list));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,882評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,208評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,746評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,666評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,477評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,960評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,047評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,200評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,726評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,617評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,807評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,327評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,049評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,425評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,674評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,432評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,769評論 2 372

推薦閱讀更多精彩內(nèi)容