一、redis Client介紹
1.1、簡介
Jedis Client是Redis官網(wǎng)推薦的一個面向Java客戶端,庫文件實現(xiàn)了對各類API進行封裝調(diào)用。
Jedis源碼工程地址:https://github.com/xetorthio/jedis
1.2、使用
Redis Client最好選用與服務(wù)端對應的版本,本例中使用Redis 2.8.19客戶端使用jedis -2.6.3,maven工程添加如下引用即可。
<dependency> ?????????<groupid>redis.clients</groupid> ?????????<artifactid>jedis</artifactid> ?????????<version>2.6.3</version> ?????????<type>jar</type> ?????????<scope>compile</scope> ???</dependency>
1.3、注意事項
Redis Client擁有眾多對接版本,本項目目前使用Jedis為官方推薦Java對接客戶端,是基于其對Redis良好的版本支持和API對接,另外編碼中盡量避免使用廢棄接口。
Redis目前正在新版過渡期,3.0版本暫未穩(wěn)定,但是由于3.0版本提供了最新的集群功能,可能在日后穩(wěn)定版發(fā)布以后升級到3.0,目前使用的Jedis支持3.0的目前版本API。
二、Redis Client常用API
2.1、環(huán)境要求
語言:Java
JDK:1.7
Redis : 2.8.19(穩(wěn)定版)
2.2、系統(tǒng)使用
2.2.1、建立連接
普通連接
Jedis?jedis?=?new?Jedis("localhost"); ???????jedis.set("foo",?"bar"); ???????String?value?=?jedis.get("foo"); ???????System.out.println(value);
設(shè)置連接池配置
該方法用于得到redis連接池連接使用的連接池配置,該連接池配置也可以通過spring注入的方式來進行相對應的配置,連接池采用的是平時比較常用的org.apache.commons.pool2.impl.GenericObjectPoolConfig來進行的連接池管理
配置文件如下
#redis服務(wù)器ip?#??? ????redis.ip=172.30.5.117? ??? ????#redis服務(wù)器端口號#? ????redis.port=6379? ????? ????###jedis##pool##config###? ????#jedis的最大分配對象#? ????jedis.pool.maxActive=1024? ??? ????#jedis最大保存idel狀態(tài)對象數(shù)?#? ????jedis.pool.maxIdle=200? ??? ????#jedis池沒有對象返回時,最大等待時間?#? ????jedis.pool.maxWait=1000? ??? ????#jedis調(diào)用borrowObject方法時,是否進行有效檢查#? ????jedis.pool.testOnBorrow=true? ??? ????#jedis調(diào)用returnObject方法時,是否進行有效檢查?#? ????jedis.pool.testOnReturn=true
連接池配置實例化代碼(也可通過spring注入進行配置):
???/** ????*?獲取化連接池配置 ????*?@return?JedisPoolConfig ????*?*/ ???private?JedisPoolConfig?getPoolConfig(){ ??????if(config?==?null){ ?????????config?=?new?JedisPoolConfig(); ?????????//最大連接數(shù) config.setMaxTotal(Integer.valueOf(getResourceBundle().getString("redis.pool.maxTotal"))); ?????????//最大空閑連接數(shù) config.setMaxIdle(Integer.valueOf(getResourceBundle().getString("redis.pool.maxIdle"))); ?????????//獲取連接時的最大等待毫秒數(shù)(如果設(shè)置為阻塞時BlockWhenExhausted),如果超時就拋異常,?小于零:阻塞不確定的時間,??默認-1 config.setMaxWaitMillis(Long.valueOf(getResourceBundle().getString("redis.pool.maxWaitMillis"))); ?????????//在獲取連接的時候檢查有效性,?默認false config.setTestOnBorrow(Boolean.valueOf(getResourceBundle().getString("redis.pool.testOnBorrow"))); ?????????//在獲取返回結(jié)果的時候檢查有效性,?默認false config.setTestOnReturn(Boolean.valueOf(getResourceBundle().getString("redis.pool.testOnReturn"))); ??????} ??????return?config; ???}
普通連接池連接
??這里展示的是普通的連接池方式鏈接redis的方案,跟普通的數(shù)據(jù)庫連接池的操作方式類似; /** ????????*?初始化JedisPool ????????*?*/ ???private?void?initJedisPool(){ ??????if(pool?==?null){ ?????????//獲取服務(wù)器IP地址 ?????????String?ipStr?=?getResourceBundle().getString("redis.ip"); ?????????//獲取服務(wù)器端口 ?????????int?portStr?=?Integer.valueOf(getResourceBundle() .getString("redis.port")); ?????????//初始化連接池 ?????????pool?=?new?JedisPool(getPoolConfig(),?ipStr,portStr); ??????} ???}
sentinel連接池連接
該連接池用于應對Redis的Sentinel的主從切換機制,能夠正確在服務(wù)器宕機導致服務(wù)器切換時得到正確的服務(wù)器連接,當服務(wù)器采用該部署策略的時候推薦使用該連接池進行操作;
?private?void?initJedisSentinelPool(){ ??????if(sentinelpool?==?null){ ?????????//監(jiān)聽器列表 ?????????Set<string>?sentinels?=?new?HashSet<string>(); ?????????//監(jiān)聽器1 ?????????sentinels.add(new?HostAndPort("192.168.50.236", 26379).toString()); ?????????//監(jiān)聽器2 ?????????sentinels.add(new?HostAndPort("192.168.50.237", 26379).toString()); //實際使用的時候在properties里配置即可:redis.sentinel.hostandports =192.168.50.236:26379,192.168.50.237:26379 getResourceBundle().getString("redis.sentinel.hostandports") //mastername是服務(wù)器上的master的名字,在master服務(wù)器的sentinel.conf中配置: ?????????????????????//[sentinel?monitor?server-1M??192.168.50.236?6379?2] ?????????????????????//中間的server-1M即為這里的masterName ?????????String?masterName?=?getResourceBundle() .getString("redis.sentinel.masterName"); ?????????//初始化連接池 ?????????sentinelpool?=?new?JedisSentinelPool(masterName, sentinels,?getPoolConfig()); ??????} ???}</string></string>
ShardedJedisPool連接池分片連接
???/** ????????*?初始化ShardedJedisPool ????????*?Redis在容災處理方面可以通過服務(wù)器端配置Master-Slave模式來實現(xiàn)。 ????????*?而在分布式集群方面目前只能通過客戶端工具來實現(xiàn)一致性哈希分布存儲,即key分片存儲。 ????????*?Redis可能會在3.0版本支持服務(wù)器端的分布存儲 ????????*?*/ ???private?void?initShardedJedisPool()?{ ??????if?(shardPool?==?null)?{ ?????????//?創(chuàng)建多個redis共享服務(wù) ?????????String?redis1Ip?=?getResourceBundle().getString("redis1.ip"); ?????????int?redis1Port?=?Integer.valueOf(bundle.getString("redis.port")); ?????????JedisShardInfo?jedisShardInfo1?=?new?JedisShardInfo(redis1Ip,?redis1Port); ?????????String?redis2Ip?=?getResourceBundle().getString("redis2.ip"); ?????????int?redis2Port?=?Integer.valueOf(bundle.getString("redis.port")); ?????????JedisShardInfo?jedisShardInfo2?=?new?JedisShardInfo(redis2Ip,?redis2Port); ? ?????????List<jedisshardinfo>?serverlist?=?new?LinkedList<jedisshardinfo>(); ?????????serverlist.add(jedisShardInfo1); ?????????serverlist.add(jedisShardInfo2); ?????????//?初始化連接池 ?????????shardPool?=?new?ShardedJedisPool(getPoolConfig(),serverlist); ??????} ???}</jedisshardinfo></jedisshardinfo>
讀寫刪除操作
//?從池中獲取一個Jedis對象 ??????Jedis?jedis?=?sentinelpool.getSentinelpoolResource(); ??????String?keys?=?"name"; ???//?刪除key-value對象,如果key不存在則忽略此操作 ??????jedis.del(keys); ???//?存數(shù)據(jù) ??????jedis.set(keys,?"snowolf"); //?判斷key是否存在,不存在返回false存在返回true ??????jedis.exists(keys); ???//?取數(shù)據(jù) ??????String?value?=?jedis.get(keys); ???//?釋放對象池(3.0將拋棄該方法) ??????sentinelpool.returnSentinelpoolResource(jedis);
三、示例代碼
1.?????String的簡單追加
//?從池中獲取一個Jedis對象 ???JedisUtil.getInstance().STRINGS.append(key,?value);
2.?????價格時間排序(前提是已經(jīng)存儲了價格,時間的SortSet)
//執(zhí)行2級排序操作()
String?stPriceSet?=?“stPriceSet”;//stPriceSet價格的sortset列表名 String?stTimeSet?=?“stTimeSet”;?//?stTimeSet時間的sortset列表名 ???Set<tuple>?sumSet?=?JedisUtilEx.getInstance() .getSortSetByPirceUpAndTimeDown(stPriceSet,?stTimeSet); //排序以后可以重復獲取上次排序結(jié)果(緩存時間10分鐘) Set<tuple>?sumSet?=?JedisUtilEx.getInstance() getLastPirceUpAndTimeDownSet();</tuple></tuple>
3.??價格時間排序(前提是已經(jīng)存儲了價格,時間的SortSet)
//執(zhí)行2級排序操作 String?stPriceSet?=?“stPriceSet”;//stPriceSet價格的sortset列表名 String?stTimeSet?=?“stTimeSet”;?//?stTimeSet時間的sortset列表名 ???Set<tuple>?sumSet?=?JedisUtilEx.getInstance() .?getSortSetByPirceDownAndTimeDown?(stPriceSet,?stTimeSet); ???//排序以后可以重復獲取上次排序結(jié)果(緩存時間10分鐘) Set<tuple>?sumSet?=?JedisUtilEx.getInstance() getLastPirceDownAndTimeDownSet?();</tuple></tuple>
4.?????保存JavaBean到hash表中
//?bean繼承至RedisBean JedisUtilEx.getInstance().setBeanToHash(bean);
5.?????從hash表中讀取JavaBean
//uuid為業(yè)務(wù)制定的唯一標識符規(guī)則(相當于主鍵) String?uuid?=?“1”;?//該ID是我們提前就知道的 //T繼承至RedisBean; JedisUtilEx.getInstance().getBeanFromHash?(uuid,Class<t>?cls);</t>
6.?????將JavaBean列表裝入hash中
//list中的bean繼承至RedisBean List<t>?beanList?=?…; JedisUtilEx.getInstance().setBeanListToHash(beanList); //異步版本的存儲列表到hash JedisUtilEx.getInstance().setBeanListToHashSyn(beanList);</t>
7.?????普通的操作流程示例
//獲取jedis引用 Jedis?jedis?=?JedisUtil.getInstance().getJedis(); //執(zhí)行業(yè)務(wù)以及調(diào)用jedis提供的接口功能 … jedis.hset(…); … //執(zhí)行完成以后務(wù)必釋放資源 JedisUtil.getInstance().returnJedis(jedis); //若以后不會使用JEDIS,需要關(guān)閉所有鏈接池 ???RedisConnetcion.destroyAllPools();
8.?????事務(wù)執(zhí)行流程
//獲取連接資源 ???Jedis?jd?=?JedisUtil.getInstance().getJedis(); //開啟事務(wù) Transaction?ts?=?jd.multi(); //執(zhí)行業(yè)務(wù)以及調(diào)用jedis提供的接口功能 … jedis.hset(…); … //執(zhí)行事務(wù) ???List<object>?list?=?ts.exec(); //釋放資源 JedisUtil.getInstance().returnJedis(jd);</object>
9.?????異步執(zhí)行
//獲取連接資源 ???Jedis?jedis?=?JedisUtil.getInstance().getJedis(); ???//獲取管道 Pipeline?pipeline?=?jedis.pipelined(); //執(zhí)行業(yè)務(wù)以及調(diào)用jedis提供的接口功能 … jedis.hset(…); … //提交并釋放管道 pipeline.syncAndReturnAll(); //釋放資源 JedisUtil.getInstance().returnJedis(jedis);
10.??如何獲取Jedis命名規(guī)則的合成KEY
//獲取類的唯一鍵值key,例如:User:1(User為class,1為uuid)其中user繼承于Reidsbean JedisUtilEx.getInstance().getBeanKey(user); //另一種獲取類的唯一鍵值key的方法 JedisUtilEx.getInstance().getBeanKey(String?uuid,Class<t>?cls); //獲取bean對應的KEY(對應列的唯一鍵值key) JedisUtilEx.getInstance().getBeanKey(String?uuid,Class<t>?cls,String...?fileds); //獲取bean對應的KEY(集群key) JedisUtilEx.getInstance().getBeanKey(Class<t>?cls,String...?fileds);</t></t></t>
四、jedis操作命令:
1.對value操作的命令
?exists(key):確認一個key是否存在 ?????del(key):刪除一個key ?????type(key):返回值的類型 ?????keys(pattern):返回滿足給定pattern的所有key ?????randomkey:隨機返回key空間的一個key ?????rename(oldname,?newname):將key由oldname重命名為newname,若newname存在則刪除newname表示的key ?????dbsize:返回當前數(shù)據(jù)庫中key的數(shù)目 ?????expire:設(shè)定一個key的活動時間(s) ?????ttl:獲得一個key的活動時間 ?????select(index):按索引查詢 ?????move(key,?dbindex):將當前數(shù)據(jù)庫中的key轉(zhuǎn)移到有dbindex索引的數(shù)據(jù)庫 ?????flushdb:刪除當前選擇數(shù)據(jù)庫中的所有key ?????flushall:刪除所有數(shù)據(jù)庫中的所有key
2.對String操作的命令
??set(key,?value):給數(shù)據(jù)庫中名稱為key的string賦予值value ?????get(key):返回數(shù)據(jù)庫中名稱為key的string的value ?????getset(key,?value):給名稱為key的string賦予上一次的value ?????mget(key1,?key2,…,?key?N):返回庫中多個string(它們的名稱為key1,key2…)的value ?????setnx(key,?value):如果不存在名稱為key的string,則向庫中添加string,名稱為key,值為value ?????setex(key,?time,?value):向庫中添加string(名稱為key,值為value)同時,設(shè)定過期時間time ?????mset(key1,?value1,?key2,?value2,…key?N,?value?N):同時給多個string賦值,名稱為key?i的string賦值value?i ?????msetnx(key1,?value1,?key2,?value2,…key?N,?value?N):如果所有名稱為key?i的string都不存在,則向庫中添加string,名稱key?i賦值為value?i ?????incr(key):名稱為key的string增1操作 ?????incrby(key,?integer):名稱為key的string增加integer ?????decr(key):名稱為key的string減1操作 ?????decrby(key,?integer):名稱為key的string減少integer ?????append(key,?value):名稱為key的string的值附加value ?????substr(key,?start,?end):返回名稱為key的string的value的子串
3.對List操作的命令
?rpush(key,?value):在名稱為key的list尾添加一個值為value的元素 ?????lpush(key,?value):在名稱為key的list頭添加一個值為value的?元素 ?????llen(key):返回名稱為key的list的長度 ?????lrange(key,?start,?end):返回名稱為key的list中start至end之間的元素(下標從0開始,下同) ?????ltrim(key,?start,?end):截取名稱為key的list,保留start至end之間的元素 ?????lindex(key,?index):返回名稱為key的list中index位置的元素 ?????lset(key,?index,?value):給名稱為key的list中index位置的元素賦值為value ?????lrem(key,?count,?value):刪除count個名稱為key的list中值為value的元素。count為0,刪除所有值為value的元素,count>0??????從頭至尾刪除count個值為value的元素,count0,則遇到上述情況時,等待timeout秒,如果問題沒有解決,則對key?i+1開始的list執(zhí)行pop操作。 ?????brpop(key1,?key2,…?key?N,?timeout):rpop的block版本。參考上一命令。 ?????rpoplpush(srckey,?dstkey):返回并刪除名稱為srckey的list的尾元素,并將該元素添加到名稱為dstkey的list的頭部
4.對Set操作的命令
??sadd(key,?member):向名稱為key的set中添加元素member ?????srem(key,?member)?:刪除名稱為key的set中的元素member ?????spop(key)?:隨機返回并刪除名稱為key的set中一個元素 ?????smove(srckey,?dstkey,?member)?:將member元素從名稱為srckey的集合移到名稱為dstkey的集合 ?????scard(key)?:返回名稱為key的set的基數(shù) ?????sismember(key,?member)?:測試member是否是名稱為key的set的元素 ?????sinter(key1,?key2,…key?N)?:求交集 ?????sinterstore(dstkey,?key1,?key2,…key?N)?:求交集并將交集保存到dstkey的集合 ?????sunion(key1,?key2,…key?N)?:求并集 ?????sunionstore(dstkey,?key1,?key2,…key?N)?:求并集并將并集保存到dstkey的集合 ?????sdiff(key1,?key2,…key?N)?:求差集 ?????sdiffstore(dstkey,?key1,?key2,…key?N)?:求差集并將差集保存到dstkey的集合 ?????smembers(key)?:返回名稱為key的set的所有元素 ?????srandmember(key)?:隨機返回名稱為key的set的一個元素
5.對zset(sorted?set)操作的命令
???zadd(key,?score,?member):向名稱為key的zset中添加元素member,score用于排序。如果該元素已經(jīng)存在,則根據(jù)score更新該元素的順序。 ?????zrem(key,?member)?:刪除名稱為key的zset中的元素member ?????zincrby(key,?increment,?member)?:如果在名稱為key的zset中已經(jīng)存在元素member,則該元素的score增加increment;否則向集合中添加該元素,其score的值為increment ?????zrank(key,?member)?:返回名稱為key的zset(元素已按score從小到大排序)中member元素的rank(即index,從0開始),若沒有member元素,返回“nil” ?????zrevrank(key,?member)?:返回名稱為key的zset(元素已按score從大到小排序)中member元素的rank(即index,從0開始),若沒有member元素,返回“nil” ?????zrange(key,?start,?end):返回名稱為key的zset(元素已按score從小到大排序)中的index從start到end的所有元素 ?????zrevrange(key,?start,?end):返回名稱為key的zset(元素已按score從大到小排序)中的index從start到end的所有元素 ?????zrangebyscore(key,?min,?max):返回名稱為key的zset中score?>=?min且score?=?min且rank?=?min且score?<p>6.對Hash操作的命令</p><pre class="brush:php;toolbar:false">???hset(key,?field,?value):向名稱為key的hash中添加元素fieldvalue ?????hget(key,?field):返回名稱為key的hash中field對應的value ?????hmget(key,?field1,?…,field?N):返回名稱為key的hash中field?i對應的value ?????hmset(key,?field1,?value1,…,field?N,?value?N):向名稱為key的hash中添加元素field?ivalue?i ?????hincrby(key,?field,?integer):將名稱為key的hash中field的value增加integer ?????hexists(key,?field):名稱為key的hash中是否存在鍵為field的域 ?????hdel(key,?field):刪除名稱為key的hash中鍵為field的域 ?????hlen(key):返回名稱為key的hash中元素個數(shù) ?????hkeys(key):返回名稱為key的hash中所有鍵 ?????hvals(key):返回名稱為key的hash中所有鍵對應的value ?????hgetall(key):返回名稱為key的hash中所有的鍵(field)及其對應的value
五、Redis命名規(guī)則
由于Redis所有數(shù)據(jù)為鍵值對,即所有數(shù)據(jù)均只能通過鍵值(Key)來進行管理,故需
要規(guī)范命名規(guī)則,jedis客戶端包裝了有專門的命名規(guī)則生產(chǎn)函數(shù),調(diào)用即可!代碼參考實例代碼:
?
六、參考資料
API:http://www.php.cn/dic/54.html
更多功能可以參考該文檔去調(diào)用
更多Redis相關(guān)技術(shù)文章,請訪問http://www.php.cn/dic/54.html欄目進行學習!