redis 和 memcache 的区别

Posted 从零开始的DBA生活

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis 和 memcache 的区别相关的知识,希望对你有一定的参考价值。

1. Redis 和 memcache 的区别

1. memcache 多线程 ,redis 单线程

2. redis 支持5种数据类型,memcache只支持一种字符串类型

3. 内存管理

redis :

redis使用malloc和free来进行内存分配,会导致内存碎片,加重操作系统内存管理器的负担,但是在4.0之后增加了自动回收内存碎片的功能,activedefrag

过期key:惰性删除 + 定期删除

  • 惰性删除,当使用get命令获取key的时候,再进行判断是否过期,过期则删除key,并且不返回value。
  • 定期删除: hz 参数控制,表示执行后台任务的频率,默认为10,此值越大表示redis对"间歇性task"的执行次数越频繁(次数/秒)。"间歇性task"包括"过期集合"检测、关闭"空闲超时"的连接等,不是全部设置了过期时间的键都检查,只是抽样检查

达到maxmemory时的处理:配合maxmemory-policy 和  maxmemory-samples

maxmemory-policy:

volatile-lru   ## 利用LRU算法移除设置过过期时间的key。

volatile-random   ## 随机移除设置过过期时间的key。

volatile-ttl    ## 移除即将过期的key,根据最近过期时间来删除(辅以TTL)

allkeys-lru    ## 利用LRU算法移除任何key。

allkeys-random    ## 随机移除任何key。

noeviction   ## 不移除任何key,只是返回一个写错误

举个栗子:

REDIS的LRU:按策略采样 N 个 key(max-memory-samples) ,淘汰访问时间离现在最久的一个  ---volatile从设置了过期时间的key中抽样,allkeys从所有key中抽样

 

memcache:

Memcached默认情况下采用了名为Slab Allocator的机制分配、管理内存,在该机制出现以前,内存的分配是通过对所有记录简单地进行malloc和free来进行的。但是,这种方式会导致内存碎片,加重操作系统内存管理器的负担,最坏的情况下,会导致操作系统比memcached进程本身还慢。Slab Allocator就是为解决该问题而诞生的。

过期key:惰性删除

  • 跟redis 不太一样,同样是get key时判断是否过期,但是过期只是把key标志为过期,并不会真的去删除,当有新key 进来的时候,替换过期的key

 

先说memcache的几个概念:

Page为内存分配的单位

Memcached的内存分配以page为单位,默认情况下一个page是1M,可以通过-I参数修改,最小1K,最大128M。如果需要申请内存时,memcached会划分出一个新的page并分配给需要的slab区域。page一旦被分配在memcached重启前不会被回收或者重新分配

 

Slabs划分数据空间

Memcached并不是将所有大小的数据都放在一起的,而是预先将数据空间划分为一系列大小的slabs,每个slab只负责一定大小范围内的数据存储。每个slab只存储大于其上一个slab的size并小于或者等于自己最大size的数据。例如:slab 3只存储大小介于137 到 224 bytes的数据。如果一个数据大小为230byte的数据进行存储,它将被分配到slab 4中。每个slab负责的空间其实是不等的,memcached默认情况下下一个slab的最大值为前一个的1.25倍,这个可以通过修改-f参数来修改增长比例

 

Chunk才是存放缓存数据的单位
Chunk是一系列固定的内存空间,这个大小就是管理它的slab的最大存放大小。例如:slab 1的所有chunk都是104byte,而slab 4的所有chunk都是280byte。chunk是memcached实际存放缓存数据的地方,因为chunk的大小固定为slab能够存放的最大值,所以所有分配给当前slab的数据都可以被chunk存下。如果实际的数据大小小于chunk的大小,空余的空间将会被闲置,这个是为了防止内存碎片而设计的。举例来说,如果chunk size是224byte,而存储的数据只有200byte,剩下的24byte将被闲置。此外,memcached允许配置的最小的chunk空间为48个字节(key+value+flags),通过-n参数可以调节这个数值

 

达到maxmemory: memcache有三种LRU,Hot LRU , Warm LRU, COLD LRU

Hot LRU , Warm LRU都有特定的长度,当新数据访问,会放到Hot lru,然后末尾的元素插入到Warm LRU, warm lru末尾的元素插入到cold lru

当达到max memory 时,会从cold lru中剔除最久没有被访问的数据

内存驱逐策略LRU不是全局的,当不能为某个slab再分配页的时候,就会触发LRU机制,清除这个slab中最不经常使用的数据

Memcached在启动时通过-m指定最大使用内存,但是这个不会一启动就占用,是随着需要逐步分配给各slab的。 如果一个新的缓存数据要被存放,memcached首先选择一个合适的slab,然后查看该slab是否还有空闲的chunk,如果有则直接存放进去;或者替换已经标记为过期的键,如果没有则要进行申请。当没有内存页能够分配的时候(就是已经分配的内存达到启动时的-m参数),就会去驱逐策略去驱逐键

  • 可以通过查看stats items 配置中的 evicted (没过期就被驱逐的次数),如果很多,表示这类slab要存的数据非常多,但是分配的页不够多
  • 可以通过对比used_chunks,total_chunks, 三个参数,如果total chunks很多,但是used_chunks很少,差距是几个页的数量级,就证明以前这类slab有很多数据但现在没怎么用了,然后过期了。

根据以上情况,memcached 加入了页面重分配机制

  • 自动重分配:启动配置 -o slab_reassign, slab_automove 若某个slab在10秒内出现3次eviction,则从过去30秒内没有出现eviction的slab里挪取一个内存页使用
  • 手动重分配,启动配置 -o slab_reassign,在mc运行时输入echo "slabs reassign 1 4" | nc localhost 11211 把slab1 的一个页面移动到 slab4 中,有数据也能移动,剩一页就不能再移动

2. memcached 的LRU内存驱逐 和 page move 页移动

 

以上是关于redis 和 memcache 的区别的主要内容,如果未能解决你的问题,请参考以下文章

redis与memcached有什么区别

redis和memcached的区别详解

redis和memcached的区别

redis和memcached的区别

redis和memcached的区别

redis和memcached的区别