Memcached的内存分配器是如何工作的?为什么不适用malloc/free!?为何要使用slabs?

参考回答

Memcached 的内存分配器通过 Slab Allocation 机制进行内存管理,避免了直接使用 malloc/free 所带来的内存碎片和性能问题。
Slab Allocation 通过将内存预划分为固定大小的块(chunk),并根据数据大小分配到合适的块中,从而实现高效的内存管理和分配。


详细讲解与拓展

1. 为什么 Memcached 不直接使用 malloc/free

  1. 内存碎片问题
    • 如果使用 malloc/free 动态分配内存,缓存的数据大小各异,会导致内存碎片增多(即未使用的小内存块分布在内存中,无法有效利用)。
    • 内存碎片会降低内存利用率,进而影响缓存的容量和性能。
  2. 性能问题
    • 动态分配内存涉及频繁的系统调用,malloc 的分配和 free 的释放需要维护复杂的数据结构(如空闲链表),这些操作耗时较多,不适合高并发、高性能场景。
  3. 不确定性
    • 动态内存分配的效率会随着系统状态和内存碎片的增加而变化,无法提供稳定的性能。

2. Slab Allocation 的内存管理机制

Slab Allocation 的核心思想是:预分配内存并分层管理,以减少内存碎片和动态分配开销。

  1. 内存划分
    • 启动 Memcached 时,系统会根据指定的总内存容量(如 1 GB),将内存分为多个 slab。
    • 每个 slab 被划分为固定大小的内存块(chunk),不同 slab 的 chunk 大小不同(如 64 字节、128 字节、256 字节等)。
  2. 分配过程
    • 每次需要存储数据时,根据数据的大小选择一个合适的 slab,将数据存储到该 slab 中的 chunk。
    • 每个 slab 中的 chunk 大小是固定的,chunk 内部无法存储多个 item,一个 chunk 只能存储一个 item。
  3. 管理策略
    • 如果某个 slab 的 chunk 被使用完,Memcached 会动态扩展 slab 的容量,或者根据 LRU 策略清理旧数据。

3. 使用 Slab Allocation 的优点

  1. 减少内存碎片
    • 由于 chunk 的大小是固定的,且每个 slab 中的 chunk 尺寸相同,能有效避免因数据大小不一致而导致的内存碎片。
  2. 提高内存利用率
    • 每个 slab 针对一类数据大小进行优化,确保小数据不会浪费大块的内存。
  3. 性能稳定
    • 预分配内存后,不再需要频繁调用 malloc/free,减少了系统调用的开销,提高了分配效率。
  4. 可预测的分配效率
    • Slab Allocation 的分配和回收速度较快,不会因系统状态的变化而波动,能提供一致的性能。

4. Slab Allocation 的工作流程

  1. 初始化
    • 启动时,将分配的总内存分为多个 slab,每个 slab 中的 chunk 尺寸递增,例如:64B、128B、256B 等。
  2. 分配数据
    • 根据存储数据的大小,选择最小能容纳该数据的 chunk。如果数据大小为 100 字节,则会分配到 128B 的 slab 中。
  3. 回收内存
    • 当某个 slab 的 chunk 被释放时,该 chunk 会被标记为空闲,可以重新分配给新数据。

5. Slab Allocation 的限制

  1. 可能造成内存浪费
    • 由于每个 chunk 的大小固定,数据大小不足 chunk 的容量时,会造成浪费。例如,存储 65 字节的数据需要一个 128 字节的 chunk。
  2. 数据迁移复杂
    • Slab Allocation 固定了每个 slab 的 chunk 大小,数据无法轻易迁移到其他 slab。

举例说明

假设 Memcached 有 512 MB 内存分配,总共划分为 5 个 slab

Slab ID Chunk 大小 Slab 数量 总内存占用
Slab 1 64B 10,000 640 KB
Slab 2 128B 8,000 1 MB
Slab 3 256B 6,000 1.5 MB
Slab 4 512B 4,000 2 MB
Slab 5 1024B 2,000 2 MB

如果存储一个 200 字节的数据:
1. Memcached 会将其分配到 256B 的 slab
2. 即使只使用了 200 字节,剩余的 56 字节也会浪费,称为 内存对齐开销


总结

Memcached 使用 Slab Allocation 代替 malloc/free 是为了减少内存碎片、优化性能和提高内存分配的效率。虽然 Slab Allocation 有一定的内存浪费,但它在高性能和高并发场景下表现优异。通过合理的内存划分,Memcached 在性能和内存利用率之间找到了平衡,是其高效运行的重要基础。

发表评论

后才能评论