面试题:“选redis还是memcache”

5,002 阅读6分钟

有时,面试官并没有对自己的提问,预设任何答案,只要候选人的思路是清晰的,逻辑是自洽的,即使给出的未必是最优的方案,也是能让人眼前一亮。做技术方案,技术选型的时候,一定是针对业务需求来折衷的。

选型考虑因素:

  • 是否需要复杂的数据结构选择?若是则请使用Redis作为存储,否则Redis及MC都可以考虑。若只有简单的get/set请求,且需要较高的性能需求,可以使用MC代替Redis。
  • 是否需要进行数据持久化存储,数据不允许丢失?若是,则请使用Redis进行数据存储,并在申请服务的时候注明需要作为存储而非缓存,需要开启持久化存储及数据定期备份。
  • 是否需要Master/Slave机制保证服务的HA?若是,则请使用Redis进行数据存储,平台会默认为所有的Redis服务部署Slave从库,以保证Master/Slave机制。
  • 是否是计数服务?若是请使用Redis作为存储,性能保证的同时开启aof保证数据不会丢失。
  • 是否需要多分片进行分布式部署?若是则请使用Twemproxy进行服务部署,使用Redis作为存储时需考虑命令的支持程度,部分Redis的命令在Twemproxy上并不支持;否则请使用单机的Redis或MC作为存储,或则自行在客户端进行分片操作。平台使用Twemproxy+MC部署的时候,会采用自动剔除异常服务实例的方式以保证整体服务的质量,剔除异常服务实例后,部分请求将会出现MISS;使用Twemproxy+Redis部署的时候会通过Redis的Master/Slave机制,在Master异常的是有自动提升Slave,以保证服务的质量。

典型使用场景:

Memcached:

  • Session存储:全站Session业务,移动WAP Session
  • 移动MAPI业务

Redis:

  • 计数服务
  • 队列服务:消息队列
  • 专场列表数据(hashset,通过hashset存储某个专场下面的所有商品)
  • 集合去重:PMS用来发送短信服务的Redis,使用多个集合去重以防止同一用户收到多条短信,造成骚扰。

Memcached

Memcached的优点

  • Memcached可以利用多核优势,单实例吞吐量极高,可以达到几十万QPS(取决于key、value的字节大小以及服务器硬件性能,日常环境中QPS高峰大约在4-6w左右)。适用于最大程度扛量。
  • 支持直接配置为session handle。
  • 坑少。

Memcached的局限性:

  • 只支持简单的key/value数据结构,不像Redis可以支持丰富的数据类型。
  • 无法进行持久化,数据不能备份,只能用于缓存使用,且重启后数据全部丢失。
  • 无法进行数据同步,不能将MC中的数据迁移到其他MC实例中。
  • Memcached内存分配采用Slab Allocation机制管理内存,value大小分布差异较大时会造成内存利用率降低,并引发低利用率时依然出现踢出等问题。需要用户注重value设计。

Redis

Redis的优点:

  • 支持多种数据结构,如 string(字符串)、 list(双向链表)、dict(hash表)、set(集合)、zset(排序set)、hyperloglog(基数估算)
  • 支持持久化操作,可以进行aof及rdb数据持久化到磁盘,从而进行数据备份或数据恢复等操作,较好的防止数据丢失的手段。
  • 支持通过Replication进行数据复制,通过master-slave机制,可以实时进行数据的同步复制,支持多级复制和增量复制,master-slave机制是Redis进行HA的重要手段。
  • 单线程请求,所有命令串行执行,并发情况下不需要考虑数据一致性问题。
  • 支持pub/sub消息订阅机制,可以用来进行消息订阅与通知。
  • 支持简单的事务需求,但业界使用场景很少,并不成熟。

Redis的局限性:

  • Redis只能使用单线程,性能受限于CPU性能,故单实例CPU最高才可能达到5-6wQPS每秒(取决于数据结构,数据大小以及服务器硬件性能,日常环境中QPS高峰大约在1-2w左右)。
  • 支持简单的事务需求,但业界使用场景很少,并不成熟,既是优点也是缺点。
  • Redis在string类型上会消耗较多内存,可以使用dict(hash表)压缩存储以降低内存耗用。

Twemproxy

Twemproxy分布式方案的优点:

  • 简单的分布式解决方案,业务方仅仅使用一个IP/PORT的映射即可(线上使用LVS+VIP+VPORT的方式部署),所有的分片数据存取都通过Twemproxy内部进行。
  • Redis和Memcached都可以使用Twemproxy作为自己的分布式解决方案。
  • 支持多种hash算法,较少的性能损失。
  • 可以通过扩展Twemproxy来解决中间层单点性能低以及HA的问题(线上业务通常使用5-10个Twemproxy,通过LVS进行负载均衡和故障转移)
  • Twemproxy内部支持简单的后端存储故障转移方案,比如后端MC实例down,则可以将路由到该MC的请求转移到其他MC实例上去。内部定制版本的Twemproxy,通过与Sentinel集群结合,支持Redis主从方案的故障转移,若Redis master down,则将请求路由到slave上。
  • 可以简单方便的进行后端服务的迁移、扩容等操作,不再依赖与DNS或服务配置,所有的配置变更都可以在LVS及Twemproxy上完成,对服务是透明的,业务无需关心,方便运维。

Twemproxy分布式方案的局限性:

  • 使用Redis作为后端存储时,很多原生的Redis命令请求会受到限制,Twemproxy本身并不支持。
  • Twemproxy为中间层解决方案,增加一层会导致服务请求延时增加,且Twemproxy作为中间层本身可能成为服务的瓶颈,比如CPU或流量问题,当然可以通过增加Twemproxy实例的方式解决,但响应的增加了服务器的投入成本。
  • 服务部署的难度增加,管理成本和复杂度增加,需要有快速简单的自动化服务部署及管理方案,对运维人员的要求增大。
  • Twemproxy分布式中间层多节点需要LVS的支持,LVS本身的性能限制可能造成服务瓶颈,之前发生过一次LVS网卡丢包的问题,之后已经进行较大规模的优化和拆分。