Jedis是官方提供的唯一Redis Client For Java Provider。
<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); } }二、连接池的使用
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=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); } }三、一致性哈希
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=63792.实例代码
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.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。