Redis实战之Redis + Jedis

时间:2021-04-14 20:30:45

Memcached,对于缓存对象大小有要求,单个对象不得大于1MB,且不支持复杂的数据类型,譬如SET

等。基于这些限制,有必要考虑Redis

相关链接:

Redis实战

Redis实战之Redis + Jedis

Redis实战之征服 Redis + Jedis + Spring (一)

Redis实战之征服 Redis + Jedis + Spring (二)

Redis实战之征服 Redis + Jedis + Spring (三)

 

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

  • Jredis
  • Jedis
  • Redis4J

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

 

一、简单使用Jedis

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

 

Xml代码   Redis实战之Redis + Jedis
  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>  
<dependency>
	<groupId>redis.clients</groupId>
	<artifactId>jedis</artifactId>
	<version>2.1.0</version>
	<type>jar</type>
	<scope>compile</scope>
</dependency>

 

 

 

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

 

Java代码   Redis实战之Redis + Jedis
  1. Jedis jedis = new Jedis("10.11.20.140");  
  2. String keys = "name";  
  3.   
  4. // 删数据  
  5. jedis.del(keys);  
  6. // 存数据  
  7. jedis.set(keys, "snowolf");  
  8. // 取数据  
  9. String value = jedis.get(keys);  
  10.   
  11. 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代码   Redis实战之Redis + Jedis
  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  
#最大分配的对象数
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=10.11.20.140
#Port
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. }  
	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. // 删数据  
  6. jedis.del(keys);  
  7. // 存数据  
  8. jedis.set(keys, "snowolf");  
  9. // 取数据  
  10. String value = jedis.get(keys);  
  11.   
  12. System.out.println(value);  
  13.   
  14. // 释放对象池  
  15. 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.   
  6. List<JedisShardInfo> list = new LinkedList<JedisShardInfo>();  
  7. list.add(jedisShardInfo1);  
  8. 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.   
  12. System.out.println(v);  
  13.   
  14. // 释放对象池  
  15. 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-placeholder location="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-arg index="1">  
  27.         <list>  
  28.             <bean class="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.             <bean class="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>  
	<context:property-placeholder location="classpath:redis.properties" />
	<bean
		id="jedisPoolConfig"
		class="redis.clients.jedis.JedisPoolConfig"
	>
		<property
			name="maxActive"
			value="${redis.pool.maxActive}" />
		<property
			name="maxIdle"
			value="${redis.pool.maxIdle}" />
		<property
			name="maxWait"
			value="${redis.pool.maxWait}" />
		<property
			name="testOnBorrow"
			value="${redis.pool.testOnBorrow}" />
	</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>

 

 代码可以更简洁一些:

 

Java代码  
  1. private ApplicationContext app;  
  2. private ShardedJedisPool pool;  
  3.   
  4. @Before  
  5. public void before() throws Exception {  
  6.     app = new ClassPathXmlApplicationContext("applicationContext.xml");  
  7.     pool = (ShardedJedisPool) app.getBean("shardedJedisPool");  
  8. }  
  9.   
  10. @Test  
  11. public void test() {  
  12.   
  13.     // 从池中获取一个Jedis对象  
  14.     ShardedJedis jedis = pool.getResource();  
  15.     String keys = "name";  
  16.     String value = "snowolf";  
  17.     // 删数据  
  18.     jedis.del(keys);  
  19.     // 存数据  
  20.     jedis.set(keys, value);  
  21.     // 取数据  
  22.     String v = jedis.get(keys);  
  23.   
  24.     System.out.println(v);  
  25.   
  26.     // 释放对象池  
  27.     pool.returnResource(jedis);  
  28.   
  29.     assertEquals(value, v);  
  30. }  
	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,以后有机会再深入研究。

 

相关链接:

Redis实战

Redis实战之Redis + Jedis

Redis实战之征服 Redis + Jedis + Spring (一)

Redis实战之征服 Redis + Jedis + Spring (二)

Redis实战之征服 Redis + Jedis + Spring (三)