欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Redis實(shí)戰(zhàn)之Jedis使用技巧詳解

 更新時間:2022年12月22日 10:35:06   作者:鴨血粉絲Tang  
Jedis?是老牌的?Redis?的?Java?客戶端,提供了比較全面的?Redis?命令的操作支持,也是目前使用最廣泛的客戶端。這篇文章主要為大家詳細(xì)介紹了Jedis的使用技巧,需要的可以參考一下

一、摘要

在上一篇文章中,我們詳細(xì)的介紹了 redis 的安裝和常見的操作命令,以及可視化工具的介紹。

剛知道服務(wù)端的操作知識,還是遠(yuǎn)遠(yuǎn)不夠的,如果想要真正在項(xiàng)目中得到應(yīng)用,我們還需要一個 redis 的客戶端,然后將其集成到項(xiàng)目中,讓程序自動根據(jù)我們的業(yè)務(wù)需要自動處理。

基于 redis 開放的通信協(xié)議,大神們紛紛開發(fā)了各種語言的 redis 客戶端,有 c、c++、java、python、php、nodeJs 等等開發(fā)語言的客戶端,準(zhǔn)確來說其實(shí)這些客戶端都是基于 redis 命令做了一層封裝,然后打包成工具以便大家更佳方便的操作 redis,以 Java 項(xiàng)目為例,使用最廣的就是以下三種客戶端:

  • Jedis
  • Lettuce
  • Redisson

由于篇幅的原因,我們分三篇文章來詳細(xì)的講解每個客戶端的使用方式以及它的優(yōu)缺點(diǎn)。

廢話不多說,直奔主題!

二、Jedis

Jedis 是老牌的 Redis 的 Java 客戶端,提供了比較全面的 Redis 命令的操作支持,也是目前使用最廣泛的客戶端。

官方網(wǎng)址如下:

https://github.com/redis/jedis

如何在項(xiàng)目中集成 Jedis 呢?請看下文!

2.1、基本使用

首先創(chuàng)建一個普通的 Maven 項(xiàng)目,然后添加Jedis依賴包!

<dependency>
??<groupId>redis.clients</groupId>
??<artifactId>jedis</artifactId>
??<version>3.9.0</version>
</dependency>

然后創(chuàng)建一個簡單的測試,即可實(shí)現(xiàn)連接!

public?class?JedisMain?{

????public?static?void?main(String[]?args)?{
????????//?1.構(gòu)造一個?Jedis?對象,因?yàn)檫@里使用的默認(rèn)端口?6379,所以不用配置端口
????????Jedis?jedis?=?new?Jedis("127.0.0.1",?6379);
????????//?2.密碼認(rèn)證
????????jedis.auth("111111");
????????//?3.測試是否連接成功
????????String?ping?=?jedis.ping();
????????//?4.返回?pong?表示連接成功
????????System.out.println(ping);
????}
}

對于 Jedis 而言,一旦連接上了 Redis 服務(wù)器,剩下的操作就非常容易了,由于 Jedis 中的 API 和 Redis 的命令高度一致,所以,Jedis 中的方法見名知意,直接使用即可。

2.2、連接池

雖然 redis 服務(wù)端是單線程操作,但是在實(shí)際項(xiàng)目中,使用 Jedis 對象來操作 redis 時,每次操作都需要新建/關(guān)閉 TCP 連接,連接資源開銷很高,同時 Jedis 對象的個數(shù)不受限制,在極端情況下可能會造成連接泄漏,同時 Jedis 存在多線程不安全的問題。

為什么說 Jedis 線程不安全,更加詳細(xì)的原因可以參考:使用Jedis面臨的非線程安全問題詳解

所以我們需要將 Jedis 交給線程池來管理,使用 Jedis 對象時,從連接池獲取 Jedis,使用完成之后,再還給連接池。

在使用之前,需要添加common-pool線程池依賴包!

<dependency>
?<groupId>org.apache.commons</groupId>
?<artifactId>commons-pool2</artifactId>
?<version>2.11.1</version>
</dependency>

創(chuàng)建一個簡單的使用線程池測試用例。

public?class?JedisPoolMain?{

????public?static?void?main(String[]?args)?{
????????//?1.?構(gòu)造一個?Jedis?連接池
????????JedisPool?pool?=?new?JedisPool("127.0.0.1",?6379);
????????//?2.?從連接池中獲取一個?Jedis?連接
????????Jedis?jedis?=?pool.getResource();
????????jedis.auth("111111");
????????//?3.?Jedis?操作
????????String?ping?=?jedis.ping();
????????System.out.println(ping);
????????//?4.?歸還連接
????????jedis.close();
????}
}

2.3、連接池配置

在實(shí)際的使用過程中,我們常常會這樣來初始化線程池JedisPool,詳細(xì)代碼如下:

public?class?RedisPoolUtils?{

????private?static?JedisPool?jedisPool?=?null;

????/**
?????*?redis服務(wù)器地址
?????*/
????private?static?String?addr?=?"127.0.0.1";

????/**
?????*?redis服務(wù)器端口
?????*/
????private?static?int?port?=?6379;

????/**
?????*?redis服務(wù)器密碼
?????*/
????private?static?String?auth?=?"111111";


????static{
????????try?{
????????????JedisPoolConfig?config?=?new?JedisPoolConfig();
????????????//連接耗盡時是否阻塞,?false報(bào)異常,ture阻塞直到超時,?默認(rèn)true
????????????config.setBlockWhenExhausted(true);
????????????//設(shè)置的逐出策略類名,?默認(rèn)DefaultEvictionPolicy(當(dāng)連接超過最大空閑時間,或連接數(shù)超過最大空閑連接數(shù))
????????????config.setEvictionPolicyClassName("org.apache.commons.pool2.impl.DefaultEvictionPolicy");
????????????//是否啟用pool的jmx管理功能,?默認(rèn)true
????????????config.setJmxEnabled(true);
????????????//MBean?ObjectName?=?new?ObjectName("org.apache.commons.pool2:type=GenericObjectPool,name="?+?"pool"?+?i);?默認(rèn)為"pool",?JMX不熟,具體不知道是干啥的...默認(rèn)就好.
????????????config.setJmxNamePrefix("pool");
????????????//是否啟用后進(jìn)先出,?默認(rèn)true
????????????config.setLifo(true);
????????????//最大空閑連接數(shù),?默認(rèn)8個
????????????config.setMaxIdle(8);
????????????//最大連接數(shù),?默認(rèn)8個
????????????config.setMaxTotal(8);
????????????//獲取連接時的最大等待毫秒數(shù)(如果設(shè)置為阻塞時BlockWhenExhausted),如果超時就拋異常,?小于零:阻塞不確定的時間,??默認(rèn)-1
????????????config.setMaxWaitMillis(-1);
????????????//逐出連接的最小空閑時間?默認(rèn)1800000毫秒(30分鐘)
????????????config.setMinEvictableIdleTimeMillis(1800000);
????????????//最小空閑連接數(shù),?默認(rèn)0
????????????config.setMinIdle(0);
????????????//每次逐出檢查時?逐出的最大數(shù)目?如果為負(fù)數(shù)就是?:?1/abs(n),?默認(rèn)3
????????????config.setNumTestsPerEvictionRun(3);
????????????//對象空閑多久后逐出,?當(dāng)空閑時間>該值?且?空閑連接>最大空閑數(shù)?時直接逐出,不再根據(jù)MinEvictableIdleTimeMillis判斷??(默認(rèn)逐出策略)
????????????config.setSoftMinEvictableIdleTimeMillis(1800000);
????????????//在獲取連接的時候檢查有效性,?默認(rèn)false
????????????config.setTestOnBorrow(false);
????????????//在空閑時檢查有效性,?默認(rèn)false
????????????config.setTestWhileIdle(false);
????????????//逐出掃描的時間間隔(毫秒)?如果為負(fù)數(shù),則不運(yùn)行逐出線程,?默認(rèn)-1
????????????config.setTimeBetweenEvictionRunsMillis(-1);
????????????jedisPool?=?new?JedisPool(config,?addr,?port,?3000,?auth);
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????}
????}

????/**
?????*?獲取?Jedis?資源
?????*?@return
?????*/
????public?static?Jedis?getJedis()?{
????????if?(jedisPool?!=?null)?{
????????????return?jedisPool.getResource();
????????}
????????return?null;
????}

????/**
?????*?釋放Jedis資源
?????*/
????public?static?void?close(final?Jedis?jedis)?{
????????if?(jedis?!=?null)?{
????????????jedis.close();
????????}
????}

}

簡單測試

public?static?void?main(String[]?args)?throws?InterruptedException?{
????//獲取?jedis?客戶端
????Jedis?jedis?=?RedisPoolUtils.getJedis();

????System.out.println("清空數(shù)據(jù):"+jedis.flushDB());
????System.out.println("判斷某個鍵是否存在:"+jedis.exists("username"));
????System.out.println("新增<'username','xmr'>的鍵值對:"+jedis.set("username",?"xmr"));
????System.out.println(jedis.exists("username"));
????System.out.println("新增<'password','password'>的鍵值對:"+jedis.set("password",?"123"));
????System.out.print("系統(tǒng)中所有的鍵如下:");
????Set<String>?keys?=?jedis.keys("*");
????System.out.println(keys);
????System.out.println("刪除鍵password:"+jedis.del("password"));
????System.out.println("判斷鍵password是否存在:"+jedis.exists("password"));
????System.out.println("設(shè)置鍵username的過期時間為5s:"+jedis.expire("username",?8L));
????TimeUnit.SECONDS.sleep(1);
????System.out.println("查看鍵username的剩余生存時間:"+jedis.ttl("username"));
????System.out.println("移除鍵username的生存時間:"+jedis.persist("username"));
????System.out.println("查看鍵username的剩余生存時間:"+jedis.ttl("username"));
????System.out.println("查看鍵username所存儲的值的類型:"+jedis.type("username"));
????RedisPoolUtils.close(jedis);
}

運(yùn)行結(jié)果如下:

清空數(shù)據(jù):OK
判斷某個鍵是否存在:false
新增<'username','xmr'>的鍵值對:OK
true
新增<'password','password'>的鍵值對:OK
系統(tǒng)中所有的鍵如下:[password, username]
刪除鍵password:1
判斷鍵password是否存在:false
設(shè)置鍵username的過期時間為5s:1
查看鍵username的剩余生存時間:7
移除鍵username的生存時間:1
查看鍵username的剩余生存時間:-1
查看鍵username所存儲的值的類型:string

2.4、字符串常用 API 操作

public?class?RedisClientUtil?{

????private?static?final?Logger?log?=?LoggerFactory.getLogger(RedisClientUtil.class);


????/**
?????*?獲取指定key的值,如果key不存在返回null
?????*?返回值:返回?key?的值,如果?key?不存在時,返回?nil
?????*?@param?key
?????*?@return
?????*/
????public?static?String?get(String?key)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.get(key);
????????}?catch?(Exception?e){
????????????log.error("get命令操作失敗,請求參數(shù):{}",?key,e);
????????}
????????return?null;
????}


????/**
?????*?設(shè)置key的值為value
?????*?返回值:操作成功完成時返回?OK
?????*?@param?key
?????*?@return
?????*/
????public?static?String?set(String?key,?String?value)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.set(key,?value);
????????}?catch?(Exception?e){
????????????log.error("set命令操作失敗,參數(shù)key:{},參數(shù)value:{}",?key,?value,e);
????????}
????????return?null;
????}


????/**
?????*?刪除指定的key,返回值:被刪除?key?的數(shù)量
?????*?返回值:被刪除?key?的數(shù)量
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?del(String?key)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????Long?result?=?jedis.del(key);
????????????return?jedis.del(key);
????????}?catch?(Exception?e){
????????????log.error("del命令操作失敗,參數(shù)key:{}",?key,e);
????????}
????????return?0L;
????}


????/**
?????*?通過key向指定的value值追加值
?????*?返回值:追加指定值之后,?key中字符串的長度
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?append(String?key,?String?value)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.append(key,?value);
????????}?catch?(Exception?e){
????????????log.error("append命令操作失敗,參數(shù)key:{},參數(shù)value:{}",?key,?value,e);
????????}
????????return?0L;
????}

????/**
?????*?判斷key是否存在
?????*?返回值:true/false
?????*?@param?key
?????*?@return
?????*/
????public?static?Boolean?exists(String?key)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.exists(key);
????????}?catch?(Exception?e){
????????????log.error("exists命令操作失敗,參數(shù)key:{}",?key,e);
????????}
????????return?false;
????}


????/**
?????*?設(shè)置key的超時時間為seconds
?????*?返回值:若?key?存在返回?1?,否則返回?0
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?expire(String?key,?long?seconds)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.expire(key,?seconds);
????????}?catch?(Exception?e){
????????????log.error("expire命令操作失敗,參數(shù)key:{},參數(shù)seconds:{}",?key,?seconds,e);
????????}
????????return?0L;
????}

????/**
?????*?返回?key?的剩余過期時間(單位秒)
?????*?返回值:當(dāng)?key?不存在時,返回?-2?。?當(dāng)?key?存在但沒有設(shè)置剩余生存時間時,返回?-1?。?否則,以秒為單位,返回?key?的剩余生存時間
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?ttl(String?key)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.ttl(key);
????????}?catch?(Exception?e){
????????????log.error("ttl命令操作失敗,參數(shù)key:{}",?key,e);
????????}
????????return?0L;
????}


????/**
?????*?設(shè)置指定key的值為value,當(dāng)key不存在時才設(shè)置
?????*?返回值:設(shè)置成功返回?1,設(shè)置失敗返回?0
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?setnx(String?key,?String?value)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.setnx(key,?value);
????????}?catch?(Exception?e){
????????????log.error("setnx命令操作失敗,參數(shù)key:{},參數(shù)value:{}",?key,?value,e);
????????}
????????return?0L;
????}

????/**
?????*?設(shè)置指定key的值為value,并設(shè)置過期時間
?????*?返回值:設(shè)置成功時返回?OK
?????*?@param?key
?????*?@return
?????*/
????public?static?String?setex(String?key,?String?value,?long?seconds)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.setex(key,?seconds,?value);
????????}?catch?(Exception?e){
????????????log.error("setex命令操作失敗,參數(shù)key:{},參數(shù)value:{}",?key,?value,e);
????????}
????????return?null;
????}

????/**
?????*?通過key?和offset?從指定的位置開始將原先value替換
?????*?返回值:被修改后的字符串長度
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?setrange(String?key,?int?offset,?String?value)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.setrange(key,?offset,?value);
????????}?catch?(Exception?e){
????????????log.error("setrange命令操作失敗,參數(shù)key:{},參數(shù)value:{},參數(shù)offset:{}",?key,?value,?offset,e);
????????}
????????return?null;
????}


????/**
?????*?通過批量的key獲取批量的value
?????*?返回值:一個包含所有給定?key?的值的列表。
?????*?@param?keys
?????*?@return
?????*/
????public?static?List<String>?mget(String...?keys)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.mget(keys);
????????}?catch?(Exception?e){
????????????log.error("mget命令操作失敗,參數(shù)key:{}",?keys.toString(),e);
????????}
????????return?null;
????}

????/**
?????*?批量的設(shè)置key:value,也可以一個
?????*?返回值:總是返回?OK
?????*?@param?keysValues
?????*?@return
?????*/
????public?static?String?mset(String...?keysValues)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.mset(keysValues);
????????}?catch?(Exception?e){
????????????log.error("mset命令操作失敗,參數(shù)key:{}",?keysValues.toString(),e);
????????}
????????return?null;
????}


????/**
?????*?設(shè)置key的值,并返回一個舊值
?????*?返回值:返回給定?key?的舊值,當(dāng)?key?沒有舊值時,即?key?不存在時,返回?nil
?????*?@param?key
?????*?@return
?????*/
????public?static?String?getSet(String?key,?String?value)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.getSet(key,?value);
????????}?catch?(Exception?e){
????????????log.error("getSet命令操作失敗,參數(shù)key:{},參數(shù)value:{}",?key,?value,e);
????????}
????????return?null;
????}

????/**
?????*?通過下標(biāo)和?key?獲取指定下標(biāo)位置的?value
?????*?返回值:截取得到的子字符串
?????*?@param?key
?????*?@return
?????*/
????public?static?String?getrange(String?key,?int?startOffset,?int?endOffset)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.getrange(key,?startOffset,?endOffset);
????????}?catch?(Exception?e){
????????????log.error("getrange命令操作失敗,參數(shù)key:{},參數(shù)startOffset:{},參數(shù)offset:{}",?key,?startOffset,?endOffset,e);
????????}
????????return?null;
????}


????/**
?????*?通過key?對value進(jìn)行加值+1操作,當(dāng)value不是int類型時會返回錯誤,當(dāng)key不存在是則value為1
?????*?返回值:執(zhí)行INCR命令之后?key?的值
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?incr(String?key)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.incr(key);
????????}?catch?(Exception?e){
????????????log.error("incr命令操作失敗,參數(shù)key:{}",?key,?e);
????????}
????????return?0L;
????}


????/**
?????*?通過key給指定的value加值
?????*?返回值:執(zhí)行INCR命令之后?key?的值
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?incrBy(String?key,?long?increment)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.incrBy(key,?increment);
????????}?catch?(Exception?e){
????????????log.error("incrBy命令操作失敗,參數(shù)key:{},參數(shù)increment:{}",?key,?increment,e);
????????}
????????return?0L;
????}

????/**
?????*?對key的值做減減操作
?????*?返回值:執(zhí)行INCR命令之后?key?的值
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?decr(String?key)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.decr(key);
????????}?catch?(Exception?e){
????????????log.error("decr命令操作失敗,參數(shù)key:{}",?key,?e);
????????}
????????return?0L;
????}

????/**
?????*?對key的值做減減操作,減去指定的值
?????*?返回值:執(zhí)行INCR命令之后?key?的值
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?decrBy(String?key,?long?decrement)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.decrBy(key,?decrement);
????????}?catch?(Exception?e){
????????????log.error("decrBy命令操作失敗,參數(shù)key:{},參數(shù)decrement:{}",?key,?decrement,e);
????????}
????????return?0L;
????}


????/**
?????*?通過key獲取value值的長度
?????*?返回值:value值的長度
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?strlen(String?key)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.strlen(key);
????????}?catch?(Exception?e){
????????????log.error("strlen命令操作失敗,參數(shù)key:{}",?key,?e);
????????}
????????return?0L;
????}
}

2.5、哈希常用 API 操作

public?class?RedisClientUtil?{

????private?static?final?Logger?log?=?LoggerFactory.getLogger(RedisClientUtil.class);


????/**
?????*?通過key?和?field?獲取指定的?value
?????*?返回值:對應(yīng)的value值
?????*?@param?key
?????*?@return
?????*/
????public?static?String?hget(String?key,?String?field)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.hget(key,?field);
????????}?catch?(Exception?e){
????????????log.error("hget命令操作失敗,參數(shù)key:{},參數(shù)field:{}",?key,?field,e);
????????}
????????return?null;
????}

????/**
?????*?通過key給field設(shè)置指定的值,如果key不存在,則先創(chuàng)建
?????*?返回值:如果字段是哈希表中的一個新建字段,并且值設(shè)置成功,返回?1?;如果哈希表中域字段已經(jīng)存在且舊值已被新值覆蓋,返回?0?。
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?hset(String?key,?String?field,?String?value)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.hset(key,?field,?value);
????????}?catch?(Exception?e){
????????????log.error("hset命令操作失敗,參數(shù)key:{},參數(shù)field:{},參數(shù)value:{}",?key,?field,?value,e);
????????}
????????return?0L;
????}


????/**
?????*?通過key和field判斷是否有指定的value存在
?????*?返回值:true/false
?????*?@param?key
?????*?@return
?????*/
????public?static?Boolean?hexists(String?key,?String?field)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.hexists(key,?field);
????????}?catch?(Exception?e){
????????????log.error("hexists命令操作失敗,參數(shù)key:{},參數(shù)field:{}",?key,?field,e);
????????}
????????return?false;
????}


????/**
?????*?通過key返回field的數(shù)量
?????*?返回值:field的數(shù)量
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?hlen(String?key)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.hlen(key);
????????}?catch?(Exception?e){
????????????log.error("hlen命令操作失敗,參數(shù)key:{}",?key,e);
????????}
????????return?0L;
????}


????/**
?????*?通過key?刪除指定的?field
?????*?返回值:刪除的數(shù)量
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?hdel(String?key,?String...?fields)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.hdel(key,?fields);
????????}?catch?(Exception?e){
????????????log.error("hdel命令操作失敗,參數(shù)key:{},參數(shù)fields:{}",?key,?fields.toString(),e);
????????}
????????return?0L;
????}


????/**
?????*?通過key返回所有的field
?????*?返回值:field集合
?????*?@param?key
?????*?@return
?????*/
????public?static?Set<String>?hkeys(String?key)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.hkeys(key);
????????}?catch?(Exception?e){
????????????log.error("hkeys命令操作失敗,參數(shù)key:{}",?key,e);
????????}
????????return?null;
????}


????/**
?????*?通過key獲取所有的field和value
?????*?返回值:map對象
?????*?@param?key
?????*?@return
?????*/
????public?static?Map<String,?String>?hgetAll(String?key)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.hgetAll(key);
????????}?catch?(Exception?e){
????????????log.error("hgetAll命令操作失敗,參數(shù)key:{}",?key,e);
????????}
????????return?null;
????}
}

2.6、列表常用 API 操作

public?class?RedisClientUtil?{

????private?static?final?Logger?log?=?LoggerFactory.getLogger(RedisClientUtil.class);


????/**
?????*?過key向list頭部添加字符串
?????*?返回值:執(zhí)行?LPUSH?命令后,列表的長度
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?lpush(String?key,?String...?strs)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.lpush(key,?strs);
????????}?catch?(Exception?e){
????????????log.error("lpush命令操作失敗,參數(shù)key:{},參數(shù)strs:{}",?key,?strs.toString(),e);
????????}
????????return?null;
????}


????/**
?????*?通過key向list尾部添加字符串
?????*?返回值:執(zhí)行?RPUSH?命令后,列表的長度
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?rpush(String?key,?String...?strs)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.rpush(key,?strs);
????????}?catch?(Exception?e){
????????????log.error("rpush命令操作失敗,參數(shù)key:{},參數(shù)strs:{}",?key,?strs.toString(),e);
????????}
????????return?null;
????}

????/**
?????*?通過key設(shè)置list指定下標(biāo)位置的value?如果下標(biāo)超過list里面value的個數(shù)則報(bào)錯
?????*?返回值:操作成功返回?ok?,否則返回錯誤信息
?????*?@param?key
?????*?@return
?????*/
????public?static?String?lset(String?key,?Long?index,?String?value)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.lset(key,?index,?value);
????????}?catch?(Exception?e){
????????????log.error("lset命令操作失敗,參數(shù)key:{},參數(shù)index:{},參數(shù)value:{}",?key,?index,?value,e);
????????}
????????return?null;
????}


????/**
?????*?通過key從對應(yīng)的list中刪除指定的count個?和?value相同的元素
?????*?返回值:返回被刪除的個數(shù)
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?lrem(String?key,?long?count,?String?value)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.lrem(key,?count,?value);
????????}?catch?(Exception?e){
????????????log.error("lrem命令操作失敗,參數(shù)key:{},參數(shù)count:{},參數(shù)value:{}",?key,?count,?value,e);
????????}
????????return?null;
????}



????/**
?????*?通過key保留list中從strat下標(biāo)開始到end下標(biāo)結(jié)束的value值
?????*?返回值:操作成功返回?ok?,否則返回錯誤信息
?????*?@param?key
?????*?@return
?????*/
????public?static?String?ltrim(String?key,?long?start,?long?end)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.ltrim(key,?start,?end);
????????}?catch?(Exception?e){
????????????log.error("ltrim命令操作失敗,參數(shù)key:{},參數(shù)start:{},參數(shù)end:{}",?key,?start,?end,e);
????????}
????????return?null;
????}


????/**
?????*?通過key從list的頭部刪除一個value,并返回該value
?????*?返回值:value值
?????*?@param?key
?????*?@return
?????*/
????public?static?String?lpop(String?key)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.lpop(key);
????????}?catch?(Exception?e){
????????????log.error("lpop命令操作失敗,參數(shù)key:{}",?key,e);
????????}
????????return?null;
????}

????/**
?????*?通過key從list尾部刪除一個value,并返回該元素
?????*?返回值:value值
?????*?@param?key
?????*?@return
?????*/
????public?static?String?rpop(String?key)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.rpop(key);
????????}?catch?(Exception?e){
????????????log.error("rpop命令操作失敗,參數(shù)key:{}",?key,e);
????????}
????????return?null;
????}


????/**
?????*?通過key獲取list中指定下標(biāo)位置的value
?????*?返回值:value值
?????*?@param?key
?????*?@return
?????*/
????public?static?String?lindex(String?key,?long?index){
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.lindex(key,?index);
????????}?catch?(Exception?e){
????????????log.error("lindex命令操作失敗,參數(shù)key:{},參數(shù)index:{}",?key,?index,e);
????????}
????????return?null;
????}


????/**
?????*?通過key返回list的長度
?????*?返回值:value值
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?llen(String?key)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.llen(key);
????????}?catch?(Exception?e){
????????????log.error("llen命令操作失敗,參數(shù)key:{}",?key,e);
????????}
????????return?null;
????}


????/**
?????*?通過key獲取list指定下標(biāo)位置的value?如果start?為?0?end?為?-1?則返回全部的list中的value
?????*?返回值:value值
?????*?@param?key
?????*?@return
?????*/
????public?static?List<String>?lrange(String?key,?long?start,?long?end)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.lrange(key,?start,?end);
????????}?catch?(Exception?e){
????????????log.error("lrange命令操作失敗,參數(shù)key:{},參數(shù)start:{},參數(shù)end:{}",?key,?start,?end,e);
????????}
????????return?null;
????}

}

2.7、集合常用 API 操作

public?class?RedisClientUtil?{

????private?static?final?Logger?log?=?LoggerFactory.getLogger(RedisClientUtil.class);


????/**
?????*?通過key向指定的set中添加value
?????*?返回值:添加成功的個數(shù)
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?sadd(String?key,?String...?members)??{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.sadd(key,?members);
????????}?catch?(Exception?e){
????????????log.error("sadd命令操作失敗,參數(shù)key:{},參數(shù)members:{}",?key,?members.toString(),e);
????????}
????????return?null;
????}

????/**
?????*?通過key刪除set中對應(yīng)的value值
?????*?返回值:刪除成功的個數(shù)
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?srem(String?key,?String...?members)??{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.srem(key,?members);
????????}?catch?(Exception?e){
????????????log.error("srem命令操作失敗,參數(shù)key:{},參數(shù)members:{}",?key,?members.toString(),e);
????????}
????????return?null;
????}

????/**
?????*?通過key獲取set中value的個數(shù)
?????*?返回值:value的個數(shù)
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?scard(String?key)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.scard(key);
????????}?catch?(Exception?e){
????????????log.error("scard命令操作失敗,參數(shù)key:{}",?key,e);
????????}
????????return?0L;
????}


????/**
?????*?通過key判斷value是否是set中的元素
?????*?返回值:true/false
?????*?@param?key
?????*?@return
?????*/
????public?static?Boolean?sismember(String?key,?String?member)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.sismember(key,?member);
????????}?catch?(Exception?e){
????????????log.error("sismember命令操作失敗,參數(shù)key:{},參數(shù)member:{}",?key,?member,e);
????????}
????????return?false;
????}


????/**
?????*?通過key獲取set中所有的value
?????*?返回值:所有的value
?????*?@param?key
?????*?@return
?????*/
????public?static?Set<String>?smembers(String?key)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.smembers(key);
????????}?catch?(Exception?e){
????????????log.error("smembers命令操作失敗,參數(shù)key:{}",?key,e);
????????}
????????return?null;
????}

}

2.8、有序集合常用 API 操作

public?class?RedisClientUtil?{

????private?static?final?Logger?log?=?LoggerFactory.getLogger(RedisClientUtil.class);

????/**
?????*?通過key向zset中添加value,score,其中score就是用來排序的?如果該value已經(jīng)存在則根據(jù)score更新元素
?????*?返回值:被成功添加的新成員的數(shù)量,不包括那些被更新的、已經(jīng)存在的成員
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?zadd(String?key,?double?score,?String?member)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.zadd(key,?score,?member);
????????}?catch?(Exception?e){
????????????log.error("zadd命令操作失敗,參數(shù)key:{},參數(shù)score:{},參數(shù)member:{}",?key,?score,?member,e);
????????}
????????return?null;
????}


????/**
?????*?通過key刪除在zset中指定的value
?????*?返回值:刪除個數(shù)
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?zrem(String?key,?String...?members)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.zrem(key,?members);
????????}?catch?(Exception?e){
????????????log.error("zrem命令操作失敗,參數(shù)key:{},參數(shù)members:{}",?key,?members.toString(),e);
????????}
????????return?null;
????}


????/**
?????*?通過key增加該zset中value的score的值
?????*?返回值:member?成員的新分?jǐn)?shù)值
?????*?@param?key
?????*?@return
?????*/
????public?static?Double?zincrby(String?key,?double?score,?String?member)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.zincrby(key,?score,?member);
????????}?catch?(Exception?e){
????????????log.error("zincrby命令操作失敗,參數(shù)key:{},參數(shù)score:{},參數(shù)member:{}",?key,?score,?member,e);
????????}
????????return?null;
????}

????/**
?????*?通過key返回zset中value的排名?下標(biāo)從小到大排序
?????*?返回值:返回?member?的排名
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?zrank(String?key,?String?member)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.zrank(key,?member);
????????}?catch?(Exception?e){
????????????log.error("zrank命令操作失敗,參數(shù)key:{},參數(shù)member:{}",?key,?member,e);
????????}
????????return?null;
????}


????/**
?????*?通過key將獲取score從start到end中zset的value?socre從大到小排序?當(dāng)start為0?end為-1時返回全部
?????*?返回值:返回?member?集合
?????*?@param?key
?????*?@return
?????*/
????public?static?Set<String>?zrevrange(String?key,?long?start,?long?end)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.zrevrange(key,?start,?end);
????????}?catch?(Exception?e){
????????????log.error("zrevrange命令操作失敗,參數(shù)key:{},參數(shù)start:{},參數(shù)end:{}",?key,?start,?end,e);
????????}
????????return?null;
????}

????/**
?????*?返回指定區(qū)間內(nèi)zset中value的數(shù)量
?????*?返回值:返回?member?集合
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?zcount(String?key,?String?min,?String?max)??{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.zcount(key,?min,?max);
????????}?catch?(Exception?e){
????????????log.error("zcount命令操作失敗,參數(shù)key:{},參數(shù)min:{},參數(shù)max:{}",?key,?min,?max,e);
????????}
????????return?null;
????}


????/**
?????*?通過key返回zset中的value個數(shù)
?????*?返回值:返回?member?集合
?????*?@param?key
?????*?@return
?????*/
????public?static?Long?zcard(String?key)??{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.zcard(key);
????????}?catch?(Exception?e){
????????????log.error("zcard命令操作失敗,參數(shù)key:{}",?key,e);
????????}
????????return?null;
????}


????/**
?????*?返回滿足pattern表達(dá)式的所有key?keys(*)?返回所有的key
?????*?返回值:返回?key?集合
?????*?@param?pattern
?????*?@return
?????*/
????public?static?Set<String>?keys(String?pattern)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.keys(pattern);
????????}?catch?(Exception?e){
????????????log.error("keys命令操作失敗,參數(shù)pattern:{}",?pattern,e);
????????}
????????return?null;
????}

????/**
?????*?通過key判斷值得類型
?????*?返回值:值的類型
?????*?@param?key
?????*?@return
?????*/
????public?static?String?type(String?key)?{
????????try?(Jedis?jedis?=?jedisPool.getResource())?{
????????????return?jedis.type(key);
????????}?catch?(Exception?e){
????????????log.error("type命令操作失敗,參數(shù)key:{}",?key,e);
????????}
????????return?null;
????}

}

三、集群配置

在實(shí)際的項(xiàng)目生產(chǎn)環(huán)境中,redis 通常不是以單臺服務(wù)實(shí)例來運(yùn)行的,因?yàn)橐坏┓?wù)器掛了,可能所有的下游服務(wù)都會受到影響,因此為了保障單臺服務(wù)器即使出現(xiàn)故障也能運(yùn)行,通常運(yùn)維組會搭建集群環(huán)境,來保證服務(wù)高可用。

搭建的方式有兩種,哨兵模式和 Cluster 模式。

  • 哨兵模式:對redis服務(wù)器進(jìn)行監(jiān)控,如果有宕機(jī)的,就從備機(jī)里面選一個出來作為主機(jī),實(shí)現(xiàn)自動切換
  • Cluster 模式:將數(shù)據(jù)進(jìn)行分片存儲,避免全部節(jié)點(diǎn)數(shù)據(jù)都一樣,浪費(fèi)空間

3.1、哨兵模式

哨兵模式簡單的說,就是一臺主機(jī),一臺備機(jī),外加一臺監(jiān)控服務(wù),當(dāng)監(jiān)控服務(wù)觀測到主機(jī)已經(jīng)宕機(jī),就會將備用機(jī)切換成主機(jī),以便繼續(xù)提供服務(wù)。

public?class?RedisPoolUtils?{

????private?static?Jedis?jedis;

????private?static?JedisSentinelPool?jedisSentinelPool;

????static{
????????try?{
????????????JedisPoolConfig?config?=?new?JedisPoolConfig();
????????????//最大空閑連接數(shù),?默認(rèn)8個
????????????config.setMaxIdle(8);
????????????//最大連接數(shù),?默認(rèn)8個
????????????config.setMaxTotal(8);
????????????//最小空閑連接數(shù),?默認(rèn)0
????????????config.setMinIdle(0);
????????????//獲取連接時的最大等待毫秒數(shù)(如果設(shè)置為阻塞時BlockWhenExhausted),如果超時就拋異常,?小于零:阻塞不確定的時間,??默認(rèn)-1
????????????config.setMaxWaitMillis(3000);
????????????//在獲取連接的時候檢查有效性,表示取出的redis對象可用,?默認(rèn)false
????????????config.setTestOnBorrow(true);


????????????//redis服務(wù)器列表
????????????Set<String>?sentinels?=?new?HashSet<>();
????????????sentinels.add(new?HostAndPort("192.168.43.212",?26379).toString());
????????????sentinels.add(new?HostAndPort("192.168.43.213",?26379).toString());
????????????sentinels.add(new?HostAndPort("192.168.43.214",?26379).toString());

????????????//初始化連接池
????????????jedisSentinelPool?=?new?JedisSentinelPool("mymaster",?sentinels,?config,?"111111");
????????????//?從池中獲取一個Jedis對象
????????????jedis?=?jedisSentinelPool.getResource();
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????}
????}
????
}

3.2、集群模式

為了保證高可用,redis-cluster集群通常會引入主從復(fù)制模型,一個主節(jié)點(diǎn)對應(yīng)一個或者多個從節(jié)點(diǎn),當(dāng)主節(jié)點(diǎn)宕機(jī)的時候,就會啟用從節(jié)點(diǎn)。

public?class?RedisPoolUtils?{

????static{
????????try?{
????????????JedisPoolConfig?config?=?new?JedisPoolConfig();
????????????//最大空閑連接數(shù),?默認(rèn)8個
????????????config.setMaxIdle(8);
????????????//最大連接數(shù),?默認(rèn)8個
????????????config.setMaxTotal(8);
????????????//最小空閑連接數(shù),?默認(rèn)0
????????????config.setMinIdle(0);
????????????//獲取連接時的最大等待毫秒數(shù)(如果設(shè)置為阻塞時BlockWhenExhausted),如果超時就拋異常,?小于零:阻塞不確定的時間,??默認(rèn)-1
????????????config.setMaxWaitMillis(3000);
????????????//在獲取連接的時候檢查有效性,表示取出的redis對象可用,?默認(rèn)false
????????????config.setTestOnBorrow(true);

????????????Set<HostAndPort>?nodes?=?new?HashSet<>();
????????????nodes.add(new?HostAndPort("192.168.43.212",?26379));
????????????nodes.add(new?HostAndPort("192.168.43.213",?26379));
????????????nodes.add(new?HostAndPort("192.168.43.214",?26379));

????????????JedisCluster?jedisCluster?=?new?JedisCluster(nodes,?config);
????????????jedisCluster.set("key",?"hello?world");

????????????jedisCluster.close();
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????}
????}
}

四、小結(jié)

jedis客戶端是目前使用最廣泛的一款 java 客戶端,也是老牌的 Redis 的 Java 實(shí)現(xiàn)客戶端。

優(yōu)點(diǎn)很突出:

  • 比較全面的提供了 Redis 的操作特性,也就是說你能用 redis 命令操作的,Jedis 包都也給你封裝好了,直接使用即可
  • 使用廣泛,易上手

當(dāng)然,缺點(diǎn)也有:

  • Jedis 客戶端實(shí)例不是線程安全的,需要借助連接池來管理和使用 Jedis
  • 使用阻塞的I/O,且其方法調(diào)用都是同步的,程序流需要等到 sockets 處理完 I/O 才能執(zhí)行,不支持異步

到此這篇關(guān)于Redis實(shí)戰(zhàn)之Jedis使用技巧詳解的文章就介紹到這了,更多相關(guān)Redis Jedis內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • redis學(xué)習(xí)之RDB、AOF與復(fù)制時對過期鍵的處理教程

    redis學(xué)習(xí)之RDB、AOF與復(fù)制時對過期鍵的處理教程

    這篇文章主要給大家介紹了關(guān)于redis學(xué)習(xí)之RDB、AOF與復(fù)制時對過期鍵處理的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用redis具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • redis keys與scan命令的區(qū)別說明

    redis keys與scan命令的區(qū)別說明

    這篇文章主要介紹了redis keys與scan命令的區(qū)別說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • redis實(shí)現(xiàn)分布式全局唯一id的示例代碼

    redis實(shí)現(xiàn)分布式全局唯一id的示例代碼

    在某些場景中,我們需要生成全局的唯一ID,本文主要介紹了redis實(shí)現(xiàn)分布式全局唯一id的示例代碼,具有一定的參考價值,感興趣的可以了解一下
    2024-04-04
  • RedisDesktopManager遠(yuǎn)程連接redis的實(shí)現(xiàn)

    RedisDesktopManager遠(yuǎn)程連接redis的實(shí)現(xiàn)

    本文主要介紹了RedisDesktopManager遠(yuǎn)程連接redis的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • Go語言操作RediSearch進(jìn)行搜索方法示例詳解

    Go語言操作RediSearch進(jìn)行搜索方法示例詳解

    這篇文章主要為大家介紹了Go語言操作RediSearch進(jìn)行搜索方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • Redis的緩存更新策略及最佳實(shí)踐方案

    Redis的緩存更新策略及最佳實(shí)踐方案

    這篇文章主要介紹了Redis的緩存更新策略及最佳實(shí)踐方案,當(dāng)我們向redis插入太多數(shù)據(jù),此時就可能會導(dǎo)致緩存中的數(shù)據(jù)過多,所以redis會對部分?jǐn)?shù)據(jù)進(jìn)行更新,或者把它成為淘汰更合適,需要的朋友可以參考下
    2023-08-08
  • Redis消息隊(duì)列的三種實(shí)現(xiàn)方式

    Redis消息隊(duì)列的三種實(shí)現(xiàn)方式

    本文主要介紹了Redis消息隊(duì)列的三種實(shí)現(xiàn)方式,主要包括List實(shí)現(xiàn)消息隊(duì)列,PubSub消息隊(duì)列,Stream消息隊(duì)列,具有一定的參考價值,感興趣的可以了解一下
    2023-12-12
  • 基于redis 7.2.3的makefile源碼解讀學(xué)習(xí)

    基于redis 7.2.3的makefile源碼解讀學(xué)習(xí)

    這篇文章主要為大家介紹了基于redis 7.2.3的makefile源碼解讀學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • redis刪除hash的實(shí)現(xiàn)方式

    redis刪除hash的實(shí)現(xiàn)方式

    這篇文章主要介紹了redis刪除hash的實(shí)現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • redis事務(wù)_動力節(jié)點(diǎn)Java學(xué)院整理

    redis事務(wù)_動力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要介紹了redis事務(wù),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08

最新評論