一、Redis目前的集群方案主要有两种:Redis Sharding和Redis Cluster
1、Redis Sharding:3.0以前基本上使用分片实现集群,目前主流方案,客户端实现
2、Redis Cluster:3.0后官方提供了集群方案,2015年4月发布,目前大型应用验证较少,服务端实现
上面两种方案的区别请见:
二、下面只说明使用Jedis实现Redis Sharding的方案
Redis Sharding特点:
- 客户端实现
- 各个Redis节点独立,之间无关系
- 某个Redis节点挂了,整个集群不可用,所以需要对每个节点做主从备份
- 主从备份方案一般通过读写分离设置,每个master至少两个slaver,只有这样master挂掉后,才能选举其中一个Slaver成为新的master,原来master节点加入集群后成为新master的slaver节点
- redis主从切换对客户端jedis使用时透明的,即redis发生了主从切换并不影响jedis的使用
缺点:
- 节点扩展和收缩不友好
三、Redis服务集群的搭建
- Redis集群的搭建可参考文章:搭建3个master-slaver的主从配置
http://www.cnblogs.com/gossip/p/5992716.html
http://www.cnblogs.com/gossip/p/5992821.html - 注意:一般会搭建3个master节点,每个master挂2个slaver,各个master之间并无联系。Redis Cluster的方案是所有master有联系并进行心跳通信,和Redis Sharding不一样
四、Jedis客户端的使用
- 版本:2.9.0
- 实现代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
import redis.clients.jedis.*;
import redis.clients.util.JedisClusterCRC16;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class ShardingTest {
private static String ip = "127.0.0.1" ;
private static int timeout = 10000 ;
public static void main(String[] args) {
JedisPoolConfig poolConfig = getPoolConfig();
List<JedisShardInfo> listRedis = getListSherdInfo();
ShardedJedisPool jedisPool = new ShardedJedisPool(poolConfig, listRedis);
ShardedJedis jedis = jedisPool.getResource();
testData(jedis);
//initString(jedis);
//initHash(jedis); //17秒
//initHashPipeline(jedis); //0秒(是的,0秒)
System.out.println(jedis.get( "k1" ));
System.out.println(jedis.hgetAll( "product2" ));
//initHashPipeline100000(jedis); //100000 总时间 63秒
jedis.close();
jedisPool.destroy();
}
private static JedisPoolConfig getPoolConfig() {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal( 200 );
poolConfig.setMaxIdle( 30 );
//就是在进行borrowObject进行处理时,对拿到的connection进行validateObject校验
//poolConfig.setTestOnBorrow(true);
//就是在进行returnObject对返回的connection进行validateObject校验,个人觉得对数据库连接池的管理意义不大
//poolConfig.setTestOnReturn(true);
//GenericObjectPool中针对pool管理,起了一个Evict的TimerTask定时线程进行控制(可通过设置参数
//poolConfig.setTestWhileIdle(true);
return poolConfig;
}
private static List<JedisShardInfo> getListSherdInfo() {
JedisShardInfo redis1 = new JedisShardInfo(ip, 9111 );
redis1.setConnectionTimeout(timeout);
JedisShardInfo redis2 = new JedisShardInfo(ip, 9112 );
redis2.setConnectionTimeout(timeout);
JedisShardInfo redis3 = new JedisShardInfo(ip, 9113 );
redis3.setConnectionTimeout(timeout);
List<JedisShardInfo> listRedis = new ArrayList<JedisShardInfo>();
listRedis.add(redis1);
listRedis.add(redis2);
listRedis.add(redis3);
return listRedis;
}
private static void testData(ShardedJedis jedis) {
String key = "k5" ;
String value = "v5" ;
jedis.set(key, value);
System.out.println( "key:" + jedis.get(key));
System.out.println( "key:" + JedisClusterCRC16.getSlot(key));
System.out.println(jedis.type(key));
}
}
|