Redis五種數(shù)據(jù)結(jié)構(gòu)在JAVA中如何封裝使用
數(shù)據(jù)結(jié)構(gòu)
Redis有五種基礎(chǔ)數(shù)據(jù)結(jié)構(gòu),分別為:
1、string(字符串)
2、list(列表)
3、hash(字典)
4、set(集合)
5、zset(有序集合)
接下來我們就來具體看看每種數(shù)據(jù)結(jié)構(gòu)的簡介和常用指令,以及在JAVA中如何封裝使用吧!
string字符串
string字符串簡介
字符串的結(jié)構(gòu)使用非常的廣泛,常見的用途就是緩存用戶信息。比如說博主的《雜貨鋪實戰(zhàn)專欄》中的雜貨鋪項目,郵箱驗證時生成的郵箱驗證碼等等。
我們將要存儲的對象信息使用JSON序列化成字符串,然后將序列化后的字符串使用Redis進(jìn)行緩存。在取存儲信息的時候進(jìn)行一次反序列化操作就可以了。
Redis的字符串與Java的字符串有所不同的就是,Java中的String是final類型的字符串,而Redis的字符串是動態(tài)字符串,是可以修改的字符串,內(nèi)部實現(xiàn)結(jié)構(gòu)類似于Java的ArrayList,采用預(yù)分配冗余空間來減少內(nèi)存的頻繁分配。
既Redis會分配比實際字符串大的capacity(空間),擴(kuò)容的時候就擴(kuò)容加倍現(xiàn)有的空間。但是字符串的最大長度為512MB。
一些普通的操作比如set、get、exists、del如下:
當(dāng)然也可以通過mset、mget批量讀寫:
我們都知道,有些數(shù)據(jù)我們是不會讓它長久存儲在緩存里的,所以要設(shè)置對應(yīng)的過期時間,可以通過expire、setex來設(shè)置,并且可以通過sexnx來判斷key值是否存在不存在就創(chuàng)建:
當(dāng)我們的value是一個整數(shù)的時候,還可以通過incr、decr、incrby、decrby進(jìn)行增減操作,需要注意的是它的返回是介于signed long的最大值以及最小值之間的,一旦超出這個范圍,就會報錯:
string字符串在Java中的封裝
(注:以下只列舉string類型的工具類的完整寫法,其他數(shù)據(jù)結(jié)構(gòu)只列舉部分寫法)
在pom.xml引入依賴:
<!-- redis依賴包 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
你可以在yml文件中配置,或者在properties文件中配置,挑選一個你認(rèn)為看著舒服的配置上就好:
# yml文件配置 spring: redis: host: 127.0.0.1 port: 6379 password: jedis: pool: #連接池最大連接數(shù)(使用負(fù)值表示沒有限制) max-active: 20 #連接池最大阻塞等待時間(使用負(fù)值表示沒有限制) max-wait: -1 #連接池中的最大空閑連接 max-idle: 20 #連接池中的最小空閑連接 min-idle: 2 #連接超時時間(毫秒) timeout: 5000
# properties文件配置 #Redis服務(wù)器地址 spring.redis.host=127.0.0.1 #Redis服務(wù)器連接端口 spring.redis.port=6379 #Redis數(shù)據(jù)庫索引(默認(rèn)為0) spring.redis.database=0 #連接池最大連接數(shù)(使用負(fù)值表示沒有限制) spring.redis.jedis.pool.max-active=50 #連接池最大阻塞等待時間(使用負(fù)值表示沒有限制) spring.redis.jedis.pool.max-wait=3000 #連接池中的最大空閑連接 spring.redis.jedis.pool.max-idle=20 #連接池中的最小空閑連接 spring.redis.jedis.pool.min-idle=2 #連接超時時間(毫秒) spring.redis.timeout=5000
然后編寫Redis的工具類:
package com.gantiexia.redis; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import java.util.concurrent.TimeUnit; /** * @author GanTieXia * @date 2021/11/21 18:07 */ @Component public class RedisUtils { /** 引入對應(yīng)的依賴后注入即可*/ @Autowired private RedisTemplate<String, String> redisTemplate; /** * 讀取緩存 * * @param key * @return */ public String get(final String key) { return redisTemplate.opsForValue().get(key); } /** * 寫入緩存 */ public boolean set(final String key, String value) { boolean result = false; try { redisTemplate.opsForValue().set(key, value); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } /** * 帶失效時間key * * @param key * @param value * @param timeOut * @param timeUnit * @return */ public boolean setKeyTimeOut(final String key,String value,long timeOut,TimeUnit timeUnit){ boolean result = false; try { redisTemplate.opsForValue().set(key, value, timeOut, timeUnit); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } /** * 更新緩存 */ public boolean getAndSet(final String key, String value) { boolean result = false; try { redisTemplate.opsForValue().getAndSet(key, value); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } /** * 刪除緩存 */ public boolean delete(final String key) { boolean result = false; try { redisTemplate.delete(key); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } }
list列表
list列表簡介
Redis的列表相當(dāng)于Java語言中的LinkedList,但是它是鏈表,而不是數(shù)組。那么這就意味著它的插入和刪除非???,而索引定位卻是比較慢的。
列表中的每個元素是使用雙向指針連接起來的,支持向前遍歷和向后遍歷。當(dāng)列表彈出最后一個元素時,該數(shù)據(jù)結(jié)構(gòu)自動刪除,內(nèi)存被回收。
Redis的列表結(jié)構(gòu)可以用來做異步隊列使用。我們把需要延后處理的任務(wù)結(jié)構(gòu)序列化成字符串,存入Redis列表,再啟用另一個線程從列表中取得數(shù)據(jù)進(jìn)行處理。
隊列
眾所周知,隊列是先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu),可用于我們常聽到的消息隊列,可確保元素的訪問順序性。
棧
棧是一種先進(jìn)后出的數(shù)據(jù)結(jié)果,跟我們常用的撤回是一個道理。
還可以通過lindex查找對應(yīng)位置上的元素,lrange 0 -1(-1代表最后一個元素,-2代表倒數(shù)第二個元素)獲取所有的元素,ltrim可以保留某個區(qū)間的元素,砍掉其他位置的元素。但是這些操作的時間復(fù)雜度為O(n),所以一般都不推薦使用。
list列表在Java中的封裝
(完整代碼參考上文string的封裝)
// 根據(jù)你的需要傳入相應(yīng)的參數(shù) // set方法的主要語句 redisTemplate.opsForList(). ; // .后面的方法根據(jù)你的應(yīng)用場景寫入
hash(字典)
hash字典簡介
Redis的字典相當(dāng)于JAVA語言里的HashMap,它是一個無需字典,內(nèi)部存儲了很多鍵值對。
而針對HashMap的概念模型,在博主的JAVA進(jìn)階篇——HashMap底層實現(xiàn)解析(一)一文中講解得很清晰了。
不同的是,Redis的字典的值只能是字符串,并且他們的rehash也是不一樣的。Java的HashMap在字典很大的時候,rehash是非常耗時的操作,得一次性全部rehash。而redis為了延續(xù)高性能,不產(chǎn)生堵塞,采用了漸進(jìn)式的rehash策略。
漸進(jìn)式rehash策略就是會在rehash的同時,保留新舊兩個hash結(jié)構(gòu),查詢時會同時查詢兩個hash結(jié)構(gòu),然后通過后續(xù)的定時任務(wù)以及hash操作指令中,將舊的hash結(jié)構(gòu)轉(zhuǎn)移到新的hash結(jié)構(gòu)中,在最后一個hash元素搬移之后,舊hash結(jié)構(gòu)刪除,內(nèi)存被回收。
hash的好處在哪呢,舉個例子,當(dāng)我們存儲用戶信息的時候,string是將整條信息直接序列化后存儲,取出來以后還需要反序列化再獲取我們想要的信息。使用hash則可以對用戶結(jié)構(gòu)中的每一個單一字段進(jìn)行存儲,比如我們要獲取用戶名的之后,就不用拿到一整條用戶信息了,這樣就可以節(jié)省網(wǎng)絡(luò)流量。
但美中不足的是,hash結(jié)構(gòu)的存儲消耗要高于單個字符串。
接下來我們來看看操作:
hash字典在Java中的封裝
(完整代碼參考上文string的封裝)
// 根據(jù)你的需要傳入相應(yīng)的參數(shù) // set方法的主要語句 redisTemplate.opsForHash(). ; // .后面的方法根據(jù)你的應(yīng)用場景寫入
set(集合)
set集合簡介
Redis的集合相當(dāng)于Java中的HashSet,內(nèi)部的鍵值是無序的、唯一的,也就是在Java中我們所常用的使用Set去重。
Redis的集合內(nèi)部相當(dāng)于一個特殊的字典,字典中每一個key的鍵值value都是NULL,同其他數(shù)據(jù)結(jié)構(gòu)一樣,最后一個元素被移除時,數(shù)據(jù)結(jié)構(gòu)刪除,內(nèi)存被回收。
接下來我們來看看操作指令:
set集合在Java中的封裝
(完整代碼參考上文string的封裝)
// 根據(jù)你的需要傳入相應(yīng)的參數(shù) // set方法的主要語句 redisTemplate.opsForSet(). ; //.后面的方法根據(jù)你的應(yīng)用場景寫入
zset(有序列表)
zset有序列表
zset也是一個set,它保證了內(nèi)部value的唯一性,并且給每一個value賦予一個score,代表value的排序權(quán)重。
zset可以用來干什么呢?比如粉絲列表,打開粉絲列表,value存儲用戶信息,score存儲關(guān)注時間,粉絲列表就可以以關(guān)注時間排序展示…等等這里就不做過多的闡述了。
下面我們來看看操作:
zset有序列表在Java中的封裝
(完整代碼參考上文string的封裝)
// 根據(jù)你的需要傳入相應(yīng)的參數(shù) // set方法的主要語句 redisTemplate.opsForZSet(). ; // .后面的方法根據(jù)你的應(yīng)用場景寫入
到此這篇關(guān)于Redis五種數(shù)據(jù)結(jié)構(gòu)在JAVA中如何封裝使用的文章就介紹到這了,更多相關(guān)Redis的內(nèi)容請搜索本站以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持本站!
版權(quán)聲明:本站文章來源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請保持原文完整并注明來源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學(xué)習(xí)參考,不代表本站立場,如有內(nèi)容涉嫌侵權(quán),請聯(lián)系alex-e#qq.com處理。