team中的一个同窗在其项目中使用了Redis做为缓存,将热点数据存放在Redis中。为了提高性能,写Redis时采用了管道的方式,平时使用时,Redis的性能、资源使用都能符合项目需求,但当访问量增长的时候,Redis的QPS还能知足要求,但CPU使用率高的时候已经达到90%+,平时只有30%+,而众所周知,Redis是单进程的,只能占用1个CPU核,跑满了也就100%,没法利用机器的多核,而当CPU跑到100%时,必然会形成性能瓶颈。怎么解决?redis
方案一:算法
首先想到的是,增长Redis服务器的数量,在客户端对存储的key进行hash运算,存入不一样的Redis服务器中,读取时,也进行相同的hash运算,找到对应的Redis服务器,能够解决问题,可是很差的地方:缓存
第一,客户端要改动代码;服务器
第2、须要客户端记住全部的Redis服务器的地址;性能
这个方案可使用,但能不能不用改动代码就能实现扩容呢?代理
方案二:进程
搭建一个集群,因为Redis服务器使用的版本低于3.0,不支持集群,只能经过使用代理,就想到了有名的Redis代理twemproxy。资源
twemproxy的性能也是杠杠滴,虽然是代理,但它对访问性能的影响很是小,连Redis做者都推荐它。部署
twemproxy使用方便,对于一个新手来讲,不到一个小时就能学会使用,并且关键是不用改动客户端代码,几乎支持全部的Redis命令和管道操做,只须要改下客户端的配置文件中配置的Redis的IP和PORT,由原来的Redis的IP和Port改为twemproxy服务的IP和PORT。hash
客户端不须要考虑hash的问题,这些twemproxy会作,客户端就像操做一台Redis同样。
上面用了“几乎”这个词,由于有些命令,好比"keys *"就不支持
很快部署了好了twemproxy和后面跟着的四个Redis机器,压测发现,后面的四台Redis的CPU使用率降下来了,但新问题来了,twemproxy也是单进程的!性能瓶颈又跑到twemproxy上来了!
方案三:
对Redis的访问分为写和读,相似生产者和消费者, 再仔细分析,发现写的少,读的相对多些,这就能够将读写分离,写的往主的写,读的从备的读,遇到的状况刚好是读和写是两个服务,作到读写分离经过改下配置信息就能够很简单的作到,,这样分散了主Redis的压力。
这里对Redis的访问压力有好转,但不是长久之计,好比遇到举办活动, 数据量增大时,仍是会有性能的风险。
最终采用的方法是综合方案二和三,以下图所示:
这种方法对现有的服务改动最小,能够有效缓解redis压力的问题
producer端和consumer端的twemproxy使用的hash算法要求一致,否则找不到key了。
若是把方案一也加进来,会比较复杂,暂时用不到。