Idea 的提出
- Redis 有其高效的异步网络框架
- Memcached 有其高效的内存管理机制
将这两者结合在一起后,会如何呢?开始试验将Memcached内存管理机制移植至Redis。
本篇博客的姊妹篇链接: 《工程师手记-将Redis异步网络框架移植至Memcached》
调研和选型
Redis内存管理的几个缺点:
- 使用tcmalloc 或者 jmalloc 库,这两个库封装较重,内部特性也较多。
- tcmalloc 适合小空间分配,稍大的空间分配会有瓶颈。
- Redis 主要是单线程运行(只在后台任务cache持久化功能处又启动了新线程), tcmalloc 和 jmalloc 有保证线程安全,但对redis来说是不必要的功能。尤其是jmalloc,为线程安全做了很重的设计。
软件选型
- 并不是把 Memcached 的内存管理直接替换redis的内存分配,而是使用ae-memcached的内存分配方式。
- ae-memcached 的内存分配和 Memcached在原理上毫无不同,仅是从软件架构上对其进行重构和优化。具体参考:《AE-Memcached 优化记录》
- 选择 Redis 2.8.24 作为移植受体
Redis代码修改和编译 / 移植方案
- 从ae-memcached中拿出mem_cache / slab 两个类,直接移植到Redis src 目录中
- 新建两个文件 mc_malloc.h mc_malloc.c,封装mem_cache,让其提供类似 malloc、 alloc、realloc、free的接口
- 修改 zmalloc.c zmalloc.h 这两个文件,让其支持mc_malloc
- 修改 Makefile ,默认MALLOC 使用 mc_malloc
- 修改bio.c 文件,把zmalloc 和 zfree用 libc的 malloc 和 free 代替,这么做主要考虑到线程安全
- 编译、运行
代码托管地址
给新的redis起了一个新名字mc-redis,源代码托管于Github上:
https://github.com/zuocheng-liu/mc-redis
性能测试实验
硬件
- Redis-server 服务端 GenuineIntel 6 Common KVM processor 6 核 2.0GHZ 4G 内存
- redis-benchmark 和服务端部署在同一台服务器上
测试方法
- 分别运行原本Redis 和 mc-redis, 分别作为实验和对照,参数为 redis-server –port 7777
- 启动Redis,运行redis-benchmark 测试三次。重复前面步骤,Redis共重启3次,redis-benchmark共测试9次。
- mc-redis 的测试也使用上面方法
- 测试命令 ./redis-benchmark -h 127.0.0.1 -p 7778 -q -d 100
- 只观察set / get 命令的并发度
测试结果
启动一次redis,做了三组实验,数据如下:
- mc-redis GET 62972.29 / 58275.06 / 55897.15 (requests per second)
- redis GET 47281.32 / 62034.74 / 51759.83 (requests per second)
- mc-redis SET 64808.82 / 59031.88 / 56915.20 (requests per second)
- redis SET 51733.06 / 53676.86 / 56947.61 (requests per second)
结论
在刚启动时(预热阶段),mc-redis 的 set 和 get 操作,比原版redis 的并发处理能力高大约有 15%-20%。 但是稳定运行后, mc-redis 和 原版redis,性能相差较小。