集中式缓存Redis

2024-08-16

47
0

3.4.1 Memcached协议

Memcached 是一个高性能的分布式内存缓存系统,主要用于加速动态 Web 应用程序通过减轻数据库负载。它通过在 RAM(随机存取存储器)中缓存数据和对象来减少对数据库或其他较慢存储系统的重复访问。下面是关于 Memcached 的一些关键点:

用途

  • 性能优化:通过将经常访问的数据存储在内存中,减少对后端系统的请求,如数据库,从而提高应用程序的速度。

  • 负载均衡:通过减少数据库查询次数来平衡服务器负载。

技术特点

  • 键值存储:Memcached 使用简单的键值存储模型,其中数据以键值对的形式存储和检索。

  • 分布式:可以部署在多台服务器上,实现数据的分布式存储。

  • 无状态服务:Memcached 服务器是无状态的,每个实例都可以独立运行,不需要了解其他实例的状态。

架构

  • 客户端-服务器模型:Memcached 服务器负责存储数据,而客户端应用程序则通过网络连接与这些服务器进行通信。

协议

  • ASCII 协议:最初使用的协议是基于文本的简单 ASCII 协议。

  • 二进制协议:后来引入了更高效的二进制协议,提供更好的性能。

数据结构

  • 键值对:数据以字符串形式的键与任意类型的数据(值)关联起来进行存储。

  • 过期时间:可以为缓存项设置过期时间,过期后数据会被自动删除,以保持内存的有效利用。

可扩展性

  • 水平扩展:可以通过添加更多的服务器节点来扩展 Memcached 集群,实现线性的性能增长。

  • 自动分片:数据自动分布在集群中的多个服务器上,无需手动管理。

缓存机制

  • LRU(最近最少使用)算法:当内存空间不足时,Memcached 使用 LRU 算法来决定哪些缓存项应该被替换掉。

支持的语言

  • 广泛支持:Memcached 提供了许多编程语言的客户端库,包括 PHP、Python、Java 和 C++ 等。

安装与配置

  • 安装:可以通过包管理器或从源代码编译安装 Memcached。

  • 配置:可以通过命令行参数或配置文件进行基本配置,例如监听端口、最大内存限制等。

Memcached是一个开源的高性能分布式内存缓存系统,用于加速动态Web应用。它通过将数据库查询结果、API调用结果或其他数据缓存到内存中,减少对数据库的访问频率,从而提高应用的响应速度。以下是Memcached缓存中间件及其协议详解:

Memcached缓存中间件详解

  • 工作原理:Memcached的核心是一个Key-Value存储系统,支持set、get、delete、incr/decr等基本操作。缓存机制采用LRU(Least Recently Used,最近最少使用)算法管理缓存数据。

  • 架构:由多个缓存节点和客户端组成,每个缓存节点独立运行,负责处理客户端的请求。客户端通过一致性哈希算法将数据分布到不同的缓存节点上。

  • 安装与配置:安装方法因操作系统而异,配置文件通常位于/etc/memcached.conf,包括指定内存分配大小、监听端口等。

  • 使用方法:支持基本操作如set、get、delete,以及进阶操作如设置过期时间、批量操作等。Memcached提供了丰富的API,易于集成到各种编程语言中。

  • 应用场景:广泛应用于缓存数据库查询结果、API调用结果等,以提高应用性能和响应速度。

Memcached协议详解

  • 文本协议:Memcached使用简单的文本协议进行通信,命令以\r\n结尾,数据可以用\r、\n或\r\n表示数据部分的结束。

  • 二进制协议:二进制协议是在v1.4之后才支持的,具有更低的性能延迟和更好的可扩展性。协议包由包头、命令行的额外数据、key和value组成。

通过上述详解,可以看出Memcached不仅是一个高性能的缓存系统,其简单的协议和灵活的配置也使其易于在各种应用场景中使用。

Memcached 是一个高性能的、多线程的、基于事件处理机制的键值 (key-value) 缓存系统。它被设计用于加速动态 Web 应用程序,通过将数据缓存在内存中来减少对后端数据库的请求次数。以下是关于 Memcached 的详细介绍:

性能特点

  • 高性能:由于 Memcached 将数据存储在内存中,因此具有非常快的访问速度。

  • 多线程:Memcached 采用多线程模型来处理并发的客户端请求,这使得它可以有效地利用多核处理器的优势。

  • 基于事件处理机制:Memcached 使用事件驱动架构来管理网络连接和内部数据操作,这种架构非常适合处理大量并发连接。

架构与工作原理

  • 客户端-服务器模型:Memcached 通常作为服务器组件运行,客户端应用程序通过网络与之通信。

  • 键值存储:数据以键值对的形式存储。每个键是一个字符串,与一个值相关联,这个值可以是任何类型的数据,例如字符串、数字或序列化的对象。

  • 分布式缓存:Memcached 支持水平扩展,即可以通过添加更多的 Memcached 服务器来扩展缓存容量。

  • 自动分片:数据自动分布在集群中的多个服务器上,不需要手动管理数据的分布。

  • 无状态服务:每个 Memcached 服务器都是无状态的,这意味着它们不需要了解其他服务器的状态或数据,这简化了集群的管理。

协议

  • ASCII 协议:Memcached 最初使用的协议是基于文本的简单 ASCII 协议,它易于理解和调试。

  • 二进制协议:为了提高性能,Memcached 后来引入了更高效的二进制协议,它减少了网络传输的开销。

命令集

Memcached 支持多种命令,例如:

  • get: 获取一个或多个键对应的值。

  • set: 设置一个键的值。

  • add: 如果键不存在,则设置一个键的值。

  • replace: 如果键已存在,则替换键的值。

  • delete: 删除一个键。

  • incr/decr: 对数值类型的键进行递增或递减操作。

缓存机制

  • 过期时间:可以为每个缓存项设置过期时间,过期后数据将被自动删除。

  • LRU 算法:当内存空间不足时,Memcached 使用 LRU(最近最少使用)算法来决定哪些缓存项应该被替换掉。

安装与配置

  • 安装:可以通过包管理器或从源代码编译安装 Memcached。

  • 配置:可以通过命令行参数或配置文件进行基本配置,例如监听端口、最大内存限制等。

支持的语言

  • 广泛的客户端库:Memcached 提供了许多编程语言的客户端库,包括 PHP、Python、Java 和 C++ 等。

使用场景

  • 数据库查询结果缓存:存储经常查询的结果,减少数据库访问。

  • 会话数据存储:存储用户的会话数据。

  • 临时数据存储:存储一些临时数据,如验证码等。

如果您需要更具体的配置或使用方面的指导,请随时告诉我!

[](@replace=0### Memcached协议详解

Memcached使用两种协议进行通信:文本协议二进制协议

文本协议Memcached的文本协议是一种简单、直观的协议,用于与Memcached服务器进行通信。该协议包括以下部分:

  1. 命令:如`<a>Memcached的文本协议是一种简单、直观的协议,用于与Memcached服务器进行通信。该协议包括以下部分:

  2. 命令:如setgetdeleteincrdecr等,用于执行不同的操作。

  3. 键(Key):用于标识存储在Memcached中的数据。

  4. 值(Value):与键关联的数据。

  5. 过期时间(Expiration Time):可选参数,用于指定数据在Memcached中的有效时间。

  6. 分隔符:用于分隔命令、键、值和其他参数。

文本协议的命令格式如下:

<command> <key> <flags> <expiration time> <bytes> [\r\n]
<value> [\r\n]

例如,以下命令将一个键值对存储到Memcached中:

set my_key 0 0 5\r\n
hello\r\n

以下命令从Memcached中获取键为my_key的值:

get my_key\r\n

二进制协议

Memcached的二进制协议是在Memcached 1.4版本中引入的,旨在提高性能和可扩展性。二进制协议使用二进制格式传输数据,减少了文本协议中的字符编码和解码的开销。

二进制协议的结构如下:

<binary header> <command> <key> <flags> <expiration time> <bytes> <value>

其中,<binary header>包含了一些元数据,如协议版本、命令类型、键的长度等。

二进制协议的命令格式如下:

<command> <key> <flags> <expiration time> <bytes> <value>

例如,以下命令将一个键值对存储到Memcached中:

<command> <key> <flags> <expiration time> <bytes> <value>

以下命令从Memcached中获取键为my_key的值:

<command> <key> <flags> <expiration time> <bytes> <value>

Memcached与Redis的比较

  1. 功能:Redis提供了比Memcached更丰富的功能,如支持复杂的数据结构(如链表、集合、哈希表等)、事务、持久化、主从复制等。

  2. 性能:在某些情况下,Redis的性能可能优于Memcached,尤其是在处理复杂数据结构和大量数据时。

  3. 内存管理:Redis使用自己的内存管理策略,而Memcached使用Slab Allocation机制。

  4. 协议:Memcached使用文本协议和二进制协议,而Redis使用自己的协议。

  5. 安全性:Redis提供了更多的安全选项,如密码认证、SSL/TLS加密等。

  6. 社区支持:Redis和Memcached都有活跃的社区支持,但Redis的社区可能更加活跃。

总之,Redis和Memcached各有优势,选择哪一个取决于具体的应用场景和需求。

Memcached 和 Redis 都是非常流行的内存数据存储系统,但它们的设计理念和实现细节有所不同。下面是对 Memcached 协议的详细解析以及与 Redis 的比较。

Memcached 协议

Memcached 支持两种主要的网络协议:ASCII 协议和二进制协议。

ASCII 协议

  • 特点

    • 基于文本的协议,易于理解和调试。

    • 每个命令和响应都由一个换行符 (\r\n) 分隔。

  • 命令格式

    • command key [flags] [expiration_time] [bytes] [noreply]\r\n

    • get key [key ...]\r\n

    • set key flags expiration bytes [noreply]\r\n

    • add key flags expiration bytes [noreply]\r\n

    • replace key flags expiration bytes [noreply]\r\n

    • delete key [quiet]\r\n

    • incr|decr key value [expiration]\r\n

  • 响应格式

    • VALUE key flags bytes [cas]\r\n

    • END\r\n

    • NOT_STORED\r\n

    • STORED\r\n

    • EXISTS\r\n

    • DELETED\r\n

    • NOT_FOUND\r\n

    • CLIENT_ERROR message\r\n

    • SERVER_ERROR message\r\n

二进制协议

  • 特点

    • 更高效,因为它是基于二进制的,减少了网络传输的开销。

    • 支持 CAS(Compare-and-Swap)操作,可以防止缓存中的数据被并发更新。

  • 命令格式

    • 每个命令由一个固定长度的头部和一个可变长度的主体组成。

    • 头部包含命令标识符、关键字长度、额外数据长度、命令类型等信息。

    • 主体包含了实际的命令数据。

Memcached 与 Redis 的比较

数据类型

  • Memcached

    • 支持简单的键值对数据结构。

  • Redis

    • 支持多种数据类型,如字符串、列表、集合、哈希表、有序集合等。

协议

  • Memcached

    • 支持 ASCII 和二进制协议。

  • Redis

    • 使用基于文本的 Redis 协议,也称为 RESP(Redis Serialization Protocol)。

功能

  • Memcached

    • 主要用于缓存,功能相对简单。

  • Redis

    • 功能更丰富,除了缓存之外还可以作为消息队列、发布/订阅系统等。

性能

  • Memcached

    • 通常具有更高的吞吐量,特别是在读取密集的应用场景中。

  • Redis

    • 在写入密集的应用场景中表现更好,因为 Redis 支持持久化和事务。

持久化

  • Memcached

    • 不支持数据持久化,重启服务后数据会丢失。

  • Redis

    • 支持 RDB 快照和 AOF 日志两种持久化方式。

扩展性

  • Memcached

    • 支持水平扩展,可以通过添加更多的 Memcached 服务器来扩展缓存容量。

  • Redis

    • 支持主从复制和集群模式,但实现更为复杂。

其他特性

  • Memcached

    • 使用 LRU 算法来管理内存。

  • Redis

    • 支持多种内存管理策略,如 LRU、LFU(Least Frequently Used)等。

示例

以下是一个使用 ASCII 协议的 Memcached 命令示例,向 Memcached 存储一个键值对:

set test_key 0 0 5
hello

这里的命令说明如下:

  • set 表示设置命令。

  • test_key 是要设置的键。

  • 0 表示没有特殊标志。读/写速度内存使用情况磁盘 I/O 转储.伸缩性.

    请遵循站内知识共享协议,出处:http://1.13.19.192:8089/archives/ji-zhong-shi-huan-cun-redis;站点:1.13.19.192:8089

  • 0 表示该值永远不会过期。

  • 5 表示要发送的值的字节数。

  • hello 是要存储的值。

Redis 示例

Redis 使用不同的命令集,以下是一个简单的 Redis 命令示例,设置一个键值对:

SET mykey "Hello"
GET mykey

结论

Memcached 和 Redis 都是非常强大的工具,选择哪一个取决于您的具体需求。如果只需要简单的缓存功能并且对性能有极高要求,那么 Memcached 是一个不错的选择。如果需要更丰富的数据结构和更高级的功能,Redis 则更适合。

如果您需要更具体的配置或使用方面的指导,请随时告诉我!

您提供的信息非常详细,下面我将为您进行概述:读/写速度内存使用情况磁盘 I/O 转储.伸缩性.

请遵循站内知识共享协议,出处:http://1.13.19.192:8089/archives/ji-zhong-shi-huan-cun-redis;站点:1.13.19.192:8089

Memcached概述

Memcached是一个高性能的分布式内存缓存系统,旨在通过缓存数据库查询结果、API调用结果或其他数据来加速动态Web应用。它通过TCP/UDP或Unix Domain Socket与客户端通信,并默认监听11211端口。Memcached采用libev事件处理框架来处理并发请求。

Memcached支持的协议

Memcached支持两种主要的通信协议:

  1. 文本协议

    • 文本协议是Memcached最初使用的协议,也是最广泛使用的协议之一。

    • 它基于简单的文本命令和响应格式,易于理解和实现。

    • 文本协议的命令格式和协议规范在Memcached的官方文档中有详细的描述。

    • 由于文本协议的可读性和易调试性,它在开发和测试环境中非常受欢迎。

  2. 二进制协议

    • 二进制协议是在Memcached 1.4版本中引入的,旨在提供更高的性能和更紧凑的数据传输。

    • 二进制协议使用二进制格式传输数据,减少了文本协议中的字符编码和解码的开销。

    • 二进制协议具有更低的性能延迟和更好的可扩展性,因此在生产环境中通常优先选择二进制协议。

    • 二进制协议的命令格式和数据结构在Memcached的官方文档中也有详细的描述。

Memcached的工作原理

Memcached的核心是一个Key-Value存储系统,支持基本的缓存操作,如set、get、delete、incr/decr等。它采用LRU(Least Recently Used,最近最少使用)算法来管理缓存数据,确保最常用的数据保留在内存中。

Memcached的架构

Memcached由多个缓存节点和客户端组成。每个缓存节点独立运行,负责处理客户端的请求。客户端通过一致性哈希算法将数据分布到不同的缓存节点上,从而实现数据的分布式存储和访问。

Memcached的应用场景

Memcached广泛应用于缓存数据库查询结果、API调用结果、会话数据等,以提高应用性能和响应速度。它特别适用于高并发、读多写少的应用场景。

通过上述概述,可以看出Memcached不仅是一个高性能的缓存系统,其简单的协议和灵活的配置也使其易于在各种应用场景中使用。

Memcached 是一个高性能、分布式内存对象缓存系统,用于加速动态 Web 应用程序通过减轻数据库负载。它支持两种主要的网络协议:文本协议(Text Protocol)和二进制协议(Binary Protocol)。这两种协议在功能上基本相同,但在实现细节上有很大的不同。

文本协议 (Text Protocol)

  • 可读性:由于使用 ASCII 编码,文本协议的命令和响应都是可读的字符串形式,易于调试和理解。

  • 效率:文本协议在解析和序列化数据时相对低效,因为需要处理 ASCII 字符串。

  • 扩展性:对于一些较新的特性或复杂操作的支持不如二进制协议灵活。

  • 安全性:没有加密选项,所有通信都是明文传输。

二进制协议 (Binary Protocol)

  • 效率:二进制协议通过更紧凑的数据格式和更少的解析开销提高了性能。它直接使用字节表示命令和数据,减少了序列化和反序列化的开销。

  • 扩展性:支持更多的特性,如增加了一些额外的操作码来支持更复杂的操作,并且可以更容易地添加新特性。

  • 安全性:提供了加密选项,例如 TLS/SSL 加密连接,增加了数据传输的安全性。

  • 复杂性:二进制协议的实现比文本协议更为复杂,因为它涉及到更多底层细节的处理。

总结

  • 性能:二进制协议通常比文本协议更快,尤其是在高并发场景下。

  • 兼容性:大多数 Memcached 客户端都支持这两种协议,但某些老版本客户端可能只支持文本协议。

  • 开发难度:文本协议对开发者来说更加友好,而二进制协议则更适合追求极致性能的应用。

选择哪种协议取决于您的具体需求:如果您需要更好的性能和安全性,可以选择二进制协议;如果您更注重开发的便捷性和调试的容易程度,则可以考虑使用文本协议。

Memcached是一个高性能的分布式内存缓存系统,它支持两种协议:文本协议和二进制协议。这两种协议在Memcached中各有特点和适用场景。

Memcached文本协议

  • 特点:文本协议以换行表示一个请求结束,请求内部参数以空格分隔。这种协议简单易懂,易于调试和实现。

  • 优缺点

    • 优点:协议简单,易于理解和实现,适合开发和调试。

    • 缺点:由于文本协议的数据量相对较大,因此在网络传输时可能会造成一定的带宽浪费,且服务器端解析文本协议会消耗更多的CPU资源。

  • 适用场景:适合开发初期或者对协议兼容性要求较高的场景。

Memcached二进制协议

  • 特点:二进制协议以最小数据量表达所有信息,服务器解析请求时做的是数学比较而不是字符串比较,因此效率更高。

  • 优缺点

    • 优点:数据传输效率高,CPU消耗低,适合高并发场景。

    • 缺点:协议较难理解和实现,扩展性较差,一旦协议定死,难以适应不同的场景需求。

  • 适用场景:适合对性能有较高要求的场景,尤其是高并发、大数据量的应用场景。

选择建议

  • 性能要求:如果系统对性能有较高要求,尤其是在高并发环境下,推荐使用二进制协议。

  • 开发和调试:如果项目处于开发初期,或者需要频繁进行协议调试,文本协议可能更合适。

  • 兼容性:如果系统需要与多种不同的客户端和服务器兼容,文本协议可能提供更广泛的兼容性。

总的来说,Memcached的文本协议和二进制协议各有优势,选择哪种协议取决于具体的应用场景和需求。在追求高性能和低延迟的场景下,二进制协议是更优的选择;而在开发和调试阶段,或者需要考虑协议兼容性的情况下,文本协议可能更为合适。

Redis 和 Memcached 都是基于内存的数据存储系统。Memcached是高性能分布式内存缓存服务,其本质上就是一个内存key-value数据库。Redis是一个开源的key-value存储系统。与Memcached类似,Redis将大部分数据存储在内存中,支持的数据类型包括:字符串、哈希表、链表、集合、有序集合以及基于这些数据类型的相关操作。那么,Memcached与Redis有什么区别呢?

1、数据操作不同

与Memcached仅支持简单的key-value结构的数据记录不同,Redis支持的数据类型要丰富得多。Memcached基本只支持简单的key-value存储,不支持枚举,不支持持久化和复制等功能。Redis支持服务器端的数据操作相比Memcached来说,拥有更多的数据结构和并支持更丰富的数据操作,支持list、set、sorted set、hash等众多数据结构,还同时提供了持久化和复制等功能。而通常在Memcached里,使用者需要将数据拿到客户端来进行类似的修改再set回去,这大大增加了网络IO的次数和数据体积。在Redis中,这些复杂的操作通常和一般的GET/SET一样高效。所以,如果需要缓存能够支持更复杂的结构和操作, Redis会是更好的选择。

2、内存管理机制不同

在Redis中,并不是所有的数据都一直存储在内存中的。这是和Memcached相比一个最大的区别。当物理内存用完时,Redis可以将一些很久没用到的value交换到磁盘。Redis只会缓存所有的key的信息,如果Redis发现内存的使用量超过了某一个阀值,将触发swap的操作,Redis根据“swappability = age*log(size_in_memory)”计算出哪些key对应的value需要swap到磁盘。然后再将这些key对应的value持久化到磁盘中,同时在内存中清除。这种特性使得Redis可以保持超过其机器本身内存大小的数据。

而Memcached默认使用Slab Allocation机制管理内存,其主要思想是按照预先规定的大小,将分配的内存分割成特定长度的块以存储相应长度的key-value数据记录,以完全解决内存碎片问题。

从内存利用率来讲,使用简单的key-value存储的话,Memcached的内存利用率更高。而如果Redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于Memcached。

3、性能不同

由于Redis只使用单核,而Memcached可以使用多核,所以平均每一个核上Redis在存储小数据时比Memcached性能更高。而在100k以上的数据中,Memcached性能要高于Redis,虽然Redis也在存储大数据的性能上进行了优化,但是比起Memcached,还是稍有逊色。

4、集群管理不同

Memcached是全内存的数据缓冲系统,Redis虽然支持数据的持久化,但是全内存毕竟才是其高性能的本质。作为基于内存的存储系统来说,机器物理内存的大小就是系统能够容纳的最大数据量。如果需要处理的数据量超过了单台机器的物理内存大小,就需要构建分布式集群来扩展存储能力。

Memcached本身并不支持分布式,因此只能在客户端通过像一致性哈希这样的分布式算法来实现Memcached的分布式存储。相较于Memcached只能采用客户端实现分布式存储,Redis更偏向于在服务器端构建分布式存储。

小结:Redis和Memcached哪个更好?

Redis更多场景是作为Memcached的替代者来使用,当需要除key-value之外的更多数据类型支持或存储的数据不能被剔除时,使用Redis更合适。如果只做缓存的话,Memcached已经足够应付绝大部分的需求,Redis 的出现只是提供了一个更加好的选择。总的来说,根据使用者自身的需求去选择才是最合适的。

提前缓存技术,很多PHP工作者都会优先想到Reids和Memcached这两个老牌缓存组件。

有一些刚接触缓存技术的新人会认为Redis跟Memcached,只有在内存分配,工作机制上有区别而已,使用场景都是一样的,其实不然。

很多人不清楚,其实Memcached要比Redis早诞生了10年,而Redis是参照Memcached的应用场景加以改良之后,所诞生的新一代组件,所以现在的产品开发,几乎都放弃Memcached,直接选项Redis了。

1、技术选型

当我们讨论改进性能的时候,这是每次技术讨论中最常见的一个问题。每当性能需要改善时,采用缓存常常是迈出的第一步。

与此同时,选择Memcached 或者 Redis 通常是第一个需要考虑的地方。

哪个能给我们提供更佳的性能?它们的优点和缺点又是什么?

在设计任何缓存系统时,我们考虑如下几点:

读/写速度内存使用情况磁盘 I/O 转储.伸缩性.

2、相似之处

Memcached/Redis 两者都提供基于内存的、键-值数据存储,尽管Redis更准确的说是结构化数据存储。

Redis是内存中的结构化数据存储器,用于数据库、缓存、消息代理。

两者(Memcached/Redis)都属于数据管理方案中的NoSQL家族,都是基于键-值存储的。

它们都在内存中保存数据,当然使它们作为缓存层特别有用。

截至今日,Memcached提供的每项主要功能及其优势,都是Redis功能和特性的子集。

任何用例中可能使用Memcached的地方都可以对等的使用Redis(因为前面提到后,Redis就是参考Memcached诞生的新一代组件)。

它们都是闪电般快速的高速缓存组件。

但Memcached提供支持的功能只是Redis拥有功能的冰山一角。

Memcached是一个基于易失性内存的键-值存储器。

Redis一样可以做到(跟Memcached做得一样好),但是它还是一个结构化数据服务器。

3、那Memcached还有什么用?

当缓存相对较小和使用静态的数据时候,比如HTML代码片段,Memcached可能更为可取。

Memcached内部的内存管理在最简单的用例中更为有效,因为它的元数据消耗相对更少的内存资源。

当数据尺寸是动态的时候,Memcached的内存管理效率下降的很快,此时Memcached的内存会变成碎片。

而且,大的数据集经常牵扯到数据序列化,总是需要更多的空间来存储。

如果你使用Memcached,数据会随着重启动而丢失,重建缓存是个代价高昂的过程(通俗点说,就是Memcached对于频繁更新的内存,重建缓存是一个大的开销)。

Memcached比Redis更具优势的另一个场景在伸缩性。

因为Memcached是多线程的,所以你可以通过给它更多计算资源让它轻松扩展。

Redis是单线程的,可以通过集群无损水平扩展。

集群是一个有效的扩展方案,但是相对来说配置、操作复杂。

Memcached不支持复制功能(数据从一台机器自动复制到另外一台)。

Memcached 非常适合处理高流量的网站。它可以一次性读取大量的信息,并在优秀的反应时间内返回。

Redis不但能处理高流量的读,还能处理繁重的写入。

4、通俗的讲点区别

1、Redis和Memcache都是将数据存放在内存中,都是内存数据库。不过memcache还可用于缓存其他东西,例如图片、视频等等;

2、Redis不仅仅支持简单的k/v类型的数据,同时还提供listsethash等数据结构的存储;

3、虚拟内存–Redis当物理内存用完时,可以将一些很久没用到的value 交换到磁盘;

4、过期策略–memcache在set时就指定,例如set key1 0 0 8,即永不过期。Redis可以通过例如expire 设定,例如expire name 10

5、分布式–设定memcache集群,利用magent做一主多从;redis可以做一主多从。都可以一主一从;

6、存储数据安全–memcache挂掉后,数据没了;redis可以定期保存到磁盘(持久化);

7、灾难恢复–memcache挂掉后,数据不可恢复; redis数据丢失后可以通过aof恢复;

8、Redis支持数据的备份,即master-slave模式的数据备份;

9、应用场景不一样:Redis出来作为NoSQL数据库使用外,还能用做消息队列、数据堆栈和数据缓存等;Memcached适合于缓存SQL语句、数据集、用户临时性数据、延迟查询数据和session等。

5、使用场景

1、如果有持久方面的需求或对数据类型和处理有要求的应该选择redis。

2、如果简单的key/value 存储应该选择Memcached。

6、简单举个例子

在电子商务类的网站中,一般都有分类,然后还有搜索结果列表。

针对这种情况下,我们对分类的数据,可以使用Memcached,因为分类数据一般不会改变,读多写少,直接存储在Memcached中,每次查询都只需要从Memcached中获取就可以了。

那如果是缓存用户的登陆信息,减少我们业务频繁读取用户表的数据,对于这种缓存数据需要频繁读取更新的列表。

那就应该使用Redis,因为数据的读写,都是很频繁的。

7、结论

在当今这个大的开发环境下,Memcached的市场份额已经越来越低了。

Redis与Memcached相比,性能和内存使用情况相当相似。

除非你已经在Memcached上投入了大笔资金,否则向前推进使用Redis是显而易见的解决方案。

不仅Redis是更好的选择,它还支持全新类型的用例和使用模式。

下面时几个Redis可能会非常有用的一些示例应用程序:

电子商务应用:大多数的电子商务应用量级比较重,Redis可以提升你的页面加载速度。你可以存储所有的配置文件到Redis,从内存中读取这些配置信息速度会非常快速。你也可以在Redis中存储完整的页面缓存,因为它的键值容量很大。你也可以存储会话信息到Redis。物联网应用:在物联网应用中,物联网设备非常频繁的发送数据到服务器,比如每秒钟数千条。在把它们存储到任何持久性存储器之前,你可以先把这些高容量的原始数据推送到Redis。实时分析:可以在Memcached上实现一个实时的分析引擎,以数据库为后盾。但是Redis非常擅长统计列表和一系列事物。在所有的Redis功能特性中,它对键值进行排序的能力超过了Memcached,还有计算一组页面的点击次数等数据,然后将这些数字汇总进入分析系统。这些数据可通过工作人员输入到更大的分析引擎,在这些应用场合选择Redis是正确的决定之一。

最后一件事:不管你选择什么,缓存系统都不是数据库。你不能光靠缓存,系统同时需要缓存和数据库。

8、你需要注意

总体上看,Redis功能特性远优于Memcached,完全是下一代产品。

选择哪个使用似乎答案很明确。

但是必须指出,Redis的单线程设计,同时也带来了一些重要的隐患。

Redis有数据持久化功能,这个功能与Redis的单线程特性结合,就成了Redis故障的高发区域。

默认的RDB持久化会阻塞线程,使得Redis对正常请求无法响应,在高流量网站上容易出现大量请求错误。

这在系统中称为“涌现”,当然这是坏的一个。

当然后来Redis也发展出了AOF持久化方式(默认没有打开,要手工开启),一定程度上减缓了Redis的持久化问题。

Redis会fork一个子进程来单独处理持久化。

可是fork功能并非无代价,它一样有消耗内存资源,影响主程序响应请求的问题。

阻塞是Redis应用的噩梦,跟Node.js一样。

所以出现故障的时候,可以多在这个角度上分析原因,也许能很快的解决。

例如,分布式Redis多机部署,通过负载降低单机处理压力。

Redis 和 Memcached 都是基于内存的数据存储系统。Memcached是高性能分布式内存缓存服务,其本质上就是一个内存key-value数据库。Redis是一个开源的key-value存储系统。与Memcached类似,Redis将大部分数据存储在内存中,支持的数据类型包括:字符串、哈希表、链表、集合、有序集合以及基于这些数据类型的相关操作。

区别

1、Redis和Memcache都是将数据存放在内存中,都是内存数据库。不过memcache还可用于缓存其他东西,例如图片、视频等等;

2、Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,hash等数据结构的存储;

3、虚拟内存–Redis当物理内存用完时,可以将一些很久没用到的value 交换到磁盘;

4、过期策略–memcache在set时就指定,例如set key1 0 0 8,即永不过期。Redis可以通过例如expire 设定,例如expire name 10;

5、分布式–设定memcache集群,利用magent做一主多从;redis可以做一主多从。也可以一主一从;

6、存储数据安全–memcache挂掉后,数据没了;redis可以定期保存到磁盘(持久化);

7、灾难恢复–memcache挂掉后,数据不可恢复; redis数据丢失后可以通过aof恢复;

8、Redis支持数据的备份,即master-slave模式的数据备份

9、应用场景不一样:Redis出来作为NoSQL数据库使用外,还能用做消息队列、数据堆栈和数据缓存等;Memcached适合于缓存SQL语句、数据集、用户临时性数据、延迟查询数据和session等。

使用场景

1、如果有持久方面的需求或对数据类型和处理有要求的应该选择redis。 2、如果简单的key/value 存储应该选择memcached。

3.4.2 Memcached工作原理及优缺点

Memcached 多线程和状态机

网络模型

Mc 的 IO 处理线程分主线程和工作线程,每个线程各有一个 event_base,来监听网络事件。主线程负责监听及建立连接。工作线程负责对建立的连接进行网络 IO 读取、命令解析、处理及响应。

主线程

主线程在监听端口时,当有连接到来,主线程 accept 该连接,并将连接调度给工作线程。调度处理逻辑,主线程先将 fd 封装成一个 CQ_ITEM 结构,并存入新连接队列中,然后轮询一个工作线程,并通过管道向该工作线程发送通知。工作线程监听到通知后,会从新连接队列获取一个连接,然后开始从这个连接读取网络 IO 并处理,如下图所示。主线程的这个处理逻辑主要在状态机中执行,对应的连接状态为 conn_listening。

工作线程

工作线程监听到主线程的管道通知后,会从连接队列弹出一个新连接,然后就会创建一个 conn 结构体,注册该 conn 读事件,然后继续监听该连接上的 IO 事件。后续这个连接有命令进来时,工作线程会读取 client 发来的命令,进行解析并处理,最后返回响应。工作线程的主要处理逻辑也是在状态机中,一个名叫 drive_machine 的函数。

状态机

这个状态机由主线程和工作线程共享,实际是采用 switch-case 来实现的。状态机函数如下图所示,switch 连接的 state,然后根据连接的不同状态,执行不同的逻辑操作,并进行状态转换。接下来我们开始分析 Mc 的状态机。

工作线程状态事件及逻辑处理

conn_new_cmd

主线程通过调用 dispatch_conn_new,把新连接调度给工作线程后,worker 线程创建 conn 对象,这个连接初始状态就是 conn_new_cmd。除了通过新建连接进入 conn_new_cmd 状态之外,如果连接命令处理完毕,准备接受新指令时,也会将连接的状态设置为 conn_new_cmd 状态。

进入 conn_new_cmd 后,工作线程会调用 reset_cmd_handler 函数,重置 conn 的 cmd 和 substate 字段,并在必要时对连接 buf 进行收缩。因为连接在处理 client 来的命令时,对于写指令,需要分配较大的读 buf 来存待更新的 key value,而对于读指令,则需要分配较大的写 buf 来缓冲待发送给 client 的 value 结果。持续运行中,随着大 size value 的相关操作,这些缓冲会占用很多内存,所以需要设置一个阀值,超过阀值后就进行缓冲内存收缩,避免连接占用太多内存。在后端服务以及中间件开发中,这个操作很重要,因为线上服务的连接很容易达到万级别,如果一个连接占用几十 KB 以上的内存,后端系统仅连接就会占用数百 MB 甚至数 GB 以上的内存空间。

conn_parse_cmd

工作线程处理完 conn_new_cmd 状态的主要逻辑后,如果读缓冲区有数据可以读取,则进入 conn_parse_cmd 状态,否则就会进入到 conn_waiting 状态,等待网络数据进来。

conn_waiting

连接进入 conn_waiting 状态后,处理逻辑很简单,直接通过 update_event 函数注册读事件即可,之后会将连接状态更新为 conn_read。

conn_read

当工作线程监听到网络数据进来,连接就进入 conn_read 状态。对 conn_read 的处理,是通过 try_read_network 从 socket 中读取网络数据。如果读取失败,则进入 conn_closing 状态,关闭连接。如果没有读取到任何数据,则会返回 conn_waiting,继续等待 client 端的数据到来。如果读取数据成功,则会将读取的数据存入 conn 的 rbuf 缓冲,并进入 conn_parse_cmd 状态,准备解析 cmd。

conn_parse_cmd

conn_parse_cmd 状态的处理逻辑就是解析命令。工作线程首先通过 try_read_command 读取连接的读缓冲,并通过 \n 来分隔数据报文的命令。如果命令首行长度大于 1024,关闭连接,这就意味着 key 长度加上其他各项命令字段的总长度要小于 1024 字节。当然对于 key,Mc 有个默认的最大长度,key_max_length,默认设置为 250 字节。校验完毕首行报文的长度,接下来会在 process_command 函数中对首行指令进行处理。

process_command 用来处理 Mc 的所有协议指令,所以这个函数非常重要。process_command 会首先按照空格分拆报文,确定命令协议类型,分派给 process_XX_command 函数处理。

Mc 的命令协议从直观逻辑上可以分为获取类型、变更类型、其他类型。但从实际处理层面区分,则可以细分为 get 类型、update 类型、delete 类型、算术类型、touch 类型、stats 类型,以及其他类型。对应的处理函数为,process_get_command, process_update_command, process_arithmetic_command, process_touch_command 等。每个处理函数能够处理不同的协议,具体参见下图所示思维导图。

conn_parse_cmd

注意 conn_parse_cmd 的状态处理,只有读取到 \n,有了完整的命令首行协议,才会进入 process_command,否则会跳转到 conn_waiting,继续等待客户端的命令数据报文。在 process_command 处理中,如果是获取类命令,在获取到 key 对应的 value 后,则跳转到 conn_mwrite,准备写响应给连接缓冲。而对于 update 变更类型的指令,则需要继续读取 value 数据,此时连接会跳转到 conn_nread 状态。在 conn_parse_cmd 处理过程中,如果遇到任何失败,都会跳转到 conn_closing 关闭连接。

complete_nread

对于 update 类型的协议指令,从 conn 继续读取 value 数据。读取到 value 数据后,会调用 complete_nread,进行数据存储处理;数据处理完毕后,向 conn 的 wbuf 写响应结果。然后 update 类型处理的连接进入到 conn_write 状态。

conn_write

连接 conn_write 状态处理逻辑很简单,直接进入 conn_mwrite 状态。或者当 conn 的 iovused 为 0 或对于 udp 协议,将响应写入 conn 消息缓冲后,再进入 conn_mwrite 状态。

conn_mwrite

进入 conn_mwrite 状态后,工作线程将通过 transmit 来向客户端写数据。如果写数据失败,跳转到 conn_closing,关闭连接退出状态机。如果写数据成功,则跳转到 conn_new_cmd,准备下一次新指令的获取。

conn_closing

最后一个 conn_closing 状态,前面提到过很多次,在任何状态的处理过程中,如果出现异常,就会进入到这个状态,关闭连接,这个连接也就 Game Over 了。

Mc 命令处理全流程


Mc 启动后,主线程监听并准备接受新连接接入。当有新连接接入时,主线程进入 conn_listening 状态,accept 新连接,并将新连接调度给工作线程。

Worker 线程监听管道,当收到主线程通过管道发送的消息后,工作线程中的连接进入 conn_new_cmd 状态,创建 conn 结构体,并做一些初始化重置操作,然后进入 conn_waiting 状态,注册读事件,并等待网络 IO。

有数据到来时,连接进入 conn_read 状态,读取网络数据。

读取成功后,就进入 conn_parse_cmd 状态,然后根据 Mc 协议解析指令。

对于读取指令,获取到 value 结果后,进入 conn_mwrite 状态。

对于变更指令,则进入 conn_nread,进行 value 的读取,读取到 value 后,对 key 进行变更,当变更完毕后,进入 conn_write,然后将结果写入缓冲。然后和读取指令一样,也进入 conn_mwrite 状态。

进入到 conn_mwrite 状态后,将结果响应发送给 client。发送响应完毕后,再次进入到 conn_new_cmd 状态,进行连接重置,准备下一次命令处理循环。

在读取、解析、处理、响应过程,遇到任何异常就进入 conn_closing,关闭连接