write smart proxy step by step 1 (理论简介)

REMOTE DICTIONARY SERVER

为什么写这系列?

前段时间《7月,redis迷情》里面提到,我司线上 Redis Cluster + Smart Proxy 模式。我把代码放到了个人github上,大家感兴趣的可以下载使用。如果遇到问题,随时开Issue,或是直接找我。支持命令有限制,README里有详细介绍。

# go get  github.com/dongzerun/smartproxy

# make && ./cmd/redis_proxy  -config_file=example.ini

为什么要重写呢,有如下原因:

1. 当前实现需要对输入做字符串转化,大家知道在Golang中,大量 Byte[] To String 性能不高且对GC压力较大。可以参考 Bitly 对 NSQ 的优化官方文档。

2. 复用 Go Redis Driver,封装网络层,导致存在无效处理流程,重写后可以从底层优化。

3. Redis 在数据库领域里相当小巧,开发中间件有助于对数据库的理解。

4. 按模块开发,附以 Go 的单元测试,加深对 Go语言的认知和性能调优。


新的 Proxy 目标

老的代理当前使用上没问题,性能也足够用。新的要实现如下功能

1. 支持 Redis Cluster 协议,屏蔽语言的差异,这是核心。

2. 命令检测,对危险或是不支持的命令提前检测。

3. 支持 Pipeline,这个使用场景还是很多,老的代理无法实现。

4. 更详细的性能统计,内建 Http DashBoard 以供查询。

5. 服务发现与注册,支持 Zookeeper 和 Etcd。


Redis Client Protocol

Redis协议相比MySQL协议简单太多,感兴趣的同学可以查看相应驱动源码,加深对协议的理解。Redis属于文本协议,基于 Request-Response Model 模型,官方称做 RESP (REdis Serialization Protocol) 。

Response Protol

RESP协议有五种应答类型,每部分以 CRLF(\\r\\n) 结尾

1. Simple Strings: 简单字符应答以"+"开头,跟随字符串数据,并以 CRLF 结尾

Simple Strings Reply

例中返回数据为+OK\\r\\n

2. Errors: 错误应答以"-"开头,跟随错误原因的字符串,并以 CRLF 结尾

Errors Reply

例中返回数据为-ERR wrong number of arguments for 'get' command\\r\\n

3. Integers: 整数应答以":"开头,跟随整数值,并以 CRLF 结尾

Integers Reply

例中返回数据为:2\\r\\n

4. Bulk Strings: 字符串应答以"$"开头,跟随真实数据的长度和数据

Bulk String Reply

例中返回数据为$3\\r\\nBAR\\r\\n

5. Arrays: 数组类型应答以"*"开头,跟随多个 Bulk Strings的应答

Array Reply

例中返回数据为*4\\r\\n$1\\r\\nb\\r\\n$1\\r\\n$a\\r\\n$1\\r\\nd\\r\\n$-1\\r\\n, 其中最后一个-1表示对应 command 中最后一个 key 不存在

Command Protol

举个最简单的命令 SET FOOFOO  BAR,那么客户端实际发送给 Server 的数据为

*3\\r\\n$3\\r\\nSET\\r\\n$6\\r\\nFOOFOO\\r\\n$3\\r\\nBAR\\r\\n

使用 telnet 模拟如下

set foofoo bar

最后的+OK表示命令执行成功,反回 simple string OK,也就是说 Command 行为和 Array Reply 一致。

Redis Cluster 简介

官网有两篇文章 cluster-speccluster-tutorial ,详细讲解了 Redis Cluster 实现原理和搭建,湖南TV提供了 Python 版的 Redis-trib,大家可以使用搭建和迁移 Cluster 数据很方便。如何搭建和 Cluster 内部选举算法这里不做讲解,需要注意 cluster-require-full-coverage 这个参数要设为 no

If this is set to yes, as it is by default, the cluster stops accepting writes if some percentage of the key space is not covered by any node. If the option is set to no, the cluster will still serve queries even if only requests about a subset of keys can be processed.

简单来说,Cluster 将 Key(或是根据 hash tag) 按照 CRC16 处理得到 hash value,对值按 16384 取模,这样会将数据均匀分到 16384 slots 中,属于逻辑槽,逻辑 slots 再根据 Cluster-nodes.conf 确定具体属于哪个物理主从对

cluster-nodes.conf
cluster info

使用 Cluster Info 命令可以看到当前集群信息,cluster_slots_assigned 表示当前已分配物理节点的 slots 数量,cluster_slots_ok 表示当前有多少个 slots 正常服务,fail和pfail分别表示当前节点谁为主观宕机和客观宕机的 slots 数量,cluster_size 表示集群有多少个物理主从对,对参数更详细的请参考官方文档。

由于采用无中心的设计,客户端随机连接一个节点,发起请求。Redis 根据 Key 获取 hash 值后取模,得到 Slot ID,在内存中查找 Slot ID 当前属于哪个物理节点。如果不是本机,那么 Redis 返回客户端一个 Errors Reply, 错误内容是一个 MOVE 重定向,例如:

127.0.0.1:6494> get b

(error) MOVED 3300 10.10.10.178:6494

此时客户端根据 MOVED 指令,去连接10.10.10.178:6494实例,发起同样的请求,得到正确的数据。理想情况下,Smart 客户端只需 MOVED 跳转一次即可找到正确节点。

当 Slot 发生迁移时,Redis 会在源节点标记该 Slot 为 Migrating 状态,同时标记目标节点该 Slot 为 Importing 状态。当客户端发起请求时,所有流量都会转发到源节点,如果数据存在那么返回。如果数据不存在,那么可能已经迁移到目标节点。源节点返回一个 -ASK 错误附加目标节点信息,客户端连接目标节点,先发起一个 ASKING 命令,再发送正常的请求。如果不先发送 ASKING 命令,那么目标节点会认为是非法请求,返回 MOVED 重定向。

Smart Proxy 设计思路

明白了 Redis Cluster 原理,那么核心设计起来也就简单多了。其它功能都是添枝加叶。具体模块划分留到下一篇分享吧,每篇编写一个模块,并附件详细的 Go Test 和性能测试。

1. 定期获取 Cluster Config 配置信息,缓存到 Proxy 内存中。

2. 对请求 Key 取 Hash Value后,查询 Slots 配置,发送到指定后端节点。

3. 处理好 MOVED 和 ASK 两个异常即可。


结语

这篇只讲些理论基础,后续再具体编码,希望自已能坚持写完~_~ 推荐大家一首歌《压缩饼干》来自大冰

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

推荐阅读更多精彩内容