redis學習及實踐3---Jedis、JedisPool、Jedis分佈式實例介紹

一、相關jar包

    主要用到的是jedis的核心包,筆者用到的是2.1.0版;另根據“池”的應用等還需要用到相關jar包。下圖是筆者建立的簡單的jedis測試project圖:

wKioL1MdK_fybGUhAACpWhNr9Ik847.jpg

    jar包的文檔可參考:

http://www.boyunjian.com/javadoc/org.apache.servicemix.bundles/org.apache.servicemix.bundles.jedis/2.1.0_1/_/redis/clients/jedis/JedisShardInfo.html

二、簡單的Jedis實例

    在引入相關jar包後,只要new一個Jedis對象,就能做redis相關操作了。以下是一個簡單的jedis實例:

package com.pptv.redis;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import redis.clients.jedis.Jedis;
public class JedisDemo {
public void test(){
Jedis  redis = new Jedis ("172.0.0.1",6379);//連接redis
redis.auth("redis");//驗證密碼,如果需要驗證的話
// STRING 操作
//SET key value將字符串值value關聯到key。
redis.set("name", "wangjun1");
redis.set("id", "123456");
redis.set("address", "guangzhou");
//SETEX key seconds value將值value關聯到key,並將key的生存時間設爲seconds(以秒爲單位)。
redis.setex("foo", 5, "haha");
//MSET key value [key value ...]同時設置一個或多個key-value對。
redis.mset("haha","111","xixi","222");
//redis.flushAll();清空所有的key
System.out.println(redis.dbSize());//dbSize是多少個key的個數
//APPEND key value如果key已經存在並且是一個字符串,APPEND命令將value追加到key原來的值之後。
redis.append("foo", "00");//如果key已經存在並且是一個字符串,APPEND命令將value追加到key原來的值之後。
//GET key 返回key所關聯的字符串值
redis.get("foo");
//MGET key [key ...] 返回所有(一個或多個)給定key的值
List list = redis.mget("haha","xixi");
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
}
public static void main(String[] args) {
JedisDemo t1 = new JedisDemo();
t1.test();
}
}

三、JedisPool應用

Jedis使用commons-pool完成池化實現。

    先做個配置文件(properties文件):

#最大分配的對象數
redis.pool.maxActive=1024
#最大能夠保持idel狀態的對象數
redis.pool.maxIdle=200
#當池內沒有返回對象時,最大等待時間
redis.pool.maxWait=1000
#當調用borrow Object方法時,是否進行有效性檢查
redis.pool.testOnBorrow=true
#當調用return Object方法時,是否進行有效性檢查
redis.pool.testOnReturn=true
#IP
redis.ip=172.0.0.1
#Port
redis.port=6379

    jedisPool的相關詳細配置可參考:http://www.2cto.com/database/201311/254449.html    

    在靜態代碼段中完成初始化:

private static JedisPool pool;
static {
ResourceBundle bundle = ResourceBundle.getBundle("redis");
if (bundle == null) {
throw new IllegalArgumentException(
"[redis.properties] is not found!");
}
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxActive(Integer.valueOf(bundle
.getString("redis.pool.maxActive")));
config.setMaxIdle(Integer.valueOf(bundle
.getString("redis.pool.maxIdle")));
config.setMaxWait(Long.valueOf(bundle.getString("redis.pool.maxWait")));
config.setTestOnBorrow(Boolean.valueOf(bundle
.getString("redis.pool.testOnBorrow")));
config.setTestOnReturn(Boolean.valueOf(bundle
.getString("redis.pool.testOnReturn")));
pool = new JedisPool(config, bundle.getString("redis.ip"),
Integer.valueOf(bundle.getString("redis.port")));
}

    然後修改#2的簡單實例,修改爲Jedis從pool中獲得:

// 從池中獲取一個Jedis對象
Jedis jedis = pool.getResource();
String keys = "name";
// 刪數據
jedis.del(keys);
// 存數據
jedis.set(keys, "snowolf");
// 取數據
String value = jedis.get(keys);
System.out.println(value);
// 釋放對象池
pool.returnResource(jedis);

四、Jedis分佈式(Sharding/shared一致性哈希)

    Memcached完全基於分佈式集羣,而RedisMaster-Slave,如果想把Reids,做成集羣模式,無外乎多做幾套Master-Slave,每套Master-Slave完成各自的容災處理,通過Client工具,完成一致性哈希。(PS:Memcached是在Server端完成ShardingRedis只能依靠各個ClientSharding可能會在Redis 3.0系列支持ServerSharding

    shared一致性哈希採用以下方案:

  1. Redis服務器節點劃分:將每臺服務器節點採用hash算法劃分爲160個虛擬節點(可以配置劃分權重)

  2. 將劃分虛擬節點採用TreeMap存儲

  3. 對每個Redis服務器的物理連接採用LinkedHashMap存儲

  4. 對Key or KeyTag 採用同樣的hash算法,然後從TreeMap獲取大於等於鍵hash值得節點,取最鄰近節點存儲;當key的hash值大於虛擬節點hash值得最大值時,存入第一個虛擬節點

sharded採用的hash算法:MD5 和 MurmurHash兩種;默認採用64位的MurmurHash算法;有興趣的可以研究下,MurmurHash是一種高效,低碰撞的hash算法;參考地址:  

    保留前面的JedisPoolConfig,新增兩個Redis的IP(redis1.ip,redis2.ip),完成兩個JedisShardInfo實例,並將其丟進List中:

JedisShardInfo jedisShardInfo1 = new JedisShardInfo(
bundle.getString("redis1.ip"), Integer.valueOf(bundle                       .getString("redis.port")));
JedisShardInfo jedisShardInfo2 = new JedisShardInfo(
bundle.getString("redis2.ip"), Integer.valueOf(bundle                       .getString("redis.port")));
List<JedisShardInfo> list = new LinkedList<JedisShardInfo>();
list.add(jedisShardInfo1);
list.add(jedisShardInfo2);

    初始化ShardedJedisPool代替JedisPool:

ShardedJedisPool pool = new ShardedJedisPool(config, list);

     改由ShardedJedis,獲取Jedis對象:

// 從池中獲取一個Jedis對象
ShardedJedis jedis = pool.getResource();
String keys = "name";
String value = "snowolf";
// 刪數據
jedis.del(keys);
// 存數據
jedis.set(keys, value);
// 取數據
String v = jedis.get(keys);
System.out.println(v);
// 釋放對象池
pool.returnResource(jedis);

    通過以上方式,向redis進行set操作的key-value,會通過hash而均勻的分配到pool裏的redis機器中。

五、綜合實例

package com.pptv.redis;
import java.util.ArrayList;
import java.util.List;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;
/**
* redis的Java客戶端Jedis測試驗證
*
* @author
*/
public class Test {
/**
* 非切片客戶端鏈接
*/
private Jedis jedis;
/**
* 非切片鏈接池
*/
private JedisPool jedisPool;
/**
* 切片客戶端鏈接
*/
private ShardedJedis shardedJedis;
/**
* 切片鏈接池
*/
private ShardedJedisPool shardedJedisPool;
private String ip = "172.16.205.186";
/**
* 構造函數
*/
public Test() {
initialPool();
initialShardedPool();
shardedJedis = shardedJedisPool.getResource();
jedis = jedisPool.getResource();
}
private void initialPool() {
// 池基本配置
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxActive(20);
config.setMaxIdle(5);
config.setMaxWait(1000l);
config.setTestOnBorrow(false);
jedisPool = new JedisPool(config, ip, 6379);
}
/**
* 初始化切片池
*/
private void initialShardedPool() {
// 池基本配置
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxActive(20);
config.setMaxIdle(5);
config.setMaxWait(1000l);
config.setTestOnBorrow(false);
// slave鏈接
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
shards.add(new JedisShardInfo(ip, 6379, "master"));
// 構造池
shardedJedisPool = new ShardedJedisPool(config, shards);
}
public void show() {
// key檢測
testKey();
// string檢測
testString();
// list檢測
testList();
// set檢測
testSet();
// sortedSet檢測
testSortedSet();
// hash檢測
testHash();
shardedJedisPool.returnResource(shardedJedis);
}
private void testKey() {
System.out.println("=============key==========================");
// 清空數據
System.out.println(jedis.flushDB());
System.out.println(jedis.echo("foo"));
// 判斷key否存在
System.out.println(shardedJedis.exists("foo"));
shardedJedis.set("key", "values");
System.out.println(shardedJedis.exists("key"));
}
private void testString() {
System.out.println("=============String==========================");
// 清空數據
System.out.println(jedis.flushDB());
// 存儲數據
shardedJedis.set("foo", "bar");
System.out.println(shardedJedis.get("foo"));
// 若key不存在,則存儲
shardedJedis.setnx("foo", "foo not exits");
System.out.println(shardedJedis.get("foo"));
// 覆蓋數據
shardedJedis.set("foo", "foo update");
System.out.println(shardedJedis.get("foo"));
// 追加數據
shardedJedis.append("foo", " hello, world");
System.out.println(shardedJedis.get("foo"));
// 設置key的有效期,並存儲數據
shardedJedis.setex("foo", 2, "foo not exits");
System.out.println(shardedJedis.get("foo"));
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
System.out.println(shardedJedis.get("foo"));
// 獲取並更改數據
shardedJedis.set("foo", "foo update");
System.out.println(shardedJedis.getSet("foo", "foo modify"));
// 截取value的值
System.out.println(shardedJedis.getrange("foo", 1, 3));
System.out.println(jedis.mset("mset1", "mvalue1", "mset2", "mvalue2",
"mset3", "mvalue3", "mset4", "mvalue4"));
System.out.println(jedis.mget("mset1", "mset2", "mset3", "mset4"));
System.out.println(jedis.del(new String[] { "foo", "foo1", "foo3" }));
}
private void testList() {
System.out.println("=============list==========================");
// 清空數據
System.out.println(jedis.flushDB());
// 添加數據
shardedJedis.lpush("lists", "vector");
shardedJedis.lpush("lists", "ArrayList");
shardedJedis.lpush("lists", "LinkedList");
// 數組長度
System.out.println(shardedJedis.llen("lists"));
// 排序
//      System.out.println(shardedJedis.sort("lists"));
// 字串
System.out.println(shardedJedis.lrange("lists", 0, 3));
// 修改列表中單個值
shardedJedis.lset("lists", 0, "hello list!");
// 獲取列表指定下標的值
System.out.println(shardedJedis.lindex("lists", 1));
// 刪除列表指定下標的值
System.out.println(shardedJedis.lrem("lists", 1, "vector"));
// 刪除區間以外的數據
System.out.println(shardedJedis.ltrim("lists", 0, 1));
// 列表出棧
System.out.println(shardedJedis.lpop("lists"));
// 整個列表值
System.out.println(shardedJedis.lrange("lists", 0, -1));
}
private void testSet() {
System.out.println("=============set==========================");
// 清空數據
System.out.println(jedis.flushDB());
// 添加數據
shardedJedis.sadd("sets", "HashSet");
shardedJedis.sadd("sets", "SortedSet");
shardedJedis.sadd("sets", "TreeSet");
// 判斷value是否在列表中
System.out.println(shardedJedis.sismember("sets", "TreeSet"));
;
// 整個列表值
System.out.println(shardedJedis.smembers("sets"));
// 刪除指定元素
System.out.println(shardedJedis.srem("sets", "SortedSet"));
// 出棧
System.out.println(shardedJedis.spop("sets"));
System.out.println(shardedJedis.smembers("sets"));
//
shardedJedis.sadd("sets1", "HashSet1");
shardedJedis.sadd("sets1", "SortedSet1");
shardedJedis.sadd("sets1", "TreeSet");
shardedJedis.sadd("sets2", "HashSet2");
shardedJedis.sadd("sets2", "SortedSet1");
shardedJedis.sadd("sets2", "TreeSet1");
// 交集
System.out.println(jedis.sinter("sets1", "sets2"));
// 並集
System.out.println(jedis.sunion("sets1", "sets2"));
// 差集
System.out.println(jedis.sdiff("sets1", "sets2"));
}
private void testSortedSet() {
System.out.println("=============zset==========================");
// 清空數據
System.out.println(jedis.flushDB());
// 添加數據
shardedJedis.zadd("zset", 10.1, "hello");
shardedJedis.zadd("zset", 10.0, ":");
shardedJedis.zadd("zset", 9.0, "zset");
shardedJedis.zadd("zset", 11.0, "zset!");
// 元素個數
System.out.println(shardedJedis.zcard("zset"));
// 元素下標
System.out.println(shardedJedis.zscore("zset", "zset"));
// 集合子集
System.out.println(shardedJedis.zrange("zset", 0, -1));
// 刪除元素
System.out.println(shardedJedis.zrem("zset", "zset!"));
System.out.println(shardedJedis.zcount("zset", 9.5, 10.5));
// 整個集合值
System.out.println(shardedJedis.zrange("zset", 0, -1));
}
private void testHash() {
System.out.println("=============hash==========================");
// 清空數據
System.out.println(jedis.flushDB());
// 添加數據
shardedJedis.hset("hashs", "entryKey", "entryValue");
shardedJedis.hset("hashs", "entryKey1", "entryValue1");
shardedJedis.hset("hashs", "entryKey2", "entryValue2");
// 判斷某個值是否存在
System.out.println(shardedJedis.hexists("hashs", "entryKey"));
// 獲取指定的值
System.out.println(shardedJedis.hget("hashs", "entryKey"));
// 批量獲取指定的值
System.out
.println(shardedJedis.hmget("hashs", "entryKey", "entryKey1"));
// 刪除指定的值
System.out.println(shardedJedis.hdel("hashs", "entryKey"));
// 爲key中的域 field 的值加上增量 increment
System.out.println(shardedJedis.hincrBy("hashs", "entryKey", 123l));
// 獲取所有的keys
System.out.println(shardedJedis.hkeys("hashs"));
// 獲取所有的values
System.out.println(shardedJedis.hvals("hashs"));
}
/**
* @param args
*/
public static void main(String[] args) {
new Test().show();
}
}


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