用Codis实现Redis分布式集群

一、Redis集群概述

Redis官方近期推出的Redis Cluster,Redis集群有三种实现机制,分别介绍如下,(1)客户端分片,(2)代理分片,(3)Redis Cluster

1.1 客户端分片

这种方案将分片工作放在业务程序端,程序代码根据预先设置的路由规则,直接对多个Redis实例进行分布式访问。这样的好处是,不依赖于第三方分布式中间件,实现方法和代码都自己掌控,可随时调整,不用担心踩到坑。

这实际上是一种静态分片技术。Redis实例的增减,都得手工调整分片程序。基于此分片机制的开源产品,现在仍不多见。

这种分片机制的性能比代理式更好(少了一个中间分发环节)。但缺点是升级麻烦,对研发人员的个人依赖性强——需要有较强的程序开发能力做后盾。如果主力程序员离职,可能新的负责人,会选择重写一遍。

所以,这种方式下,可运维性较差。出现故障,定位和解决都得研发和运维配合着解决,故障时间变长。

1.2 代理分片

这种方案,将分片工作交给专门的代理程序来做。代理程序接收到来自业务程序的数据请求,根据路由规则,将这些请求分发给正确的Redis实例并返回给业务程序。

这种机制下,一般会选用第三方代理程序(而不是自己研发),因为后端有多个Redis实例,所以这类程序又称为分布式中间件。

这样的好处是,业务程序不用关心后端Redis实例,运维起来也方便。虽然会因此带来些性能损耗,但对于Redis这种内存读写型应用,相对而言是能容忍的。

这是我们推荐的集群实现方案。像基于该机制的开源产品Twemproxy,便是其中代表之一,应用非常广泛。

1.3 Redis Cluster

在这种机制下,没有中心节点(和代理模式的重要不同之处)。所以,一切开心和不开心的事情,都将基于此而展开。

Redis

Cluster将所有Key映射到16384个Slot中,集群中每个Redis实例负责一部分,业务程序通过集成的Redis

Cluster客户端进行操作。客户端可以向任一实例发出请求,如果所需数据不在该实例中,则该实例引导客户端自动去对应实例读写数据。

Redis Cluster的成员管理(节点名称、IP、端口、状态、角色)等,都通过节点之间两两通讯,定期交换并更新。

由此可见,这是一种非常“重”的方案。已经不是Redis单实例的“简单、可依赖”了。可能这也是延期多年之后,才近期发布的原因之一。

这令人想起一段历史。因为Memcache不支持持久化,所以有人写了一个Membase,后来改名叫Couchbase,说是支持Auto Rebalance,好几年了,至今都没多少家公司在使用。

这是个令人忧心忡忡的方案。为解决仲裁等集群管理的问题,Oracle RAC还会使用存储设备的一块空间。而Redis Cluster,是一种完全的去中心化……

二、 Twemproxy代理

Twemproxy是一种代理分片机制,由Twitter开源。Twemproxy作为代理,可接受来自多个程序的访问,按照路由规则,转发给后台的各个Redis服务器,再原路返回。

这个方案顺理成章地解决了单个Redis实例承载能力的问题。当然,Twemproxy本身也是单点,需要用Keepalived做高可用方案。

我想很多人都应该感谢Twemproxy,这么些年来,应用范围最广、稳定性最高、最久经考验的分布式中间件,应该就是它了。只是,他还有诸多不方便之处。

Twemproxy最大的痛点在于,无法平滑地扩容/缩容。

这样导致运维同学非常痛苦:业务量突增,需增加Redis服务器;业务量萎缩,需要减少Redis服务器。但对Twemproxy而言,基本上都很难操作(那是一种锥心的、纠结的痛……)。

或者说,Twemproxy更加像服务器端静态sharding。有时为了规避业务量突增导致的扩容需求,甚至被迫新开一个基于Twemproxy的Redis集群。

Twemproxy另一个痛点是,运维不友好,甚至没有控制面板。

三、Codis

Codis由豌豆荚于2014年11月开源,基于Go和C开发,是近期涌现的、国人开发的优秀开源软件之一。

https://github.com/CodisLabs/codis

一、概要

Codis 是一个分布式Redis解决方案, 对于上层的应用来说, 连接到 Codis Proxy 和连接原生的 Redis Server 没有明显的区别 (有一些命令不支持), 上层应用可以像使用单机的 Redis 一样使用, Codis 底层会处理请求的转发, 不停机的数据迁移等工作, 所有后边的一切事情, 对于前面的客户端来说是透明的, 可以简单的认为后边连接的是一个内存无限大的 Redis 服务,当然,前段时间redis官方的3.0出了稳定版,3.0支持集群功能,codis的实现原理和3.0的集群功能差不多。

二、架构

三、角色分批

zookeeper集群:

10.10.0.47

10.10.0.48

10.10.1.76

codis-config、codis-ha:

10.10.32.10:18087

codis-proxy:

10.10.32.10:19000

10.10.32.49:19000

codis-server:

10.10.32.42:6379、10.10.32.43:6380(主、从)

10.10.32.43:6379、10.10.32.44:6380(主、从)

10.10.32.44:6379、10.10.32.42:6380(主、从)

四、部署

1、安装zookeeper

1yum -y installzookeeper jdk  ##安装服务

vim /etc/hosts##添加host

10.10.0.47 ZooKeeper-node1

10.10.0.48 ZooKeeper-node2

10.10.1.76 ZooKeeper-node3

vim /etc/zookeeper/conf/zoo.cfg ##撰写zk的配置文件

maxClientCnxns=50

tickTime=2000

initLimit=10

syncLimit=5

dataDir=/data/zookeeper/

clientPort=2181

server.1=ZooKeeper-node1:2888:3888

server.2=ZooKeeper-node2:2888:3888

server.3=ZooKeeper-node3:2888:3888

mkdir/data/zookeeper/##创建zk的datadir目录

echo"2">/data/zookeeper/myid##生成ID,这里需要注意, myid对应的zoo.cfg的server.ID,比如ZooKeeper-node2对应的myid应该是2

/usr/lib/zookeeper/bin/zkServer.sh start  ## 服务启动

2、go安装(codis是go语言写的,所以那些机器需要安装你懂得)

wget https://storage.googleapis.com/golang/go1.4.1.linux-amd64.tar.gz

tar-zxvf go1.4.1.linux-amd64.tar.gz

mvgo /usr/local/

cd/usr/local/go/src/

bashall.bash

cat>> ~/.bashrc << _bashrc_export

exportGOROOT=/usr/local/go

exportPATH=\$PATH:\$GOROOT/bin

exportGOARCH=amd64

exportGOOS=linux

_bashrc_export

source~/.bashrc

3、下载并编译codis(codis-config、codis-proxy、codis-server所在的机器)

mkdir/data/go

exportGOPATH=/data/go

/usr/local/go/bin/goget github.com/wandoulabs/codis

cd/data/go/src/github.com/wandoulabs/codis/

./bootstrap.sh

makegotest

五、服务启动及初始化集群

1、启动 dashboard(codis-config上操作)

cat/etc/codis/config_10.ini ##撰写配置文件

zk=10.10.0.47:2181,10.10.0.48:2181,10.10.1.76:2181

product=zh_news

proxy_id=codis-proxy_10

net_timeout=5000

proto=tcp4

dashboard_addr=10.10.32.10:18087

1cd/data/go/src/github.com/wandoulabs/codis/&&  ./bin/codis-config-c /etc/codis/config_10.ini  dashboard &

2、初始化 slots (codis-config上操作)

1cd/data/go/src/github.com/wandoulabs/codis/&&  ./bin/codis-config-c /etc/codis/config_10.ini slot init

3、启动 Codis Redis , 和官方的Redis Server参数一样(codis-server上操作)

1cd/data/go/src/github.com/wandoulabs/codis/&& ./bin/codis-server/etc/redis_6379.conf &

4、添加 Redis Server Group , 每一个 Server Group 作为一个 Redis 服务器组存在, 只允许有一个 master, 可以有多个 slave, group id 仅支持大于等于1的整数(codis-config上操作)

cd/data/go/src/github.com/wandoulabs/codis/

./bin/codis-config-c /etc/codis/config_10.ini server add 1 10.10.32.42:6379 master

./bin/codis-config-c /etc/codis/config_10.ini server add 1 10.10.32.43:6380 slave

./bin/codis-config-c /etc/codis/config_10.ini server add 2 10.10.32.43:6379 master

./bin/codis-config-c /etc/codis/config_10.ini server add 2 10.10.32.44:6380 slave

./bin/codis-config-c /etc/codis/config_10.ini server add 3 10.10.32.44:6379 master

./bin/codis-config-c /etc/codis/config_10.ini server add 3 10.10.32.42:6380 slave

5、设置

server group 服务的 slot 范围 Codis 采用 Pre-sharding 的技术来实现数据的分片, 默认分成 1024 个

slots (0-1023), 对于每个key来说, 通过以下公式确定所属的 Slot Id : SlotId = crc32(key) %

1024 每一个 slot 都会有一个特定的 server group id 来表示这个 slot 的数据由哪个 server group

来提供.(codis-config上操作)

cd/data/go/src/github.com/wandoulabs/codis/

./bin/codis-config-c /etc/codis/config_10.ini slot range-set0 300 1 online

./bin/codis-config-c /etc/codis/config_10.ini slot range-set301 700 2 online

./bin/codis-config-c /etc/codis/config_10.ini slot range-set701 1023 3 online

6、启动 codis-proxy  (codis-proxy上操作

cat/etc/codis/config_10.ini ##撰写配置文件

zk=10.10.0.47:2181,10.10.0.48:2181,10.10.1.76:2181

product=zh_news

proxy_id=codis-proxy_10  ##10.10.32.49上改成codis-proxy_49,多个proxy,proxy_id 需要唯一

net_timeout=5000

proto=tcp4

dashboard_addr=10.10.32.10:18087

cd/data/go/src/github.com/wandoulabs/codis/&&  ./bin/codis-proxy-c /etc/codis/config_10.ini -L /data/log/codis-proxy_10.log  --cpu=4 --addr=0.0.0.0:19000 --http-addr=0.0.0.0:11000 &

cd/data/go/src/github.com/wandoulabs/codis/&&  ./bin/codis-proxy-c /etc/codis/config_49.ini -L /data/log/codis-proxy_49.log  --cpu=4 --addr=0.0.0.0:19000 --http-addr=0.0.0.0:11000 &

OK,整个集群已经搭建成功了,截图给你们show show

六、codis-server的HA

codis-ha实现codis-server的主从切换,codis-server主库挂了会提升一个从库为主库,从库挂了会设置这个从库从集群下线

1、安装

exportGOPATH=/data/go

/usr/local/go/bin/goget github.com/ngaut/codis-ha

cd/data/go/src/github.com/ngaut/codis-ha

go build

cpcodis-ha /data/go/src/github.com/wandoulabs/codis/bin/

使用方法:

codis-ha --codis-config=dashboard地址:18087 --productName=集群项目名称

2、使用supervisord管理codis-ha进程

1yum -y installsupervisord

/etc/supervisord.conf中添加如下内容:

[program:codis-ha]

autorestart = True

stopwaitsecs = 10

startsecs = 1

stopsignal = QUIT

command= /data/go/src/github.com/wandoulabs/codis/bin/codis-ha--codis-config=10.10.32.17:18087 --productName=zh_news

user = root

startretries = 3

autostart = True

exitcodes = 0,2

3、启动supervisord服务

/etc/init.d/supervisordstart

chkconfig supervisord  on

此时,ps -ef |grep codis-ha 你回发现codis-ha进程已经启动,这个时候你去停掉一个codis-server的master,看看slave会不会提升为master呢

七、关于监控

关于整个codis集群的监控,我们这边用的是zabbix,监控的指标比较简单,所以这块大家有什么好的建议多给我提提哈

zookeeper:监控各个节点的端口联通性(以后想着把进程也监控上)

codis-proxy:监控了端口的联通性,这个监控远远不够呀

codis-server:监控了内存使用率、连接数、联通性

codis-ha:监控进程

dashboard:监控端口联通性

八、使用过程中遇到的问题

1、codis-proxy的日志切割,codis-proxy的默认日志级别是info,日志量很大,我们这边每天产生50多G日志,目前codis-proxy还不支持热重启,想修改启动参数还是比较麻烦的,日志切割推荐用logrotate

2、codis-proxy的监听地址默认没有具体ipv4,也就是codis-proxy启动之后没有0.0.0.0:19000这样的监听,这样会导致的问题就是前端lvs没有办法负载均衡codis-proxy,不能转发请求过,这个问题已联系作者处理了,在codis-proxy启动的配置文件中加上proto=tcp4这个参数就支持监听ipv4了

3、添加

Redis Server

Group的时候,非codis-server(原生的redis)竟然也能加入到codis集群里面,在redis和codis-server共存在一个物理机上的清楚,很容易加错,希望能有个验证,非codis-server不能加入到codis集群

4、codis集群内部通讯是通过主机名的,如果主机名没有做域名解析那dashboard是通过主机名访问不到proxy的http-addr地址的,这会导致从web界面上看不到 OP/s的数据,至于还有没有其他问题,目前我这边还没有发现,建议内部通讯直接用内网IP

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • 一、codis介绍codis是一个分布式redis集群解决方案,对于上层的应用来说, 连接到codis-proxy...
    曹振华阅读 6,297评论 0 9
  • Codis 3.2 部署配置汇总 概念总结 集群配置前需要了解架构,集群分片主要分三种: 客户端分片:这个需要自己...
    三杯水Plus阅读 5,959评论 0 11
  • Codis 是一个分布式 Redis 解决方案, 对于上层的应用来说, 连接到 Codis Proxy 和连接原生...
    柏树_Jeff阅读 788评论 0 2
  • 一. 应用场景 redis 作为数据结构存储引擎,有着很多优点 高性能单机引擎可以达到5-10W qps 数据结构...
    skywalker阅读 15,832评论 4 29
  • 一、codis 简介 摘自官方:Codis 是一个分布式 Redis 解决方案, 对于上层的应用来说, 连接到 C...
    撸大师阅读 1,206评论 0 3