Codis集群搭建
下载安装JDK
下载解压缩安装包
yum install java-1.7.0-openjdk-devel.x86_64
/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.141-2.6.10.1.el7_3.x86_64
mv /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.151.x86_64/ /mnt/jdk1.7
下载安装GO
1.下载依赖
yum install -y gcc glibc gcc-c++ make git
2.下载安装包并解压
wget https://storage.googleapis.com/golang/go1.8.linux-amd64.tar.gz
tar zxvf go1.8.linux-amd64.tar.gz
创建复制到相应目录
mkdir -p /usr/local/go/codis
配置变量
vi /etc/profile
export JAVA_HOME=/mnt/jdk1.7
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export GOROOT=/usr/local/go
export GOPATH=/usr/local/go/codis
export PATH=$PATH:$JAVA_HOME/bin:$GOROOT/bin:$GOPATH/bin
是变量生效
source /etc/profile
验证是否安装成功
Java -version
Go -version
Zookeeper集群搭建
(需要在安装zookeeper的每一台机上操作)
1.部署zookeeper(可部署1个,建议部署多台[奇数]提供集群服务,须安装JDK)
cd /usr/local
wget http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.9/zookeeper-3.4.9.tar.gz
tar zxvf zookeeper-3.4.9.tar.gz
mv /usr/local/zookeeper-3.4.9 /usr/local/zookeeper
配置变量
vi /etc/profile
export JAVA_HOME=/mnt/jdk1.7
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export GOROOT=/usr/local/go
export GOPATH=/usr/local/go/codis
export ZOOKEEPER_HOME=/usr/local/zookeeper
export PATH=$PATH:$JAVA_HOME/bin:$GOROOT/bin:$GOPATH/bin:$ZOOKEEPER_HOME/bin
source /etc/profile
#这里是搭建zk伪机群,
cd /opt
mkdir zk1 zk2 zk3
复制zoo_sample.cfg 并改名
cp /usr/local/zookeeper/conf/zoo_sample.cfg /opt/zk1/zk1.cfg
cp /usr/local/zookeeper/conf/zoo_sample.cfg /opt/zk2/zk2.cfg
cp /usr/local/zookeeper/conf/zoo_sample.cfg /opt/zk3/zk3.cfg
grep "^[a-z]" /opt/zk1/zk1.cfg
更改每个的配置文件
vi /opt/zk1/zk1.cfg
tickTime=6000 #服务器和客户端的心跳维持间隔,间隔多久发送心跳 ,6000微秒等于6毫秒
initLimit=10 #选举的时候的时间间隔是10次,10次 * 6000微秒 即60秒
syncLimit=10 # Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度
dataDir=/opt/zk1 # 数据保存目录
clientPort=2181 # 客户端连接的端口
server.1=172.17.0.3:2887:3887
server.2=172.17.0.3:2888:3888
server.3=172.17.0.3:2889:3889
server.1=122.14.208.184:2887:3887
server.2=122.14.208.184:2888:3888
server.3=122.14.208.184:2889:3889
vi /opt/zk2/zk2.cfg
tickTime=6000 #服务器和客户端的心跳维持间隔,间隔多久发送心跳 ,6000微秒等于6毫秒
initLimit=10 #选举的时候的时间间隔是10次,10次 * 6000微秒 即60秒
syncLimit=10 # Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度
dataDir=/opt/zk2 # 数据保存目录
clientPort=2182 # 客户端连接的端口
server.1=172.17.0.3:2887:3887
server.2=172.17.0.3:2888:3888
server.3=172.17.0.3:2889:3889
vi /opt/zk3/zk3.cfg
tickTime=6000 #服务器和客户端的心跳维持间隔,间隔多久发送心跳 ,6000微秒等于6毫秒
initLimit=10 #选举的时候的时间间隔是10次,10次 * 6000微秒 即60秒
syncLimit=10 # Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度
dataDir=/opt/zk3 # 数据保存目录
clientPort=2183 # 客户端连接的端口
server.1=172.17.0.3:2887:3887
server.2=172.17.0.3:2888:3888
server.3=172.17.0.3:2889:3889
grep "^[a-z]" /opt/zk1/zk1.cfg
#准备zookeeper 服务ID,每个服务器的ID是不同的
echo 1 > zk1/myid
echo 2 > zk2/myid
echo 3 > zk3/myid
启动zk
/usr/local/zookeeper/bin/zkServer.sh restart /opt/zk1/zk1.cfg
/usr/local/zookeeper/bin/zkServer.sh restart /opt/zk2/zk2.cfg
/usr/local/zookeeper/bin/zkServer.sh restart /opt/zk3/zk3.cfg
测试连接到zookeeper节点
2.检查zookeeper所有节点状态
/usr/local/zookeeper/bin/zkCli.sh -server 192.168.218.159:2181
Codis安装搭建
1.下载安装codis (在每个需要安装codis的服务器上操作)
安装依赖包
yum install -y gcc make gcc-c++ automake lrzsz openssl-devel zlib-* bzip2-* readline* zlib-* bzip2-* git nmap unzip wget lsof xz net-tools mercurial vim
创建相应目录
mkdir -p $GOPATH/src/github.com/CodisLabs
cd /usr/local/go/codis/src/github.com/CodisLabs/
git clone https://github.com/CodisLabs/codis.git -b release3.2
yum install autoconf automake libtool -y
cd /usr/local/go/codis/src/github.com/CodisLabs/codis
//执行编译
Make
执行测试:
Make gotest
执行成功后进入bin目录,会新增几个文件,如下:
表示编译成功
2.配置redis文件(我以2个为例,数量随意)(在每个安装了codis的服务器上操作)
mkdir -pv /var/lib/redis_638{1..2}
cd extern/redis-3.2.8/
cp redis.conf /usr/local/go/codis/src/github.com/CodisLabs/codis/
cd /usr/local/go/codis/src/github.com/CodisLabs/codis/
vi redis.conf
bind 122.14.208.184
port 6381
pidfile /var/run/redis_6381.pid
logfile "/tmp/redis_6381.log"
dbfilename dump_6381.rdb
dir /var/lib/redis_6381
maxmemory 1g #一定要设置最大内存,否则后面的codis无法使用
cp redis.conf redis_6381.conf
cp redis_6381.conf redis_6382.conf
sed -i 's/6381/6382/g' redis_6382.conf
sed -i 's/6381/6383/g' redis_6383.conf
启动redis
执行之前注意将log和data的文件生成目录建好,不然会启动失败
./bin/codis-server ./conf/redis_6381.conf &
./bin/codis-server ./conf/redis_6382.conf &
3.启动bashboard (仅在需要启动管理界面的codis的服务器上操作)
1)配置文件
vi config/dashboard.toml
coordinator_name #外部存储类型,接受 zookeeper/etcd
coordinator_addr #外部存储地址
product_name #集群名称,满足正则 \w[\w\.\-]*
product_auth #集群密码,默认为空
admin_addr #RESTful API 端口
2)启动:
nohup ./bin/codis-dashboard --ncpu=1 --config=config/dashboard.toml --log=dashboard.log --log-level=WARN >> /var/log/codis_dashboard.log 2>& 1&
说明:
--ncpu=N #最大使用 CPU 个数
-c CONF, --config=CONF #指定启动配置文件
-l FILE, --log=FILE #设置 log 输出文件
--log-level=LEVEL #设置 log 输出等级:INFO,WARN,DEBUG,ERROR;默认INFO,推荐WARN
l 对于同一个业务集群而言,可以同时部署多个codis-proxy 实例;
l 不同 codis-proxy 之间由 codis-dashboard 保证状态同步。
执行完成后出现以下内容说明成功.
more ./logs/dashboard.log日期
如果提示中有错误信息,如:
看到有错误信息则表示无法启动,这种看似启动,实际上是不正常的,需要做如下处理:
在zookeeper集群服务器上登录任意一个zookeeper服务器。
cd /opt/zookeeper-3.4.6/bin/
./zkCli.sh
rmr /codis3
4.启动codis-proxy (仅在需要启动proxy的codis的服务器上操作)
1)配置文件
vi config/proxy.toml
填写上面箭头位置标识的信息。
配置文件解析:
product_name #集群名称,参考dashboard参数说明
product_auth #集群密码,默认为空
admin_addr #RESTfulAPI 端口
proto_type #Redis 端口类型,接受tcp/tcp4/tcp6/unix/unixpacket
proxy_addr #Redis 端口地址或者路径
jodis_addr #Jodis 注册 zookeeper地址
jodis_timeout #Jodis 注册 sessiontimeout时间,单位second
backend_ping_period #与codis-server 探活周期,单位second,0表示禁止
session_max_timeout #与 client 连接最大读超时,单位second,0表示禁止
session_max_bufsize #与 client 连接读写缓冲区大小,单位byte
session_max_pipeline #与 client 连接最大的pipeline 大小
session_keepalive_period #与 client 的 tcp keepalive 周期,仅tcp有效,0表示禁止
2)启动codis-proxy
nohup ./bin/codis-proxy --ncpu=1 --config=config/proxy.toml --log=proxy.log --log-level=WARN >> /var/log/codis_proxy.log 2>& 1&
codis-proxy启动后,处于 waiting 状态,监听proxy_addr 地址,但是不会 accept 连接,添加到集群并完成集群状态的同步,才能改变状态为online。
添加proxy的方法有以下两种(选其中任意一种即可):
1)通过 codis-fe 添加:通过 Add Proxy 按钮,将 admin_addr 加入到集群中;
2)通过 codis-admin 命令行工具添加,方法如下:
./bin/codis-admin --dashboard=192.168.218.159:18080 --create-proxy -x 192.168.218.159:11080
其中 192.168.10.60:18080 以及 192.168.10.60:11080 分别为 dashboard 和 proxy 的 admin_addr 地址;
添加过程中,dashboard 会完成如下一系列动作:
① 获取 proxy 信息,对集群 name 以及 auth 进行验证,并将其信息写入到外部存储中;
② 同步 slots 状态;
③ 标记 proxy 状态为 online,此后 proxy 开始 accept 连接并开始提供服务;
./bin/codis-admin --proxy=192.168.10.60:11080 --auth="" --shutdown
./bin/codis-proxy -h
Usage:
codis-proxy [--ncpu=N][--config=CONF] [--log=FILE] [--log-level=LEVEL] [--host-admin=ADDR]
[--host-proxy=ADDR] [--ulimit=NLIMIT]
codis-proxy --default-config
codis-proxy --version
Options:
--ncpu=N #最大使用 CPU 个数
-c CONF, --config=CONF #指定启动配置文件
-l FILE, --log=FILE #设置 log 输出文件
--log-level=LEVEL #设置log输出等级:INFO,WARN,DEBUG,ERROR;默认INFO,推荐WARN
--ulimit=NLIMIT #检ulimit -n 的结果,确保运行时最大文件描述不少于 NLIMIT
5.配置启动codis FE 集群管理界面 (仅在需要启动dashboard的codis的服务器上操作)
启动codis-fe
nohup ./bin/codis-fe --ncpu=1 --log=fe.log --log-level=WARN --zookeeper=192.168.218.159:2181 --listen=192.168.218.159:8090 2>& 1&
看生成的日志出现如下情况说明没问题
至此codis的图形界面已经能够显示(在此之前是不可以访问图形界面的)。
netstat -ntlp
正常关闭dashboard命令: bin/codis-admin --dashboard=172.16.200.71:18080 --shutdown
6.图形界面创建组、添加redis服务器和solt节点分配
1)打开浏览器访问http://192.168.218.159:18090,通过管理界面操作codis。
创建组
输入编号1,点击New Group,第一组创建完成。
2)添加实例
在后面输入组的id号,然后后面框内输入redis实例所在机器的ip地址和redis实例的端口号,点击Add Server即可添加完成实例 ,再添加第二个实例完成后G-1那一列会有向上的箭头(PROMPTE),点击后可升为master,点击第二个redis实例中master那一列的
图标,即可将此实例设置为slave,
此图标可以将对应的实例从该组中删除,如下两图:
3)对slots进行分组
如下图所示,输入你所要分组的slots的起和止的范围,然后输入组ID,点击后面按钮即可。
4)添加管理proxy
如下图所示,在框内输入proxy所对应的ip地址和端口号点击Add proxy即可。
此外除了图形界面进行如上操作外,还可以通过命令行进行操作(如果通过界面操作了就不需要再通过命令操作,当然为了快速生成可以存成脚本执行),以下为使用命令行操作实例:
创建组(这里建了两个分组):
./bin/codis-admin --dashboard=192.168.10.60:18080 --create-group --gid=1
./bin/codis-admin --dashboard=192.168.10.60:18080 --create-group --gid=2
组添加服务器(这里添加了两个redis服务):
./bin/codis-admin --dashboard=192.168.10.60:18080 --group-add --gid=1 \
--addr=192.168.10.61:6379
./bin/codis-admin --dashboard=192.168.10.60:18080 --group-add --gid=1 \
--addr=192.168.10.61:6380
把从库跟主库同步:(同一组的两个实例都要执行)
./bin/codis-admin --dashboard=192.168.10.60:18080 --sync-action --create \
--addr=192.168.10.61:6379
./bin/codis-admin --dashboard=192.168.10.60:18080 --sync-action --create \
--addr=192.168.10.61:6380
若从库需要提升为master,操作如下:
./bin/codis-admin --dashboard=192.168.10.60:18080 --promote-server --gid=1 \
--addr=192.168.10.61:6380(从库ip和端口)
初始化 slots,并设置 server group 服务的slot范围((只在一节点执行一次)sid是slot的编号。Codis 采用 Pre-sharding 的技术来实现数据的分片, 默认分成1024个slots (0-1023), 对于每个key来说, 通过以下公式确定所属的Slot Id : SlotId = crc32(key) % 1024 每一个slot都会有一个且必须有一个特定的server group id来表示这个slot的数据由哪个server group来提供。
./bin/codis-admin --dashboard=192.168.10.60:18080 --slot-action --create-range --beg=0 \
--end=300 --gid=1
./bin/codis-admin --dashboard=192.168.10.60:18080 --slot-action --create-range --beg=301 \
--end=601 --gid=2
echo "创建组..."
./bin/codis-admin --dashboard=192.168.10.60:18080 --create-group --gid=1
./bin/codis-admin --dashboard=192.168.10.60:18080 --create-group --gid=2
./bin/codis-admin --dashboard=192.168.10.60:18080 --create-group --gid=3
echo "创建了3个分组,组ID为1 2 3"
echo "向组中添加Redis服务器..."
./bin/codis-admin --dashboard=192.168.10.60:18080 --group-add --gid=1 --addr=192.168.10.61:6379
./bin/codis-admin --dashboard=192.168.10.60:18080 --group-add --gid=1 --addr=192.168.10.61:6380
./bin/codis-admin --dashboard=192.168.10.60:18080 --group-add --gid=2 --addr=192.168.10.62:6379
./bin/codis-admin --dashboard=192.168.10.60:18080 --group-add --gid=2 --addr=192.168.10.62:6380
./bin/codis-admin --dashboard=192.168.10.60:18080 --group-add --gid=3 --addr=192.168.10.63:6379
./bin/codis-admin --dashboard=192.168.10.60:18080 --group-add --gid=3 --addr=192.168.10.63:6380
echo "向组中添加Redis服务器结束,分别向3组中各添加两台服务器..."
echo "把从库跟主库同步..."
./bin/codis-admin --dashboard=192.168.10.60:18080 --sync-action --create --addr=192.168.10.61:6379
./bin/codis-admin --dashboard=192.168.10.60:18080 --sync-action --create --addr=192.168.10.61:6380
./bin/codis-admin --dashboard=192.168.10.60:18080 --sync-action --create --addr=192.168.10.62:6379
./bin/codis-admin --dashboard=192.168.10.60:18080 --sync-action --create --addr=192.168.10.62:6380
./bin/codis-admin --dashboard=192.168.10.60:18080 --sync-action --create --addr=192.168.10.63:6379
./bin/codis-admin --dashboard=192.168.10.60:18080 --sync-action --create --addr=192.168.10.63:6380
echo "把从库跟主库同步完成"
echo "分配slot"
./bin/codis-admin --dashboard=192.168.10.60:18080 --slot-action --create-range --beg=0 --end=300 --gid=1
./bin/codis-admin --dashboard=192.168.10.60:18080 --slot-action --create-range --beg=301 --end=601 --gid=2
./bin/codis-admin --dashboard=192.168.10.60:18080 --slot-action --create-range --beg=602 --end=1023 --gid=3
echo "分配slot 完毕"
echo "添加proxy..."
./bin/codis-admin --dashboard=192.168.10.60:18080 --create-proxy -x 192.168.10.60:11080
echo "添加proxy完毕"
完成配置并完全启动的界面:
测试
1)命令测试
cd /opt/codis
./bin/redis-benchmark -h 192.168.218.159 -p 19000 -q -d 100 #SET/GET 100 bytes 检测host为192.168.218.159 ,代理服务端口为19000的redis服务器性能。
./bin/redis-benchmark -h 192.168.218.159 -p 19000 -c 1000 -n 100000 #500个并发连接,10000个请求,检测host为192.168.218.159,proxy端口为19000的redis服务器性能。
2)JAVA程序访问代理方式
package io.codis.jodis;
import java.util.List;
import redis.clients.jedis.Jedis;
public class CodisProxyTest {
/**
* @param args
*/
public static void main(String[] args) {
//Jedis jedis = new Jedis("192.168.159.159", 6381, 0);
//Jedis jedis = new Jedis("192.168.160.159", 6382, 0);
Jedis jedis = new Jedis("192.168.218.159", 19000, 0);
String value;
// 1. k-v存储
jedis.set("name", "helloword");
value = jedis.get("name");
System.out.println("1: " + value);
// 2. 将新增的值添加到旧值后面
jedis.append("name", " append new info,");
value = jedis.get("name");
System.out.println("2: " + value);
// 3. 删除key对应的记录
// jedis.del("name");
// value = jedis.get("name");
// System.out.println("3: " + value);
// 4. 清空数据,所有的
// System.out.println(jedis.flushDB());
// 6. 截取value的值
System.out.println("6: " + jedis.getrange("name", 1, 3));
// 返回messages对应的集合长度
System.out.println("9: " + jedis.llen("messages"));
// 取数据,第一个是key,第二个是起始位置,第三个是结束位置,jedis.llen获取长度 -1表示取得所有
List<String> values = jedis.lrange("messages", 0, 1);
System.out.println("9: " + values);
// 7. k-v存储,v表示的List(堆栈形式) //后进先出
jedis.lpush("desc", "1");
jedis.lpush("desc", "2");
jedis.lpush("desc", "3");
jedis.lpush("desc", "4");
}
}
3)JAVA程序访问zookeeper方式
package io.codis.jodis;
import redis.clients.jedis.Jedis;
public class demo4 {
public static void main(String[] args) {
JedisResourcePool jedisPool = RoundRobinJedisPool.create().
curatorClient("192.168.218.159:2181,192.168.218.160:2181,192.168.218.161:2181", 30000).
timeoutMs(3000).
zkProxyDir("/codis3/codis-demo/proxy")//.password("123456")
//zkProxyDir("/codis3/codis-demo/proxy")
.build();
Jedis jedis = jedisPool.getResource();
jedis.set("foo", "bar");
String value = jedis.get("foo");
System.out.println(value);
}
}
Codis的正确关闭姿势
不能直接reboot或halt codis-dashboard所在的服务器,不能使用kill -9的方式关闭codis-dashboard,只能使用kill 关闭codis-dashboard。
如果使用了上面这些方法,当再次重新启动codis-dashboard时会提示以下信息:
看到有错误信息则表示无法启动,这种看似启动,实际上是不正常的,需要做如下处理:
在zookeeper集群服务器上登录任意一个zookeeper服务器。
cd /opt/zookeeper-3.4.6/bin/
./zkCli.sh
rmr /codis3
你如果这样做了,那么就会清空所有配置,重启后需要重新添加代理服务器、分组、添加redis服务器及分配slot等。
正确的启动姿势
在各redis机上启动codis服务:
./bin/codis-server ./conf/redis6379.conf &
./bin/codis-server ./conf/redis6380.conf &
在管理机上启动:
nohup ./bin/codis-dashboard --ncpu=4 --config=./conf/dashboard.conf --log=./logs/dashboard.log --log-level=WARN &
查看是否正常启动:
more ./logs/dashboard.log日期
如果有错误提示(不正确的关闭方式引起的,不能直接关闭或使用kill -9关闭codis-dashboard进程,只能使用kill的方式关闭codis-dashboard服务),则进行如下操作:
cd /opt/zookeeper-3.4.6/bin/
./zkCli.sh
rmr /codis3 #执行这个语句后所有的组、添加的服务器及添加的代理等配置都将丢失,相关于重新配置
关机时做以下操作就不会有这个问题了:
./bin/codis-admin --proxy=192.168.10.60:11080 --auth="" --shutdown
./bin/codis-admin --dashboard=192.168.10.60:18080 --remove-proxy --force -x 192.168.10.60:11080
在代理机上启动代理服务:
nohup ./bin/codis-proxy --ncpu=4 --config=./conf/proxy.conf --log=./logs/proxy.log --log-level=WARN &
在配置机启动codis-fe配置管理界面:
nohup ./bin/codis-fe --ncpu=4 --log=./logs/fe.log --log-level=WARN --dashboard-list=./conf/codis.json --listen=192.168.10.60:18090 &