Redis和Memcached的恩怨情仇

vincent0809
发布于 2022-4-15 14:24
浏览
0收藏

近些年来各路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的恩怨情仇-鸿蒙开发者社区

 

二、Redis与Memcached对比

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机制:

 Redis和Memcached的恩怨情仇-鸿蒙开发者社区

 

像一般的内存池一样,从操作系统分配到一大块内存后,为了方便管理,把这大块内存划分为各种大小的 chunk,chunk的大小按照一定比例逐渐递增,如下图所示:

Redis和Memcached的恩怨情仇-鸿蒙开发者社区

 

Slab Allocation的主要术语:

 

Page :分配给Slab的内存空间,默认是1MB。分配给Slab之后根据slab的大小切分成chunk。(这也是为什么默认value不能超过1M的原因,不过可以调整。)

 

Chunk:用于缓存记录的内存空间,是存储的最小单位。

 

Slab Class:特定大小的chunk的组。

 

(2) 数据是如何存储的


Memcached根据收到的数据的大小,选择最适合数据大小的slab。Memcached中保存着slab内空闲chunk的列表,根据该列表选择chunk,然后将数据缓存于其中。

Redis和Memcached的恩怨情仇-鸿蒙开发者社区

 

(3) slab带来的挑战


由于分配的是特定长度的内存,因此无法有效利用分配的内存。例如,将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了;所以需注重value的设计。

Redis和Memcached的恩怨情仇-鸿蒙开发者社区

 

2、Redis内存碎片是什么


(1) 定义

Redis和Memcached的恩怨情仇-鸿蒙开发者社区

 

其中,used_memory_rss表示 操作系统角度Redis占用的物理内存大小;used_memory表示Redis进程以及存储所有数据占用的大小。

 

(2) 碎片原理


Redis默认的内存分配器采用jemalloc, 可选的分配器还有:glibc、tcmalloc。内存分配器为了更好地管理和重复利用内存, 分配内存策略一般采用固定范围的内存块进行分配。例如jemalloc在64位系统中将内存空间划分为:小、 大、 巨大三个范围。每个范围内又划分为多个小的内存块单位,如下所示:

Redis和Memcached的恩怨情仇-鸿蒙开发者社区

 

比如当保存5KB对象时jemalloc可能会采用8KB的块存储, 而剩下的3KB空间变为了内存碎片不能再分配给其他对象存储。

 

jemalloc针对碎片化问题专门做了优化(Redis 4.0版本加入了碎片清理功能), 一般不会存在过度碎片化的问题, 正常的碎片率( mem_fragmentation_ratio) 在1.03左右。

 

内存碎片过大的可能原因:

 

频繁做更新操作, 例如频繁对已存在的键执行append、 setrange等更新操作。大量过期键删除, 键对象过期删除后, 释放的空间无法得到充分利用, 导致碎片率上升。

 

四、典型应用架构


下面是一些Memcached的典型用法

 

1、Memcached的双活用法


Memcached本身不支持持久化和数据迁移,而其对QPS和热点key等支持较好,所以在用法上可以做些改变;

 

即一个逻辑机房对应两个一模一样的集群(即双活),利用双活集群来保证可用性;如下:

Redis和Memcached的恩怨情仇-鸿蒙开发者社区

 

Redis和Memcached的恩怨情仇-鸿蒙开发者社区

 

双活模式下,即使其中一活的节点宕机,在另外一活和回写机制的保证下,也可以保证整个Memcached的可用性;并且在此基础上,又演变出双机房单活和多活模式。

 

目前,线上单活最高QPS 6000w+,单活最大容量40T,单活单key最大512M,而且线上一些小文件对象也有用到Memcached缓存。

 

2、多级缓存


Memcached挡在Redis的前面,利用各自优势,形成多级缓存,满足业务需求的同时承担更多的读请求,某个计数应用架构如下:

 

相比纯Redis,可以支撑更大的读请求。

Redis和Memcached的恩怨情仇-鸿蒙开发者社区

 

五、总结


Redis和Memcached各有千秋,对于一些超高QPS(例如千万级别)、超大big key、以及存在较高热点的业务,在memcahced满足相关功能需求的情况下,建议大家使用Memcached;否则建议大家使用Redis。

 

文章转自公众号:Redis开发运维实战

分类
标签
收藏
回复
举报
回复
    相关推荐