Redis和Memcached的恩怨情仇
近些年来各路KV缓存强势崛起,尤其Redis一骑绝尘,很多新进的程序员可能都没听说过Memcached,还有很多老程序员觉得Memcached不行:功能少,不持久化,高可用差,但事实并非如此,本文将对Redis和Memcached进行对比看看Memcached是不是真的”一无是处“了
下面我们来看一个场景
业务同学A:你好,我申请了一个20G,100000 QPS的Memcached,麻烦审批下?
业务同学B:hello,请问什么时候用Redis?什么时候用Memcached?
业务同学C: Memcached支持数据迁移和持久化吗?
业务同学D:我这里可能会有一些热点和大key的需求,Redis还是Memcached有什么建议吗?
......
不少同学在选型的时候会纠结,到底是选Memcached还是Redis,该考虑哪些因素?
一、考虑因素
首先我们需要知道,自己业务有哪些特点,需要考虑哪些因素?如下是在选型对比中,通常需要考虑的因素。
二、Redis与Memcached对比
1、数据类型
Redis支持丰富的数据类型,比如string、hash、list、set、zset。
Memcached只支持简单的key/value数据结构。
2、单线程/多线程/承载QPS
Redis是单线程请求,所有命令串行执行,并发情况下不需要考虑数据一致性问题;性能受限于CPU,单实例QPS在4-6w。
Memcached是多线程,可以利用多核优势,单实例在正常情况下,可以达到写入60-80w qps,读80-100w qps。
3、持久化/数据迁移
Redis支持持久化操作,可以进行aof及rdb数据持久化到磁盘。
Memcached无法进行持久化,数据不能备份,只能用于缓存使用,且重启后数据全部丢失。
4、对热点、bigkey支持的友好度
Redis的big key与热key类操作,如果qps较高则容易造成Redis阻塞,影响整体请求。
Memcached因为是多线程,与Redis相比,在big key与热key类操作上支持较好。
5、高可用/HA
Redis支持通过Replication进行数据复制,通过master-slave机制,可以实时进行数据的同步复制,
支持多级复制和增量复制,master-slave机制是Redis进行HA的重要手段。
Memcached无法进行数据同步,不能将实例中的数据迁移到其他MC实例中。
6、发布订阅机制
Redis支持pub/sub消息订阅机制,可以用来进行消息订阅与通知。
Memcached不支持发布订阅。
7、周边支持
Redis相对Memcached,周边工具支持较好,比如迁移、数据分析等方便,目前KCC支持全量和指定前缀等数据分析和删除功能。
Memcched周边支持较少,且原生不支持key分析等操作,目前KCC自研实现针对中小memached集群的key分析和指定前缀数据删除功能。
注:KCC是公司Redis、Memcached、ElasticSearch、Pika管控平台,目前管理70w+Cache实例,3000+ElasticSearch实例的智能化运维。
三、常见核心问题
1、Memcached内存分配原理
(1) Slab Allocator的机制
Memcached默认情况下采用了名为Slab Allocator的机制分配、管理内存。
slab机制相当于内存池机制, 实现从操作系统分配一大块内存, 然后 Memcached 自己管理这块内存, 负责分配与回收。
咱们深入浅出,官方原文这样描述slab机制:
With slab allocation, memory is reserved in blocks of 1MB. The slab is divided up into a number of blocks of equal size. When you
try to store a value into the cache, Memcached checks the size of the value that you are adding to the cache and determines which
slab contains the right size allocation for the item. If a slab with the item size already exists, the item is written to the block
within the slab.
像一般的内存池一样,从操作系统分配到一大块内存后,为了方便管理,把这大块内存划分为各种大小的 chunk,chunk的大小按照一定比例逐渐递增,如下图所示:
Slab Allocation的主要术语:
Page :分配给Slab的内存空间,默认是1MB。分配给Slab之后根据slab的大小切分成chunk。(这也是为什么默认value不能超过1M的原因,不过可以调整。)
Chunk:用于缓存记录的内存空间,是存储的最小单位。
Slab Class:特定大小的chunk的组。
(2) 数据是如何存储的
Memcached根据收到的数据的大小,选择最适合数据大小的slab。Memcached中保存着slab内空闲chunk的列表,根据该列表选择chunk,然后将数据缓存于其中。
(3) slab带来的挑战
由于分配的是特定长度的内存,因此无法有效利用分配的内存。例如,将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了;所以需注重value的设计。
2、Redis内存碎片是什么
(1) 定义
其中,used_memory_rss表示 操作系统角度Redis占用的物理内存大小;used_memory表示Redis进程以及存储所有数据占用的大小。
(2) 碎片原理
Redis默认的内存分配器采用jemalloc, 可选的分配器还有:glibc、tcmalloc。内存分配器为了更好地管理和重复利用内存, 分配内存策略一般采用固定范围的内存块进行分配。例如jemalloc在64位系统中将内存空间划分为:小、 大、 巨大三个范围。每个范围内又划分为多个小的内存块单位,如下所示:
比如当保存5KB对象时jemalloc可能会采用8KB的块存储, 而剩下的3KB空间变为了内存碎片不能再分配给其他对象存储。
jemalloc针对碎片化问题专门做了优化(Redis 4.0版本加入了碎片清理功能), 一般不会存在过度碎片化的问题, 正常的碎片率( mem_fragmentation_ratio) 在1.03左右。
内存碎片过大的可能原因:
频繁做更新操作, 例如频繁对已存在的键执行append、 setrange等更新操作。大量过期键删除, 键对象过期删除后, 释放的空间无法得到充分利用, 导致碎片率上升。
四、典型应用架构
下面是一些Memcached的典型用法
1、Memcached的双活用法
Memcached本身不支持持久化和数据迁移,而其对QPS和热点key等支持较好,所以在用法上可以做些改变;
即一个逻辑机房对应两个一模一样的集群(即双活),利用双活集群来保证可用性;如下:
双活模式下,即使其中一活的节点宕机,在另外一活和回写机制的保证下,也可以保证整个Memcached的可用性;并且在此基础上,又演变出双机房单活和多活模式。
目前,线上单活最高QPS 6000w+,单活最大容量40T,单活单key最大512M,而且线上一些小文件对象也有用到Memcached缓存。
2、多级缓存
Memcached挡在Redis的前面,利用各自优势,形成多级缓存,满足业务需求的同时承担更多的读请求,某个计数应用架构如下:
相比纯Redis,可以支撑更大的读请求。
五、总结
Redis和Memcached各有千秋,对于一些超高QPS(例如千万级别)、超大big key、以及存在较高热点的业务,在memcahced满足相关功能需求的情况下,建议大家使用Memcached;否则建议大家使用Redis。
欢迎订阅我的公众号:关注Redis开发运维实战相关问题,干掉所有的坑。
招聘广告:长期招聘Redis开发运维工程师、KV存储开发工程师、ElasticSearch工程师