Redis Codis
Redis 在 3.0 的时候,推出了一个集群解决方案: redis-cluster。能让开发者通过官方的方式构建Redis集群,但在之前,生产环境跑的基本是redis 2.x 版本的实例,如果需要进行集群管理,很多开发者采用的方案都是twitter的Twemproxy。
Twemproxy 本身是一个静态的分布式方案,进行扩容、缩容的时候对devops的要求很高,而且很难得做到平滑的扩容、缩容。而且没有用于集群管理的 Dashboard,这样十分不便。
为了解决这些痛点,豌豆荚开源了它们的 Codis,很感谢作者们带来了这么好的工具,不管是使用或者学习CAP相关开发,codis都是很好的参考。
Codis 官方项目地址 :https://github.com/CodisLabs/codis

codis架构

image.png
上图是codis的一个总体架构,可以得到几个关键组合件:codis-server、codis-proxy、codis-dashboard、codis-admin、 codis-fe、 cois-ha等。

  • Codis Server:基于 redis-2.8.21 分支开发。增加了额外的数据结构,以支持 slot 有关的操作以及数据迁移指令。具体的修改可以参考文档 redis 的修改。
  • Codis Proxy:客户端连接的 Redis 代理服务, 实现了 Redis 协议。除部分命令不支持以外(不支持的命令列表),表现的和原生的 Redis 没有区别(就像 Twemproxy)。
    • 对于同一个业务集群而言,可以同时部署多个 codis-proxy 实例;
    • 不同 codis-proxy 之间由 codis-dashboard 保证状态同步。
  • Codis Dashboard:集群管理工具,支持 codis-proxy、codis-server 的添加、删除,以及据迁移等操作。在集群状态发生改变时,codis-dashboard 维护集群下所有 codis-proxy 的状态的一致性。
    • 对于同一个业务集群而言,同一个时刻 codis-dashboard 只能有 0个或者1个;
    • 所有对集群的修改都必须通过 codis-dashboard 完成。
  • Codis Admin:集群管理的命令行工具。
    • 可用于控制 codis-proxy、codis-dashboard 状态以及访问外部存储。
  • Codis FE:集群管理界面。
    • 多个集群实例共享可以共享同一个前端展示页面;
    • 通过配置文件管理后端 codis-dashboard 列表,配置文件可自动更新。
  • Codis HA:为集群提供高可用。
    • 依赖 codis-dashboard 实例,自动抓取集群各个组件的状态;
    • 会根据当前集群状态自动生成主从切换策略,并在需要时通过 codis-dashboard 完成主从切换。
  • Storage:为集群状态提供外部存储。
    • 提供 Namespace 概念,不同集群的会按照不同 product name 进行组织;
    • 目前仅提供了 Zookeeper 和 Etcd 两种实现,但是提供了抽象的 interface 可自行扩展。

理解了上面的组件含义,对部署和维护codis很有帮助,所以在搭建环境之前,务必先认真理解上面的组件的意义。

codis及依赖环境配置

codis主要是采用golang开发,而且依赖zk或etcd进行配置管理的,所以基本的先要把go的环境先搭建起来。

1、go开发环境搭建

建议参考官方的指引:https://golang.org/doc/install
安装后,检查是否成功:

  1. $ go version
  2. go version go1.7 linux/amd64

2、go编译环境设置

添加 到PATH,例如:

  1. export GOROOT=/usr/local/go
  2. export GOPATH=/home/apps/devgo
  3. export GOBIN=/home/apps/devgo/bin
  4. export PATH=$PATH:$GOROOT/bin

3、安装godep

  1. $ go get -u github.com/tools/godep

如果输入which godep 报命令command not found的错误,可以这样解决:

  1. $ sudo cp $GOPATH/bin/godep /usr/local/bin/

4、安装codis

  1. $ mkdir -p $GOPATH/src/github.com/CodisLabs
  2. $ cd $_ && git clone https://github.com/CodisLabs/codis.git -b release3.0

项目检出成功后,可以看到codis完整目录;由于codis的extern包含了一个redis的基础工具。所以,需要在 codis的主目录下执行make命令

  1. $ cd $GOPATH/src/github.com/CodisLabs/codis
  2. $ make
  3. make -j -C extern/redis-2.8.21/
  4. ... ...
  5. go build -i -o bin/codis-dashboard ./cmd/dashboard
  6. go build -i -o bin/codis-proxy ./cmd/proxy
  7. go build -i -o bin/codis-admin ./cmd/admin
  8. go build -i -o bin/codis-ha ./cmd/ha
  9. go build -i -o bin/codis-fe ./cmd/fe
  1. $ ls bin/
  2. 总用量 74528
  3. drwxrwxr-x 3 apps apps 4096 10 2 09:52 .
  4. drwxrwxr-x 12 apps apps 4096 10 2 09:51 ..
  5. drwxrwxr-x 4 apps apps 4096 10 2 09:52 assets
  6. -rwxrwxr-x 1 apps apps 15710271 10 2 09:52 codis-admin
  7. -rwxrwxr-x 1 apps apps 16978383 10 2 09:52 codis-dashboard
  8. -rwxrwxr-x 1 apps apps 15810040 10 2 09:52 codis-fe
  9. -rwxrwxr-x 1 apps apps 8730288 10 2 09:52 codis-ha
  10. -rwxrwxr-x 1 apps apps 10267404 10 2 09:52 codis-proxy
  11. -rwxrwxr-x 1 apps apps 4308197 10 2 09:52 codis-server
  12. -rwxrwxr-x 1 apps apps 2166709 10 2 09:52 redis-benchmark
  13. -rwxrwxr-x 1 apps apps 2314614 10 2 09:52 redis-cli
  14. -rw-rw-r-- 1 apps apps 146 10 2 09:52 version
  15. ... ...
  16. $ cat bin/version
  17. version = 2016-09-29 13:58:59 +0800 @29199bb81e7b0b3cdb4bd7e005c96c9fd674a6ea
  18. compile = 2016-10-02 09:52:18 +0800 by go version go1.7 linux/amd64

接下来,需要处理一下 bin/ 下的命令工具

  1. sudo cp codis-* /usr/local/bin
  2. sudo cp redis-* /usr/local/bin

5、安装etcd

由于使用etcd作为配置管理,所以需要进行etcd的安装配置,但如果喜欢zookeeper,那么可以忽略本点,自己安装zk.

  1. $ curl -L https://github.com/coreos/etcd/releases/download/v2.3.7/etcd-v2.3.7-linux-amd64.tar.gz
  2. $ tar xzvf etcd-v2.3.7-linux-amd64.tar.gz
  3. $ cd etcd-v2.3.7-linux-amd64 && sudo cp etcd /usr/local/bin/ && cp etcdctl /usr/local/bin/

检查etcd安装是否成功

  1. $ etcd --version
  2. etcd Version: 2.3.7
  3. Git SHA: fd17c91
  4. Go Version: go1.6.2
  5. Go OS/Arch: linux/amd64

codis demo 运行

源码中提供了可供本地测试使用的脚本 scripts/demo.sh,该脚本会生成一个本地集群。

  1. etcd.pid=22387
  2. codis-server-16379.pid=22388
  3. codis-server-16380.pid=22389
  4. codis-server-16381.pid=22393
  5. codis-server-16382.pid=22394
  6. codis-server-16383.pid=22395
  7. codis-server-16384.pid=22396
  8. codis-server-16385.pid=22397
  9. codis-server-16386.pid=22398
  10. proxy-11080x19000.pid=22400
  11. proxy-11081x19001.pid=22402
  12. proxy-11082x19002.pid=22405
  13. proxy-11083x19003.pid=22410
  14. dashboard.pid=22412
  15. fe.pid=22428
  16. migrate slot-[ 512, 767] to group-3
  17. migrate slot-[ 768,1023] to group-4
  18. migrate slot-[ 0, 255] to group-1
  19. migrate slot-[ 256, 511] to group-2
  20. done
  21. done
  22. ....
  23. ....
  24. ....

脚本会输出每一个进程的 PID,并将每个实例的日志会输出到 scripts/tmp 目录下;
启动后,可以通过 http://127.0.0.1:8080 来访问 codis-fe。
2021-11-24-22-26-52-861926.png
Codis 入门与实践 - 图3
Codis 入门与实践 - 图4

小结

上述已经可以快速跑一个demo版的codis,但这还不够的,还需要进一步去学习codis的开发和运维。

自定义参数与环境方式搭建

通过运行了一个名称为“codis-test”的codis的demo方案,下面尝试通过官方的相关命令组件,运行自己的自定义环境。继续选用etcd作为配置管理工具。
注意:请按照顺序逐步完成操作。

一、启动etcd

使用etcd的默认端口 2379

  1. nohup etcd --name=codis-demo &>/home/apps/codis/log/etcd/etcd.log &

如果启动过程中,出现被锁的异常,可以清理相关历史记录:

  1. etcdctl rm --recursive /codis3

二、启动codis-server

先启动一个单节点的server codis-server,本身就是一个redis实例, 开启一个端口为16379的server实例

  1. nohup ./bin/codis-server --port 16379 &>/home/apps/codis/log/redis/redis-16379.log &
  2. [44886] 02 Oct 16:50:11.381 # You requested maxclients of 10000 requiring at least 10032 max file descriptors.
  3. [44886] 02 Oct 16:50:11.381 # Redis can't set maximum open files to 10032 because of OS error: Operation not permitted.
  4. [44886] 02 Oct 16:50:11.381 # Current maximum open files is 4096. maxclients has been reduced to 4064 to compensate for low ulimit. If you need higher maxclients increase 'ulimit -n'.
  5. _._
  6. _.-``__ ''-._
  7. _.-`` `. `_. ''-._ Redis 2.8.21 (29199bb8/0) 64 bit
  8. .-`` .-```. ```\/ _.,_ ''-._
  9. ( ' , .-` | `, ) Running in stand alone mode
  10. |`-._`-...-` __...-.``-._|'` _.-'| Port: 16379
  11. | `-._ `._ / _.-' | PID: 44886
  12. `-._ `-._ `-./ _.-' _.-'
  13. |`-._`-._ `-.__.-' _.-'_.-'|
  14. | `-._`-._ _.-'_.-' | http://redis.io
  15. `-._ `-._`-.__.-'_.-' _.-'
  16. |`-._`-._ `-.__.-' _.-'_.-'|
  17. | `-._`-._ _.-'_.-' |
  18. `-._ `-._`-.__.-'_.-' _.-'
  19. `-._ `-.__.-' _.-'
  20. `-._ _.-'
  21. `-.__.-'
  22. [44886] 02 Oct 16:50:11.385 # Server started, Redis version 2.8.21
  23. [44886] 02 Oct 16:50:11.385 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
  24. [44886] 02 Oct 16:50:11.385 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
  25. [44886] 02 Oct 16:50:11.385 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
  26. [44886] 02 Oct 16:50:11.385 * DB loaded from disk: 0.000 seconds
  27. [44886] 02 Oct 16:50:11.385 * The server is now ready to accept connections on port 16379

三、启动dashboard

  1. nohup ./bin/codis-dashboard --config=/home/apps/codis/dashboard.toml --log=/home/apps/codis/log/dashboard/dashboard.log --log-level=WARN &

这里使用了自定义的dashboard.toml, 它的内容如下:

  1. ##################################################
  2. # #
  3. # Codis-Dashboard #
  4. # #
  5. ##################################################
  6. # Set Coordinator, only accept "zookeeper" & "etcd"
  7. coordinator_name = "etcd"
  8. coordinator_addr = "127.0.0.1:2379"
  9. # Set Codis Product {Name/Auth}.
  10. product_name = "codis-demo"
  11. product_auth = ""
  12. # Set bind address for admin(rpc), tcp only.
  13. admin_addr = "0.0.0.0:18080"

四、启动codis-proxy

  1. nohup ./bin/codis-proxy --config=/home/apps/codis/proxy.toml --log=/home/apps/codis/log/proxy/proxy.log --log-level=WARN &

proxy.toml的内容如下:

  1. product_name = "codis-demo"
  2. product_auth = ""
  3. proto_type = "tcp4"
  4. admin_addr = "0.0.0.0:11080"
  5. proxy_addr = "0.0.0.0:19000"

五、启动fe

  1. nohup ./bin/codis-fe -d /home/apps/codis/codis.json --listen=0.0.0.0:8080 &

condis.json的内容如下:

  1. [
  2. {
  3. "name": "codis-demo",
  4. "dashboard": "127.0.0.1:18080"
  5. }
  6. ]

六、配置codis-admin

上面已经启动了基本的组件,接下来需要通过codis-admin把proxy进行分组管理。
增加proxy组

  1. ./bin/codis-admin --dashboard=127.0.0.1:18080 --create-group --gid 1

添加分组

  1. ./bin/codis-admin --dashboard=127.0.0.1:18080 --group-add --gid 1 -x 127.0.0.1:16379

创建proxy

  1. ./bin/codis-admin --dashboard=127.0.0.1:18080 --create-proxy -x 127.0.0.1:11080

配置slot

  1. ./bin/codis-admin --dashboard=127.0.0.1:18080 --slot-action --interval=100
  2. ./bin/codis-admin --dashboard=127.0.0.1:18080 --rebalance --confirm

登陆管理面板,如下图:
2021-11-24-22-26-53-155757.png