征服 Redis + Jedis
阅读原文时间:2021年04月20日阅读:1

言归正传,目前Redis大概有3中基于Java语言的Client:

  • Jredis
  • Jedis
  • Redis4J

这里只说Jedis,因为它是官方提供的唯一Redis Client For Java Provider!

一、简单使用Jedis

需要Jedis就从Maven获取吧!
Maven Pom.xml

Xml代码  

  1. <dependency>
  2. <groupId>redis.clients</groupId>
  3. <artifactId>jedis</artifactId>
  4. <version>2.1.0</version>
  5. <type>jar</type>
  6. <scope>compile</scope>
  7. </dependency>

如果只是简单使用Jedis,以下这么几行代码足够:

Java代码  

  1. Jedis jedis = new Jedis("10.11.20.140");

  2. String keys = "name";

  3. // 删数据

  4. jedis.del(keys);

  5. // 存数据

  6. jedis.set(keys, "snowolf");

  7. // 取数据

  8. String value = jedis.get(keys);

  9. System.out.println(value);

二、池化使用Jedis

Jedis使用commons-pool完成池化实现。

先做个配置文件:

Properties代码  

  1. #最大分配的对象数
  2. redis.pool.maxActive=1024
  3. #最大能够保持idel状态的对象数
  4. redis.pool.maxIdle=200
  5. #当池内没有返回对象时,最大等待时间
  6. redis.pool.maxWait=1000
  7. #当调用borrow Object方法时,是否进行有效性检查
  8. redis.pool.testOnBorrow=true
  9. #当调用return Object方法时,是否进行有效性检查
  10. redis.pool.testOnReturn=true
  11. #IP
  12. redis.ip=10.11.20.140
  13. #Port
  14. redis.port=6379

 在静态代码段中完成初始化:

Java代码  

  1. private static JedisPool pool;
  2. static {
  3. ResourceBundle bundle = ResourceBundle.getBundle("redis");
  4. if (bundle == null) {
  5. throw new IllegalArgumentException(
  6. "[redis.properties] is not found!");
  7. }
  8. JedisPoolConfig config = new JedisPoolConfig();
  9. config.setMaxActive(Integer.valueOf(bundle
  10. .getString("redis.pool.maxActive")));
  11. config.setMaxIdle(Integer.valueOf(bundle
  12. .getString("redis.pool.maxIdle")));
  13. config.setMaxWait(Long.valueOf(bundle.getString("redis.pool.maxWait")));
  14. config.setTestOnBorrow(Boolean.valueOf(bundle
  15. .getString("redis.pool.testOnBorrow")));
  16. config.setTestOnReturn(Boolean.valueOf(bundle
  17. .getString("redis.pool.testOnReturn")));
  18. pool = new JedisPool(config, bundle.getString("redis.ip"),
  19. Integer.valueOf(bundle.getString("redis.port")));
  20. }

 然后,修改前面那段jedis操作Redis

Java代码  

  1. // 从池中获取一个Jedis对象

  2. Jedis jedis = pool.getResource();

  3. String keys = "name";

  4. // 删数据

  5. jedis.del(keys);

  6. // 存数据

  7. jedis.set(keys, "snowolf");

  8. // 取数据

  9. String value = jedis.get(keys);

  10. System.out.println(value);

  11. // 释放对象池

  12. pool.returnResource(jedis);

 改为从对象池中,获取Jedis实例:

Java代码  

  1. // 从池中获取一个Jedis对象
  2. Jedis jedis = pool.getResource();

 切记,最后使用后,释放Jedis对象:

Java代码  

  1. // 释放对象池
  2. pool.returnResource(jedis);

三、一致性哈希

Memcached完全基于分布式集群,而RedisMaster-Slave,如果想把Reids,做成集群模式,无外乎多做几套Master-Slave,每套Master-Slave完成各自的容灾处理,通过Client工具,完成一致性哈希。

PS:Memcached是在Server端完成ShardingRedis只能依靠各个ClientSharding。可能会在Redis 3.0系列支持ServerSharding

保留前面的JedisPoolConfig,新增两个Redis的IP(redis1.ip,redis2.ip),完成两个JedisShardInfo实例,并将其丢进List中:

Java代码  

  1. JedisShardInfo jedisShardInfo1 = new JedisShardInfo(

  2. bundle.getString("redis1.ip"), Integer.valueOf(bundle                       .getString("redis.port")));

  3. JedisShardInfo jedisShardInfo2 = new JedisShardInfo(

  4. bundle.getString("redis2.ip"), Integer.valueOf(bundle                       .getString("redis.port")));

  5. List list = new LinkedList();

  6. list.add(jedisShardInfo1);

  7. list.add(jedisShardInfo2);

 初始化ShardedJedisPool代替JedisPool:

Java代码  

  1. ShardedJedisPool pool = new ShardedJedisPool(config, list);

 改由ShardedJedis,获取Jedis对象:

Java代码  

  1. // 从池中获取一个Jedis对象

  2. ShardedJedis jedis = pool.getResource();

  3. String keys = "name";

  4. String value = "snowolf";

  5. // 删数据

  6. jedis.del(keys);

  7. // 存数据

  8. jedis.set(keys, value);

  9. // 取数据

  10. String v = jedis.get(keys);

  11. System.out.println(v);

  12. // 释放对象池

  13. pool.returnResource(jedis);

四、Spring封装参考

 Ok,完成上述代码足够完成简单任务,如果有必要,可以用Spring封装初始化:

Xml代码  

  1. <bean
  2. id="jedisPoolConfig"
  3. class="redis.clients.jedis.JedisPoolConfig"
  4. >
  5. <property
  6. name="maxActive"
  7. value="${redis.pool.maxActive}" />
  8. <property
  9. name="maxIdle"
  10. value="${redis.pool.maxIdle}" />
  11. <property
  12. name="maxWait"
  13. value="${redis.pool.maxWait}" />
  14. <property
  15. name="testOnBorrow"
  16. value="${redis.pool.testOnBorrow}" />
  17. </bean>
  18. <bean
  19. id="shardedJedisPool"
  20. class="redis.clients.jedis.ShardedJedisPool"
  21. >
  22. <constructor-arg
  23. index="0"
  24. ref="jedisPoolConfig" />
  25. <constructor-arg index="1">
  26. <list>
  27. <bean class="redis.clients.jedis.JedisShardInfo">
  28. <constructor-arg
  29. index="0"
  30. value="${redis1.ip}" />
  31. <constructor-arg
  32. index="1"
  33. value="${redis.port}"
  34. type="int" />
  35. </bean>
  36. <bean class="redis.clients.jedis.JedisShardInfo">
  37. <constructor-arg
  38. index="0"
  39. value="${redis2.ip}" />
  40. <constructor-arg
  41. index="1"
  42. value="${redis.port}"
  43. type="int" />
  44. </bean>
  45. </list>
  46. </constructor-arg>
  47. </bean>

 代码可以更简洁一些:

Java代码  

  1. private ApplicationContext app;

  2. private ShardedJedisPool pool;

  3. @Before

  4. public void before() throws Exception {

  5. app = new ClassPathXmlApplicationContext("applicationContext.xml");

  6. pool = (ShardedJedisPool) app.getBean("shardedJedisPool");

  7. }

  8. @Test

  9. public void test() {

  10. // 从池中获取一个Jedis对象

  11. ShardedJedis jedis = pool.getResource();

  12. String keys = "name";

  13. String value = "snowolf";

  14. // 删数据

  15. jedis.del(keys);

  16. // 存数据

  17. jedis.set(keys, value);

  18. // 取数据

  19. String v = jedis.get(keys);

  20. System.out.println(v);

  21. // 释放对象池

  22. pool.returnResource(jedis);

  23. assertEquals(value, v);

  24. }

 
当然,Spring提供了对于Redis的专门支持:spring-data-redis,以后有机会再深入研究。

一.连接池基本参数详解

  1. maxActive: 链接池中最大连接数,默认为8.
  2. maxIdle: 链接池中最大空闲的连接数,默认为8.
  3. minIdle: 连接池中最少空闲的连接数,默认为0.
  4. maxWait: 当连接池资源耗尽时,调用者最大阻塞的时间,超时将跑出异常。单位,毫秒数;默认为-1.表示永不超时.
  5. minEvictableIdleTimeMillis: 连接空闲的最小时间,达到此值后空闲连接将可能会被移除。负值(-1)表示不移除。
  6. softMinEvictableIdleTimeMillis: 连接空闲的最小时间,达到此值后空闲链接将会被移除,且保留“minIdle”个空闲连接数。默认为-1.
  7. numTestsPerEvictionRun: 对于“空闲链接”检测线程而言,每次检测的链接资源的个数。默认为3.
  8. testOnBorrow: 向调用者输出“链接”资源时,是否检测是有有效,如果无效则从连接池中移除,并尝试获取继续获取。默认为false。建议保持默认值.
  9. testOnReturn:  向连接池“归还”链接时,是否检测“链接”对象的有效性。默认为false。建议保持默认值.
  10. testWhileIdle:  向调用者输出“链接”对象时,是否检测它的空闲超时;默认为false。如果“链接”空闲超时,将会被移除。建议保持默认值.
  11. timeBetweenEvictionRunsMillis:  “空闲链接”检测线程,检测的周期,毫秒数。如果为负值,表示不运行“检测线程”。默认为-1.
  12.  whenExhaustedAction: 当“连接池”中active数量达到阀值时,即“链接”资源耗尽时,连接池需要采取的手段, 默认为1:
     -> 0 : 抛出异常,
     -> 1 : 阻塞,直到有可用链接资源
     -> 2 : 强制创建新的链接资源

详见附件!