1. 程式人生 > >Redis實戰之Redis + Jedis

Redis實戰之Redis + Jedis

Memcached,對於快取物件大小有要求,單個物件不得大於1MB,且不支援複雜的資料型別,譬如SET

等。基於這些限制,有必要考慮Redis

相關連結:

言歸正傳,目前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 = new Jedis("10.11.20.140");
		String keys = "name";

		// 刪資料
		jedis.del(keys);
		// 存資料
		jedis.set(keys, "snowolf");
		// 取資料
		String value = jedis.get(keys);

		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. privatestatic JedisPool pool;  
  2. static {  
  3.     ResourceBundle bundle = ResourceBundle.getBundle("redis");  
  4.     if (bundle == null) {  
  5.         thrownew 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. }  
	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")));
	}

 然後,修改前面那段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物件
		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例項:

Java程式碼  
  1. // 從池中獲取一個Jedis物件
  2. Jedis jedis = pool.getResource();  
// 從池中獲取一個Jedis物件
Jedis jedis = pool.getResource();

 切記,最後使用後,釋放Jedis物件:

Java程式碼  
  1. // 釋放物件池
  2. pool.returnResource(jedis);  
// 釋放物件池
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<JedisShardInfo> list = new LinkedList<JedisShardInfo>();  
  6. list.add(jedisShardInfo1);  
  7. list.add(jedisShardInfo2);  
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:

Java程式碼  
  1. ShardedJedisPool pool = new ShardedJedisPool(config, list);  
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);  
		// 從池中獲取一個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);

四、Spring封裝參考

 Ok,完成上述程式碼足夠完成簡單任務,如果有必要,可以用Spring封裝初始化:

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

 程式碼可以更簡潔一些:

Java程式碼  
  1. private ApplicationContext app;  
  2. private ShardedJedisPool pool;  
  3. @Before
  4. publicvoid before() throws Exception {  
  5.     app = new ClassPathXmlApplicationContext("applicationContext.xml");  
  6.     pool = (ShardedJedisPool) app.getBean("shardedJedisPool");  
  7. }  
  8. @Test
  9. publicvoid 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. }  
	private ApplicationContext app;
	private ShardedJedisPool pool;

	@Before
	public void before() throws Exception {
		app = new ClassPathXmlApplicationContext("applicationContext.xml");
		pool = (ShardedJedisPool) app.getBean("shardedJedisPool");
	}

	@Test
	public void test() {

		// 從池中獲取一個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);

		assertEquals(value, v);
	}

 
當然,Spring提供了對於Redis的專門支援:spring-data-redis,以後有機會再深入研究。

相關連結: