Redis - Jedis簡介及SpringDataRedis的使用

Jedis

Jedis是Redis官方推薦的Java連接開發工具,使用Jedis操作Redis需要導入commons-pool2和jedis的jar包。

 

常用API

基本與操作命令一致,下面所示只是常用API,如果想了解更多API可以百度搜索,這裏不詳細列出。

/**
 * 創建Jedis對象
 * host:Redis服務器地址
 * port:Redis服務端口
 */
Jedis jedis = new Jedis(String host, String port);

jedis.set(String key,String value);   // 設置字符串類型的數據

jedis.get(String key);    // 獲取字符串類型的數據

jedis.hset(String key , String field, String value);     // 設置哈希類型的數據

jedis.hget(String key,String field);       // 獲得哈希類型的數據

jedis.lpush(String key,String value1,String value2...);     // 設置列表類型的數據

jedis.lpop(String key);        // 列表左面彈棧

jedis.rpop(String key);        // 列表右面彈棧

jedis.del(String key);         // 刪除指定的key

 

Jedis基本操作

/**
 * 這裏以String類型舉例,其他類似
 */
public void testJedis(){
    // 設置IP地址和端口
    Jedis jedis = new Jedis("localhost",6379);
    // 設置數據
    jedis.set("name","lcy");
    // 獲取數據
    String name = jedis.get("name");
    // 打印數據
    System.out.println(name);
    // 釋放資源
    jedis.close();
}

 

Jedis連接池

Jedis連接資源的創建與銷燬是很消耗程序性能,所以Jedis爲我們提供了Jedis的池化技術

public void testJedisPool(){
    // 獲取連接池配置對象,設置配置項
    JedisPoolConfig config = new JedisPoolConfig();
    // 設置最大連接數
    config.setMaxTotal(30);
    // 設置最大空閒連接數
    config.setMaxIdle(10);

    // 獲取連接池
    JedisPool jedisPool = new JedisPool(config,"localhost",6379);
    // 獲取Jedis核心對象
    Jedis jedis = null;
    try{
        jedis = jedisPool.getResource();
        // 設置數據
        jedis.set("name","lcy");
        // 獲取數據
        String name = jedis.get("name");        
        // 打印數據
        System.out.println(name);
    }catch(Exception e){
        e.printStackTrace();
    }finally{
		if(jedis != null){
			jedis.close();
		}
		// 服務器關閉時,釋放pool資源
		if(jedisPool != null){
			jedisPool.close();
		}
	}
}

 

SpringDataRedis

SpringDataRedis是Spring大家族的一部分,提供了在Spring應用中通過簡單的配置訪問redis服務,對reids底層開發包(Jedis, JRedis, and RJC)進行了高度封裝。

RedisTemplate提供了redis各種操作、異常處理及序列化,支持發佈訂閱。

 

SpringDataRedis功能

1.連接池自動管理,提供了一個高度封裝的“RedisTemplate”類

2.針對Jedis客戶端中大量api進行了歸類封裝

①SetOperations:針對set類型數據操作

②ZSetOperations:針對zset類型數據操作

③HashOperations:針對map類型的數據操作

④ListOperations:針對list類型的數據操作

⑤ValueOperations:簡單K-V操作

 

程序工程搭建 - SpringDataRedis簡單使用

一、創建Maven工程(Jar工程),命名爲SpringDataRedisDemo

二、引入Spring、Jedis、SpringDataRedis的依賴

<!-- Junit單元測試 -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.1.7.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>5.1.7.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>5.1.7.RELEASE</version>
</dependency>
<!-- spring - test -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.1.7.RELEASE</version>
</dependency>

<!-- 緩存 -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.8.1</version>
</dependency>
<!-- spring-data-Redis -->
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>1.7.2.RELEASE</version>
</dependency>

三、在src/main/resources下創建redis-config.properties

# Redis服務器地址
redis.host=10.35.33.33
# Redis服務端口
redis.port=6379
# Redis密碼 - 安裝Redis時最好設置。我曾因沒設置密碼,導致服務器感染挖礦病毒
redis.pass=123456
redis.database=0
redis.maxIdle=300
redis.maxWait=3000
redis.testOnBorrow=true

四、 在src/main/resources下創建applicationContext-redis.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 引入properties配置文件 -->
    <context:property-placeholder location="classpath*:*.properties" />

    <!-- redis 相關配置 -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxIdle" value="${redis.maxIdle}" />
        <property name="maxWaitMillis" value="${redis.maxWait}" />
        <property name="testOnBorrow" value="${redis.testOnBorrow}" />
    </bean>
    <bean id="JedisConnectionFactory"
          class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
          p:host-name="${redis.host}"
          p:port="${redis.port}"
          p:password="${redis.pass}"
          p:pool-config-ref="poolConfig"/>
    
    <!-- RedisTemplate -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="JedisConnectionFactory" />
    </bean>
</beans>

五、建立測試Java文件【每一種測試的方法代碼在後面貼出】

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext-redis.xml"})
public class TestString {
    @Autowired
    private RedisTemplate redisTemplate;

    
}

 

String操作測試

// 字符串存取操作
@Test
public void testStringSet(){
    // String類型 - 存儲
    redisTemplate.boundValueOps("name").set("lcy");
}

@Test
public void testStringGet(){
    // 取值
    String name = (String) redisTemplate.boundValueOps("name").get();
    System.out.println(name);
}

@Test
public void testStringDel(){
    // 刪除
    redisTemplate.delete("name");
}

 

List操作測試

// List存取操作
@Test
public void testListLeftPush(){
    // 左存值
    redisTemplate.boundListOps("myListKey").leftPush("001");
    redisTemplate.boundListOps("myListKey").leftPush("002");
    redisTemplate.boundListOps("myListKey").leftPush("003");
    redisTemplate.boundListOps("myListKey").leftPush("004");
}

@Test
public void testListRightPush(){
    // 右存值
    redisTemplate.boundListOps("myListKey").rightPush("005");
    redisTemplate.boundListOps("myListKey").rightPush("006");
    redisTemplate.boundListOps("myListKey").rightPush("007");
    redisTemplate.boundListOps("myListKey").rightPush("008");
}

@Test
public void testListRange(){
    // 取值
    List<String> myListKey = redisTemplate.boundListOps("myListKey").range(0, -1);
    for (String s : myListKey) {
        System.out.println(s);
    }
}

@Test
public void testListDel(){
    // 刪除List
    redisTemplate.delete("myListKey");
}

 

Hash操作測試

// Hash
@Test
public void testHashPut(){
    // 存值
    redisTemplate.boundHashOps("keyname1").put("name","zs");
    redisTemplate.boundHashOps("keyname1").put("age","20");
    redisTemplate.boundHashOps("keyname1").put("phone","12345678910");
    redisTemplate.boundHashOps("keyname1").put("email","[email protected]");
}

@Test
public void testHashGetOne(){
    // 取一個值
    String name = (String) redisTemplate.boundHashOps("keyname1").get("name");
    String age = (String) redisTemplate.boundHashOps("keyname1").get("age");
    System.out.println("姓名:" + name + "\t年齡:" + age);
}

@Test
public void testHashGetAll(){
    // 獲取所有的值
    Map<String, String> user = redisTemplate.boundHashOps("keyname1").entries();
    Set<Map.Entry<String, String>> entries = user.entrySet();
    for (Map.Entry<String, String> entry : entries) {
        System.out.println("key = " + entry.getKey());
        System.out.println("value = " + entry.getValue());
    }
}

@Test
public void testHashDelOne(){
    // 刪除一個值
    redisTemplate.boundHashOps("keyname1").delete("name");
}

@Test
public void testHashDelAll(){
    // 刪除所有
    redisTemplate.delete("keyname1");
}

 

對象操作測試

一、創建People對象類

// 須實現序列化接口
public class Person implements Serializable {
    private String name;
    private String phone;
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

二、創建存儲Key值的常量類Constants

在真實開發中,Key是非常珍貴的,一般都是根據業務來存,通過hash的方式。比如這裏是一個用戶相關的業務(userServiced),則就可以用userService作爲主Key。

public class Constants {
    public final static String CONTENT_LIST_REDIS = "userService";
}

三、測試代碼

// 對象
@Test
public void testObjSet(){
    Person person = new Person();
    person.setAge(20);
    person.setName("lcy");
    person.setPhone("123456789");
    Person person1 = new Person();
    person1.setAge(22);
    person1.setName("jyqc");
    person1.setPhone("987654321");
    List<Person> personList = new ArrayList();
    personList.add(person);
    personList.add(person1);
    // key是很珍貴的,真正開發中,根據業務來存,即通過hash
    redisTemplate.boundHashOps("userService").put("person",personList);
}

@Test
public void testObjGet(){
    List<Person> res = (List<Person>) redisTemplate.boundHashOps(Constants.CONTENT_LIST_REDIS).get("person");
    for (Person per : res) {
        System.out.println(per.getName());
    }
}

注意:通過SpringDataRedis來進行存儲數據,會對Key和Value進行一個二進制的處理。比如存的key是"name",實際存入到Redis的是類似於"\xac\xed\x00\x05t\x00\x04name",存入的value是"lcy",實際存入到Redis的是類似於"\xac\xed\x00\x05t\x00\x03lcy"這樣的。

 

項目中運用舉例 - 廣告

獲取廣告數據的時候先從redis中獲取, 如果獲取到數據則直接返回, 就不用訪問數據庫了。如果獲取不到數據, 可以從數據庫中查詢, 查詢到後放入redis中一份, 下次就可以直接從redis中查詢到,這樣大大降低了數據庫的高併發訪問壓力。

當新增廣告的時候怎麼辦?

比如分類id爲1的廣告新增加1個,從Redis獲取數據是不會獲取到這個新增的廣告的。那麼我們可以在新增廣告的方法裏,在存入MySQL之後,我們根據分類ID來刪除對應分類的廣告集合(全部刪除完),這樣操作簡單。下一次進入頁面,獲取廣告時,Redis裏爲空,它就會先從MySQL數據庫中獲取一份,並存入Redis。也就是說第一次從MySQL獲取的數據,下一次就是從Redis獲取的數據了。

當刪除廣告的時候怎麼辦?

比如分類id爲1的廣告刪除1個,這個操作方式與新增時相似。先根據廣告id去從MySQL獲取這個廣告對應的分類id,然後根據分類id刪除Redis中對應廣告集合,然後再去刪除MySQL中這條廣告的數據。

當更新廣告的時候怎麼辦?

比如更新分類id爲1的廣告,將其分類id改爲2。我們來分析下過程,將這個廣告從分類1變成分類2,是不是就相當於分類1的廣告減少了1個,分類2的廣告增加了一個。既然清楚了這個原理就好辦了,將分類1和分類2的Redis數據都清理一下就行了。具體流程:根據更新廣告的廣告id去查詢它原來的分類id,根據原來的分類id來清理原來分類在Redis中的數據。然後根據更新之後的廣告對象的分類id去清理這個分類在Redis中的數據即可。

發佈了74 篇原創文章 · 獲贊 13 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章