codis-3.2.8集群部署详解
一、概要
Codis 是一个分布式 Redis 解决方案, 对于上层的应用来说, 连接到 Codis Proxy 和连接原生的 Redis
Server 没有明显的区别
(不支持的命令列表https://github.com/CodisLabs/codis/blob/release3.1/doc/unsupported_cmds.md),
上层应用可以像使用单机的 Redis 一样使用, Codis 底层会处理请求的转发, 不停机的数据迁移等工作, 所有后边的一切事情,
对于前面的客户端来说是透明的, 可以简单的认为后边连接的是一个内存无限大的 Redis 服务:
Codis是豌豆荚的开源方案,目前在redis集群实现方式对比,codis集群比较稳定的方案,并且客户端不需要做任何修改,相对redis
cluster兼容性更强,可节约大量开发成本并减少大量后期维护成本,豌豆荚gitlab地址https://github.com/pingcap,豌豆荚codis项目官方github地址https://github.com/CodisLabs/codis,codis
主要由以下特点:
可以无缝迁移到codis,自带迁移工具,并且案例较多
可以动态扩容和缩容
多业务完全透明,业务不知道运行的是codis
支持多核心CPU,twemproxy只能单核
codis是中心基于proxy的设计,是客户端像连接单机一样操作proxy
有部分命令不能支持,比如keys *等
支持group划分,组内可以设置一个主多个从,通过sentinel 监控redis主从,当主down了自动将从切换为主
设置的进程要最大等于CPU的核心,不能超过CPU的核心数
其依赖于zookeeper,里面保存的是key保存的redis主机位置,因此zookeeper要做高可用
监控可以使用接口和dashboard
二、架构
三、角色分配
zookeeper集群: 192.168.10.45 192.168.10.46 192.168.10.47 codis-config、codis-dashboard: 192.168.10.45 :18087 192.168.10.45:8090 codis-proxy: 192.168.10.45 :19000 192.168.10.46 :19000 192.168.10.47:19000 codis-server: 192.168.10.45:6379、192.168.10.46:6380(主、从) 192.168.10.46 :6379、192.168.10.47:6380(主、从) 192.168.10.47:6379、192.168.10.45:6380(主、从)
四、部署
4.1、安装zookeeper、jdk(45、46、47执行)
[[email protected] ~]# tar zxvf zookeeper-3.4.8.tar.gz [[email protected] ~]# mv zookeeper-3.4.8 /data/servers/ [[email protected] ~]# tar zxf jdk-8u131-linux-x64.gz [[email protected] ~]# mv jdk1.8.0_131 /data/servers/
配置java环境在/etc/profile最下面添加:
[[email protected] ~]# tail -n 3 /etc/profile export JAVA_HOME=/data/servers/jdk1.8.0_131 export PATH=$JAVA_HOME/bin:$PATH export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar [[email protected] ~]# java -version java version "1.8.0_131" Java(TM) SE Runtime Environment (build 1.7.0_79-b15) Java HotSpot(TM) 64-Bit Server VM (build 24.79-b02, mixed mode)
配置zookeeper,新建zoo.cfg:
[[email protected] ~]# vim /data/servers/zookeeper-3.4.8/conf/zoo.cfg maxClientCnxns=50 tickTime=2000 initLimit=10 syncLimit=5 dataDir=/data/zookeeper/ clientPort=2181 server.1=192.168.10.45:2888:3888 server.2=192.168.10.46:2888:3888 server.3=192.168.10.47:2888:3888 [[email protected] ~]# mkdir /data/zookeeper/ ##创建zk的datadir目录 [[email protected] ~]# echo "1" >/data/zookeeper/myid ##生成ID,这里需要注意, myid对应的zoo.cfg的server.ID,比如192.168.10.45对应的myid应该1 [[email protected] ~]# /usr/lib/zookeeper/bin/zkServer.sh start ## 服务启动 [[email protected] ~]# ss -tlnp | grep 218* #查看端口是否启动 LISTEN 0 50 *:2181 *:* users:(("java",2481,22)) [[email protected] ~]# /data/servers/zookeeper-3.4.8/bin/zkServer.sh status #查看状态 ZooKeeper JMX enabled by default Using config: /data/servers/zookeeper-3.4.8/bin/../conf/zoo.cfg Mode: follower
参数说明:
详细解释:
tickTime:这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。
dataDir:顾名思义就是 Zookeeper 保存数据的目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里。
clientPort:这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。
initLimit:这个配置项是用来配置 Zookeeper 接受客户端(这里所说的客户端不是用户连接 Zookeeper
服务器的客户端,而是 Zookeeper 服务器集群中连接到 Leader 的 Follower
服务器)初始化连接时最长能忍受多少个心跳时间间隔数。当已经超过 5个心跳的时间(也就是 tickTime)长度后 Zookeeper
服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是 10*6000=60 秒
syncLimit:这个配置项标识 Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是 5*6000=30 秒
server.A=B:C:D:其中 A 是一个数字,表示这个是第几号服务器;B 是这个服务器的 ip 地址;C
表示的是这个服务器与集群中的 Leader 服务器交换信息的端口;D 表示的是万一集群中的 Leader
服务器挂了,需要一个端口来重新进行选举,选出一个新的
Leader,而这个端口就是用来执行选举时服务器相互通信的端口。如果是伪集群的配置方式,由于 B 都是一样,所以不同的 Zookeeper
实例通信端口号不能一样,所以要给它们分配不同的端口号。
4.2、go安装(codis是go语言写的,45、46、47执行安装)
[[email protected] ~]# wget [[email protected] ~]# tar -zxvf go1.4.1.linux-amd64.tar.gz [[email protected] ~]# mv go /usr/local/ [[email protected] ~]# cd /usr/local/go/src/ [[email protected] ~]# bash all.bash [[email protected] ~]# cat >> ~/.bashrc << _bashrc_export export GOROOT=/usr/local/go export PATH=\$PATH:\$GOROOT/bin export GOARCH=amd64 export GOOS=linux _bashrc_export [[email protected] ~]# source ~/.bashrc
4.3、下载并编译codis(codis-config、codis-proxy、codis-server所在的机器)
[[email protected] ~]# mkdir -p //data/go/src/github.com/CodisLabs [[email protected] ~]# cd /data/go/src/github.com/CodisLabs [[email protected] CodisLabs]# git clone https://github.com/CodisLabs/codis.git -b release3.2 [[email protected] CodisLabs]# cd codis [[email protected] codis]# pwd /data/go/src/github.com/CodisLabs/codis [[email protected] codis]# yum install autoconf automake libtool -y #安装依赖 [[email protected] codis]# make make -j4 -C extern/redis-3.2.8/ make[1]: Entering directory `/usr/local/go/work/src/github.com/CodisLabs/codis/extern/redis-3.2.8‘ cd src && make all make[2]: Entering directory `/usr/local/go/work/src/github.com/CodisLabs/codis/extern/redis-3.2.8/src‘ ... lazy_lock : 0 tls : 1 cache-oblivious : 1 =============================================================================== go build -i -o bin/codis-dashboard ./cmd/dashboard go build -i -tags "cgo_jemalloc" -o bin/codis-proxy ./cmd/proxy go build -i -o bin/codis-admin ./cmd/admin go build -i -o bin/codis-fe ./cmd/fe
执行测试:
[[email protected] codis]# make gotest go test ./cmd/... ./pkg/...? github.com/CodisLabs/codis/cmd/admin [no test files] ? github.com/CodisLabs/codis/cmd/dashboard [no test files] ? github.com/CodisLabs/codis/cmd/fe [no test files] ? github.com/CodisLabs/codis/cmd/proxy [no test files] ? github.com/CodisLabs/codis/pkg/models [no test files] ? github.com/CodisLabs/codis/pkg/models/etcd [no test files] ? github.com/CodisLabs/codis/pkg/models/fs [no test files] ? github.com/CodisLabs/codis/pkg/models/zk [no test files] ok github.com/CodisLabs/codis/pkg/proxy 2.525s ok github.com/CodisLabs/codis/pkg/proxy/redis 0.530s ok github.com/CodisLabs/codis/pkg/topom 6.560s ok github.com/CodisLabs/codis/pkg/utils 0.009s ? github.com/CodisLabs/codis/pkg/utils/assert [no test files] ok github.com/CodisLabs/codis/pkg/utils/bufio2 0.006s ok github.com/CodisLabs/codis/pkg/utils/bytesize 0.004s ? github.com/CodisLabs/codis/pkg/utils/errors [no test files] ? github.com/CodisLabs/codis/pkg/utils/log [no test files] ok github.com/CodisLabs/codis/pkg/utils/math2 0.002s ? github.com/CodisLabs/codis/pkg/utils/redis [no test files] ? github.com/CodisLabs/codis/pkg/utils/rpc [no test files] ? github.com/CodisLabs/codis/pkg/utils/sync2 [no test files] ? github.com/CodisLabs/codis/pkg/utils/sync2/atomic2 [no test files] ok github.com/CodisLabs/codis/pkg/utils/timesize 0.009s ? github.com/CodisLabs/codis/pkg/utils/trace [no test files] ok github.com/CodisLabs/codis/pkg/utils/unsafe2 0.003s
执行全部指令后,会在 bin 文件夹内生成 codis-proxy、codis-server三个可执行文件。另外, bin/assets 文件夹是 dashboard http 服务需要的前端资源)
[[email protected] codis]# ll bin 总用量 96236 drwxr-xr-x 4 root root 4096 8月 3 12:22 assets -rwxr-xr-x 1 root root 15209294 8月 3 12:22 codis-admin -rwxr-xr-x 1 root root 16782405 8月 3 12:22 codis-dashboard -rwxr-xr-x 1 root root 14942227 8月 3 12:22 codis-fe -rwxr-xr-x 1 root root 13330799 8月 3 12:22 codis-ha -rwxr-xr-x 1 root root 18975773 8月 3 12:22 codis-proxy -rwxr-xr-x 1 root root 7985163 8月 3 12:22 codis-server -rwxr-xr-x 1 root root 5580671 8月 3 12:22 redis-benchmark -rwxr-xr-x 1 root root 5712491 8月 3 12:22 redis-cli -rw-r--r-- 1 root root 167 8月 3 12:22 version [[email protected] codis]# cat bin/version version = 2017-07-31 14:18:45 +0800 @9851f82515e4d050c9f3c9f0bbd297e5b96048ad @3.2.0-10-g9851f82 compile = 2017-08-03 12:22:18 +0800 by go version go1.8.3 linux/amd64
编译codis3.2错误记录:
make[2]: Leaving directory `/usr/local/go/work/src/github.com/CodisLabs/codis/extern/redis-3.2.8/src‘ make[1]: Leaving directory `/usr/local/go/work/src/github.com/CodisLabs/codis/extern/redis-3.2.8‘ autoconf ./autogen.sh: line 5: autoconf: command not found Error 0 in autoconf make[2]: *** [config] Error 1 make[1]: *** [build] Error 2 make: *** [codis-deps] Error 2
解决:
安装依赖
[[email protected] codis]# yum install autoconf automake libtool -y
4.4:默认启动的会读取config目录的dashboard.toml文件,编辑如下:
dashboard 的配置文件:
coordinator_name = "zookeeper" coordinator_addr = "192.168.10.45:2181,192.168.10.46:2181,192.168.10.47:2181" product_name = "codis-***"
五、服务启动及初始化集群
5.1、启动 dashboard(45上操作)
[[email protected] codis]# nohup ./bin/codis-dashboard --ncpu=1 --config=config/dashboard.toml --log=dashboard.log --log-level=WARN >> /var/log/codis_dashboard.log &
# 默认配置文件生成方式:
[[email protected] codis]# ./bin/codis-dashboard --default-config | tee dashboard.toml
启动代理
[[email protected] codis]# nohup ./bin/codis-proxy --ncpu=1 --config=config/proxy.toml --log=proxy.log --log-level=WARN >> /var/log/codis_proxy.log &
proxy.toml主要配置信息如下:
product_name = "codis-chinasoft" product_auth = "123456" jodis_name = "zookeeper" jodis_addr = "192.168.10.45:2181,192.168.10.46:2181,192.168.10.47:2181" jodis_timeout = "20s" jodis_compatible = true
启动codis-server,即创建redis实例(45、46、47每台服务器我们创建2个redis实例,给予codis修改过的redis-3.2.8非原生redis)
[[email protected] redis-3.2.8]# pwd /data/go/src/github.com/CodisLabs/codis/extern/redis-3.2.8 [[email protected] redis-3.2.8]# mkdir /data/redis [[email protected] redis-3.2.8]# cp redis.conf /data/redis/redis-6379.conf [[email protected] redis-3.2.8]# cp redis.conf /data/redis/redis-6380.conf [[email protected] redis-3.2.8]# cd /data/redis/
修改redis-6379.conf、redis-6380.conf,主要配置:
pidfile "/data/redis/redis_6379.pid" #与各自的配置文件端口号对应 logfile "/data/redis/redis_6379.log" port 6379 #与配置配置文件名称对应 dbfilename dump_6381.rdb dir /var/lib/redis_6381 logfile "/tmp/redis_6381.log" maxmemory 1g #一定要设置最大内存,否则后面的codis无法使用
通过codis-server指定redis.conf文件启动redis服务,不能通过redis命令启动redis服务,通过redis启动的redis 服务加到codis集群无法正常使用(45、46、47操作):
[[email protected] redis]# cd /data/go/src/github.com/CodisLabs/codis/ [[email protected] codis]# ./bin/codis-server /data/redis/redis-6379.conf [[email protected] codis]# ./bin/codis-server /data/redis/redis-6380.conf
验证通过codis启动redis 服务成功:
[[email protected] codis]# ss -tnlp|grep 63* LISTEN 0 128 127.0.0.1:6379 *:* users:(("codis-server",pid=11726,fd=4)) LISTEN 0 128 127.0.0.1:6380 *:* users:(("codis-server",pid=11733,fd=4))
启动codis-fe,Listen监听端口不要为8080,指定8090(在45上启动):
[[email protected] codis]# nohup ./bin/codis-fe --ncpu=1 --log=fe.log --log-level=WARN --zookeeper=192.168.10.45:2181 --listen=192.168.10.45:8090 &
通过网页访问:http://192.168.3.198:8090 可以看到codis的管理页面:
管理界面的配置实用:
1、通过fe添加group
通过web浏览器访问集群管理页面(fe地址:192.168.10.45:8090)
选择我们刚搭建的集群 codis-***,在 Proxy 栏添加我们已经启动的 Proxy,
但是 Group
栏为空,因为我们启动的 codis-server 并未加入到集群 添加 NEW GROUP,NEW GROUP 行输入 1,再点击 NEW
GROUP 即可
2、添加实例(即添加后端的redis服务器)
Add Server 行输入我们刚刚启动的 codis-server 地址,添加到我们刚新建的 Group,然后再点击 Add Server 按钮即可,如下图所示
删除实例
3、对slots进行分组
如下图所示,输入所要分组的slots的起和止的范围,然后输入组ID,点击后面按钮即可。
4、通过codis-proxy连接redis进行测试
[[email protected] src]# pwd /data/go/src/github.com/CodisLabs/codis/extern/redis-3.2.8/src [[email protected] src]# ./redis-cli -h 192.168.10.45 -p 19000 192.168.10.45:19000> info # Server redis_version:3.2.9 redis_git_sha1:9851f825 redis_git_dirty:0 redis_build_id:54896ac136841499 redis_mode:standalone os:Linux 2.6.32-696.el6.x86_64 x86_64 arch_bits:64 multiplexing_api:epoll gcc_version:4.4.7 process_id:23483 run_id:7b049be615a758989c696c143a9e1ffd23ac025d tcp_port:6379 uptime_in_seconds:509652 uptime_in_days:5 hz:10 lru_clock:9087707 executable:/data/go/src/github.com/CodisLabs/codis/./bin/codis-server config_file:/data/redis/redis-6379.conf # Clients connected_clients:49 client_longest_output_list:0 client_biggest_input_buf:0 blocked_clients:0 # Memory used_memory:4642472 used_memory_human:4.43M used_memory_rss:16519168 used_memory_rss_human:15.75M used_memory_peak:6444520 used_memory_peak_human:6.15M total_system_memory:8129425408 total_system_memory_human:7.57G used_memory_lua:37888 used_memory_lua_human:37.00K maxmemory:0 maxmemory_human:0B maxmemory_policy:noeviction mem_fragmentation_ratio:3.56 mem_allocator:jemalloc-4.0.3 # Persistence loading:0 rdb_changes_since_last_save:0 rdb_bgsave_in_progress:0 rdb_last_save_time:1501751549 rdb_last_bgsave_status:ok rdb_last_bgsave_time_sec:0 rdb_current_bgsave_time_sec:-1 aof_enabled:0 aof_rewrite_in_progress:0 aof_rewrite_scheduled:0 aof_last_rewrite_time_sec:-1 aof_current_rewrite_time_sec:-1 aof_last_bgrewrite_status:ok aof_last_write_status:ok # Stats total_connections_received:150 total_commands_processed:6412365 instantaneous_ops_per_sec:1 total_net_input_bytes:115627152 total_net_output_bytes:1227970244 instantaneous_input_kbps:0.06 instantaneous_output_kbps:1.43 rejected_connections:0 sync_full:1 sync_partial_ok:0 sync_partial_err:0 expired_keys:0 evicted_keys:0 keyspace_hits:1 keyspace_misses:0 pubsub_channels:0 pubsub_patterns:0 latest_fork_usec:793 migrate_cached_sockets:0 # Replication role:master connected_slaves:1 slave0:ip=192.168.10.45,port=6380,state=online,offset=711747,lag=1 master_repl_offset:711747 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:2 repl_backlog_histlen:711746 # CPU used_cpu_sys:270.09 used_cpu_user:171.60 used_cpu_sys_children:0.01 used_cpu_user_children:0.00 # Cluster cluster_enabled:0 # Keyspace db0:keys=1,expires=0,avg_ttl=0 192.168.10.45:19000> set name jack OK 192.168.10.45:19000> get name "jack" 192.168.10.45:19000>
web界面验证key是否添加完成,可以看到已经添加到了group2中:
连接zookeeper,可以看到codis的group,slots,proxy等信息都记录在zook中
/usr/local/zookeeper/bin/zkCli.sh -server
至此codis集群已经搭建成功,首次搭建过程中难免会出现很多问题,请大家耐心点。此文中若有错误之处请指教。