- Jredis:https://github.com/alphazero/jredis
- Jedis:https://github.com/xetorthio/jedis
- Redis4J:https://github.com/guming/redis4j
Jedis是官方提供的唯一Redis Client For Java Provider。
- <dependency>
- <groupId>redis.clients</groupId>
- <artifactId>jedis</artifactId>
- <version>2.6.2</version>
- </dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.6.2</version>
</dependency>
一、Jedis簡單使用
- package cn.slimsmart.redis.demo.jedis;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.Set;
- import redis.clients.jedis.Jedis;
- @SuppressWarnings(“resource”)
- public class JedisTest {
- private static final String HASH_KEY = “key”;
- public static void main(String[] args) {
- Jedis jedis = new Jedis(“192.168.36.189”, 6379);
- /**
- * 存儲String key-value
- */
- jedis.set(HASH_KEY, ”value”);
- /**
- * 如果已經存在key了,先刪除掉
- */
- if (jedis.exists(HASH_KEY)) {
- System.out.println(jedis.get(HASH_KEY));
- jedis.del(HASH_KEY);
- }
- /**
- * 存入單個key-value
- */
- jedis.hset(HASH_KEY, ”username”, “yourUsername”);
- /**
- * 存入多個key-value鍵值對
- */
- Map<String, String> keyValueMap = new HashMap<String, String>();
- keyValueMap.put(”password”, “YourPassword”);
- keyValueMap.put(”age”, “20”);
- jedis.hmset(HASH_KEY, keyValueMap);
- /**
- * 判斷某個key是否在指定的Hash key中
- */
- boolean existsUsernameKey = jedis.hexists(HASH_KEY, “username”);
- // true
- System.out.println(existsUsernameKey);
- /**
- * 獲取某個hash中鍵值對的數量
- */
- Long len = jedis.hlen(HASH_KEY);
- // 3
- System.out.println(len);
- /**
- * 獲取一個hash中的所有key
- */
- Set<String> keys = jedis.hkeys(HASH_KEY);
- // [password, username, age]
- System.out.println(keys);
- /**
- * 獲取一個hash中的所有values
- */
- List<String> values = jedis.hvals(HASH_KEY);
- // [yourUsername, YourPassword, 20]
- System.out.println(values);
- /**
- * 獲取指定hash的所有的鍵值對
- */
- Map<String, String> allKVMap = jedis.hgetAll(HASH_KEY);
- // {username=yourUsername, age=20, password=YourPassword}
- System.out.println(allKVMap);
- /**
- * 從一個hash中獲取某個field的值
- */
- String value = jedis.hget(HASH_KEY, ”username”);
- // yourUsername
- System.out.println(value);
- List<String> multValues = jedis.hmget(HASH_KEY, ”username”, “password”);
- // [yourUsername, YourPassword]
- System.out.println(multValues);
- }
- }
package cn.slimsmart.redis.demo.jedis;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import redis.clients.jedis.Jedis;
@SuppressWarnings("resource")
public class JedisTest {
private static final String HASH_KEY = "key";
public static void main(String[] args) {
Jedis jedis = new Jedis("192.168.36.189", 6379);
/**
* 存儲String key-value
*/
jedis.set(HASH_KEY, "value");
/**
* 如果已經存在key了,先刪除掉
*/
if (jedis.exists(HASH_KEY)) {
System.out.println(jedis.get(HASH_KEY));
jedis.del(HASH_KEY);
}
/**
* 存入單個key-value
*/
jedis.hset(HASH_KEY, "username", "yourUsername");
/**
* 存入多個key-value鍵值對
*/
Map<String, String> keyValueMap = new HashMap<String, String>();
keyValueMap.put("password", "YourPassword");
keyValueMap.put("age", "20");
jedis.hmset(HASH_KEY, keyValueMap);
/**
* 判斷某個key是否在指定的Hash key中
*/
boolean existsUsernameKey = jedis.hexists(HASH_KEY, "username");
// true
System.out.println(existsUsernameKey);
/**
* 獲取某個hash中鍵值對的數量
*/
Long len = jedis.hlen(HASH_KEY);
// 3
System.out.println(len);
/**
* 獲取一個hash中的所有key
*/
Set<String> keys = jedis.hkeys(HASH_KEY);
// [password, username, age]
System.out.println(keys);
/**
* 獲取一個hash中的所有values
*/
List<String> values = jedis.hvals(HASH_KEY);
// [yourUsername, YourPassword, 20]
System.out.println(values);
/**
* 獲取指定hash的所有的鍵值對
*/
Map<String, String> allKVMap = jedis.hgetAll(HASH_KEY);
// {username=yourUsername, age=20, password=YourPassword}
System.out.println(allKVMap);
/**
* 從一個hash中獲取某個field的值
*/
String value = jedis.hget(HASH_KEY, "username");
// yourUsername
System.out.println(value);
List<String> multValues = jedis.hmget(HASH_KEY, "username", "password");
// [yourUsername, YourPassword]
System.out.println(multValues);
}
}
二、連接池的使用
Jedis使用commons-pool完成池化實現。
1.配置文件redis.properties
- redis.pool.maxTotal=10
- redis.pool.minIdle=2
- redis.pool.maxIdle=10
- redis.pool.maxWait=1000
- redis.pool.testWhileIdle=true
- redis.pool.testOnBorrow=true
- redis.pool.testOnReturn=true
- #IP
- redis.ip=192.168.36.189
- #Port
- redis.port=6379
redis.pool.maxTotal=10
redis.pool.minIdle=2
redis.pool.maxIdle=10
redis.pool.maxWait=1000
redis.pool.testWhileIdle=true
redis.pool.testOnBorrow=true
redis.pool.testOnReturn=true
IP
redis.ip=192.168.36.189
Port
redis.port=63792.實例代碼
- package cn.slimsmart.redis.demo.jedis;
- import java.util.ResourceBundle;
- import redis.clients.jedis.Jedis;
- import redis.clients.jedis.JedisPool;
- import redis.clients.jedis.JedisPoolConfig;
- public class JedisPoolTest {
- public static void main(String[] args) {
- ResourceBundle bundle = ResourceBundle.getBundle(”redis”);
- if (bundle == null) {
- throw new IllegalArgumentException(“[redis.properties] is not found!”);
- }
- JedisPoolConfig config = new JedisPoolConfig();
- config.setMaxTotal(Integer.valueOf(bundle.getString(”redis.pool.maxTotal”)));
- config.setMinIdle(Integer.valueOf(bundle.getString(”redis.pool.minIdle”)));
- config.setMaxIdle(Integer.valueOf(bundle.getString(”redis.pool.maxIdle”)));
- config.setMaxWaitMillis(Long.valueOf(bundle.getString(”redis.pool.maxWait”)));
- config.setTestWhileIdle(Boolean.valueOf(bundle.getString(”redis.pool.testWhileIdle”)));
- config.setTestOnBorrow(Boolean.valueOf(bundle.getString(”redis.pool.testOnBorrow”)));
- config.setTestOnReturn(Boolean.valueOf(bundle.getString(”redis.pool.testOnReturn”)));
- JedisPool pool = new JedisPool(config, bundle.getString(“redis.ip”), Integer.valueOf(bundle.getString(“redis.port”)));
- // 從池中獲取一個Jedis對象
- Jedis jedis = pool.getResource();
- String key = ”key”;
- // 刪數據
- jedis.del(key);
- // 存數據
- jedis.set(key, ”abc123”);
- // 取數據
- String value = jedis.get(key);
- System.out.println(value);
- // 釋放對象池
- pool.returnResource(jedis);
- }
- }
package cn.slimsmart.redis.demo.jedis;
import java.util.ResourceBundle;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class JedisPoolTest {
public static void main(String[] args) {
ResourceBundle bundle = ResourceBundle.getBundle("redis");
if (bundle == null) {
throw new IllegalArgumentException("[redis.properties] is not found!");
}
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(Integer.valueOf(bundle.getString("redis.pool.maxTotal")));
config.setMinIdle(Integer.valueOf(bundle.getString("redis.pool.minIdle")));
config.setMaxIdle(Integer.valueOf(bundle.getString("redis.pool.maxIdle")));
config.setMaxWaitMillis(Long.valueOf(bundle.getString("redis.pool.maxWait")));
config.setTestWhileIdle(Boolean.valueOf(bundle.getString("redis.pool.testWhileIdle")));
config.setTestOnBorrow(Boolean.valueOf(bundle.getString("redis.pool.testOnBorrow")));
config.setTestOnReturn(Boolean.valueOf(bundle.getString("redis.pool.testOnReturn")));
JedisPool pool = new JedisPool(config, bundle.getString("redis.ip"), Integer.valueOf(bundle.getString("redis.port")));
// 從池中獲取一個Jedis對象
Jedis jedis = pool.getResource();
String key = "key";
// 刪數據
jedis.del(key);
// 存數據
jedis.set(key, "abc123");
// 取數據
String value = jedis.get(key);
System.out.println(value);
// 釋放對象池
pool.returnResource(jedis);
}
}
三、一致性哈希
Memcached完全基於分佈式集羣,而Redis是Master-Slave,如果想把Reids,做成集羣模式,無外乎多做幾套Master-Slave,每套Master-Slave完成各自的容災處理,通過Client工具,完成一致性哈希。Memcached是在Server端完成Sharding,Redis只能依靠各個Client做Sharding。在Redis 3.0系列支持Server端Sharding。
shared一致性哈希採用以下方案:
1.Redis服務器節點劃分:將每臺服務器節點採用hash算法劃分爲160個虛擬節點(可以配置劃分權重)
2.將劃分虛擬節點採用TreeMap存儲
3.對每個Redis服務器的物理連接採用LinkedHashMap存儲
4.對Key採用同樣的hash算法,然後從TreeMap獲取大於等於鍵hash值得節點,取最鄰近節點存儲;當key的hash值大於虛擬節點hash值得最大值時,存入第一個虛擬節點
sharded採用的hash算法:MD5和MurmurHash兩種;默認採用64位的MurmurHash算法。
1.配置文件redis.properties
- redis.pool.maxTotal=10
- redis.pool.minIdle=2
- redis.pool.maxIdle=10
- redis.pool.maxWait=1000
- redis.pool.testWhileIdle=true
- redis.pool.testOnBorrow=true
- redis.pool.testOnReturn=true
- #IP
- redis1.ip=192.168.36.189
- redis2.ip=192.168.36.54
- #Port
- redis.port=6379
redis.pool.maxTotal=10
redis.pool.minIdle=2
redis.pool.maxIdle=10
redis.pool.maxWait=1000
redis.pool.testWhileIdle=true
redis.pool.testOnBorrow=true
redis.pool.testOnReturn=true
IP
redis1.ip=192.168.36.189
redis2.ip=192.168.36.54
Port
redis.port=6379
2.實例代碼
- package cn.slimsmart.redis.demo.jedis;
- import java.util.LinkedList;
- import java.util.List;
- import java.util.ResourceBundle;
- import redis.clients.jedis.JedisPoolConfig;
- import redis.clients.jedis.JedisShardInfo;
- import redis.clients.jedis.ShardedJedis;
- import redis.clients.jedis.ShardedJedisPool;
- public class JedisShardInfoTest {
- public static void main(String[] args) {
- ResourceBundle bundle = ResourceBundle.getBundle(”redis”);
- if (bundle == null) {
- throw new IllegalArgumentException(“[redis.properties] is not found!”);
- }
- JedisPoolConfig config = new JedisPoolConfig();
- config.setMaxTotal(Integer.valueOf(bundle.getString(”redis.pool.maxTotal”)));
- config.setMinIdle(Integer.valueOf(bundle.getString(”redis.pool.minIdle”)));
- config.setMaxIdle(Integer.valueOf(bundle.getString(”redis.pool.maxIdle”)));
- config.setMaxWaitMillis(Long.valueOf(bundle.getString(”redis.pool.maxWait”)));
- config.setTestWhileIdle(Boolean.valueOf(bundle.getString(”redis.pool.testWhileIdle”)));
- config.setTestOnBorrow(Boolean.valueOf(bundle.getString(”redis.pool.testOnBorrow”)));
- config.setTestOnReturn(Boolean.valueOf(bundle.getString(”redis.pool.testOnReturn”)));
- 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);
- // 從池中獲取一個Jedis對象
- ShardedJedis jedis = pool.getResource();
- String keys = ”key”;
- String value = ”abc123”;
- // 刪數據
- jedis.del(keys);
- // 存數據
- jedis.set(keys, value);
- // 取數據
- String v = jedis.get(keys);
- System.out.println(v);
- // 釋放對象池
- pool.returnResource(jedis);
- }
- }
package cn.slimsmart.redis.demo.jedis;
import java.util.LinkedList;
import java.util.List;
import java.util.ResourceBundle;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;
public class JedisShardInfoTest {
public static void main(String[] args) {
ResourceBundle bundle = ResourceBundle.getBundle("redis");
if (bundle == null) {
throw new IllegalArgumentException("[redis.properties] is not found!");
}
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(Integer.valueOf(bundle.getString("redis.pool.maxTotal")));
config.setMinIdle(Integer.valueOf(bundle.getString("redis.pool.minIdle")));
config.setMaxIdle(Integer.valueOf(bundle.getString("redis.pool.maxIdle")));
config.setMaxWaitMillis(Long.valueOf(bundle.getString("redis.pool.maxWait")));
config.setTestWhileIdle(Boolean.valueOf(bundle.getString("redis.pool.testWhileIdle")));
config.setTestOnBorrow(Boolean.valueOf(bundle.getString("redis.pool.testOnBorrow")));
config.setTestOnReturn(Boolean.valueOf(bundle.getString("redis.pool.testOnReturn")));
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);
// 從池中獲取一個Jedis對象
ShardedJedis jedis = pool.getResource();
String keys = "key";
String value = "abc123";
// 刪數據
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機器中。
四、Spring集成
如果有必要,可以用Spring封裝初始化。
- <context:property-placeholder location=“classpath:redis.properties” />
- <bean
- id=“jedisPoolConfig”
- class=“redis.clients.jedis.JedisPoolConfig”>
- <property
- name=“maxTotal”
- value=“ {redis.pool.minIdle}” />
- <property
- name=“maxIdle”
- value=“ {redis.pool.maxWait}” />
- <property
- name=“testWhileIdle”
- value=“ {redis.pool.testOnBorrow}” />
- <property
- name=“testOnReturn”
- value=“ {redis1.ip}” />
- <constructor-arg
- index=“1”
- value=“ {redis2.ip}” />
- <constructor-arg
- index=“1”
- value=“${redis.port}”
- type=“int” />
- </bean>
- </list>
- </constructor-arg>
- </bean>
<context:property-placeholder location="classpath:redis.properties" />
<bean
id="jedisPoolConfig"
class="redis.clients.jedis.JedisPoolConfig">
<property
name="maxTotal"
value="${redis.pool.maxTotal}" />
<property
name="minIdle"
value="${redis.pool.minIdle}" />
<property
name="maxIdle"
value="${redis.pool.maxIdle}" />
<property
name="maxWait"
value="${redis.pool.maxWait}" />
<property
name="testWhileIdle"
value="${redis.pool.testWhileIdle}" />
<property
name="testOnBorrow"
value="${redis.pool.testOnBorrow}" />
<property
name="testOnReturn"
value="${redis.pool.testOnReturn}" />
</bean>
<bean
id="shardedJedisPool"
class="redis.clients.jedis.ShardedJedisPool">
<constructor-arg
index="0"
ref="jedisPoolConfig" />
<constructor-arg index="1">
<list>
<bean class="redis.clients.jedis.JedisShardInfo">
<constructor-arg
index="0"
value="${redis1.ip}" />
<constructor-arg
index="1"
value="${redis.port}"
type="int" />
</bean>
<bean class="redis.clients.jedis.JedisShardInfo">
<constructor-arg
index="0"
value="${redis2.ip}" />
<constructor-arg
index="1"
value="${redis.port}"
type="int" />
</bean>
</list>
</constructor-arg>
</bean>
當然,Spring提供了對於Redis的專門支持:spring-data-redis。