从实际案例看redis的使用
在这个案例的另一问题:
ried可能出现的各种姑臧承受了各种故障的狂轰滥炸:
- Redis被keys命令堵塞了;
- Redis服务器做了一套日志系统,将日志系统先存储到Redis里面,再通过其他程序读取数据并进行分析和计算,用来做数据报表,但是有程序向这个日志组件写了一条7MB的日志,于是Redis堵死了,一旦堵死,数千个客户端就全部无法连接,所有日志记录的操作全部失败。
- 一个非法日志服务的存在,表面上是管理问题,实质上还是技术问题,因为Redis的使用无法像关系型数据库那样有DBA的监管,它的运维者无法管理和提前知道里面放的是什么数据,开发者也无需任何申明就可以向Redis中写入数据并使用,所以这里我们发现Redis的使用没这些场景的管理后在长期的使用中比较容易失控,我们需要一个对Redis使用可治理和管控的透明层。
- Keepalived切换虚IP失败,虚IP被释放了;
- 用Redis做计算了,Redis的CPU占用率成了100%了;
- 主从同步失败了;
+ 主从Redis之间的网络出现了一点小动荡,想想这么大的一个东西在主从同步,一旦网络动荡了一下下,会怎么样呢?主从同步失败,同步失败,就直接开启全同步,于是200GB的Redis瞬间开启全同步,网卡瞬间打满。 - Redis客户端连接数爆了;
- ……
如何改变Redis用不好的误区
总结以下几点:
- 必须搭建完善的监控系统,在这之前要先预警,不能等到发生了,我们才发现问题;
- 控制和引导Redis的使用,我们需要有自己研发的Redis客户端,在使用时就开始控制和引导;
- Redis的部分角色要改,将Redis由storage角色降低为cache角色;
- Redis的持久化方案要重新做,需要自己研发一个基于Redis协议的持久化方案让使用者可以把Redis当DB用;
- Redis的高可用要按照场景分开,根据不同的场景决定采用不同的高可用方案。
留给开发同学的时间并不多,只有两个月的时间来完成这些事情。这事其实还是很有挑战的,考验开发同学这个轮胎到底能不换下来的时候到来了。同学们开始研发我们自己的Redis缓存系统,下面我们来看一下这个代号为凤凰的缓存系统第一版方案:
- 首先是监控系统:原有的开源Redis监控从大面上讲只是一些监控工具,不能算作一个完整的监控系统。当然这个监控是全方面从客户端开始一直到返回数据的全链路的监控
- 其次是改造Redis客户端。广泛使用的Redis客户端有的太简单有的太重,总之不是我们想要东西,比如,.Net下的BookSleeve和servicestack.Redis(同程还有一点老的.Net开发的应用),前者已经好久没人维护了,后者直接收费了。
好吧,我们就开发一个客户端,然后督促全公司的研发用它来替换目前正在使用的客户端。在这个客户端里面,我们植入了日志记录,记录了代码对Redis的所有操作事件,比如耗时、key、value大小、网络断开等,我们将这些有问题的事件在后台进行收集,由一个收集程序进行分析和整理,同时取消了直接的IP端口连接方式,通过一个配置中心分配IP地址和端口
当Redis发生问题并需要切换时,直接在配置中心改,由配置中心推送新的配置到客户端,这样就免去了Redis切换时需要业务员修改配置文件的麻烦
另外,把Redis的命令操作拆成两部分:安全的命令和不安全的命令。对于安全的命令可以直接使用,对于不安全的命令需要分析和审批之后才能打开,这也是由配置中心控制,这样就解决了研发人员使用Redis时的规范问题,并且将Redis定位为缓存角色,除非有特殊需求,否则一律以缓存角色对待
最后,对Redis的部署方式也进行了修改,以前是Keepalived的方式,现在换成了主从+哨兵模式。另外,我们自己实现了Redis的分片,如果业务需要申请大容量的Redis的数据库,就会把Redis拆分成多片,通过Hash算法均衡每片的大小,这样的分片对应用层也是无感知的。
当然重客户端方式不好,并且我们要做的是缓存不仅仅是单单的Redis,于是我们会做一个Redis的Proxy,提供统一的入口点,Proxy可以多份部署,客户端无论连接的是哪个Proxy,都能取得完整的集群数据,这样就基本完成了按场景选择不同的部署方式的问题。
这样的一个Proxy也解决了多种开发语言的问题,例如,运维系统是使用Python开发的,也需要用到Redis,就可以直接连Proxy,然后接入到统一的Redis体系中来。做客户端也好,做Proxy也好,不只是为代理请求而是为了统一的治理Redis缓存的使用,不让乱象的出现。
让缓存有一个可管可控的场景下稳定的运维,让开发者可以安全并肆无忌惮继续乱用Redis,但这个“乱”是被虚拟化的乱,因为它的底层是可以治理的。
当然上面这些改造都需要在不影响业务的情况下进行。实现这个起始还是有不小的挑战,特别是分片,将一个Redis拆成多个,还能让客户端正确找到所需要的Key,这需要非常小心,因为稍有不慎,内存的数据就全部消失了。在这段时间里,我们开发了多种同步工具,几乎把Redis的主从协议整个实现了一遍,终于可以将Redis平滑过渡到新的模式上了。