缓存数据库在现代系统架构中愈来愈成为标准配置之一,特别是随着微服务架构的流行,微服务无状态改造要求状态外置,外置的状态就须要存储到外部缓存服务中。Redis是当前主流的缓存数据库实现,本文介绍Redis基本概念与最佳实践。html
Redis是一个使用ANSI C编写的开源、支持网络、基于内存、可选持久性的键值对存储数据库。从2015年6月开始,Redis的开发由Redis Labs赞助,而2013年5月至2015年6月期间,其开发由Pivotal赞助。在2013年5月以前,其开发由VMware赞助。根据月度排行网站DB-Engines.com的数据,Redis是最流行的键值对存储数据库。mysql
Redis是单线程模式,由于Redis设计理念是不消耗CPU,且单线程的结合异步IO处理效率也很高,当前Redis单实例能够达到10万QPS。通常的应用场景,使用单机或主备(高可用)便可知足要求。git
可是现在应用程序愈来愈依赖Redis,对Redis的要求愈来愈高:访问低时延(<5ms)、高QPS(百万QPS)、高吞吐量(百MB/s),从而致使不少场景下,单CPU没法知足需求。所以多Redis进程组成的Redis集群是高性能缓存服务的一种解决方法。
在集群模式之下,因为应用程序特征,存在“热Key”现象,热Key会致使集群下面的Redis使用不均衡,热Key命中的实例很繁忙,其余实例空闲。解决热Key的一般作法有两个:一个是在Redis集群角度,提供读写分离特性,经过多个Redis实例分担负载,固然读写分离自己是一个复制集群,如何减小实例间数据复制时延以及复制时对主实例的消耗是读写分离模式设计的关键;另外一个方法是在应用程序内部使用内存作一级缓存,使用Redis作二级缓存。github
Redis官方版本3.0才支持集群模式,在此以前,有很多Redis集群方案,主要实现思路都是在Redis实例之上增长一个Proxy,由Proxy负责分区转发,同时Redis实例的状态由哨兵监控,哨兵将状态写入到分布式配置中心(ZK/ETCD),Proxy经过配置中心刷新Redis实例路由信息。
在开源领域承认度较高的Proxy集群实现是Codis,下图是Codis的架构。sql
Redis3.0版本支持集群模式,与上面的带Proxy集群方式不同,Redis官方提供的集群实现,在Server端是没有Proxy的,Proxy路由的功能,由客户端SDK来实现。为了与Proxy集群区分,Redis官方的集群称为原生集群。数据库
Redis集群节点之间通讯机制为 Redis Cluster Bus,基于Gossip协议实现。缓存
Redis客户端经过CLUSTER相关命令获取集群配置信息,客户端与节点之间经过MOVED/ASK来协调Key所属的槽位变动。服务器
原生集群与Proxy集群相比较,没有Proxy层以后,水平扩展能力更好,官方宣传支持1000节点。固然没有了Proxy层,流量、路由管控会更麻烦一些。网络
原生集群的槽位Slot空间总共为16383个,所以理论上集群节点数量是不能超过16383个。session
选择Redis规格时候,须要评估业务模型,避免选择的规格与实际业务模型不匹配。
根据Key写入数量/频度,TTL时常,是否显示删除判断容量增加状况,避免容量满。
当Redis内存容量满时,再次写入则会触发淘汰Key操做。同时因为内存满,可能致使系统资源不足,淘汰Key的操做会很耗时,从而致使写入超时。
数据须要落盘的话,须要确认 appendfsync=everysec
若是开启,底下磁盘是不是SSD;不然在高QPS写的场景,若是不是SSD盘,可能会致使应用访问Redis时延增长,极端状况会访问超时。
若是数据能够重生成,则不须要迁移数据。
若是数据不能重生成,那么意味着须要迁移数据。当前并无Redis在线迁移的工具或服务(DRS服务对Redis支持还不完善),所以须要业务代码配合完成迁移,根据业务状况讨论迁移方案。
典型的方法有:
QPS是选择Redis规格的主要依据之一,有的场景是数据量很小,QPS很高,因为主备版本的最大QPS有限,若是须要的QPS超过了主备版本的QPS最大值,那么也得上集群版本。
内存很小,QPS很高的场景,也是小规格集群的主要场景之一。
QPS指标须要区分读/写,写QPS很高的话要注意 AOF REWRITE,在执行 AOF REWRITE 时再写入的话,时延会变高,极端状况下会致使访问超时。
参考链接
根据要求的并发链接数选定对应的规格。若是是短连接方式访问,要特别注意。
一些场景下如MSET、MGET等消耗CPU的命令较多,评估时候必定要考虑CPU算力是否足够,有时候内存足够了可是CPU不足,致使Redis CPU繁忙。这种状况是小内存规格集群的典型使用场景。
可能有一些Key的TTL设置的很长(如一个月),且没有主动删除机制,那么就可能会致使内存满,从而触发Key淘汰策略,这时候再写入可能会超时。
在QPS很高的场景下,使用Pipeline相比较单个Key操做,效率和性能都有很大提高。可是须要限定Pipeline中的命令数量,当前Codis Proxy默认的 session_max_pipeline=10000
,建议不要超过此值。
同时还须要评估一次Pipeline返回的数据量。
有一些云厂商(如阿里云)支持Redis集群有多DB特性,不一样DB中的Key值能够相同。Codis集群、Redis原生集群是不支持多DB的。
短链接须要特别关注链接数这个指标。若是是短连接,须要关注内存参数本地端口、最大句柄数等值是否调优。
Redis做为主流缓存服务,各个云厂家都提供了托管式的Redis缓存服务,不过各个厂家实现上并不彻底一致,在此列出各个厂家主要实现原理以供选型参考。
AWS提供Redis集群托管服务。用户指定flavor机器(计算、存储、网络),AWS帮助客户讲Redis集群部署到服务器上。
同时用户建立实例时候能够指定节点数量、副本数量、槽位与节点分配方式。
阿里云提供Proxy模式的集群,Proxy自研。
腾讯里云提供Proxy模式的集群,Proxy自研。同时腾讯云提供两种Redis引擎:开源Redis,自研CKV。
华为云提供两种Proxy模式的集群:Codis与Redis原生集群。原生集群不带LB与Proxy。
更多云最佳实践 https://best.practices.cloud