在做缓存技术选型的时候,Redis和Memcached几乎是被拿来比较最多的两个方案。有些人觉得Memcached更轻量、更纯粹,也有人认为Redis功能全面,一站式解决所有问题。实际上两者没有绝对的好坏,关键在于你的业务场景需要什么。本文将从底层实现、功能特性、性能表现等多个角度做一次系统对比,最后给出具体场景下的选型建议。

一、架构设计与线程模型对比
Memcached采用多线程架构,主线程负责监听端口和接收连接,工作线程负责处理具体的读写请求。它的设计哲学非常简单:只做内存缓存这一件事,不支持复杂的数据操作。这种简单带来的好处是行为可预测,运维负担小,坏处是功能受限,只能存取字符串类型的值。
Redis的核心是单线程事件循环模型(网络IO和命令执行在6.0之前是单线程的,6.0之后引入了多线程IO但命令执行仍然串行)。很多人担心单线程会成为瓶颈,但实际上内存操作本身极快,单线程反而避免了锁竞争和上下文切换的开销,同时保证了每个命令的原子性,这也是Redis能实现Lua脚本、事务等特性的基础。
从吞吐量上看,两者在简单get/set压测中都能达到每秒十万级别的请求量。Memcached在多核利用上略有优势,尤其是value较大(比如100KB以上)时表现更稳;而Redis在小数据包、高并发连接数场景下表现同样出色,且借助pipelining可以进一步提升吞吐。
二、数据结构与功能特性差异
这是两者区别最大的地方。Memcached只支持字符串类型的key-value,值最大默认1MB(可以通过配置调整)。Redis则提供了五种基础数据结构外加更多扩展类型:
- String:字符串、数值,支持原子自增自减
- Hash:适合存储对象的字段,可以单独读写某个属性
- List:双向链表,可以做简单的消息队列
- Set:无序集合,支持交并差集运算
- ZSet:有序集合,天然适合排行榜场景
举个例子,实现一个文章点赞计数,用Memcached只能整体读出、修改、写回,存在并发覆盖问题;用Redis一行命令就搞定:
import redis
r = redis.Redis(host='127.0.0.1', port=6379)
# 原子自增,并发安全
count = r.incr('article:1001:likes')
print(f'当前点赞数: {count}')
# 设置过期时间
r.expire('article:1001:likes', 86400)
此外Redis还支持发布订阅、Lua脚本、事务、地理坐标(GEO)、位图(Bitmap)、HyperLogLog等能力。这些功能让Redis从单纯的缓存进化成了一个数据结构服务器,很多场景下甚至可以直接承担一部分存储职责。
三、持久化与高可用能力
Memcached不支持持久化,重启后所有数据丢失,也不提供原生的复制和故障转移机制。如果需要高可用,必须借助客户端一致性哈希分片或者第三方方案,运维复杂度反而上去了。
Redis提供了两种持久化方式:RDB定时快照和AOF追加日志,两者可以混合使用。RDB文件紧凑,恢复速度快,但可能丢失最后一次快照之后的数据;AOF可以配置成每秒刷盘甚至每次写入都落盘,数据安全性更高,但文件更大、恢复更慢。合理配置后,Redis在重启后可以恢复绝大部分数据。
高可用方面,Redis有完整的解决方案。主从复制实现数据冗余和读写分离;哨兵(Sentinel)负责监控主节点健康状态并自动完成故障切换;Cluster集群模式则通过16384个哈希槽实现数据分片,支持水平扩容。这一整套能力是Memcached完全不具备的。
# Redis主从配置示例,在从节点配置文件中添加 replicaof 192.168.1.100 6379 # 哨兵配置示例 sentinel monitor mymaster 192.168.1.100 6379 2 sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 60000
四、内存管理机制对比
Memcached采用Slab Allocation机制,内存被划分为不同规格的Slab Class,每种规格存放固定大小的chunk。这种分配方式几乎不会产生内存碎片,但如果value大小和chunk规格不匹配,会造成空间浪费。举个例子,如果某个class的chunk是104字节,存80字节的数据就浪费了24字节。
Redis早期使用 jemalloc 作为内存分配器(默认),通过内部多种编码格式优化小对象的存储,比如小Hash会压缩成ziplist存储。Redis的淘汰策略也更灵活,支持noeviction、allkeys-lru、volatile-lru、allkeys-lfu等多种策略,可以根据业务自由选择。Memcached则只有LRU淘汰,且按Slab Class内部进行,粒度较粗。
需要注意的一点是,Redis删除key时并不立即释放内存给操作系统,而是交给后台异步处理,所以可能出现RSS内存只增不减的现象,这在容器化部署时需要关注内存限制的配置。
五、典型场景选型建议
综合以上对比,可以给出如下选择思路。如果你要构建新的系统,或者业务涉及复杂的数据结构需求,直接选Redis,它几乎覆盖了Memcached的所有能力。具体场景包括:
- 用户会话存储:需要持久化和故障转移,Redis明显更合适
- 排行榜、计数器:ZSet和INCR是天然方案
- 分布式锁:SETNX加过期时间是标准做法
- 简单消息队列:List或Stream可以胜任低要求场景
- 热点数据缓存:String或Hash存储序列化后的对象
Memcached的适用场景则相对窄一些:纯KV缓存、value较大且以读为主、团队已有成熟的Memcached运维体系、或者需要多线程利用多核处理大value读写的场景。它的简单在这个时代依然有价值,只是对于大多数新项目来说,Redis的生态和功能优势太明显了。
六、总结
Redis和Memcached的对比本质上是一场功能丰富性与极致简单性之间的权衡。Memcached证明了做好一件事的价值,而Redis则用丰富的数据结构和完善的可用性方案赢得了更广泛的社区支持。当前的技术趋势下,Redis已经成为事实上的主流选择,除非有非常特殊的理由,否则新项目选Redis基本不会错。但理解两者的差异,能帮助你在面试和架构评审中说清楚每个技术决策背后的依据。