`
aokunsang
  • 浏览: 812666 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

redis集群codis的搭建使用

阅读更多

一、codis安装前准备工作

1、参考链接

Codis:https://github.com/CodisLabs/codis/blob/master/doc/tutorial_zh.md

            http://0xffff.me/blog/2014/11/11/codis-de-she-ji-yu-shi-xian-1/

Codis-port:https://github.com/CodisLabs/redis-port

Codis-FAQ:https://github.com/CodisLabs/codis/blob/master/doc/FAQ_zh.md

Zookeeper:https://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/

GO:https://golang.org/

 

2、准备几个目录备用

/work/soft        - 软件下载目录

/work/servers  - 软件安装目录

   go  - go安装目录【GOROOT】

   zookeeper-3.4.6 - zookeeper安装目录【ZOOKEEPER_HOME】

/work/gospace - 本机所有go项目(包括项目依赖的第三方库)的所在目录(包括codis和codis-port)【GOPATH】

/work/codis  - codis和codis-port源码下载目录

    logs - codis启动的相关日志目录(dashboard.log/proxy.log/slot.log/request.log/redis-port.log)

    rdb  - redis的RDB文件路径

/work/codis_bin - 一个软链接到codis/bin

/work/codis_port_bin - 一个软链接到codis_port/bin

/etc/codis   - codis启动的一系列配置文件(redis_xxx.conf/zoo.cfg/codis的config.ini)

 

3、环境介绍

使用一台虚拟机搭建一个codis伪集群,zookeeper没有使用集群[配置很简单,自己操作]。 

①1个redis-server - 使用它的redis.conf配置文件以及使用它模拟从redis导数据到codis集群
②1个zookeeper  -  中间件
③6个端口不同实例相同的codis-server - 见[三、codis运行]
④2个codis-proxy - 只不过配置文件不同 
⑤192.168.56.101 - 宿主机能够访问的IP(虚拟机的网络连接,网卡1:NAT,网卡2:host-only;家庭电脑尽量使用桥接,并且静态地址)
 redis-server和codis-server的不同:codis-server 是 Codis 项目维护的一个 Redis 分支, 基于 2.8.21 开发, 加入了 slot 的支持和原子的数据迁移指令. Codis 上层的 codis-proxy 和 codis-config 只能和这个版本的 Redis 交互才能正常运行。 

 

4、go/zookeeper/jdk/redis安装和环境变量配置(codis是go语言开发)

(1)进入/work/soft目录,cd /work/soft

(2)下载并解压go安装包:  

wget https://storage.googleapis.com/golang/go1.6.linux-amd64.tar.gz
tar -zx[v]f go1.6.linux-amd64.tar.gz -C /work/servers 
 (3)下载并安装zookeeper安装包:
wget http://mirrors.cnnic.cn/apache/zookeeper/zookeeper-3.4.6/zookeeper-3.4.6.tar.gz
tar -zx[v]f zookeeper-3.4.6.tar.gz -C /work/servers
cd /work/servers/zookeeper-3.4.6
mkdir data && mkdir logs
  修改zoo.cfg几个关键属性: 
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/work/servers/zookeeper-3.4.6/data
dataLogDir=/work/servers/zookeeper-3.4.6/logs
clientPort=2181

 最后把配置文件放到/etc/codis中,

cp /work/servers/zookeeper-3.4.6/conf/zoo.cfg /etc/codis/zoo.cfg

(4)jdk安装略... 

(5)redis安装略...

(6)准备codis-server(6个redis服务)的启动文件:

 修改redis.conf,主要修改这几点: 

daemonize yes
pidfile /var/run/redis_6379.pid
port 6379
dbfilename dump_6379.rdb
dir /work/codis/rdb

 然后执行下面命令:  

cp redis.conf /etc/codis/redis_6378.conf && sed -i 's/6379/6378/g' /etc/codis/redis_6378.conf
cp redis.conf /etc/codis/redis_6478.conf && sed -i 's/6379/6478/g' /etc/codis/redis_6478.conf
cp redis.conf /etc/codis/redis_6379.conf
cp redis.conf /etc/codis/redis_6479.conf && sed -i 's/6379/6479/g' /etc/codis/redis_6479.conf
cp redis.conf /etc/codis/redis_6380.conf && sed -i 's/6379/6380/g' /etc/codis/redis_6380.conf
cp redis.conf /etc/codis/redis_6480.conf && sed -i 's/6379/6480/g' /etc/codis/redis_6480.conf

 (7)配置环境变量,执行命令:vim /etc/profile,在最后一行添加: 

export GOROOT=/work/servers/go
export GOPATH=/work/gospace
export ZOOKEEPER_HOME=/work/servers/zookeeper-3.4.6
export JAVA_HOME=你的jdk根路径
export CLASSPATH=.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar
export PATH=$GOROOT/bin:$GOPATH/bin:$JAVA_HOME/bin:$ZOOKEEPER_HOME/bin:$PATH

 配置ok,刷新环境变量;  .或者source  /etc/profile。

 

(8)测试三个必须软件是否正常安装:

jdk - 执行java命令

zookeeper 

   - 启动命令:zkServer.sh start /etc/codis/zoo.cfg

   - 停止命令:zkServer.sh stop /etc/codis/zoo.cfg

   - 查看状态:zkServer.sh status /etc/codis/zoo.cfg

go - 编写个小程序(摘自go官网) 

  package main
  import "fmt"
  func main() {
	fmt.Println("Hello, 世界")
  }

 执行命令:go run hello.go。

 

 

二、codis安装与配置

1、安装codis前,需要先装下git: 

yum install -y git

 2、下载codis源码(下载目录自动到GOPATH=/work/gospace中):  

go get -u -d github.com/CodisLabs/codis

 3、切换到/work/gospace/src/github.com/CodisLabs/codis,编译测试:  

make && make gotest

 4、执行成功了上面的命令,会在bin文件夹中生成三个可执行文件:codis-config、codis-proxy、codis-server,常用命令查询: 

./codis-config -c /etc/codis/config.ini proxy -h
./codis-config -c /etc/codis/config.ini action -h
./codis-config -c /etc/codis/config.ini slot -h
./codis-config -c /etc/codis/config.ini server -h
./codis-config -c /etc/codis/config.ini dashboard -h

 5、在/work目录建立软链接方便进入bin目录: 

ln -s /work/gospace/src/github.com/CodisLabs/codis/bin codis_bin

 6、编辑config.ini文件,主要修改2点: 

zk=192.168.56.101:2181(如果是zookeeper集群,用逗号隔开继续添加)
dashboard_addr=192.168.56.101:18087
【下面可选修改】
[product=test 其实就是个Namespace区分项目,改完后在zookeeper中的路径会稍微不同,如:/zk/codis/db_product名字]
[proxy_id=proxy1 改完在启动proxy的时候,注意proxy_id的名字]

 ip地址改为客户端能访问到的,最好别搞成127.0.0.1;然后copy到/etc/codis/目录。

 

 

三、codis的运行

【说明】:

(1)首先创建2个group(group-1,group-2),分配redis端口号:6378(master-group1)、6478(slave-group1)、6379(master-group2)、6479(slave-group2),槽位分配group1:0-511,group2:512-1023;

(2)然后再创建1个group(group-3),分配redis端口号6380(master-group3)、6480(slave-group3),重新分配槽位:group1:0-340,group2:341-680,group3:681-1023; 

(3)以下所有的bash文件都是在codis_bin目录中;

(4)首次启动codis,必须按照下面1-6的顺序依次启动命令。

1、首先启动zookeeper[如果安装时候已启动,自动忽略]:

论zookeeper重要性:Codis依赖ZooKeeper来存放数据路由表和codis-proxy节点的元信息,codis-config发起的命令都会通过ZooKeeper同步到各个存活的codis-proxy。 

zkServer.sh start /etc/codis/zoo.cfg

 2、启动dashboard,方便起见写到bash文件[下同]:  

#!/bin/bash
nohup ./codis-config -c /etc/codis/config.ini -L /work/codis/logs/dashboard.log dashboard --addr=192.168.56.101:18087 --http-log=/work/codis/logs/request.log > /dev/null 2>&1 &

--addr的ip地址不能写成127.0.0.1 否则访问页面打不开。

执行:ps -ef | grep codis 能看到: 

root      1536     1  0 16:38 ?        00:00:42 ./codis-config -c /etc/codis/config.ini -L /work/codis/logs/dashboard.log dashboard --addr=192.168.56.101:18087 --http-log=/work/codis/logs/request.log
root      1970  1122  0 18:33 pts/0    00:00:00 grep codis

 3、启动redis: 

#!/bin/bash
echo 'redis starting'
./codis-server /etc/codis/redis_6378.conf
./codis-server /etc/codis/redis_6478.conf
./codis-server /etc/codis/redis_6379.conf
./codis-server /etc/codis/redis_6479.conf
./codis-server /etc/codis/redis_6380.conf
./codis-server /etc/codis/redis_6480.conf
echo 'done'

 4、初始化group: 

#!/bin/bash
echo 'groups initializing...'
./codis-config -c /etc/codis/config.ini server add 1 localhost:6378 master
./codis-config -c /etc/codis/config.ini server add 1 localhost:6478 slave

./codis-config -c /etc/codis/config.ini server add 2 localhost:6379 master
./codis-config -c /etc/codis/config.ini server add 2 localhost:6479 slave
echo 'done'

5、初始化slot: 

#!/bin/bash
echo 'slots starting...'
./codis-config -c /etc/codis/config.ini action remove-fence
./codis-config -c /etc/codis/config.ini slot init -f

./codis-config -c /etc/codis/config.ini slot range-set 0 511 1 online
./codis-config -c /etc/codis/config.ini slot range-set 512 1023 2 online
echo 'done'

6、启动proxy: 

#!/bin/bash
echo 'shutdown codis-proxy'
./codis-config -c /etc/codis/config.ini proxy offline proxy_1

sleep 2
echo 'codis-proxy starting'
nohup ./codis-proxy -c /etc/codis/config.ini --log-level=info -L /work/codis/logs/proxy.log --cpu=3 --addr=192.168.56.101:19000 --http-addr=192.168.56.101:11000 &>/dev/null &

[下面命令非必须(执行也不报错),官方文档有点问题:它指出启动后的proxy是offline状态,但是实验发现是online状态的,所以无需执行下面设置为online的命令]
sleep 2
echo 'setting codis-proxy online'
./codis-config -c /etc/codis/config.ini proxy online proxy_1
echo 'done'

 

 

全部启动正常后,打开chrome,访问:http://192.168.56.101:18087/admin/,可以看到如下界面(此时你看不到group3):



 

 

 

 

四、codis的模拟各种场景测试

1、用java程序写测试程序:

JedisResourcePool jedisPool = RoundRobinJedisPool.create().curatorClient("192.168.56.101:2181", 30000).zkProxyDir("/zk/codis/db_test/proxy").build();
Jedis jedis = jedisPool.getResource();
while(++i < 10000){
 jedis.setnx("num:"+i, i+"");
}

2、多线程测试程序: 

public static String randomstr(){
	Random rnd = new Random();
	return ""+rnd.nextInt(Integer.MAX_VALUE);
}

public static void init_data(JedisResourcePool jedisPool){
	for(int i = 0; i < 100; i++){
		new myThread(jedisPool).start();
	}
}
static class myThread extends Thread{
	private JedisResourcePool jedisPool;
	public myThread(JedisResourcePool jedisPool){
		this.jedisPool = jedisPool;
	}
	public void run() {
		for(int i=0;i<1000;i++){
			String randomstr = randomstr();
			Jedis jedis = jedisPool.getResource();
			jedis.setnx(randomstr, randomstr);
			System.out.println(Thread.currentThread().getName()+"=======>>>>"+randomstr);
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				System.out.println(e.getMessage() + "=======>>>>" + randomstr);
				e.printStackTrace();
			} finally{
				jedis.close();
			}
		}
	}
}

 3、程序检测key值定位到哪个slot: 

CRC32 crc32 = new CRC32();
crc32.update("num:1".getBytes());
System.out.println(crc32.getValue() % 1024);

  

4、把6479-redis(slave)从group1中remove掉,然后向6379-redis(master)插入数据,看是否继续同步数据到6479-redis(slave): 

./codis-config -c /etc/codis/config.ini server remove 2 localhost:6479

  

5、保持程序2在正常运行状态,同时添加group3,重新分配迁移slot,查看是否抛异常.

依次执行下面命令: 

./codis-config -c /etc/codis/config.ini server add 3 localhost:6380 master
./codis-config -c /etc/codis/config.ini server add 3 localhost:6480 slave
./codis-config -c /etc/codis/config.ini slot migrate 0 340 1 --delay=5
./codis-config -c /etc/codis/config.ini slot migrate 341 680 2 --delay=5
./codis-config -c /etc/codis/config.ini slot migrate 681 1023 3 --delay=5

 6、再启动一个proxy(proxy_2):

  【说明】:

==================================================

①config.ini中使用相同的zookeeper,dashboard_addr,product, 不同的proxy_id;

②start_proxy_2.sh中设置不同的addr,http-addr端口号,以及log日志文件名

==================================================

 复制一份config.ini重命名为config_2.ini

cd /etc/codis
cp config.ini config_2.ini && sed -i 's/proxy_1/proxy_2/g' config_2.ini

 启动proxy_2:  

#!/bin/bash
echo 'shutdown codis-proxy-2'
./codis-config -c /etc/codis/config_2.ini proxy offline proxy_2

sleep 2
echo 'codis-proxy-2 starting'
nohup ./codis-proxy -c /etc/codis/config_2.ini --log-level=info -L /work/codis/logs/proxy_2.log --cpu=3 --addr=192.168.56.101:19001 --http-addr=192.168.56.101:11001 &>/dev/null &

sleep 2
echo 'setting codis-proxy-2 online'
./codis-config -c /etc/codis/config_2.ini proxy online proxy_2
echo 'done'

启动成功后,保持程序2在正常运行状态,测试几点: 

①使用页面端mark offline按钮停掉其中一个proxy;

②然后再启动停掉的proxy;

③分别使用kill或者kill -9杀死某个proxy的进程

 

7、虚拟机退出后,再次开启,只需要启动zookeeper、dashboard、redis、proxy即可,测试以下几点:

①观察slave/master的redis是否还是slave/master;

②调用程序插入数据是否正常;

③主从同步是否正常。

 

五、测试总结

1、同一个组中,remove掉某个slave,插入到master的数据,还能同步到该slave中、

 

2、挂掉整个系统,重新启动dashboard,控制页面虽然能看到master和slave的redis状态,实际上slave不再是slave,而是master,需要进行重新add-slave操作。

 

3、dashboard启动不来,报错如下: 

dashboard.go:234: [PANIC] create zk node failed
   [error]: dashboard already exists: {"addr": "192.168.56.101:18087", "pid": 1242}

 

解决方案:delete /zk/codis/db_test/dashboard

 

4、删除一个已分配slot的group,或者redis-master时,报错: 

[error]: http status code 500, cannot remove master, use promote first

 

解决方案:已分配slot的group是删除不了的,只能转移slot数据。删除redis-master也必然不行,一个group必须有个master。可以先指定一个slave升级为master,然后可以删除该master。

 

5、kill -9强制关闭proxy,codis无法区分是否正常下线或者session过期。然后再操作分配slot时候,出现错误。

解决办法:

./codis-config -c /etc/codis/config.ini action remove-fence 
或者 进入zookeeper手动删除/zk/codis/db_test/fence

 

6、slot的迁移,程序运行对迁移状态不影响,可以在dashboard看到迁移动态。

 迁移原理:http://0xffff.me/blog/2014/11/11/codis-de-she-ji-yu-shi-xian-part-2

[ Codis 不适合少量key,value特别大的应用(这种不用分布式了,直接用单个redis就可以), 更适合海量 Key, value比较小(<= 1 MB) 的应用]

 

六、使用codis-port把项目中redis数据迁移到codis集群

1、修改安装redis-server的redis.conf的端口号为6580:

 

sed -i 's/6379/6580/g' redis.conf

 

2、启动安装的redis实例:   

redis-server ../conf/redis.conf

 

3、写个程序往6580-redis插入10w条数据:

 

Jedis jedis = new Jedis("192.168.56.101", 6580);
for(int i=20000;i<100000;i++){
	jedis.set("i:"+i, ""+i);
}

4、下载安装、编译redis-port:

cd /work
go get -u -d github.com/CodisLabs/codis-port
cd /work/gospace/src/github.com/CodisLabs/codis-port && make
ln -s /work/gospace/src/github.com/CodisLabs/redis-port/bin codis_port_bin

 5、redis数据导入到codis集群:

cd /work/codis_port_bin

 执行命令:

#!/bin/bash
nohup ./redis-port sync --ncpu=3 --from=127.0.0.1:6580 --target=192.168.56.101:19000 > /work/codis/logs/redis-port.log 2>&1 &
sleep 3
tail -f /work/codis/logs/redis-port.log

 

 

  • 大小: 102 KB
  • 大小: 63.1 KB
  • 大小: 59 KB
  • 大小: 129.4 KB
2
5
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics