javascript
Redis及Spring-Data-Redis入门学习
2019獨角獸企業重金招聘Python工程師標準>>>
繼上一篇Solr和Spring Data Solr學習,我們思考一個問題,使用Solr的目的是什么?肯定是為了加快服務器的相應速度。因為即使不適用Solr,通過請求數據庫我們一樣能完成搜索功能,但是這樣會給服務器造成很大的壓力。
而Solr僅僅是在搜索功能中用到了,但是大量請求的數據不僅僅出現在搜索中,比如用戶的登錄信息,雖然數據量很小,但是整個項目每刷新一次頁面都要請求一次用戶登錄的Token信息,也會拖慢服務器的響應速度。我們通常有兩中解決方式:1.數據緩存;2.網頁靜態化。
其實我們在Shiro實現用戶-角色-權限管理系統中已經用到了緩存技術,今天我們了解一下Redis緩存技術。
項目開源地址: Github
安裝Redis
Redis是一款開源的Key-Value數據庫。首先我們要去 官網 下載Redis,由于筆者使用的是MacOS系統,和Windows系統有所不同。
安裝過程不再敘述,這里提供兩個教程:
-
Windows: Redis安裝教程
-
MacOS&Linux: Redis安裝教程
<br/>
啟動Redis
redis-server redis-server &建議使用第二個命令,用第二個命令啟動了redis server后能繼續輸入命令,使用第一個命令則不行。
如果終端中顯示如下logo表示redis啟動成功:
<br/>
操縱Redis
上面僅僅是啟動了Redis Server,但Redis是一種Key-Value型數據庫,也包含了一些查詢數據庫的命令,操作redis命令的入口就是: redis/bin/redis-cli
./bin/redis-cliredis-cli更多的Redis命令可以參看:redis中文文檔
<br/>
Spring Data Redis
之前學習Solr的時候用到了Spring Data Solr,現在學習Redis,Spring提供了Spring Data Redis用來實現通過配置文件的方式訪問redis服務。Spring Data Redis對Redis底層開發包(Jedis, JRedis, and RJC)進行了高度封裝,RedisTemplate提供了redis各種操作、異常處理及序列化。
Jedis
Jedis是Redis官方推出的一款面向Java的客戶端,提供了很多借口供Java語言調用。
Spring Data Redis針對Jedis提供了如下功能:
- 1.連接池自動管理,提供了一個高度封住的RedisTemplate類。
- 2.針對jedis客戶端中大量api進行歸類封裝,將同一類型操作封裝為operation接口: ValueOperations: 簡單的K-V操作 SetOperations: set類型數據操作 ZSetOperations: zset類型數據操作 HashOperations: 針對Map類型的數據操作 ListOperations: 針對List類型的數據操作
準備
導入依賴
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.8.1</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.7.2.RELEASE</version> </dependency>創建redis-config.properties
redis.host=127.0.0.1 redis.port=6379 redis.pass= redis.database=0 redis.maxIdle=300 redis.maxWait=3000 redis.testOnBorrow=true解釋
創建spring-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:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><context:property-placeholder location="classpath:other/*.properties"/><!-- redis 相關配置 --><bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig"><!-- 最大空閑數 --><property name="maxIdle" value="${redis.maxIdle}"/><!-- 連接時最大的等待時間(毫秒) --><property name="maxWaitMillis" value="${redis.maxWait}"/><!-- 在提取一個jedis實例時,是否提前進行驗證操作;如果為true,則得到的jedis實例均是可用的 --><property name="testOnBorrow" value="${redis.testOnBorrow}"/></bean><bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"><property name="hostName" value="${redis.host}"/><property name="port" value="${redis.port}"/><property name="password" value="${redis.pass}"/><property name="poolConfig" ref="poolConfig"/></bean><bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"><property name="connectionFactory" ref="jedisConnectionFactory"/></bean> </bean>實例
本實例源碼:Github
首先加載配置文件spring-redis.xml,注入RedisTemplate模板類:
@Autowired private RedisTemplate redisTemplate;值類型
RedisTemplate提供的很多操作redis數據庫的方法都是boundxxOps這種。
添加
@Test public void setValue(){redisTemplate.boundValueOps("name").set("tycoding"); }如果配置都正常的情況下,運行此方法就能向db0數據庫中添加一條key為name的記錄;那么我們在redis命令行中查看所有的key:
奇怪,我添加的key明明是name,為什么查出來的確實一堆亂碼值呢?我們再使用redis命令行單獨添加一條記錄:
set testK testV此時我們又發現,使用redis原生命令添加的數據是不會亂碼的;那么就肯定是Spring Data Redis的原因了。經查詢是因為redisTemplate模板類在操作redis序列化的原因,我們要手動配置序列化方式為:StringRedisSerializer
修改之前創建的spring-redis.xml配置文件:
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"><property name="connectionFactory" ref="jedisConnectionFactory"/><!-- 序列化策略 推薦使用StringRedisSerializer --><property name="keySerializer"><bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/></property><property name="valueSerializer"><bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/></property><property name="hashKeySerializer"><bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/></property><property name="hashValueSerializer"><bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/></property> </bean>再次添加數據
查詢
@Test public void getValue(){Object name = redisTemplate.boundValueOps("name").get();System.out.println(name); }刪除
@Test public void deleteValue(){redisTemplate.delete("name"); }Set類型
添加
@Test public void setValueBySet(){redisTemplate.boundSetOps("nameset").add("tycoding"); }查詢
@Test public void getValueBySet(){Set nameset = redisTemplate.boundSetOps("nameset").members();System.out.println(nameset); }刪除Set中某一個值
@Test public void deleteValueBySet(){redisTemplate.boundSetOps("nameset").remove("涂陌"); }刪除整個Set
@Test public void deleteAllValueByset(){redisTemplate.delete("nameset"); }List類型
右壓棧
右壓棧,后添加的對象排在后邊
@Test public void setRightValueByList(){redisTemplate.boundListOps("namelist").rightPush("tycoding");redisTemplate.boundListOps("namelist").rightPush("涂陌"); }顯示右壓棧集合
@Test public void getRightValueByListI(){List namelist = redisTemplate.boundListOps("namelist").range(0, 10);System.out.println(namelist); }左壓棧
左壓棧,后添加的對象排在前面
@Testpublic void setLeftValueByList(){redisTemplate.boundListOps("namelist2").leftPush("tycoding");redisTemplate.boundListOps("namelist2").leftPush("涂陌");}顯示左壓棧的集合:
@Testpublic void getLeftValueByList(){List name2 = redisTemplate.boundListOps("namelist2").range(0, 10);System.out.println(name2);}根據索引查詢集合中的元素
@Testpublic void searchByIndex(){Object namelist = redisTemplate.boundListOps("namelist").index(1);System.out.println(namelist);}Hash類型
添加
@Testpublic void setValueByHash(){redisTemplate.boundHashOps("namehash").put("a","tycoding");}提取所有的KEY
@Testpublic void getKeysByHash(){Set namehash = redisTemplate.boundHashOps("namehash").keys();System.out.println(namehash);}提取所有的VALUE
@Testpublic void getValuesByHash(){List namehash = redisTemplate.boundHashOps("namehash").values();System.out.println(namehash);}根據KEY取值
@Testpublic void getValueByHash(){Object o = redisTemplate.boundHashOps("namehash").get("a");System.out.println(o);}根據KEY移除值
@Testpublic void deleteValueByHash(){redisTemplate.boundHashOps("namehash").delete("a");}<br/>
測試
上面說了一大堆,沒有實際的測試,著實不清楚Redis究竟效果如何,是不是真的提高了訪問速度?
下面我們以查詢數據庫所有值的功能來看一下使用Redis緩存和未使用緩存直接查詢數據庫所用時間。
本例源碼地址:Github
未使用Redis緩存,直接請求數據庫
public List<Goods> findAll() {return goodsMapper.findAll(); }使用了Redis緩存
首先通過boundHashOps獲取Redis數據庫中是否存在KEY為all的數據,有的話就返回;沒有的話就查詢數據庫并將查詢到的數據添加到Redis數據庫中,且KEY為all
public List<Goods> findAll() {List<Goods> contentList = (List<Goods>) redisTemplate.boundHashOps("goods").get("all");if (contentList == null) {//說明緩存中沒有數據System.out.println("從數據庫中讀取數據放入redis...");contentList = goodsMapper.findAll();redisTemplate.boundHashOps("goods").put("all", contentList); //存入redis中} else {System.out.println("從緩存中讀取數據...");}// return goodsMapper.findAll();return contentList; }TestTime.java
@Test public void run1() {Long startTime = System.currentTimeMillis(); //開始時間goodsMapper.findAll();Long endTime = System.currentTimeMillis(); //結束時間System.out.println("查詢數據庫--共耗時:" + (endTime - startTime) + "毫秒"); //1007毫秒 }@Test public void run2() {Long startTime = System.currentTimeMillis(); //開始時間goodsService.findAll();Long endTime = System.currentTimeMillis(); //結束時間System.out.println("從redis中讀取所有數據,共耗時:" + (endTime - startTime) + "毫秒"); }在測試類中調用Service層的這兩個方法,得到的結果如下:
查詢數據庫--共耗時:1047毫秒從redis中讀取所有數據,共耗時:197毫秒<br/>
交流
如果大家有興趣,歡迎大家加入我的Java交流技術群:671017003 ,一起交流學習Java技術。博主目前一直在自學JAVA中,技術有限,如果可以,會盡力給大家提供一些幫助,或是一些學習方法,當然群里的大佬都會積極給新手答疑的。所以,別猶豫,快來加入我們吧!
<br/>
聯系
If you have some questions after you see this article, you can contact me or you can find some info by clicking these links.
- [Blog@TyCoding's blog](http://www.tycoding.cn)
- [GitHub@TyCoding](https://github.com/TyCoding)
- [ZhiHu@TyCoding](https://www.zhihu.com/people/tomo-83-82/activities)
轉載于:https://my.oschina.net/u/3955926/blog/2208586
總結
以上是生活随笔為你收集整理的Redis及Spring-Data-Redis入门学习的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Ubuntu与 Fedora之对比
- 下一篇: gradle idea java ssm