Redis的使用及Spring-data-redis對Redis的簡化開發

在這裏插入圖片描述
redis 是一款開源的 Key-Value 數據庫,運行在內存中,由 ANSI C 編寫。企業開發通常採用 Redis 來實現緩存。同類的產品還有 memcache 、memcached 、MongoDB 等。

Redis支持豐富的數據結構,常用的有string、list、hash、set、sortset這幾種。學習這些數據結構是使用Redis的基礎!

首先還是得聲明一下,Redis的存儲是以key-value的形式的。Redis中的key一定是字符串,value可以是string、list、hash、set、sortset這幾種常用的。

一,Redis的下載和使用

目前官網只提供了linux版本的下載,我們想要使用windows版本的,只能在github上下載。

官網下載地址:http://redis.io/download

windows版本的Redis在github下載地址:https://github.com/MSOpenTech/redis/tags

爲了大家使用方便,博主在文章末的示例項目提供了redis的windows版本,裏面中win32位和win64位,供大家使用。

將下載的redis解壓到指定的目錄
在這裏插入圖片描述

主要有三個核心文件:

redis.windows.conf 配置文件,裏面是關於redis的一些配置,一般情況下,使用默認即可。
redis-cli.exe 啓動客戶端執行文件。
redis-server.exe啓動服務端執行文件

點擊redis-server.exe啓動redis服務

在這裏插入圖片描述

二,把Redis設置成windows下的服務

上面這種方式,雖然啓動了Redis服務,但是隻要一關閉cmd窗口,redis就會消失。所以要把redis設置成windows下的服務。

設置服務命令
redis-server --service-install redis.windows.conf --loglevel verbose

打開cmd,進入到redis的安裝目錄,執行上面的命令

在這裏插入圖片描述

我們win + R 鍵 打開運行窗口,輸入services.msc 查看windows服務

在這裏插入圖片描述

在這裏插入圖片描述

選中Redis服務,右鍵屬性

在這裏插入圖片描述

點擊服務狀態下的啓動按鈕這個服務就進行了開啓。如果你想讓這個服務在電腦開機的時候就啓動,在這個服務啓動之後,啓動類型保持默認自動就可以了,如果不想電腦開機時就啓動這個服務,可以設置啓動類型爲手動。博主在這裏選擇手動啓動類型,在需要這個服務時,再進行啓動,給電腦減輕負擔,嘿嘿,有沒有很機智!

這個服務被設置爲windows服務之後,還有一種方便的啓動與停止的方式。

管理員身份打開cmd窗口,輸入 net start 服務名 即可啓動windows服務

在這裏插入圖片描述

輸入net stop 服務名 ,停止windows服務

在這裏插入圖片描述

這樣方式有沒有看起來逼格更高一點呢,小小嘚瑟一下😌

注意:

1.一定要以管理員的身份運行cmd窗口

2.服務名對應windows服務列表中的服務名稱

三, redis-cli.exe 啓動客戶端

言歸正傳,我們下面介紹使用redis-cli.exe客戶端可執行文件啓動redis客戶端來操作Redis

點擊redis安裝目錄下的redis-cli.exe啓動客戶端(服務端要保存開啓狀態)

redis的常用操作命令:

查看所有的key:keys*

設置值: set key的名稱 value值

獲取指定key的值: get key的名稱

在這裏插入圖片描述

四,Jedis 使用和圖形界面工具

Jedis 是 Redis 官方推出的一款面向 Java 的客戶端,提供了很多接口供 Java 語言調用。可以在 Redis 官網下載,當然還有一些開源愛好者提供的客戶端,如 Jredis、SRP 等等,推薦使用 Jedis。

Jedis網址: https://github.com/xetorthio/jedis

在這裏插入圖片描述

創建一個maven項目
在這裏插入圖片描述

主要引入的依賴:
Jedis : redis的java客戶端
Junit :方便進行代碼測試

引入的插件:
maven-compiler-plugin : 由於maven項目默認的編譯插件版本過低,需要這個編譯插件來設置編譯的版本

<dependencies>
  	<!-- Jedis -->
  	<dependency>
	    <groupId>redis.clients</groupId>
	    <artifactId>jedis</artifactId>
	    <version>2.9.0</version>
	    <type>jar</type>
	    <scope>compile</scope>
    </dependency>

	<!-- 單元測試 -->
  	<dependency>
  		<groupId>junit</groupId>
  		<artifactId>junit</artifactId>
  		<version>4.12</version>
  	</dependency>
  </dependencies>
  
  <build>
  	<plugins>
  		<!-- 編譯插件 -->
  		<plugin>
  			<groupId>org.apache.maven.plugins</groupId>
  			<artifactId>maven-compiler-plugin</artifactId>
  			<version>3.5.1</version>
  			<configuration>
  				<source>1.7</source>
  				<target>1.7</target>
  				<encoding>utf-8</encoding>
  			</configuration>
  		</plugin>
  	</plugins>
  </build>

在引入編譯插件之後,項目會報錯,需要選中項目---->右鍵---->Maven---->Update Project 來更新項目

在這裏插入圖片描述

項目的編譯版本修改成功,變更爲1.7

準備工作就緒,接下來編寫redis java客戶端代碼,進行測試

    @Test
	public void redisTest() {
		Jedis jedis = new Jedis("localhost");   //localhost 表示連接的是本地的Redis服務端
		jedis.set("foo", "蘋果");    
		String value = jedis.get("foo");  
		System.out.println(value);
	}

控制檯輸出
在這裏插入圖片描述

說明連接redis服務端連接成功,可以進行簡單的存值和取值

我們可以打開redis-cli.exe客戶端查看剛纔設置的key和value

在這裏插入圖片描述

當我們存取中文字符時,用redis-cli.exe客戶端查看發現對中文字符進行了轉碼,查看不很方便,這時,我們可以安裝redis 安裝圖形化界面客戶端來進行查看

在這裏插入圖片描述

這個安裝程序,在文章末的示例項目中提供。安裝步驟很簡單,不再演示。

安裝成功之後,按照下面操作即可

在這裏插入圖片描述

在這裏插入圖片描述

點擊創建的連接,裏面有16個db,默認使用的是db0

在這裏插入圖片描述

TTL 是 redis 的 key 有效時間,顯示-1 ,沒有設置 key 的有效期

一般通過java程序設置key的有效時間,不會使用圖形化界面來進行設置

設置key的有效週期
在這裏插入圖片描述

使用圖形化界面查看

在這裏插入圖片描述

如果我們要設置key的有效時間爲一天,那麼需要設置 60 * 60 * 24秒,這樣來換算,顯得不是很方便。當然,Jedis在很多方面的操作都是比較偏向底層的,使用起來不是很方便,而是在其上在封裝一層,作爲業務的使用。通常在開發中,使用Spring Data Redis來操作Redis。

五,Spring Data Redis 使用

Spring-data-redis 是 spring 大家族的一部分,提供了在 srping 應用中通過簡單的配置訪問 redis 服務,對 reids 底層開發包(Jedis, JRedis, and RJC)進行了高度封裝,RedisTemplate 提供了 redis 各種操作、異常處理及序列化,支持發佈訂閱,並對 spring 3.1 cache 進行了實現。

spring-data-redis 針對 jedis提供瞭如下功能:

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

2.針對jedis客戶端的大量api進行了歸類封裝,把同一類型的操作封裝成了Operation接口.支持redis中的五種數據類型的操作.

3.針對數據的"序列化與反序列化",提供了多種可以選擇的策略(RedisSerializer)

JdkSerializationRedisSerializer:當需要存儲java對象時使用.

StringRedisSerializer:當需要存儲string類型的字符串時使用.

JacksonJsonRedisSerializer:將對象序列化成json的格式存儲在redis中,需要jackson-json工具的支持

redisTemplate有兩個方法經常用到,一個是opsForXXX一個是boundXXXOps,XXX是value的類型

opsForXXXboundXXXOps的區別

前者獲取到一個Opercation,但是沒有指定操作的key,可以在一個連接(事務)內操作多個key以及對應的value;後者會獲取到一個指定了key的operation,在一個連接內只操作這個key對應的value.

在實際開發過程中,選擇其中任意一種方式都可以。不過在示例項目中,這兩種方式都進行演示,大家根據喜好進行選擇。

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

在項目的pom.xml文件中引入的依賴:

spring-data-redis:對 reids 底層開發包(Jedis, JRedis, and RJC)進行了高度封裝,提供了一個高度封裝的“RedisTemplate”類來操作redis

spring-test:加載spring的配置文件,方便測試

<dependencies>
  	<!-- Jedis -->
  	<dependency>
	    <groupId>redis.clients</groupId>
	    <artifactId>jedis</artifactId>
	    <version>2.9.0</version>
	    <type>jar</type>
	    <scope>compile</scope>
    </dependency>

	<!-- 單元測試 -->
  	<dependency>
  		<groupId>junit</groupId>
  		<artifactId>junit</artifactId>
  		<version>4.12</version>
  	</dependency>
  	<!--spring-data-redis  -->
  	<dependency>
  		<groupId>org.springframework.data</groupId>
  		<artifactId>spring-data-redis</artifactId>
  		<version>1.7.3.RELEASE</version>
  	</dependency>
	<!--spring整合juint測試  -->
  	<dependency>
  		<groupId>org.springframework</groupId>
  		<artifactId>spring-test</artifactId>
  		<version>4.3.8.RELEASE</version>
  	</dependency>
  </dependencies>

spring的配置文件applicationContext-cache.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:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop" 
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:jpa="http://www.springframework.org/schema/data/jpa" 
	xmlns:jaxws="http://cxf.apache.org/jaxws"
	xmlns:cache="http://www.springframework.org/schema/cache"
	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
	http://www.springframework.org/schema/aop
	http://www.springframework.org/schema/aop/spring-aop.xsd
	http://www.springframework.org/schema/tx 
	http://www.springframework.org/schema/tx/spring-tx.xsd
	http://www.springframework.org/schema/data/jpa
	http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
	http://cxf.apache.org/jaxws
	http://cxf.apache.org/schemas/jaxws.xsd
	http://www.springframework.org/schema/cache
	http://www.springframework.org/schema/cache/spring-cache.xsd">
	
	
	<!-- Jedis數據庫連接池 -->
	 <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">  
       <property name="maxIdle" value="300" />        
       <property name="maxWaitMillis" value="3000" />  
       <!-- 保證獲得的每一個Jedis實例都是可用的 -->
       <property name="testOnBorrow" value="true" />  
    </bean>  
	
	<!-- redis連接工廠  跟配置數據庫連接池類似,需要配置JedisConnectionFactory來通過服務器或者連接池的方式獲取redis服務器的連接 -->
	<bean id="connectionFactory"  
        class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"  
        p:host-name="localhost" p:port="6379" p:pool-config-ref="poolConfig"  
        p:database="0" />  
        
     <bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
    <bean id="jdkSerializationRedisSerializer" class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>


    <!-- redis模板配置  spring-data-redis提供了一個基礎的泛型RedisTemplate封裝了基礎的crud操作-->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="connectionFactory"/>
        <!-- 序列化配置   可選配置-->
        <property name="defaultSerializer" ref="stringRedisSerializer"/>
        <property name="keySerializer" ref="stringRedisSerializer"/>
        <property name="valueSerializer" ref="stringRedisSerializer"/>
    </bean>  
</beans>

編寫代碼演示opsForXXX的用法

方法一:opsForValue() 簡單 K-V 操作

	/**
	 * 簡單key-value類型操作
	 */
	@Test
	public void opsForValue() {
		
		//設置key和value  並設置key的有效時間
		redisTemplate.opsForValue().set("opsForValue", "小鬼",30,TimeUnit.SECONDS);
		
		String value = (String) redisTemplate.opsForValue().get("opsForValue");
		
		System.out.println(value);
	}
	
	/**
	 * 簡單key-value類型刪除操作
	 */
	@Test
	public void delOpsForValue() {
		
		redisTemplate.delete("opsForValue");
	}

在這裏插入圖片描述

使用redis客戶端圖形化界面查看

在這裏插入圖片描述

方法二:opsForHash() 針對 map 類型的數據操作

這次不再向先前那樣,存放字符串,嘗試存放的數據是一個裝着User對象的List集合

/**
	 * 針對 map 類型的數據操作
	 */
	@Test
	public void opsForHash() {
		
		List<User> list = new ArrayList<>();
		
		User u1 = new User();
		u1.setId(1);
		u1.setAge(1);
		u1.setUsername("小張");
		
		User u2 = new User();
		u2.setId(2);
		u2.setAge(2);
		u2.setUsername("小王");
		
		list.add(u1);
		list.add(u2);
		
		//向redis中存入一個list集合,list集合中存放的是user對象
		
		//第一個參數 屬於大key 對應的值value是一個map 第二個參數是map的key  第三個參數是map的value
		redisTemplate.opsForHash().put("opsForHash", "mapKey",list);
	}

執行單元測試,出現了錯誤

java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.lang.String

大概就是說類轉換異常,不能把ArrayList類轉成String類

出現的原因:

在這裏插入圖片描述

解決方式有兩種:

方式一:

1.修改屬性keySerializer爲hashKeySerializer 2.修改屬性valueSerializer爲hashValueSerializer 對應的ref="jdkSerializationRedisSerializer"
 <bean id="stringRedisSerializer" 
     class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
    <bean id="jdkSerializationRedisSerializer" 
    class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>


    <!-- redis模板配置  spring-data-redis提供了一個基礎的泛型RedisTemplate封裝了基礎的crud操作-->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="connectionFactory"/>
        <!-- 序列化配置   可選配置-->
        <property name="defaultSerializer" ref="stringRedisSerializer"/>
        <property name="hashKeySerializer" ref="stringRedisSerializer"/>
        <property name="hashValueSerializer" ref="jdkSerializationRedisSerializer"/>
    </bean> 

2.,註釋掉序列化配置,使用默認的即可,推薦使用第二種。可以減少配置的同時,麻煩也少了

第二種實現的原理:

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

通過查看RedisTemplate這個類的源碼,發現由於defaultSerializer的序列化方式被初始化爲JdkSerializationRedisSerializer,再通把defaultSerializer的值賦值給keySerializer,valueSerializer,hashKeySerializer,hashValueSerializer,所以他們的值都爲JdkSerializationRedisSerializer。當向redis中存儲不是String字符串也是OK的。

修改完配置文件,進行代碼測試

/**
	 * 針對 map 類型的數據操作
	 */
	@Test
	public void opsForHash() {
		
		List<User> list = new ArrayList<>();
		
		User u1 = new User();
		u1.setId(1);
		u1.setAge(1);
		u1.setUsername("小張");
		
		User u2 = new User();
		u2.setId(2);
		u2.setAge(2);
		u2.setUsername("小王");
		
		list.add(u1);
		list.add(u2);
		
		//向redis中存入一個list集合,list集合中存放的是user對象
		
		//第一個參數 屬於大key 對應的值value是一個map 第二個參數是map的key  第三個參數是map的value
		redisTemplate.opsForHash().put("opsForHash", "mapKey",list);
		redisTemplate.opsForHash().put("opsForHash", "mapKey2",list);
		redisTemplate.opsForHash().put("opsForHash", "mapKey3",list);
		
		
		//獲取所有的小key
		Set keys = redisTemplate.opsForHash().keys("opsForHash");
		
		System.out.println("獲取所有的小key:"+keys);
		
		//獲取所有的value
		list =  redisTemplate.opsForHash().values("opsForHash");
		
		System.out.println("獲取所有的value: "+list);
		
		
		//獲取某一個小key的value
		list =(List<User>) redisTemplate.opsForHash().get("opsForHash", "mapKey");
		
		System.out.println("獲取某一個小key的value: "+list);
		
		
		
	}

控制檯成功輸出

在這裏插入圖片描述

刪除大key中的某一個小key 和 刪除整個大key

/**
	 * 針對 map 數據刪除操作
	 */
	@Test
	public void delOpsForHash() {
		
		//刪除大key中的某一個map
		redisTemplate.opsForHash().delete("opsForHash", "mapKey");
		
		//刪除大key
		redisTemplate.delete("opsForHash");
	}

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

剩下的三種方式使用大致相同,不做演示

opsForSet() set 類型數據操作

opsForList() 針對 list 類型的數據操作

opsForZSet() zset 類型數據操作

編寫代碼演示BoundXXXOpsTest的用法

方法一:boundValueOps() 簡單 K-V 操作

/**
	 * 簡單key-value類型操作
	 */
	@Test
	public void boundValueOps() {
		
		//設置key和value  並設置key的有效時間
		redisTemplate.boundValueOps("boundValueOps").set("小鬼",30,TimeUnit.SECONDS);
		
		String value = (String) redisTemplate.opsForValue().get("boundValueOps");
		
		System.out.println(value);
	}
	
	/**
	 * 簡單key-value類型刪除操作
	 */
	@Test
	public void delBoundValueOps() {
		
		redisTemplate.delete("boundValueOps");
	}

方法二:boundHashOps() 針對 map 類型的數據操作

	/**
	 * 針對 map 類型的數據操作
	 */
	@Test
	public void boundHashOps() {
		
		List<User> list = new ArrayList<>();
		
		User u1 = new User();
		u1.setId(1);
		u1.setAge(1);
		u1.setUsername("小張");
		
		User u2 = new User();
		u2.setId(2);
		u2.setAge(2);
		u2.setUsername("小王");
		
		list.add(u1);
		list.add(u2);
		
		//向redis中存入一個list集合,list集合中存放的是user對象
		
		//第一個參數 屬於大key 對應的值value是一個map 第二個參數是map的key  第三個參數是map的value
		redisTemplate.boundHashOps("boundHashOps").put("key1", list);
		redisTemplate.boundHashOps("boundHashOps").put("key2", list);
		redisTemplate.boundHashOps("boundHashOps").put("key3", list);
		
		
		//獲取所有的小key
		Set keys = redisTemplate.boundHashOps("boundHashOps").keys();
		
		System.out.println("獲取所有的小key:"+keys);
		
		//獲取所有的value
		list =  redisTemplate.boundHashOps("boundHashOps").values();
		
		System.out.println("獲取所有的value: "+list);
		
		
		//獲取某一個小key的value
		list =(List<User>) redisTemplate.boundHashOps("boundHashOps").get("key1");
		
		System.out.println("獲取某一個小key的value: "+list);
		
		
		
	}
	
	/**
	 * 針對 map 數據刪除操作
	 */
	@Test
	public void delBoundHashOps() {
		
		//刪除大key中的某一個map
		redisTemplate.boundHashOps("boundHashOps").delete("key1");
		
		//刪除大key
		redisTemplate.delete("opsForHash");
	}
	

剩下的三種方式使用大致相同,不做演示

boundSetOps() set 類型數據操作

boundListOps() 針對 list 類型的數據操作

boundZSetOps() zset 類型數據操作

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

以上就是有關Spring-data-redis對Redis的常用操作,後續會補充Redis搭建集羣的相關知識。

最後分享示例項目在碼雲的地址:https://gitee.com/xiaoguixiaogege/springdataredis

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章