迁移Redis过程中存在的问题总结

需求的产生

由于公司业务需求,我对较高访问量的页面做了全局随机缓存优化,主要缓存了部分API、RPC接口。特点是代码层无需变化,无需改变原有逻辑,有较高的可控性和可维护性,降低了代码的冗余。同时对缓存做了进一步的封装,便于下一步的维护与变更。
增加随机缓存主要是防止缓存数据穿透问题,就是确保缓存数据不会同时在一个特定的时间全部失效,进而导致RPC、数据库请求剧增。
同时提供了打印请求过程、记录参数、超时告警、请求时间、超时自动结束等功能。便于进一步跟踪代码的执行情况。

产生的问题

由于原先的Memcached使用的是代理机制,1带4的方案,缓存的一天请求数可能接近1亿次左右,老的Memcached可能没有考虑到大规模应用缓存的需求,在高峰时期,有可能会挂掉。
甚至由于Memcached所在的服务器单一IP,Memcached的请求数在某一时刻会达到好几万,巨大的请求数没有及时结束,造成了大量的Time Wait,已经影响到正常的PHP服务。

期间,我们也做过一些尝试,看能否更换机器解决,最终发现还是远远无法满足未来的需求,急需扩容。

Redis的选择

公司原有众多业务也有使用到Redis、Kafka,考虑到Redis支持的类型更多,在扩容的时候,直接切换到Redis似乎是更好的选择。

Redis Cluster

一开始我们定了这个方案,一是他的高可用,二是它能够做到自动扩容,可以把机器当成资源池使用。同时配置了多台主从,理论上应该是性能超佳才是。
但在测试阶段就遇到众多问题,发现在单台服务器连接的时候,就出现了请求数过大、网卡过载、连接超时等问题。主要原因可能是:
1、长连接及连接池,PHP的机制导致了PHP是没有内存这个说法,没有办法建立一个长连接,然后让所有进程来共享使用,同时由于默认自带的参数是使用的长连接的形式,会导致进程结束,但是连接并未结束,一直占用着端口。在使用PHPRedis发现无法解决存在的问题,我还尝试了使用PRedis,发现问题还是一样,巨大的连接数对服务器是一个很大的负担,通过修改系统配置也没有很好的解决。
2、网卡可能不够用了,Redis Cluster的机制我没有特别深入去了解,也不是很明白为什么几千的请求数就能够把千兆网卡打满,这是否说明了Redis Cluster不仅仅把数据放大了2倍,而是n倍?同时还需要以转发的形式,来取得真正的值?这与Redis支持10万请求/秒的理论值相距深远。
3、Redis Cluster可能还不够成熟,大规模应用是否可行、是否经过完全测试?文档不齐全、案例较少、没有一个很好的PHP客户端也是一个大问题。

其中有一个同事提出能否由PHP端来分片,使用短连接,直接写入Redis Cluster,最终我们发现,似乎原有方法不支持这个功能,连接单机时会提示错误。

Redis

最终由于时间有限,我们暂时是选择了Redis单机的模式,经过对Linux系统的配置,降低了实时的请求数占用情况。同时在代码层实现分片功能。

1
2
3
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1