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/
三.安装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
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 Setnodes = new HashSet (); 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 > result = new ArrayList >(threadNum); for (int i = 0; i < threadNum; ++i) { result.add(threadPool.submit(new IncrThread(rcc, key_cnt + i, count))); } for (Future 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 { 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; } } }