Codis使用理解

参考:https://juejin.im/post/5c132b076fb9a04a08218eef

          https://blog.csdn.net/antony9118/article/category/7045910

         http://www.cnblogs.com/EasonJim/p/7818004.html

         https://github.com/CodisLabs/codis/blob/release3.2/doc/FAQ_zh.md

目录

1.框架介绍

2.组件启动

3.配置文件中的关键参数

4.客户端测试

5.数据存储特点

6.支持的命令

7.主从区别

8.zookeeper的存储信息

9.多数据库问题


Codis 是一个分布式 Redis 解决方案, 对于上层的应用来说, 连接到 Codis Proxy 和连接原生的 Redis Server 没有显著区别 (除了一些命令不支持外), 上层应用可以像使用单机的 Redis 一样使用, Codis 底层会处理请求的转发, 不停机的数据迁移等工作, 所有后边的一切事情, 对于前面的客户端来说是透明的, 可以简单的认为后边连接的是一个内存无限大的 Redis 服务。

1.框架介绍

了解框架中的部分概念:

codis-fe:用户的最直观操作,用户可以通过可视化页面直接操作集群;

codis-dashboard: codis的集群管理工具,支持proxy和server的添加、删除、数据迁移,所有对集群的操作必须通过dashboard;

codis-proxy:客户端连接的Redis代理服务,本身实现了Redis协议,表现很像原生的Redis (就像 Twemproxy)。一个业务可以部署多个 codis-proxy,其本身是无状态的;

codis-group:组中可包含slot的分片情况及主从实例,且一个组中只能有一个master;

codis-server:Codis 项目维护的一个Redis分支,加入了slot的支持和原子的数据迁移指令。等同于redis-server;

redis-sentinel:sentinel是redis集群高可用的保障。当一个master挂掉后,可以将slave升级为master。

ZooKeeper:Codis依赖ZooKeeper来存放数据路由表和codis-proxy节点的元信息,发起的命令会通过 ZooKeeper同步到各个存活的codis-proxy。

框架理解:

用户可通过jodis-client、redis-client操作codis-proxy,也可通过可视化codis-fe,结合集群管理工具codis-dashboard实现proxy,server,sentinel的管理。用户通过codis-proxy发起一个操作请求,codis首先根据key确定slotId,slotId = crc32(key) % 1024,计算出slotId,根据group的slot范围,确定该slotId在哪一个group中,从而确定数据存储的机器.再根据codis-server(等同于redis-server)实现redis的操作。如果codis-group中的master挂掉或者需要将slave升级为master,就需要借助codis-sentinel了。整个过程中zookeeper会存储一些基本的元数据信息,比如proxy,sentinel,group等。

2.组件启动

启动:

nohup /usr/local/software/codis3.2.2-go1.9.2-linux/codis-server /redis/data/config/redis_6379.conf &

nohup /usr/local/software/codis3.2.2-go1.9.2-linux/codis-server /redis/data/config/redis_6380.conf &

nohup /usr/local/software/codis3.2.2-go1.9.2-linux/redis-sentinel  /redis/data/config/sentinel.conf &

nohup /usr/local/software/codis3.2.2-go1.9.2-linux/codis-proxy --ncpu=4 --config=/redis/data/config/proxy.conf --log=/redis/data/logs/proxy.log &

nohup /usr/local/software/codis/codis-dashboard --ncpu=4 --config=/redis/data/config/dashboard.conf --log=/redis/data/logs/codis_dashboard.log --log-level=WARN &

验证

ss -ntplu |grep codis-server

ss -ntplu |grep codis-proxy

ss -ntplu |grep codis-dashboard

proxy启动过程:

读取配置文件,获取Config对象。根据Config新建Proxy,填充Proxy的各个属性,这里面比较重要的是填充models.Proxy(详细信息可以在zk中查看),并且与zk连接、注册相关路径。启动goroutine监听11080端口的codis集群发过来的请求并进行转发,以及监听发到19000端口(客户端redis-cli访问代理的端口)的redis请求并进行相关处理

在启动proxy的时候,会有一个goroutine专门负责监听发送到19000端口的redis请求。每次有redis请求过来,会新建一个session,并启动两个goroutine,loopReader和loopWriter。loopReader的作用是,Router根据请求指派到slot,并找到slot后面真正处理请求的BackendConn,再将请求放入BackendConn的RequestChan中,等待后续取出并进行处理,然后将请求写入session的RequestChan。loopWriter则将请求的结果从session的RequestChan(Request的*redis.Resp属性)中取出并返回,如果是MSET这种批处理的请求,要注意合并结果再返回

dashboard的启动:

dashboard是codis的集群管理工具,支持proxy和server的添加、删除、数据迁移,所有对集群的操作必须通过dashboard。dashboard的启动过程和proxy类似。dashboard的启动只是初始化一些必要的数据结构。

启动的时候,首先读取配置文件,填充config信息。根据coordinator的信息,如果是zookeeper而不是etcd的话,就创建一个zk客户端。然后根据client和config创建一个topom。首先来看看topom中有哪些信息。这个类在/pkg/topom/topom.go中。Topom非常重要,这个结构里面存储了集群中某一时刻所有的节点信息,在深入codis的过程中我们会逐步看到。

启动dashboard的过程中,需要连接zk,创建Topom这个struct,通过18080这个端口与集群进项交互,并将该端口收到的信息进行转发。最重要的是启动了四个goroutine,刷新集群中的redis和proxy的状态,以及处理slot和同步操作。

fe的启动:

虽然dashboard负责对集群的实际操作,但是用户的最直观操作,都是来自于fe的。首先,启动的时候指定fe的监听端口,这个就是我们最后通过浏览器打开fe的端口。然后根据系统参数找到assets文件夹目录,再在这个目录下寻找index.html,没错,就是浏览器中看到的html。如果在本地启动的时候这一步报错,assets目录下找不到index.html,就自己手动写死assets的地址即可。接下来,找启动的时候配置的codis.json。通过codis.json连接到dashboard,fe就算是和集群关联起来了。使用martini框架,新建路由和handler。最终我们得到了一个拥有完整规则的请求处理器handler,就是m。下一步,监听启动端口,新建路由表并将路由表指向刚才的martini框架的Router。最后一步,hs.Serve(l)这里,服务器接收指定监听器收到的请求,并为每个请求新建goroutine。goroutine负责读取并调用srv.Handler对请求进行相应。

3.配置文件中的关键参数

配置文件关键参数
redis_6379.conf

port 6379

logfile /redis/data/logs/redis_6379.log #日志路径

requirepass "codisqwer"  #所有codis-proxy集群相关的redis-server认证密码必须全部一致

masterauth "codisqwer"#如果做故障切换,不论主从节点都要填写密码且要保持一致

databases 64#修改库的个数

redis_6380.conf

port 6380

logfile /redis/data/logs/redis_6380.log #日志路径

requirepass "codisqwer"

masterauth "codisqwer"

slaveof 10.2.10.109 6379

databases 64

sentinel.conf

logfile /redis/data/logs/sentinel_26379.log #日志路径

port 26379

proxy.conf

product_auth = "codisqwer" #设置登录dashboard的密码(与真实redisrequirepass一致)

session_auth = "qwer!23” #客户端(redis-cli)的登录密码(与真实redisrequirepass不一致),是登录codis的密码

admin_addr = "0.0.0.0:11080"#管理的端口,0.0.0.0即对所有ip开放,基于安全考虑,可以限制内网

jodis_name = "zookeeper"

proxy_addr = "0.0.0.0:19000"#客户端(redis-cli)访问代理的端口,0.0.0.0即对所有ip开放

backend_number_databases = 64#修改库的个数

dashboard.confproduct_auth = "codisqwer"

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

4.客户端测试

通过proxy/usr/local/software/codis/redis-cli -h 10.2.10.109 -p 19000 -a qwer!23

通过redis-server/usr/local/software/codis/redis-cli -h 10.2.10.109 -p 6379 -a codisqwer

5.数据存储特点

数据写入测试:通过proxy写入key,会先按照key进行计算,SlotId = crc32(key) % 1024,计算出slotId,根据group的slot范围,确定该slotId在哪一个group中,从而确定数据存储的机器,将数据存储在该机器对应的slotId中。如果刚好该机器挂掉,则返回错误(error) ERR handle response, backend conn reset/failure;

通过codis-server写入key,会先按照key进行计算,SlotId = crc32(key) % 1024,计算出slotId,则直接将该数据存储在该codis-server对应的机器上的slotId中。如果刚好该机器挂掉,则返回错误Could not connect to Redis at %host%:%port%: Connection refused

注意:通过codis-proxy写set a1 800,会根据a1计算其所在的机器,比如在机器1。在机器3的codis-server上执行set a1 100,则a1会写在机器3上。在机器3上的codis-proxy执行get a1,会获得800;在机器3上的codis-server执行get a1,会获得100。

在写入数据报错的情况下,可以通知管理员。管理员可以进行以下操作:

操作一:

借助codis-fe面板,观察GROUP情况,比如出现以下情况

如上图所示,当10.2.10.108:6379挂掉,10.2.10.108:6380正常的话,可以手动点击PROMOTE和如下图所示,则可以继续写入数据。

操作二:

借助codis-fe面板,观察GROUP情况,比如出现以下情况

重新启动10.2.10.108:6379的codis-server

/usr/local/software/codis3.2.2-go1.9.2-linux/codis-server /redis/data/config/redis_6379.conf

数据迁移测试:不管是通过proxy还是codis-server写入的数据,在数据迁移时都会受影响。

***补充:判断key是处于哪一个slot上?***

Codis 采用 Pre-sharding 的技术来实现数据的分片, 默认分成 1024 个 slots (0-1023), 对于每个key来说, 通过以下公式确定所属的 Slot Id : SlotId = crc32(key) % 1024

验证:

crc32(key):https://www.lammertbies.nl/comm/info/crc-calculation.html

十六进制转十进制:https://www.sojson.com/hexconvert/16to10.html

在线余数:http://www.ab126.com/shuxue/2892.html

测试值:

key=a1               slot=35

key=s1 slot=240

key=a2 slot=409

key=c1 slot=673

key=-f1 slot=740

key=z1 slot= 953

key=p1 slot=819

***判断key是处于哪一个slot上***

***补充:存储在slot的具体信息***

slotsinfo 查看数据存储在哪个slot上,存储了多少数据,codis-server上操作

slotsscan slotId cursor [count] 查看指定slotId上的key列表,codis-server和codis-proxy上均可执行。不过有区别,codis-server上执行该命令,是获得该台机器上该slotId上的相应数量的keys列表,而codis-proxy上执行该命令,是获得该集群中通过codis-proxy写入数据中符合要求的keys列表。

更多新指令参考https://github.com/CodisLabs/codis/blob/release3.2/doc/redis_change_zh.md

***存储在slot的具体信息***

6.支持的命令

不支持的命令参见https://github.com/CodisLabs/codis/blob/release3.2/doc/unsupported_cmds.md

***补充:实现类似于keys效果***

方案一:https://github.com/CodisLabs/codis/issues/1152,借助proxy的slotsscan命令遍历1024个slot实现

方案二:附上前缀,将前缀用花括号括起来,计算出前缀应该所在的slotId,借助proxy的slotsscan命令遍历

比如:set         {a}0      0

set         {a}1      0

set         {a}2      0

set         {a}3      0

set         {a}4      0

a按照SlotId = crc32(key) % 1024,计算出slotId=579,再执行命令slotsscan 579 0 count 10

***实现类似于keys效果***

7.主从区别

slave仅可以读数据,不能写数据;

当master挂掉的时候,可以将slave升级为master,继续写入数据。

8.zookeeper的存储信息

 

 

 

9.多数据库问题

首先Redis不支持自定义数据库的名字,每个数据库都以编号命名,开发者必须自己记录哪些数据库存储了哪些数据。另外Redis也不支持为每个数据库设置不同的访问密码,所以一个客户端要么可以访问全部数据库,要么连一个数据库也没有权限访问。最重要的一点是多个数据库之间并不是完全隔离的,比如FLUSHALL命令可以清空一个Redis实例中所有数据库中的数据。综上所述,这些数据库更像是一种命名空间,而不适宜存储不同应用程序的数据。比如可以使用0号数据库存储某个应用生产环境中的数据,使用1号数据库存储测试环境中的数据,但不适宜使用0号数据库存储A应用的数据而使用1号数据库B应用的数据,不同的应用应该使用不同的Redis实例存储数据。

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值