第1页
Codis Design & Implementation
姓名: 刘奇 微博 : @goroutine Storage-基础架构部-豌豆荚
第2页
典型业务
image-service (单个 value 较大) 好友关系(set, key count 4亿+) applist (720G, 32 instances) …...
第3页
业务特点
持久存储:MySQL 或者 HBase 缓存:memcached + Redis
第4页
豌豆荚的 Redis 历程
● 单实例 ● 多实例,业务代码中做 Sharding ● 单个 Twemproxy ● 多个 Twemproxy ● Codis 豌豆荚自己开发的分布式 Redis 服务
第5页
使用 Redis 的一些痛点
1. 单机内存有限 2. 带宽压力 3. 单点问题 4. 不能动态扩容 5. 磁盘损坏时数据抢救
第6页
How to scale Redis ?
● 客户端静态分片(Consistent Hash)
● 通过 Proxy 分片
○ Twemproxy
● 官方的 Redis Cluster
第7页
Why not Twemproxy
● 最大痛点:无法平滑的扩/缩容(Scale!!!!)
○ 甚至修改个配置都需要重启服务。。。
● 不可运维,甚至没有 Dashboard
第8页
Why not Redis Cluster (official)
● 无中心的设计,难把程序写对 ● 代码有点吓人,clusterProcessPacket 函数有
426行,大脑难处理到所有的状态切换 ● 迟迟没有正式版本,等了4年之久 ● 目前还缺乏 Best Practice,还没有人写一个
Redis Cluster 若干条注意事项 ● 整个系统高度耦合,升级比较困难
第9页
为什么一定要redis 关于 Tair, Couchbase…
良好的数据结构支持
第10页
What’s Codis?
● Distributed Redis Proxy ● Redis Cluster 又一个解决方案 ● HA ● Design for Scalability ● No SPOF ● Powered by and C
第11页
Codis 解决了哪些问题?
● 自动扩容,缩容 ● 单点故障 ● 单点带宽不足 ● 高可用 ● 轻松将数据从 Twemproxy 迁移到 Codis ● 轻松运维,监控
第12页
Codis 整体设计
● Pre-sharding
○ Slot => [0, 1023]
● Zookeeper ● Proxy 无状态 ● 平滑扩容/缩容 ● 扩容对用户透明
第13页
设计考量
● 分布式系统是复杂的 ● 开发人员不足 ● 尽量拆分,简化每个模块,同时易于升级 ● 每个组件只负责自己的事情 ● Redis 只作为存储引擎 ● Proxy 状态
第14页
设计考量
● Redis 是否挂掉的判定放到外部,因为分布式 系统存活的判定是复杂的
● 提供 API 让外部调用,当 Redis master 挂掉 的时候,提升 slave 为 master
第15页
设计考量
● graph everything
○ slot status ○ proxy status ○ group status ○ lock ○ action
第16页
proxy vs smart client
proxy: 更好的监控,控制 后端信息不暴露,易于升级
smart client: 更好的性能 更低的延迟,升级比较麻烦
第17页
Codis Architecture
第18页
Zookeeper
● Distributed Lock service ● Router Table
○ Pre-sharding: 1024 slots
● Server Groups
○ Server Groups ○ groupX: [master, slave]
第19页
Read/Write Flow (Normal)
第20页
Read/Write Flow (Migrating)
第21页
Migration
1. 将 slot_X 状态标记为 ‘pre_migrate’ 2. 等待所有的 proxy 确认 3. 将 slot_X 状态标记为‘migrating’ 4. 不断发送 SLOTSMGRT 命令给 source redis instance 直到 slot_X 所有的 key 迁移完成 5. 将 slot_X 状态标记为 ‘online’
第22页
How it works?
● make sure all proxies updated its routing table
○ 2-phase commit ○ Zookeeper
● Atomic migration
○ Redis is single threaded ○ little C patch…
第23页
How it works(do migrate)
第24页
How it works(codis-redis)
Redis
key => value key1 => value1 key2 => value2 key3 => value3 key4 => value4 key5 => value5 … keyN => valueN
Codis Redis
key => value key1 => value1 key2 => value2
key3 => value3 key4 => value4 key5 => value5
...
slot 1 slot 2 slot X
第25页
Router Table
ZooKeeper ZNode:
/codis/db_{xx}
{xx} means 产品名, 如: /codis/db_sync , /codis/db_applist
/codis/db_{xx}/servers/group_{N}/{ server addr (e.g. 127.0.0.1:6379) }
存储真实的 redis 组 (主master、从slave), N为一个自定义的整数编号, in JSON, 内容包括服务器地址, 角色(master or slave)等信息
第26页
Router Table
// 存储 key slot 的分布信息, N 为 hash(key)
/codis/db_{xx}/slots/slot_{N} ( 0 < N < 1024) => { ‘group’ : ‘group_znode_name’, ‘state’ : { ‘status’ : ‘ ONLINE| OFFLINE | MIGRATING | PRE_MIGRATE’, ‘op_ts’ : ‘123123123123’, } }
第27页
Codis’ Redis
● Slot support ● Atomic migration
○ 每个操作迁移一个key
第28页
Codis Config Tool (cconfig)
● Rebalance ● Manage Server Groups ● Dashboard (HTTP) ● RESTful APIs
第29页
可是我的数据已经在 Twemproxy 上了,太大 了,还没法重建,我还懒 得写迁移脚本, 没法迁 移!!! 肿么办!!!
第30页
CodisPort
● 通过replication的方式将twemproxy/redis的数 据迁移到codis
● Sync协议 ● Fake Slave
第31页
CodisPort
Twemproxy
Redis 1 CodisPort
Redis 1 CodisPort
Redis
1 CodisPort
CodisProxy
第32页
使用注意事项
1. 单key的value别太大了(< 1 MB)
○ list别太大...
第33页
TODO
● Persistent storage support
○ LevelDB, Rocksdb …...
● Redis HA module 有些公司是单独运行codis的, 没有和运维系统结合,也不想自己调用
codis API
第34页
Performance
Codis会比Twemproxy慢20%左右
第35页
open-source
github.com/wandoulabs/codis
第36页
Thanks
QA