redis实践-cluster搭建
redis3开始支持cluster集群模式,解决单点的瓶颈问题,本文以3.0.3为例搭建并测试cluster集群
搭建步骤
一.安装ruby
a) wget https://cache.ruby-lang.org/pub/ruby/2.2/ruby-2.2.3.tar.gz
b) tar -xvzf ruby-2.2.3.tar.gz
c) cd ruby-2.2.3
d) ./configure
e) make
d) make install
二.安装rubygems & ruby redis
a) yum install rubygems
b) gem install redis
上述过程中可能由于gem source问题导致下载失败,可以换成国内的
添加源 gem sources -a http://ruby.taobao.org/
删除源 gem sources --remove http://rubygems.org/
查看源 gem sources -l
三.安装redis
a) wget http://download.redis.io/releases/redis-3.0.3.tar.gz
b) tar -xzvf redis-3.0.3.tar.gz
c) cd redis-3.0.3
d) make
e) make install
四.集群配置
集群10.2.102.7, 10.2.102.8,10.2.102.9相互打通,每台机器部署两个redis实例
a) 在每台机器上建立两个目录
mkdir redis-cluster/7000 redis-cluster/70001
b) 在每个目录下创建配置文件redis.conf,配置如下,其中port值和目录名对应
五.启动
a) 进入每台机器的实例目录,执行
redis-server redis.conf
成功后可以在实例目录下的redis.log中看到如下日志
b) 关联实例创建集群
3台机器6个实例,一主一备将slots切分为3份
redis-trib.rb create --replicas 1 10.2.102.7:7000 10.2.102.7:7001 10.2.102.8:7000 10.2.102.8:7001 10.2.102.9:7000 10.2.102.9:7001
输入 yes 接受 主备节点分配
在每个实例目录下可以看见生成了一份nodes.conf,如下
六.测试
可以通过redis-cli脚本,但须要加上-c参数指定cluster模式连接。用junit代码如下,其中RedisClusterClient是基于JedisCluster的封装:
public class RedisClusterCliTest {
private final static String key_cnt = "key_cnt";
final static Set<HostAndPort> nodes = new HashSet<HostAndPort>();
static {
nodes.add(new HostAndPort("10.2.102.7", 7000));
nodes.add(new HostAndPort("10.2.102.7", 7001));
//nodes.add(new HostAndPort("10.2.102.8", 7000));
//nodes.add(new HostAndPort("10.2.102.8", 7001));
//nodes.add(new HostAndPort("10.2.102.9", 7000));
//nodes.add(new HostAndPort("10.2.102.9", 7001));
}
private RedisClusterClient rcc;
@Before
public void init() {
rcc = new RedisClusterClient(nodes);
}
@After
public void destroy() {
rcc.close();
}
@Test
public void test_set() {
for (int i = 0; i < 100; ++i) {
rcc.setex("key" + i, 60 * 10, String.valueOf(i));
}
}
@Test
public void test_get() {
for (int i = 0; i < 100; ++i) {
String value = rcc.get("key" + i);
System.out.println(value);
}
}
@Test
public void test_incr() {
System.out.println("Before incr : " + rcc.get(key_cnt));
rcc.incr(key_cnt);
System.out.println("After incr : " + rcc.get(key_cnt));
}
@Test
public void test_incr_multi() {
long start = Long.parseLong(rcc.get(key_cnt));
System.out.println("Before incr : " + start + ", " + new Date());
int threadNum = 100;
int count = 100;
ExecutorService threadPool = Executors.newFixedThreadPool(threadNum, new ThreadFactory(){
AtomicInteger index = new AtomicInteger(0);
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "Thread-incr-" + index.incrementAndGet());
}
});
List<Future<Boolean>> result = new ArrayList<Future<Boolean>>(threadNum);
for (int i = 0; i < threadNum; ++i) {
result.add(threadPool.submit(new IncrThread(rcc, key_cnt + i, count)));
}
for (Future<Boolean> f : result) {
try {
if(!f.get()) {
System.err.println("Fail ....");
break;
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
System.out.println("After incr : " + rcc.get(key_cnt) + ", Except " + (start + count * threadNum) + ", " + new Date());
}
@Test
public void test_decr() {
System.out.println("Before decr : " + rcc.get(key_cnt));
rcc.decr(key_cnt);
System.out.println("After decr : " + rcc.get(key_cnt));
}
class IncrThread implements Callable<Boolean> {
RedisClusterClient rcc;
String key;
int count;
IncrThread(RedisClusterClient rcc, String key, int count) {
this.rcc = rcc;
this.key = key;
this.count = count;
}
@Override
public Boolean call() {
for (int i = 0; i < count; ++i) {
rcc.incr(key);
}
return true;
}
}
}