精英联盟总队 缓存框架Redis、Memcached技术选型,「微服务」( 二 )


Redis6.0与Memcached多线程模型对比:**相同点:**都采用了master线程-worker线程的模型
不同点:Memcached执行主逻辑也是在worker线程里 , 模型更加简单 , 实现了真正的线程隔离 , 符合我们对线程隔离的常规理解 。 而Redis把处理逻辑交还给master线程 , 虽然一定程度上增加了模型复杂度 , 但也解决了线程并发安全等问题 。
数据支持类型MemcachedMemcached使用key-value形式存储和访问数据(所以 , Memcached仅支持Key-Value) , 在内存中维护一张巨大的HashTable , 使得对数据查询的时间复杂度降低到O(1) , 保证了对数据的高性能访问 。
RedisRedis支持常见的数据结构 , 如Set、ZSet、Hash、Bitmap、List、Geo等 。
同时还有Pub/Sub、Transaction等特性 。
对于当前的一些业务场景中 , 很多时候都可以直接套用 。 比如 , 利用Pub/Sub实现简单的消息队列 , 利用Geo实现附近的人、利用ZSet实现实时排行榜等 。
如图所示 , 它首先从操作系统申请一大块内存 , 并将其分割成各种尺寸的块Chunk , 并把尺寸相同的块分成组SlabClass 。 其中 , Chunk就是用来存储key-value数据的最小单位 。 每个SlabClass的大小 , 可以在Memcached启动的时候通过制定GrowthFactor来控制 。
假定图中GrowthFactor的取值为1.25 , 如果第一组Chunk的大小为88个字节 , 第二组Chunk的大小就为112个字节 , 依此类推 。
当一条数据库过期或者丢弃时 , 该记录所占用的Chunk就可以回收 , 重新添加到空闲列表中 。
从以上过程我们可以看出Memcached的内存管理制效率高 , 而且不会造成内存碎片 , 但是它最大的缺点就是会导致空间浪费 。
因为每个Chunk都分配了特定长度的内存空间 , 所以变长数据无法充分利用这些空间 。 如图所示 , 将100个字节的数据缓存到128个字节的Chunk中 , 剩余的28个字节就浪费掉了 。
Redis为了方便内存的管理 , 在分配一块内存之后 , 会将这块内存的大小存入内存块的头部 。
如图所示 , real_ptr是redis调用malloc后返回的指针 。 redis将内存块的大小size存入头部 , size所占据的内存大小是已知的 , 为size_t类型的长度 , 然后返回ret_ptr 。
当需要释放内存的时候 , ret_ptr被传给内存管理程序 。 通过ret_ptr , 程序可以很容易的算出real_ptr的值 , 然后将real_ptr传给free释放内存 。