Codis 是一个分布式 Redis 解决方案

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介:

Codis源码地址:https://github.com/wandoulabs/codis

关于Codis组件可以参考:https://github.com/wandoulabs/codis/blob/master/doc/tutorial_zh.md


今天分享的这篇文章纯属个人的一些理解和使用的一些心得体会,如果错误也请朋友指出。

更重要的是为了认识一些正在使用或将要使用Codis的朋友有或多或少的帮助。


关于Codis的整体架构和功能介绍官方文档给的在详细不过了,所以我也不想在画蛇添足。


由于当前使用的是AWS的ec2主机,所以默认当前用户是ec2-user,而非root用户。


1、安装基础Go环境,所有节点均安装.

1
2
3
4
5
# sudo yum -y install gcc gcc-c++ make git wget go 
# sudo vim /etc/profile.d/go.sh
export  GOPATH= /opt/mygo
export  PATH=$GOPATH /bin :$JAVA_HOME /bin :$PATH
# source /etc/profile


2、安装Codis,除ZooKeeper节点外其余节点均正常安装.

1
2
3
4
5
6
# sudo mkdir /opt/mygo
# sudo chown -R ec2-user.ec2-user /opt/mygo/
# go get -u -d github.com/wandoulabs/codis
# cd /opt/mygo/src/github.com/wandoulabs/codis/
# make
# make gotest


3、安装ZooKeeper,仅需要在此节点安装.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# yum -y install java-1.8.0
 
# wget https://www.apache.org/dist/zookeeper/zookeeper-3.4.7/zookeeper-3.4.7.tar.gz
# tar -zxf zookeeper-3.4.7.tar.gz -C /opt
# cd /opt/zookeeper-3.4.7
# cp conf/zoo_sample.cfg conf/zoo.cfg
# mkdir /data/{zookeeper,logs} -p
 
# sudo vim conf/zoo.cfg
dataLogDir= /data/logs
dataDir= /data/zookeeper
server.1=localhost:2888:3888
 
# vim /data/zookeeper/myid
1
 
# vim /etc/profile.d/zookeeper.sh
PATH=$PATH: /opt/zookeeper-3 .4.7 /bin
 
# source /etc/profile
# sudo /opt/zookeeper-3.4.7/bin/zkServer.sh start conf/zoo.cfg
 
# netstat -alnut | grep 2181
# nc -v localhost 2181
# zkServer.sh status  #查看ZooKeeper的角色(leader|follower|standalone)
 
# zkCli.sh -server 127.0.0.1:2181
     ls  /
     create  /Test  hellozk
     get  /Test
     set  /Test  hellozookeeper
     get  /Test
     delete  /Test
     get  /Test
     quit


4、启动codis-redis服务.仅需要在redis节点.

1
2
3
4
# sudo mkdir /etc/redis
# cd /opt/mygo/src/github.com/wandoulabs/codis
# sudo ./bin/codis-server /etc/redis/redis.conf
# sudo netstat -tnlp |grep codis-se


5、在dashbaord节点上操作.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1> 配置dashboard服务
# cd /opt/mygo/src/github.com/wandoulabs/codis/
# mkdir /etc/codis
# cp config.ini /etc/codis/codis-config.ini
# vim vim /etc/codis/codis-config.ini
zk=172.31.16.33:2181
product=cn_release_codis
dashboard_addr=localhost:18087
proxy_id=proxy_1
proto=tcp4
 
2> 启动dashboard服务
# cd /opt/mygo/src/github.com/wandoulabs/codis/
# ./bin/codis-config -c /etc/codis/codis-config.ini dashboard  
 
3> 初始化 slots(该命令会在zookeeper上创建slot相关信息)
# cd /opt/mygo/src/github.com/wandoulabs/codis/
# ./bin/codis-config -c /etc/codis/codis-config.ini slot init
 
4> 强制格式化slot
# ./bin/codis-config -c /etc/codis/codis-config.ini slot init


6、添加codis-group-redis

> 添加第一组codis

1
2
# ./bin/codis-config -c /etc/codis/codis-config.ini server add 1 172.31.51.119:6379 master
# ./bin/codis-config -c /etc/codis/codis-config.ini server add 1 172.31.51.125:6379 slave

> 添加第二组codis

1
2
# ./bin/codis-config -c /etc/codis/codis-config.ini server add 2 172.31.51.126:6379 master
# ./bin/codis-config -c /etc/codis/codis-config.ini server add 2 172.31.51.124:6379 slave

> 开启分片

1
2
# ./bin/codis-config -c /etc/codis/codis-config.ini slot range-set 0 511 1 online
# ./bin/codis-config -c /etc/codis/codis-config.ini slot range-set 512 1023 2 online

> 扩容,在线添加新分片

1
2
3
# ./bin/codis-config -c codis-config.ini server add 3 192.168.10.131:6381 master
# ./bin/codis-config -c codis-config.ini server add 3 192.168.10.132:6381 slave
# ./bin/codis-config -c codis-config.ini slot migrate 256 511 3


7、启动codis-proxy服务.

比如线上有两个Codis-proxy服务.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# cd /opt/mygo/src/github.com/wandoulabs/codis/
# mkdir /etc/codis
# cp config.ini /etc/codis/codis-proxy.ini 
# vim /etc/codis/codis-proxy.ini 
zk=172.31.51.123:2181
product=cn_release_codis
dashboard_addr=172.31.51.120:18087
proxy_id=proxy_1
proto=tcp4
# ./bin/codis-proxy -c /etc/codis/codis-proxy.ini -L /var/log/codis_proxy.log --cpu=1 --addr=172.31.51.122:19000 --http-addr=172.31.51.122:11000
 
# cd /opt/mygo/src/github.com/wandoulabs/codis/
# mkdir /etc/codis
# cp config.ini /etc/codis/codis-proxy.ini 
# vim /etc/codis/codis-proxy.ini 
zk=172.31.51.123:2181
product=cn_release_codis
dashboard_addr=172.31.51.120:18087
proxy_id=proxy_2
proto=tcp4
# ./bin/codis-proxy -c /etc/codis/codis-proxy.ini -L /var/log/codis_proxy.log --cpu=1 --addr=172.31.51.121:19000 --http-addr=172.31.51.121:11000


8、dashboard监控页面

http://<dashboard_ip>:18087/admin/

wKiom1Z9WMyCr7pXAABfLaMu-Ec810.png


9、移除分片流程

1
2
3
4
5
6
7
8
9
---假设将分片3移除---
1. 设置codis-proxy为offline状态.
. /bin/codis-config  -c codis-config.ini proxy offline proxy_1
 
2. 迁移分片3上的数据到分片1
. /bin/codis-config  -c codis-config.ini slot migrate 256 511 1
 
3. 彻底移除分片3
. /bin/codis-config  -c codis-config.ini server remove-group 3


10、codis-server的HA

1
2
3
4
5
# export GOPATH=/opt/mygo
# go get github.com/ngaut/codis-ha
# cp /opt/mygo/bin/codis-ha /opt/mygo/src/github.com/wandoulabs/codis/bin/
# cd /opt/mygo/src/github.com/wandoulabs/codis/
# ./bin/codis-ha -codis-config="localhost:18087" -log-level="info" -productName="cn_release_codis"



遇到的问题以及解决办法,也希望这部分对朋友有用。

(1)

1
2
3
2015 /12/11  16:49:10 dashboard.go:160: [INFO] dashboard listening on addr: :18087
2015 /12/11  16:49:10 dashboard.go:234: [PANIC] create zk node failed
[error]: dashboard already exists: { "addr" "172.31.16.30:18087" "pid" : 7762}

解决办法:

这种问题是由于使用了kill -9导致了dashboard服务异常终止,而退出服务的时候没有在zk上清除自已的信息,所以就出现了这种问题。

所以我们在停止codis集群的任何服务的时候都不要轻易使用kill -9,可以使用kill.

如果使用kill,那么服务在终止的时候也会自动的到zk上清除自已的信息,下次再启动的时候会立刻注册。


临时性的解决办法就是:

# rmr /zk/codis/db_codis_proxy_test/dashboard


(2)

dashboard提供的api接口

http://debugAddr/setloglevel?level=debug

http://debugAddr/debug/vars #主要是获取ops信息的还可以设置日志级别

浏览器访问proxy的debug_addr对应地址/debug/vars路径,可以看到每个proxy的qps信息。


(3)

codis-proxy的服务日志中产生的信息解释。

quit : client主动发的quit指令

EOF  : 连接直接断开了,就是proxy从client的tcp读的时候遇到EOF了


codis每次主动关闭client的连接都会打log的,一般来说主要可能有:

非法操作、该请求连的底层redis挂了、这个session很久没请求触发了proxy这边的清理逻辑。

第三个可能更大些,看时间是6点多,是不是你们的访问量不大?


session_max_timeout=1800

如果30分钟内没有任何ops 那么codis就主动关闭这个连接。

嗯,主要是有人反馈说他们的环境下有时候client主动关了连接但是proxy这边没收到close的消息,导致proxy这边最后积累了一大堆连接把资源吃满了


(4)

NaN GB

因为redis配置文件中没有设置内存maxmemory参数



(5)

codis中所有的读写操作都是在redis-master上执行的,redis-slave只负责数据的冗余,当master出现down之后 可以进行master和slave的切换。


(6)******

在codis集群中product是用来区分是否为同一个集群的。所以如果是同一个集群,那么dashboard和codis-proxy中的product要设置的一样。否则就面临的下面这个问题

zk: node does not exist

codis-proxy配置文件中的proxy_id 是用来区分同一个集群下的不同成员,所以这个参数要唯一。


(7)

codis-ha只负责在master挂掉的时候自动选择一个slave提升为master,但没有把剩余的slave重新挂在新的master上,而且也没有确保选择的slave是最优的


(8)

Too many open files

在用python多线程对redis进行压力测试的时候,压力超过4000的时候就出现这种问题。

2台codis-proxy支持并发2-3w没有太大的问题。


(9)

dashboard服务即使停止也不会影响app通过codis-proxy正常的访问redis服务。

但是会影响codis-ha服务,则主备不会自动切换啦.


意思也就是dashboard服务如果停止,那么app还是可以正常访问redis的,但是codis-ha会终止运行期。


(10)

同一个group中可以实现redis数据的主从复制,但是不同的group中无法实现。

如果同一个group中所有的master和slave都挂掉了,那么数据就丢失了,但是你如果还查询挂掉的group中的key就会提示错误。并且那个key也就会占用啦。

所有的写操作codis-proxy就不会发送到挂掉的group上去了。


(11)

同一个Group中的codis-server 实例下,多个slave 是否会分担master的读请求?

codis的设计理念是更注重一致性,redis的主从同步不是强一致的,因此codis不支持读写分离


(12)

一个集群中只能有一个dashboard服务出于运行状态,可以有多个 但是同时只能有一个服务出于running状态。




如果正在使用Codis的朋友,那么肯定也会遇到这样一个问题,就是关于dashboard的登录认证问题。在这里我做了一个基于nginx的用户登录认证,配置如下。

wKioL1Z9b_aDHql0AABFfwoiA-g909.png

wKioL1Z9Wt6ibZb6AAAxqvS7_ls831.png

当时我在做这个登录认证的时候,也花了2~3小时才解决,不是因为多么复杂,是因为dashboard很多都是基于api来获取数据的,如果少了配置中rewrite重定向那么就会只显示页面 而获取不到数据。切记


下一篇Codis文章补充部分:

  1. Codis集群中每个角色服务强烈建议成server式的服务启动脚本,这个我已经完成了,但是还是需要调整。

  2. 关于Dashboard服务的监控,我认为更多的是Redis主从,这个我也会在下篇讲解遇到Redis的坑。

  3. 由于dashboard没有友好的登录认证机制,建议关闭dashboard服务,而另外开发一个可查看但是没有权限操作的可视化界面。






     本文转自zys467754239 51CTO博客,原文链接:http://blog.51cto.com/467754239/1728423,如需转载请自行联系原作者



相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
10天前
|
存储 NoSQL Java
使用lock4j-redis-template-spring-boot-starter实现redis分布式锁
通过使用 `lock4j-redis-template-spring-boot-starter`,我们可以轻松实现 Redis 分布式锁,从而解决分布式系统中多个实例并发访问共享资源的问题。合理配置和使用分布式锁,可以有效提高系统的稳定性和数据的一致性。希望本文对你在实际项目中使用 Redis 分布式锁有所帮助。
29 5
|
13天前
|
NoSQL Java 数据处理
基于Redis海量数据场景分布式ID架构实践
【11月更文挑战第30天】在现代分布式系统中,生成全局唯一的ID是一个常见且重要的需求。在微服务架构中,各个服务可能需要生成唯一标识符,如用户ID、订单ID等。传统的自增ID已经无法满足在集群环境下保持唯一性的要求,而分布式ID解决方案能够确保即使在多个实例间也能生成全局唯一的标识符。本文将深入探讨如何利用Redis实现分布式ID生成,并通过Java语言展示多个示例,同时分析每个实践方案的优缺点。
28 8
|
16天前
|
消息中间件 监控 NoSQL
Redis脑裂问题详解及解决方案
Redis脑裂问题是分布式系统中常见的复杂问题,合理配置Redis Sentinel、使用保护模式、采用分布式锁机制以及优化网络和客户端连接策略等措施,可以有效预防和解决脑裂问题。通过深入理解Redis脑裂问题的成因和影响,采取相应的解决方案,能够提高系统的可用性和数据一致性,保障Redis集群的稳定运行。希望本文能帮助你更好地理解和应对Redis脑裂问题。
24 2
|
29天前
|
NoSQL Redis
Redis分布式锁如何实现 ?
Redis分布式锁通过SETNX指令实现,确保仅在键不存在时设置值。此机制用于控制多个线程对共享资源的访问,避免并发冲突。然而,实际应用中需解决死锁、锁超时、归一化、可重入及阻塞等问题,以确保系统的稳定性和可靠性。解决方案包括设置锁超时、引入Watch Dog机制、使用ThreadLocal绑定加解锁操作、实现计数器支持可重入锁以及采用自旋锁思想处理阻塞请求。
55 16
|
22天前
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
36 5
|
NoSQL Go Redis
基于Codis的Redis集群部署
Codis是基于代理的高性能Redis集群方案,使用Go语言进行开发,现在在在豌豆荚及其它公司内已经广泛使用,当然也包括我们公司。 Codis与常见的Redis集群方案对比。
|
2月前
|
存储 缓存 NoSQL
数据的存储--Redis缓存存储(一)
数据的存储--Redis缓存存储(一)
96 1
|
2月前
|
消息中间件 缓存 NoSQL
Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。
【10月更文挑战第4天】Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。随着数据增长,有时需要将 Redis 数据导出以进行分析、备份或迁移。本文详细介绍几种导出方法:1)使用 Redis 命令与重定向;2)利用 Redis 的 RDB 和 AOF 持久化功能;3)借助第三方工具如 `redis-dump`。每种方法均附有示例代码,帮助你轻松完成数据导出任务。无论数据量大小,总有一款适合你。
78 6
|
28天前
|
缓存 NoSQL 关系型数据库
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
本文详解缓存雪崩、缓存穿透、缓存并发及缓存预热等问题,提供高可用解决方案,帮助你在大厂面试和实际工作中应对这些常见并发场景。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
|
29天前
|
存储 缓存 NoSQL
【赵渝强老师】基于Redis的旁路缓存架构
本文介绍了引入缓存后的系统架构,通过缓存可以提升访问性能、降低网络拥堵、减轻服务负载和增强可扩展性。文中提供了相关图片和视频讲解,并讨论了数据库读写分离、分库分表等方法来减轻数据库压力。同时,文章也指出了缓存可能带来的复杂度增加、成本提高和数据一致性问题。
【赵渝强老师】基于Redis的旁路缓存架构