redis是一个高性能的开源、分布式内存数据库,redis不光支持普通的kv存在,还支持复杂的数据结构,包括list、set、hash、有序集合等。说的redis就会提到memcached,memcached也是一种非常流行的开源分布式内存数据库,memcached只支持普通的kv存储,不支持复杂的数据结构。下面我们从以下几个方面来分别介绍redis和memcached之前的区别。
1.网络IO模型
redis是基于单线程多了IO复用网络,内部分装了AeEvent事件处理框架,主要实现了linux下的epoll, kqueue和select,对于简单的存储来说可以将网络IO的作用发挥到最大,但是如果进行复杂计算比如排序等操作将会严重阻塞IO,拖慢整体速度。
memcached是基于多线程非阻塞IO复用的网络模型,内部实现了React网络模型,通过一个监听主线程和工作子线程进行操作,内部采用开源网络框架libevent封装事件。memcached采用多线程网络模型可以将多核CPU的作用发挥到最大,但是多线程网络带来了锁、以及线程间数据同步问题给系统带来了复杂性。
2.数据存储
redis支持内存存储,也支持持久化存储。
memcached只支持内存存储,一旦机器宕机数据将会丢失。
3.数据类型
redis支持String、Hash、List、Set、Sorted set、pub/sub、Transactions。
memcached只支持key-value
4.数据一致性问题
redis由于支持事务,能够保证某个操作的原子性。
memcached支持cas操作,保证多并发请求下数据一致性。
5.内存模型及管理机制
作为数据内存数据库,高效的内存管理机制格外重要,redis和memcached都没有使用malloc/free分配内存,而是实现了自己的内存分配机制。
redis内存模型:
Redis的内存管理主要通过源码中zmalloc.h和zmalloc.c两个文件来实现的。Redis没有直接使用malloc/free分配内存,而是在malloc/free上面封装了一层自己的类型分配机制,为了方便对内存进行管理,redis分配一块内存后会将这块内存的大小存入内存头部。redi内部定义了一个数组来记录内存分配情况,数组大小是ZMALLOC_MAX_ALLOC_STAT,这个数组就是zmalloc_allocations,其中zmalloc_allocations[i]表示分配长度为ibytes内存块的个数,其中zmalloc.c中有一个静态变量 used_memory用来记录当前分配的内存总大小。总的来说redis是基于malloc/free的包装的轻量级内存管理。
memcached内存模型:
Memcached默认使用Slab Allocation机制来对内存进行管理,其主要思想是按照预先设定的大小,将内存分配成特定大小的快,用于解决再内存分配过程中带来的内存碎片问题,Slab Allocation只是针对外部存储数据设计的内存管理机制,memcached自身的内存分配机制还是基于C的malloc/free。
如图所示:首先Memcached会从系统中申请一块很大的内存,将将其分成大小不同的Chunk,相同大小的Chunk组成一组Slab Class,Chunk是用于存储kv数据的最小单位,每个Slab Class的大小可以通过参数Growth Factor设定,Chunk的起始大小可以在初始化设置,Growth Factor的默认大小为1.25,Chunk的最大值通过page设定且为1M,如果Chunk的初始化大小设定为88B,Growth Factor是1.25,则会生成88、112、144、184……1M等39组Slab。Slab就是一组相同大小的Chunk的集合,而这个集合的大小为1M,
如果有新的对象进来后首先会根据对象的大小去寻找Slab,比如对象大小为100KB,根据损失最小的原则将该对象放入到Slab class2中,如果Slab class2没有Chunk,将会去申请1M内存然后切分成相同大小的Slab,如果到达设定上限会看是否设定了LRU删除算法否则会报错,已经申请的page不会被回收。100KB永远都不会被放进到非Slab class2中,哪怕是其它Slab中有空的Chunk存在。这样带来了很大的内存浪费情况。而且将100KB大小对象放入到128KB中会造成28KB大小内存浪费。实际上每个Chunk本身自己需要占用48B内存(自身数据结构),Slab class2实际上是不能存在128KB大小的数据,要小于这个值即把本身自己所占的48B减去。
如果用户数据大于1M,会对数据进行分割放入到不同的Chunk中,memcached key 长度不能超过255字符长度,value 长度不能超过1024 * 1024字符长度(即 1M)
6.集群机制
redis:
主从集群、rddis cluster codis等代理工具。
memcached:
本身不支持分布式集群,只能通过客户端一致性Hash进行分布式集群。