`
阅读更多

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

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

 

相关链接:

征服 Redis

征服 Redis + Jedis

征服 Redis + Jedis + Spring (一)—— 配置&常规操作(GET SET DEL)

征服 Redis + Jedis + Spring (二)—— 哈希表操作(HMGET HMSET)

征服 Redis + Jedis + Spring (三)—— 列表操作

 

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

  • Jredis
  • Jedis
  • Redis4J

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

 

一、简单使用Jedis

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

 

<dependency>
	<groupId>redis.clients</groupId>
	<artifactId>jedis</artifactId>
	<version>2.1.0</version>
	<type>jar</type>
	<scope>compile</scope>
</dependency>

 

 

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

 

		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完成池化实现。

先做个配置文件:

#最大分配的对象数
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

 

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

 

	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

		// 从池中获取一个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实例:

 

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

 

 

 切记,最后使用后,释放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中:

 

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);

 改由ShardedJedis,获取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封装初始化:

 

	<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>

 代码可以更简洁一些:

 

	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 + Jedis

征服 Redis + Jedis + Spring (一)—— 配置&常规操作(GET SET DEL)

征服 Redis + Jedis + Spring (二)—— 哈希表操作(HMGET HMSET)

征服 Redis + Jedis + Spring (三)—— 列表操作

25
2
分享到:
评论
25 楼 bluky999 2015-07-16  
cz19870902 写道
请教:池化配置的时候,怎么选择使用16个库中的哪个库呢?ShardedJedis 这个类提供了选择库的方法了吗?




new ShardedJedisPool(config, list,hashing, pattern);  这里可以指定hash策略


不过同时建议设置  shard 的name,否则会有麻烦: new JedisShardInfo("ip",port,"shard-1");
24 楼 bluky999 2014-08-28  
对于读写分离的master-slave, 这样做可以自动识别并分发读写请求么?
23 楼 cz19870902 2014-08-18  
请教:池化配置的时候,怎么选择使用16个库中的哪个库呢?ShardedJedis 这个类提供了选择库的方法了吗?
22 楼 ss979577961 2014-07-28  
求教,我两台redis集群,slave只读,用shardjedis写操作的时候就报错READONLY You can't write against a read only slave.是我哪里配置出错了么
21 楼 Java-feifeiok 2014-07-25  
ccuzhanglei 写道
Java-feifeiok 写道
老兄,我写到集群中数据后,当宕机一台,那么我连一台的数据都取不出来了!!有没有方法啊!

config.setTestOnBorrow(false);  这样就可以去到其他实例上的信息了

谢谢
20 楼 ccuzhanglei 2014-07-18  
大神您好!我想问一下,如果一个主挂了3个从,那么其中一个从挂掉,其他两个从还可以读取,但是,我们现在是给分片了,就会有失败的情况?能否随机读从实例(slave:1失败,其他两个还是活着的),这个不成功就读别的实例上的信息

请教请教!!!谢谢啦
19 楼 ccuzhanglei 2014-07-18  
Java-feifeiok 写道
老兄,我写到集群中数据后,当宕机一台,那么我连一台的数据都取不出来了!!有没有方法啊!

config.setTestOnBorrow(false);  这样就可以去到其他实例上的信息了
18 楼 hapic89 2014-06-27  
请问,那个jedis怎么用maven下载的?
17 楼 Java-feifeiok 2014-06-17  
老兄,我写到集群中数据后,当宕机一台,那么我连一台的数据都取不出来了!!有没有方法啊!
16 楼 Java-feifeiok 2014-06-17  
不错,不错,受用了
15 楼 di1984HIT 2014-04-14  
不错,学习了
14 楼 zhuyijian135757 2014-03-06  
PS:Memcached是在Server端完成Sharding ???

刚看了xmemcached的源码表示 memcached sharding也是在客户端完成的
13 楼 candou 2014-02-21  
请问,如何选择某一个数据库,
就是 select(1)
这样的功能.
找了很多都找不到.
12 楼 snowolf 2013-08-26  
timesongjie 写道
貌似 master挂掉后 ,slave也跟着死掉了,集群和容灾 是不是没效果,还是我理解有问题,还望指教

不会的,以前公司用的方式是keep-alive自动切换,ms互换。
11 楼 timesongjie 2013-08-25  
貌似 master挂掉后 ,slave也跟着死掉了,集群和容灾 是不是没效果,还是我理解有问题,还望指教
10 楼 jdbcy 2013-07-23  
你的释放只是归还连接回池子,程序结束的时候 要destroy掉连接池
9 楼 chenzhou123520 2013-07-11  
初学redis,很受用,顶一个
8 楼 fandayrockworld 2013-04-12  
snowolf 写道
fandayrockworld 写道

redis.pool.maxActive 
redis.pool.maxIdle
这两项jedis里默认的值都很小,貌似是8,博主给弄的这么大估计会有问题,做个长时间的测试吧。

长时间会有哪方面的问题?内存占用?链接不能自动释放?细心求教


不好意思,刚才看了下,那是jedis引用的commons-pool的默认值,这样的话,配那么大应该没什么问题了,打扰了。。
7 楼 snowolf 2013-04-12  
fandayrockworld 写道

redis.pool.maxActive 
redis.pool.maxIdle
这两项jedis里默认的值都很小,貌似是8,博主给弄的这么大估计会有问题,做个长时间的测试吧。

长时间会有哪方面的问题?内存占用?链接不能自动释放?细心求教
6 楼 fandayrockworld 2013-04-12  

redis.pool.maxActive 
redis.pool.maxIdle
这两项jedis里默认的值都很小,貌似是8,博主给弄的这么大估计会有问题,做个长时间的测试吧。

相关推荐

Global site tag (gtag.js) - Google Analytics