1. 程式人生 > >【Redis】深入淺出Redis(三)——在專案中使用Jedis對Redis操作

【Redis】深入淺出Redis(三)——在專案中使用Jedis對Redis操作

一、前言

      在前幾篇部落格中小編向大家介紹了搭建單機版和叢集版的redis。雖然叢集搭建起來了,但是如何在專案中使用呢?在這篇部落格中,小編向大家介紹Jedis,用Jedis來對Redis進行增加、刪除、設定有效時間等操作。

二、什麼是Jedis?

      使用Jedis連線redis伺服器,Java客戶端在github上start最高的是Jedis和Redisson。Jedis提供了完整Redis命令,而Redisson有更多分散式的容器實現。

      Jedis類是整個客戶端的入口,通過Jedis可以建立與Redis Server的連線併發送命令。Jedis繼承自BinaryJedis,同時Jedis和BinaryJedis都實現了很多介面,通過一張類圖來描述:

這裡寫圖片描述

      每一個介面都代表了一類Redis命令,例如JedisCommands中包含了SET GET等命令,MultiKeyCommands中包含了針對多個Key的MSET MGET等命令。一部分命令有兩個版本的介面,如JedisCommands和BinaryJedisCommands。JedisCommands是字串引數版本命令,會在Jedis內部將引數轉換成UTF-8編碼的位元組陣列。BinaryJedisCommands提供的是位元組引數版本,允許使用者自己決定編碼等細節。ClusterCommands和SentinelCommands與叢集、高可用等相關的命令只有一個版本。

三、具體實現

3.1 環境搭建

  • Redis

  • java maven專案

3.2 引入Jedis的jar包

      向maven專案的pom.xml檔案中插入Jedis的座標:

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

3.2 建立redis客戶端實現類

這裡寫圖片描述

      建立的這個類就是為了抽象redis的操作,我們都知道的redis有很多操作,這裡就封裝了redis的新增雜湊值、獲取雜湊值、增加1、減少1、設定有效時間、檢視有效時間、刪除等操作。並通過JedisClientSingle和JedisClientCluster,單機和叢集版分別實現了操作,不同的設定,使用不同的實現,系統很靈活。

      JedisClient:

package com.taotao.rest.component;

public interface JedisClient {
    public String set(String key,String value);
    public String get(String key);
    //新增雜湊值
    public Long hset(String key,String item,String value);
    //獲取雜湊
    public String hget(String key,String item);
    //增加1
    public Long incr(String key);
    //減少1
    public Long decr(String key);
    //設定有效時間
    public Long expire(String key,int second);
    //檢視當前有效時間
    public Long ttl(String key);
    //刪除
    public Long hdel(String key,String item);
}

      叢集版JedisClientCluster:

package com.taotao.rest.component.impl;

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

import redis.clients.jedis.JedisCluster;

import com.taotao.rest.component.JedisClient;
/**
 * 叢集版
 * @author Ares
 *
 */
public class JedisClientCluster implements JedisClient {

    @Autowired
    private 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 Long hset(String key, String item, String value) {
        return jedisCluster.hset(key, item, value);
    }

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

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

    @Override
    public Long decr(String key) {
        return jedisCluster.decr(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 hdel(String key, String item) {
        return jedisCluster.hdel(key, item);
    }

}

      單機版JedisClientSingle:

package com.taotao.rest.component.impl;

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

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

import com.taotao.rest.component.JedisClient;
/**
 * 單機版
 * 
 * @author Ares
 *
 */
public class JedisClientSingle implements JedisClient {

    @Autowired
    private JedisPool jedisPool;

    /**
     * 設定值K-V
     */
    @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 Long hset(String key, String item, String value) {
        //建立連線
        Jedis jedis = jedisPool.getResource();
        //設定雜湊
        Long result = jedis.hset(key, item, value);
        //關閉連線
        jedis.close();
        return result;
    }

    @Override
    public String hget(String key, String item) {
        //建立連線
        Jedis jedis = jedisPool.getResource();
        //讀取雜湊
        String result = jedis.hget(key, item);
        //關閉連線
        jedis.close();
        return result;
    }

    @Override
    public Long incr(String key) {
        //建立連線
        Jedis jedis = jedisPool.getResource();
        //+1
        Long result = jedis.incr(key);
        //關閉連線
        jedis.close();
        return result;
    }

    @Override
    public Long decr(String key) {
        //建立連線
        Jedis jedis = jedisPool.getResource();
        //-1
        Long result = jedis.decr(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 hdel(String key, String item) {
        //建立連線
        Jedis jedis = jedisPool.getResource();
        //檢視有效時間
        Long result = jedis.hdel(key, item);
        //關閉連線
        jedis.close();
        return result;
    }

}

3.2 託付給Spring管理

      這裡我們把Redis客戶端託付給Spring管理,配置Redis的主機地址以及埠。

      然後配置redis客戶端的實現類,這裡小編列出了單機版和叢集版兩種。

<?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">

    <!-- 包掃描器,掃描帶@Service註解的類 -->
    <context:component-scan base-package="com.taotao.rest.service"></context:component-scan>
    <!-- 配置redis客戶端單機版 -->
    <bean id="jedisPool" class="redis.clients.jedis.JedisPool">
        <constructor-arg name="host" value="192.168.137.12"></constructor-arg>
        <constructor-arg name="port" value="6379"></constructor-arg>
    </bean>
    <!-- 配置redis客戶端實現類 -->
    <bean id="jedisClientSingle" class="com.taotao.rest.component.impl.JedisClientSingle"/>

    <!-- 配置redis客戶端叢集版 -->
    <!--<bean id="jedisCluster" class="redis.clients.jedis.JedisCluster">
        <constructor-arg>
            <set>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.137.12"/>
                    <constructor-arg name="port" value="7001"/>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.137.12"/>
                    <constructor-arg name="port" value="7002"/>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.137.12"/>
                    <constructor-arg name="port" value="7003"/>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.137.12"/>
                    <constructor-arg name="port" value="7004"/>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.137.12"/>
                    <constructor-arg name="port" value="7005"/>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.137.12"/>
                    <constructor-arg name="port" value="7006"/>
                </bean>
            </set>
        </constructor-arg>
    </bean>
    <bean id="jedisClientCluster" class="com.taotao.rest.component.impl.JedisClientCluster"/> --> 

</beans>

3.5 業務邏輯中新增快取

      注意:新增快取時不要影響正常的業務邏輯

@Override
    public List<TbContent> getContentList(Long cid) {
        //新增快取
        //查詢資料庫之前先查詢快取,如果有直接返回
        try {
            //從redis中取快取資料
            String json = jedisClient.hget(REDIS_CONTENT_KEY, cid+"");
            if (!StringUtils.isBlank(json)) {
                //把json轉換成List
                List<TbContent> list = JsonUtils.jsonToList(json, TbContent.class);
                return list;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 根據cid查詢內容列表
        TbContentExample example = new TbContentExample();
        Criteria criteria = example.createCriteria();
        criteria.andCategoryIdEqualTo(cid);
        //執行查詢
        List<TbContent> list = contentMapper.selectByExampleWithBLOBs(example);

        //返回結果之前,向快取中新增資料
        try {
            //為了規範key可以使用hash
            //定義一個儲存內容的key,hash中每個項就是cid
            //value是list,需要把list轉換成json資料。
            jedisClient.hset(REDIS_CONTENT_KEY, cid+"", JsonUtils.objectToJson(list));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

四、小結

      通過使用Jedis,可以對redis進行操作。這樣快取我們就可以很好的使用了,另外就是對快取使用的時候不能影響業務邏輯。還要設定超時時間,如果連結超時也要進行資料庫查詢了。

      下一篇部落格將向大家介紹redis的快取同步問題。