`
gaozzsoft
  • 浏览: 424670 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

codis架构原理研究

 
阅读更多

Redis 集群,顾名思义就是使用多个 Redis 节点构成的集群,从而满足在数据量和并发数大的业务需求。

在单个 Redis 的节点实例下,存储的数据量大和高并发的情况下,内存很容易就暴涨。同时,一个 Redis 的节点,内存也是受限的,两个原因,一个是内存过大,在进行数据同步的时候,全量同步的时候会导致时间过长,会增加同步失败的风险;另一个原因就是一般的 Redis 都是部署在云服务器上的,这个也会受到CPU的使用率的影响。

所以,在面对着大数据量的时候,就会 Redis 集群的方案来管理,同时也是把这么多 Redis 实例的CPU计算能力汇集到一起,从而完成关于大数据和高并发量的的读写操作。

目录

  • Redis集群的方案有哪些?优缺点分别是什么?
  • Codis集群的分片原理是怎么样的?
  • Codis集群的迁移方式和工具有哪些?
  • Codis为什么很多命令行不支持?
  • 如果 Codis 集群正在迁移中,怎么处理发送过来的读写请求?

正文

Redis 集群方案有哪些

Redis 的集群解决方案有社区的,也有官方的,社区的解决方案有 CodisTwemproxy,Codis是由我国的豌豆荚团队开源的,TwemproxyTwitter团队的开源的;官方的集群解决方案就是 Redis Cluster,这是由 Redis 官方团队来实现的。下面的列表可以很明显地表达出三者的不同点。

- Codis Twemproxy Redis Cluster
resharding without restarting cluster Yes No Yes
pipeline Yes Yes No
hash tags for multi-key operations Yes Yes Yes
multi-key operations while resharding Yes   No(details)
Redis clients supporting Any clients Any clients Clients have to support cluster protocol

Codis 集群

Codis 是一个代理中间件,用的是 GO 语言开发的,如下图,Codis 在系统的位置是这样的。

image

 

Codis分为四个部分,分别是Codis Proxy (codis-proxy)Codis Dashboard (codis-config)Codis Redis (codis-server)ZooKeeper/Etcd.

Codis就是起着一个中间代理的作用,能够把所有的Redis实例当成一个来使用,在客户端操作着SDK的时候和操作Redis的时候是一样的,没有差别。

因为Codis是一个无状态的,所以可以增加多个Codis来提升QPS,同时也可以起着容灾的作用。

Codis 分片原理

Codis中,Codis会把所有的key分成1024个槽,这1024个槽对应着的就是Redis的集群,这个在Codis中是会在内存中维护着这1024个槽与Redis实例的映射关系。这个槽是可以配置,可以设置成 2048 或者是4096个。看你的Redis的节点数量有多少,偏多的话,可以设置槽多一些。

Codiskey的分配算法,先是把key进行CRC32 后,得到一个32位的数字,然后再hash%1024后得到一个余数,这个值就是这个key对应着的槽,这槽后面对应着的就是redis的实例。(可以思考一下,为什么Codis很多命令行不支持,例如KEYS操作)

CRC32:CRC本身是“冗余校验码”的意思,CRC32则表示会产生一个32bit(8位十六进制数)的校验值。由于CRC32产生校验值时源数据块的每一个bit(位)都参与了计算,所以数据块中即使只有一位发生了变化,也会得到不同的CRC32值。

CodisKey的算法代码如下

//Codis中Key的算法
hash = crc32(command.key)
slot_index = hash % 1024
redis = slots[slot_index].redis
redis.do(command)
复制代码

Codis之间的槽位同步

思考一个问题:如果这个Codis节点只在自己的内存里面维护着槽位与实例的关系,那么它的槽位信息怎么在多个实例间同步呢?

Codis把这个工作交给了ZooKeeper来管理,当CodisCodis Dashbord 改变槽位的信息的时候,其他的Codis节点会监听到ZooKeeper的槽位变化,会及时同步过来。如图:

 

image

 

Codis中的扩容

思考一个问题:在Codis中增加了Redis节点后,槽位的信息怎么变化,原来的key怎么迁移和分配?如果在扩容的时候,这个时候有新的key进来,Codis的处理策略是怎么样的?

因为Codis是一个代理中间件,所以这个当需要扩容Redis实例的时候,可以直接增加redis节点。在槽位分配的时候,可以手动指定Codis Dashbord来为新增的节点来分配特定的槽位。

Codis中实现了自定义的扫描指令SLOTSSCAN,可以扫描指定的slot下的所有的key,将这些key迁移到新的Redis的节点中(话外语:这个是Codis定制化的其中一个好处)。

首先,在迁移的时候,会在原来的Redis节点和新的Redis里都保存着迁移的槽位信息,在迁移的过程中,如果有key打进将要迁移或者正在迁移的旧槽位的时候,这个时候Codis的处理机制是,先是将这个key强制迁移到新的Redis节点中,然后再告诉Codis,下次如果有新的key的打在这个槽位中的话,那么转发到新的节点。代码策略如下:

slot_index = crc32(command.key) % 1024
if slot_index in migrating_slots:
	do_migrate_key(command.key)  # 强制执行迁移
	redis = slots[slot_index].new_redis
else:
	redis = slots[slot_index].redis
redis.do(command)
复制代码

自动均衡策略

面对着上面讲的迁移策略,如果有成千上万个节点新增进来,都需要我们手动去迁移吗?那岂不是得累死啊。当然,Codis也是考虑到了这一点,所以提供了自动均衡策略。自动均衡策略是这样的,Codis 会在机器空闲的时候,观察Redis中的实例对应着的slot数,如果不平衡的话就会自动进行迁移。

Codis的牺牲

因为CodisRedis的基础上的改造,所以在Codis上是不支持事务的,同时也会有一些命令行不支持,在官方的文档上有(Codis不支持的命令)

官方的建议是单个集合的总容量不要超过1M,否则在迁移的时候会有卡顿感。在Codis中,增加了proxy来当中转层,所以在网络开销上,是会比单个的Redis节点的性能有所下降的,所以这部分会有些的性能消耗。可以增加proxy的数量来避免掉这块的性能损耗。

MGET的过程

思考一个问题:如果熟悉Redis中的MGETMSETMSETNX命令的话,就会知道这三个命令都是原子性的命令。但是,为什么Codis支持MGETMSET,却不支持MSETNX命令呢?

 

image

 

原因如下: 在Codis中的MGET命令的原理是这样的,先是在Redis中的各个实例里获取到符合的key,然后再汇总到Codis中,如果是MSETNX的话,因为key可能存在在多个Redis的实例中,如果某个实例的设值成功,而另一个实例的设值不成功,从本质上讲这是不成功的,但是分布在多个实例中的Redis是没有回滚机制的,所以会产生脏数据,所以MSETNX就是不能支持了。

Codis集群总结

  • Codis是一个代理中间件,通过内存保存着槽位和实例节点之间的映射关系,槽位间的信息同步交给ZooKeeper来管理。
  • 不支持事务和官方的某些命令,原因就是分布多个的Redis实例没有回滚机制和WAL,所以是不支持的.


---------------------------------------------------------------------------------------------------------------------------------

 

codis原理及部署

一.codis介绍

  • Codis是一个分布式Redis解决方案,对于上层的应用来说,连接到Codis Proxy和连接原生的RedisServer没有明显的区别,有部分命令不支持
  • Codis底层会处理请求的转发,不停机的数据迁移等工作,所有后边的一切事情,对于前面的客户端来说是透明的,可以简单的认为后边连接的是一个内存无限大的Redis服务.
  • Codis由四部分组成
    • Codis-proxy:实现redis协议,由于本身是无状态的,因此可以部署很多个节点
    • Codis-config :是codis的管理工具,包括添加/删除redis节点添加删除proxy节点,发起数据迁移等操作,自带httpserver,支持管理后台方式管理配置
    • Codis-server :是codis维护的redis分支,基于2.8.21分支,加入了slot的支持和原子的数据迁移指令; codis-proxy和codis-config只能和这个版本的redis交互才能正常运行
    • Zookeeper,用于codis集群元数据的存储,维护codis集群节点

image

二.Codis优缺点

优点
  • 对客户端透明,与codis交互方式和redis本身交互一样
  • 支持在线数据迁移,迁移过程对客户端透明有简单的管理和监控界面
  • 支持高可用,无论是redis数据存储还是代理节点
  • 自动进行数据的均衡分配
  • 最大支持1024个redis实例,存储容量海量
  • 高性能
缺点
  • 采用自有的redis分支,不能与原版的redis保持同步
  • 如果codis的proxy只有一个的情况下, redis的性能会下降20%左右
  • 某些命令不支持,比如事务命令muti
  • 国内开源产品,活跃度相对弱一些

三.部署codis,并写代码访问codis

3.1 zookeeper
  • 1.三集群节点
172.16.10.142   zoo1
172.16.10.143   zoo2
172.16.10.144   zoo3
# 确保每个节点hostname -i返回的是正确IP地址
  • 2.获取安装软件
wget http://apache.fayea.com/zookeeper/zookeeper-3.4.12/zookeeper-3.4.12.tar.gz
scp -rp zookeeper-3.4.12 172.16.10.143:/usr/local
scp -rp zookeeper-3.4.12 172.16.10.144:/usr/local
mv zookeeper-3.4.12 /usr/local/zookeeper-3.4.12/
  • 3.设置环境变量
export ZOOKEEPER_HOME=/usr/local/zookeeper-3.4.12/
export PATH=$PATH:$ZOOKEEPER_HOME/bin
  • 4.单机环境配置文件
cd /usr/local/zookeeper-3.4.12/conf
cp -rp zoo_sample.cfg zoo.cfg
vi zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/usr/local/zookeeper/data
dataLogDir=/usr/local/zookeeper/log
clientPort=2181
# tickTime : 服务器与客户端之间交互的基本时间单元(ms
# dataDir : 保存zookeeper数据路径
# dataLogDir : 保存zookeeper日志路径,当此配置不存在时默认路径与dataDir一致
# clientPort : 客户端访问zookeeper时经过服务器端时的端口号
  • 5.集群环境配置文件
cd /usr/local/zookeeper-3.4.12/conf
cp -rp zoo_sample.cfg zoo.cfg
vi zoo.cfg
tickTime=2000
# tickTime : 服务器与客户端之间交互的基本时间单元(ms
initLimit=10
# initLimit : 此配置表示允许follower连接并同步到leader的初始化时间,它以tickTime的倍数来表示。当超过设置倍数的tickTime时间,则连接失败。
syncLimit=5
# syncLimit : Leader服务器与follower服务器之间信息同步允许的最大时间间隔,如果超过次间隔,默认follower服务器与leader服务器之间断开链接。
dataDir=/usr/local/zookeeper/data
# dataDir : 保存zookeeper数据路径
dataLogDir=/usr/local/zookeeper/log/tran_logs
# dataLogDir : 保存zookeeper日志路径,当此配置不存在时默认路径与dataDir一致,事务日志,会产生version2目录
clientPort=2181
# clientPort : 客户端访问zookeeper时经过服务器端时的端口号
maxClientCnxns=60
# maxClientCnxns : 限制连接到zookeeper服务器客户端的数量。
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888
# server.id=host:port:port : 表示了不同的zookeeper服务器的自身标识,作为集群的一部分,每一台服务器应该知道其他服务器的信息。用户可以从“server.id=host:port:port中读取到相关信息。在服务器的data(dataDir参数所指定的目录)下创建一个文件名为myid的文件,这个文件的内容只有一行,指定的是自身的id值。比如,服务器“1”应该在myid文件中写入“1”。这个id必须在集群环境中服务器标识中是唯一的,且大小在1~255之间。这一样配置中,zoo1代表第一台服务器的IP地址。第一个端口号(port)是从follower连接到leader机器的端口,第二个端口是用来进行leader选举时所用的端口。所以,在集群配置过程中有三个非常重要的端口:clientPort:2181、port:2888、port:3888
  • 5.写id到文件
ssh 172.16.10.142 "echo '1' > /usr/local/zookeeper-3.4.12/data/myid"
ssh 172.16.10.143 "echo '2' > /usr/local/zookeeper-3.4.12/data/myid"
ssh 172.16.10.144 "echo '3' > /usr/local/zookeeper-3.4.12/data/myid"
  • 6.更改日志输出

/usr/local/zookeeper-3.4.12/conf/log4j.properties
#zookeeper.root.logger=INFO, CONSOLE
zookeeper.root.logger=INFO, ROLLINGFILE
#log4j.appender.ROLLINGFILE=org.apache.log4j.RollingFileAppender
log4j.appender.ROLLINGFILE=org.apache.log4j.DailyRollingFileAppender
#log4j.appender.ROLLINGFILE.MaxFileSize=10MB
# 更改app应用的日志输出
vi zkEnv.sh
if [ "x${ZOO_LOG_DIR}" = "x" ]
then
    ZOO_LOG_DIR="/usr/local/zookeeper/log/app_logs/"
fi

if [ "x${ZOO_LOG4J_PROP}" = "x" ]
then
    ZOO_LOG4J_PROP="INFO,ROLLINGFILE"
fi
3.2 go

https://www.golangtc.com/download

  • 1.下载
wget https://www.golangtc.com/static/go/1.9.2/go1.9.2.linux-amd64.tar.gz
tar -zxvf go1.9.2.linux-amd64.tar.gz -C /usr/local
  • 2.配置环境变量
export GOROOT=/usr/local/go //后面的值指向go解压的目录
export GOPATH=/usr/local/go/gowork //go环境境的扩展包目录,所有go环境境共用,工作目录
PATH=$PATH:$GOROOT/bin:$GOPATH/bin

# go命令依赖一个重要的环境变量:$GOPATH 
# GOPATH允许多个目录,当有多个目录时,请注意分隔符,多个目录的时候Windows是分号;,Linux系统是冒号: 
#当有多个GOPATH时默认将go get获取的包存放在第一个目录下 
#$GOPATH目录约定有三个子目录
# - src存放源代码(比如:.go .c .h .s等)
# - pkg编译时生成的中间文件(比如:.a
# - bin编译后生成的可执行文件(为了方便,可以把此目录加入到 $PATH 变量中,如果有多个gopath,那么使用${GOPATH//://bin:}/bin添加所有的bin目录)
  • 3.查看版本
[root@slave01 go]# go version
go version go1.8.3 linux/amd64
3.3 CodsLabs

https://github.com/CodisLabs/codis

  • 1.下载
go get github.com/wandoulabs/codis
# cd .; git clone https://github.com/wandoulabs/codis /usr/local/go/gowork/src/github.com/wandoulabs/codis
Cloning into '/usr/local/go/gowork/src/github.com/wandoulabs/codis'...
fatal: unable to access 'https://github.com/wandoulabs/codis/': Peer reports incompatible or unsupported protocol version.

yum update nss curl git

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

1.linux二进制 https://github.com/CodisLabs/codis/releases 2.或者直接下载zip包

  • 2.安装
cd $GOPATH/src/github.com/CodisLabs/codis
$ make
  • 3.提取有用程序
# 进入源码目录
mkdir /usr/local/codis
cp -rp bin admin config /usr/local/codis/

http://blog.51cto.com/brucewang/2159131

3.4 部署codis-dashboard
  • 1.修改配置文件
vi /usr/local/codis/config/dashboard.toml
#coordinator_name = "filesystem"
#coordinator_addr = "/tmp/codis"
coordinator_name = "zookeeper"
coordinator_addr = "172.16.10.142:2181,172.16.10.143:2181,172.16.10.144:2181"
  • 2.启动dashboard
cd /usr/local/codis
./admin/codis-dashboard-admin.sh start
ss -tpnl |grep  18080
# 可以查看log确认状态 /usr/local/codis/log/codis-dashboard.log.
  • 3.dashboard地址
admin_addr = "0.0.0.0:18080"
3.5 部署codis-fe管理后台
  • 1.修改启动文件
vi /usr/local/codis/admin/codis-fe-admin.sh
#COORDINATOR_NAME="filesystem"
#COORDINATOR_ADDR="/tmp/codis"
COORDINATOR_NAME="zookeeper"
COORDINATOR_ADDR="172.16.10.142:2181,172.16.10.143:2181,172.16.10.144:2181"
  • 2.启动fe
cd /usr/local/codis
./admin/codis-fe-admin.sh start
ss -tpnl|grep 9090
# 可以查看log确认状态 /usr/local/codis/log/codis-fe.log.
  • 3.后台管理地址
CODIS_FE_ADDR="0.0.0.0:9090"
3.6 部署codis-server加入集群

部署4个节点的server 172.16.10.142/143/144/154

  • 1.所有server机器启动codis-server
/usr/local/codis/admin/codis-server-admin.sh start
  • 2.redis.conf修改了如下参数(仅用于测试)
protected-mode no
port 6369
pidfile /usr/local/codis/log/redis_6369.pid
logfile "/usr/local/codis/log/redis_6369.log"
dbfilename dump_6369.rdb
dir /usr/local/codis/log/
appendfilename "appendonly.aof"
  • 3.fe管理后台添加2个group,每个group分配2个机器 imageimage

  • 4.点击分配槽位 imageimage

3.7 部署codis-proxy代理服务

部署3个节点的server 172.16.10.142/143/144

  • 1.修改配置文件proxy.toml,zookeeper地址
vi /usr/local/codis/config/proxy.toml
#jodis_name = ""
#jodis_addr = ""
jodis_name = "zookeeper"
jodis_addr = "172.16.10.142:2181,172.16.10.143:2181,172.16.10.144:2181"
  • 2.修改启动文件并启动,指向dashboard IP:PORT
vi /usr/local/codis/admin/codis-proxy-admin.sh
#CODIS_DASHBOARD_ADDR="127.0.0.1:18080"
CODIS_DASHBOARD_ADDR="172.16.10.154:18080"

/usr/local/codis/admin/codis-proxy-admin.sh  start
ss -tpnl |grep 19000
  • 3.proxy启动默认会自动注册到dashboard中,也可以在fe中手动添加 image
3.8 部署redis-sentinel实现集群HA

部署3个节点的server 172.16.10.142/143/144

  • 1.修改配置文件
vi /usr/local/codis/config/sentinel.conf
port 26379
dir "/tmp"
protected-mode no
  • 2启动sentinel
#sentinel部署官方脚本,是根据codis-server启动脚本进行修改
# 源文件目录:./ansible/roles/redis-sentinel/templates/redis-sentinel-admin.sh
/usr/local/codis/admin/codis-sentinel-admin.sh start
ss -tpnl |grep 26379
  • 3.fe界面添加Sentinels imageimageimage
分享到:
评论

相关推荐

    SpringBoot+ElasticSearch集群+RocketMQ+Codis集群架构,满足亿级流量实时计算,实时监控的系统

    一个满足亿级流量实时计算,实时监控的系统,SpringBoot+ElasticSearch集群+RocketMQ+Codis集群架构实现,项目经过严格测试,确保可以运行! 主要功能是通过ElasticSearch实现实时计算、实时分析海量数据,聚合处理...

    redis-codis集群

    Redis-Codis是一个在中国互联网行业中广泛应用的分布式Redis解决方案。它主要解决了单个Redis实例在处理大规模数据和高并发请求时...了解和掌握Redis-Codis的原理和使用方法,对于提升系统的可扩展性和稳定性至关重要。

    Codis ansiable playbook 一键部署

    1. **Codis 架构**:Codis 由三部分组成:Proxy、Zookeeper 和 Dashboard。Proxy 作为客户端与 Redis 之间的代理,负责分发命令;Zookeeper 用于协调和管理各个组件的状态;Dashboard 提供了一个 Web UI,用于监控和...

    Codis3.1集群搭建文档

    Codis集群架构主要包括四个组件:Codis Server、Codis Manager、Codis Proxy和Codis FE。Codis Server是Redis服务的主要组件,负责处理客户端请求;Codis Manager是集群管理组件,负责管理集群节点的配置和状态;...

    codis集群安装包及文档

    CODIS架构主要包括三部分:Proxy、Zookeeper和Redis实例。Proxy作为客户端与Redis之间的桥梁,处理客户端请求并分发到合适的Redis实例。Zookeeper用于存储元数据,包括Slot(槽)的映射信息以及Redis实例的状态。...

    codis-3.2.2.zip

    下面我们将深入探讨Codis的设计原理、功能特点以及3.2.2版本中的关键改进。 1. Codis设计原理: Codis采用了Proxy中间件模式,它将客户端与多个Redis实例之间的通信进行透明化管理。客户端连接到Proxy,Proxy根据...

    codis安装文档以及安装包

    **一、CODIS架构** CODIS由三部分组成:Proxy、Zookeeper和Dashboard。Proxy作为客户端与数据库之间的代理,负责数据路由和分片管理;Zookeeper用于存储系统状态信息,保证服务高可用;Dashboard则是一个Web管理...

    Redis 集群解决方案 Codis.zip

    架构:特性:自动平衡使用非常简单图形化的面板和管理工具支持绝大多数 Redis 命令,完全兼容 twemproxy支持 Redis 原生客户端安全而且透明的数据移植,可根据需要轻松添加和删除节点提供命令行接口RESTful APIs安装...

    Go-codis-3.2.2源码分析

    Codis的核心架构包括三部分:Proxy、Zookeeper和Redis集群。Proxy作为客户端与Redis之间的中间层,处理客户端的请求并分发到相应的Redis实例;Zookeeper用于协调和管理整个集群的状态,包括Proxy和Redis实例的注册...

    codis-release3.1.zip

    1. **CODIS架构**:CODIS的核心架构包括Proxy、Zookeeper、Dashboard和Redis实例四部分。Proxy作为客户端与Redis之间的中间层,负责请求转发和数据分片;Zookeeper用于协调各个组件,存储元数据信息;Dashboard是Web...

    codis测试环境搭建

    Codis 的核心架构由四个主要组件组成: 1. **Codis-Proxy**:作为客户端连接的 Redis 代理服务,它实现了 Redis 协议,确保客户端与 Codis 交互时的透明性。 Codis-Proxy 是无状态的,可以部署多个实例以提高并发...

    codis集群部署

    一、CODIS架构 CODIS的核心组件包括三部分:Proxy、Dashboard和Zookeeper。 1. Proxy:作为客户端与Redis之间的透明代理,它接收客户端的请求,根据内部的路由规则将请求转发到合适的Redis实例,同时处理数据的...

    codis for pika 二进制包

    - **分布式架构**:Codis通过Proxy代理层实现了客户端与多个Redis实例之间的透明通信,使得客户端无需感知后端Redis集群的结构变化。 - **动态扩容/缩容**:Codis支持在线添加或删除Redis节点,无需停机,保证业务...

    Codis集群搭建文档

    ### Codis集群搭建知识点 #### 一、Go语言环境配置 **目的:** Codis是用Go语言编写的,因此需要在服务器上安装并配置Go环境。 **步骤:** 1. **下载Go语言安装包:** ```shell wget ...

    Codis使用入门

    对于想要理解 Codis 内部工作原理或者对其进行优化的人来说,阅读源码会是很有价值的学习途径。 文件名“codis比较.txt”可能包含了对Codis与其他类似分布式缓存解决方案的对比,例如Redis Cluster或Twemproxy。在...

    codis3.2.0-go1.7.5-linux.tar.gz安装包

    首先,让我们详细了解CODIS的核心功能和架构: 1. **分片路由**:CODIS提供了基于Slot(槽)的分片策略,将数据均匀分布在多个Redis实例上。每个数据都有一个与之关联的Slot,客户端通过Key来确定其归属的Slot,...

    codis+lvs+keepalived

    在Codis集群中,可以有多个Codis Server构成高可用的主从架构。 - Codis Dashboard:管理后台,通过该后台可以配置和管理集群状态,如添加、删除Proxy、Server等。 - Zookeeper:用于集群元信息的存储和管理,提供...

    细细品味架构·分布式Redis解决方案Codis(第9期)

    1.2.3 Codis 的使用经验 1.2.4 分布式数据库和架构 1.2.5 现场答疑(Q&A) 2、知识扩展 2.1 CAP 理论简介 2.1.1 CAP 的历史 2.1.2 CAP 被上升为定理 2.1.3 前所未有的质疑 2.1.4 对质疑的回应 2.1.5 该如何看待...

Global site tag (gtag.js) - Google Analytics