mongodb,redis,memcached,mysql对比

时间:2023-03-08 15:59:52

1、性能
都比较高,性能对我们来说应该都不是瓶颈
总体来讲,TPS方面redis和memcache差不多,要大于mongodb

2、操作的便利性
memcache数据结构单一
redis丰富一些,数据操作方面,redis更好一些,较少的网络IO次数
mongodb支持丰富的数据表达,索引,最类似关系型数据库,支持的查询语言非常丰富
mysql是持久化存储,存放在磁盘里面,检索的话,会涉及到一定的IO瓶颈。
推理到redis+mysql,它是内存+磁盘关系的一个映射,mysql放在磁盘,redis放在内存,这样的话,web应用每次只访问redis,如果没有找到的数据,才去访问Mysql。

3、内存空间的大小和数据量的大小
redis在2.0版本后增加了自己的VM特性,突破物理内存的限制;可以对key value设置过期时间(类似memcache)
memcache可以修改最大可用内存,采用LRU算法
mongoDB适合大数据量的存储,依赖操作系统VM做内存管理,采用镜像文件存储,吃内存也比较厉害,服务不要和别的服务在一起,官方建议独立部署在64位系统(32位有最大2.5G文件限制,64位没有改限制)

当物理内存不够用的时候,redis和mongodb都会使用虚拟内存。当物理内存和虚拟内存都不够用的时候,估计除了mysql你没什么好选择了。其实,从数据存储原理来看,我更倾向于将mongodb归类为硬盘数据库,但是使用了mmap作为加速的手段而已。

4、可用性(单点问题)
对于单点问题,
redis,依赖客户端来实现分布式读写;主从复制时,每次从节点重新连接主节点都要依赖整个快照,无增量复制,因性能和效率问题,所以单点问题比较复杂;不支持自动sharding,需要依赖程序设定一致hash 机制。
一种替代方案是,不用redis本身的复制机制,采用自己做主动复制(多份存储),或者改成增量复制的方式(需要自己实现),一致性问题和性能的权衡。
Memcache本身没有数据冗余机制,也没必要;对于故障预防,采用依赖成熟的hash或者环状的算法,解决单点故障引起的抖动问题。
mongoDB支持master-slave,replicaset(内部采用paxos选举算法,自动故障恢复),auto sharding机制,对客户端屏蔽了故障转移和切分机制。MongoDB优于Redis;单点问题上,MongoDB应用简单,相对用户透明,Redis比较复杂,需要客户端主动解决。(MongoDB 一般会使用replica sets和sharding功能结合,replica sets侧重高可用性及高可靠性,而sharding侧重于性能、易扩展)

5、可靠性(持久化)
对于数据持久化和数据恢复,
redis支持(快照、AOF):依赖快照进行持久化,aof增强了可靠性的同时,对性能有所影响
memcache不支持,通常用在做缓存,提升性能;
MongoDB从1.8版本开始采用binlog方式(MySQL同样采用该方式)支持持久化的可靠性,mongodb的所有数据实际上是存放在硬盘的,所有要操作的数据通过mmap的方式映射到内存某个区域内。mmap数据flush到硬盘之前,系统宕机了,数据就会丢失。

6、数据一致性(事务支持)
Memcache 在并发场景下,用cas保证一致性
redis事务支持比较弱,只能保证事务中的每个操作按顺序连续执行
mongoDB不支持事物,靠客户端自身保证

7、数据分析
mongoDB内置了数据分析的功能(mapreduce),其他不支持

8、应用场景
redis:数据量较小的更性能操作和运算上,
memcache:用于在动态系统中减少数据库负载,提升性能;做缓存,提高性能(适合读多写少,对于数据量比较大,可以采用sharding)
MongoDB:主要解决海量数据的访问效率问题

11.数据结构:
memcache只是提供了简单的数据结构,比如 string存储。
Redis不仅仅支持简单的k/v类型的数据,同时还提供 string(字符串)、 list(双向链表)、dict(hash表)、set(集合)、zset(排序set)、hyperloglog(基数估算)等数据结构的存储。。

Mongodb和Memcached不是一个范畴内的东西。Mongodb是文档型的非关系型数据库,其优势在于查询功能比较强大,能存储海量数据。Mongodb 和 Memcached不存在谁替换谁的问题。

Memcached 和 Redis它们都是内存型数据库,数据保存在内存中,通过tcp直接存取,优势是速度快,并发高。

Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态、数据库驱动网站的速度。

Memcached 的分布式不是在服务器端实现的,而是在客户端应用中实现的,即通过内置算法制定目标数据的节点,Memcached 的分布式是基于客户端的Key的hash来做均衡,是个伪分布式的系统。

Redis是一个key-value存储系统。和 Memcached 类似,它支持存储的value类型相对更多,包括string(字符串)、 list(链表)、set(集合)和zset(有序集合)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,Redis支持各种不同方式的排序。与 Memcached 一样,为了保证效率,数据都是缓存在内存中。区别的是Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件。

mongodb,redis,memcached,mysql对比

总结: 
    • 没有必要过于关注性能,因为二者的性能都已经足够高了。由于Redis只使用单核,而Memcached可以使用多核,Memcached可以利用多核优势,单实例吞吐量极高,可以达到几十万QPS(取决于key、value的字节大小以及服务器硬件性能,日常环境中QPS高峰大约在4-6w左右),适用于最大程度扛量,所以二者比较起来,平均每一个核上,Redis在存储小数据时比Memcached性能更高。而在100k以上的数据中,Memcached性能要高于Redis。虽然Redis最近也在存储大数据的性能上进行优化,但是比起Memcached,还是稍有逊色。说了这么多,结论是,无论你使用哪一个,每秒处理请求的次数都不会成为瓶颈。 
    • 在内存使用效率上,如果使用简单的key-value存储,Memcached的内存利用率更高。而如果Redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于Memcached。当然,这和你的应用场景和数据特性有关。 
    • 如果你对数据持久化和数据同步有所要求,那么推荐你选择Redis。因为这两个特性Memcached都不具备。即使你只是希望在升级或者重启系统后缓存数据不会丢失,选择Redis也是明智的。 
    • 当然,最后还得说到你的具体应用需求。Redis相比Memcached来说,拥有更多的数据结构,并支持更丰富的数据操作。通常在Memcached里,你需要将数据拿到客户端来进行类似的修改再set回去。这大大增加了网络IO的次数和数据体积。在Redis中,这些复杂的操作通常和一般的GET/SET一样高效。所以,如果你需要缓存能够支持更复杂的结构和操作,那么Redis会是不错的选择。

• memcached支持直接配置为session handle

>>Memcached的局限性:
只支持简单的key/value数据结构,不像Redis可以支持丰富的数据类型。
无法进行持久化,数据不能备份,只能用于缓存使用,且重启后数据全部丢失。
无法进行数据同步,不能将MC中的数据迁移到其他MC实例中。
Memcached内存分配采用Slab Allocation机制管理内存,value大小分布差异较大时会造成内存利用率降低,并引发低利用率时依然出现踢出等问题。需要用户注重value设计。

>>Redis的局限性:
Redis只能使用单线程,性能受限于CPU性能,故单实例CPU最高才可能达到5-6wQPS每秒(取决于数据结构,数据大小以及服务器硬件性能,日常环境中QPS高峰大约在1-2w左右),并发情况下不需要考虑数据一致性问题,。
支持简单的事务需求,但业界使用场景很少,并不成熟,既是优点也是缺点。
Redis在string类型上会消耗较多内存,可以使用dict(hash表)压缩存储以降低内存耗用。
Mc和Redis都是Key-Value类型,不适合在不同数据集之间建立关系,也不适合进行查询搜索。比如redis的keys pattern这种匹配操作,对redis的性能是灾难。

>>mongoDB
mongoDB 是一种文档性的数据库。先解释一下文档的数据库,即可以存放xml、json、bson类型系那个的数据。
这些数据具备自述性(self-describing),呈现分层的树状数据结构。redis可以用hash存放简单关系型数据。
mongoDB 存放json格式数据。
适合场景:事件记录、内容管理或者博客平台,比如评论系统。

MongoDB和Redis区别
MongoDB更类似Mysql,支持字段索引、游标操作,其优势在于查询功能比较强大,擅长查询xml、json、bson数据,能存储海量数据,但是不支持事务。
Mysql在大数据量时效率显著下降,MongoDB更多时候作为关系数据库的一种替代。

内存管理机制
Redis数据全部存在内存,定期写入磁盘,当内存不够时,可以选择指定的LRU算法删除数据。
MongoDB数据存在内存,由linux系统mmap实现,当内存不够时,只将热点数据放入内存,其他数据存在磁盘。

支持的数据结构
Redis支持的数据结构丰富,包括hash、set、list等。
MongoDB数据结构比较单一,但是支持丰富的数据表达,索引,最类似关系型数据库,支持的查询语言非常丰富。

性能
二者性能都比较高,应该说都不会是瓶颈。

可靠性
二者均支持持久化。

集群
MongoDB集群技术比较成熟,Redis从3.0开始支持集群。

不适用场景
Ø 需要使用复杂sql的操作
Ø 事务性系统

Redis很适合用来做缓存,但除此之外,它实际上还可以在一些“读写分离”的场景下作为“读库”来用,特别是用来存放Hadoop或Spark的分析结果。
Redis的读写性能在100,000 ops/s左右,时延一般为10~70微妙左右;而HBase的单机读写性能一般不会超过1,000ops/s,时延则在1~5毫秒之间。
Redis的魅力还在于它不像HBase只支持简单的字符串,他还支持集合set,有序集合zset和哈希hash
Redis适合存储全局变量,比如微信token每两小时刷新一次,就比较适合用redis存储,读也比较方便。
hbase是列数据库,不支持二级索引,写性能高,适合写多读少的业务场景,可用来存储BI数据。
mongodb 适合存储json类型数据,不经常变化,比如排行榜,每天刷新一次,remove一次再从db更新过去。Hbase暂时没用过。
mongodb主要是做社交这一类的应用。redis是个in memory cache,主要作为软件里一个部件来提升整体性能的。

MongoDB在A:{B,C}上建立索引,查询A:{B,C}和A:{C,B}都会使用索引吗?不会,只会在A:{B,C}上使用索引。
为什么MongoDB的数据文件很大?MongoDB采用的预分配空间的方式来防止文件碎片。

Redis的局限性:
(1)Redis只能使用单线程,性能受限于CPU性能,故单实例CPU最高才可能达到5-6wQPS每秒(取决于数据结构,数据大小以及服务器硬件性能,日常环境中QPS高峰大约在1-2w左右)。
(2)支持简单的事务需求,但业界使用场景很少,并不成熟,既是优点也是缺点。
(3)Redis在string类型上会消耗较多内存,可以使用dict(hash表)压缩存储以降低内存耗用。
(4)Mc和Redis都是Key-Value类型,不适合在不同数据集之间建立关系,也不适合进行查询搜索。比如redis的keys pattern这种匹配操作,对redis的性能是灾难。

MongoDB 与 MySQL 的适用场景:
MongoDB 的适用场景为:数据不是特别重要(例如通知,推送这些),数据表结构变化较为频繁,数据量特别大,数据的并发性特别高,数据结构比较特别(例如地图的位置坐标),这些情况下用 MongoDB , 其他情况就还是用 MySQL ,这样组合使用就可以达到最大的效率。
1.如果需要将 MongoDB 作为后端 db 来代替MySQL使用,即这里 MySQL 与 MongoDB 属于平行级别,那么,这样的使用可能有以下几种情况的考量:
(1)MongoDB 所负责部分以文档形式存储,能够有较好的代码亲和性,json 格式的直接写入方便。(如日志之类)
(2)从 data models 设计阶段就将原子性考虑于其中,无需事务之类的辅助。开发用如 nodejs 之类的语言来进行开发,对开发比较方便。
(3)MongoDB 本身的 failover 机制,无需使用如 MHA 之类的方式实现。

2.将 MongoDB 作为类似 Redis,memcache 来做缓存db,为 MySQL 提供服务,或是后端日志收集分析。 考虑到 MongoDB 属于 No SQL 型数据库,SQL 语句与数据结构不如 MySQL 那么亲和 ,也会有很多时候将 MongoDB 做为辅助MySQL 而使用的类 Redis memcache 之类的缓存db来使用。 亦或是仅作日志收集分析。
MongoDB 有一个最大的缺点,就是它占用的空间很大,因为它属于典型空间换时间原则的类型。那么它的磁盘空间比普通数据库会浪费一些,而且到目前为止它还没有实现在线压缩功能,在 MongoDB 中频繁的进行数据增删改时,如果记录变了,例如数据大小发生了变化,这时候容易产生一些数据碎片,出现碎片引发的结果,一个是索引会出现性能问题。
另外一个就是在一定的时间后,所占空间会莫明其妙地增大,所以要定期把数据库做修复,定期重新做索引,这样会提升MongoDB 的稳定性和效率。

1.MySQL 来自女儿的名字; MongoDB 来自 humongous
2.MySQL 使用 Table/Row/Column; MongoDB 使用 Collection/Document
3.MySQL 需要指定 table 的 schema; MongoDB的 collection 的每个 document 的 schema 可以*修改
4.MySQL 支持 join; MongoDB 没有 join
5.MySQL 使用 SQL 语言; MongoDB 使用类似 JavaScript 的函数

命令对比
MongoDB 与 MySQL 命令对比 传统的关系数据库一般由数据库(database)、表(table)、记录(record)三个层次概念组成,MongoDB 是由数据库(database)、集合(collection)、文档对象(document)三个层次组成。MongoDB对于关系型数据库里的表,但是集合中没有列、行和关系概念,这体现了模式*的特点。
MongoDB (文档型数据库):提供可扩展的高性能数据存储
1、基于分布式文件存储
2、高负载情况下添加更多节点,可以保证服务器性能
3、将数据存储为一个文档
MongoDB 与 MySQL 的比较
1、稳定性
2、索引,索引放在内存中,能够提升随机读写的性能。如果索引不能完全放在内存,一旦出现随机读写比较高的时候,就会频繁地进行磁盘交换,MongoDB 的性能就会急剧下降
3、占用的空间很大,因为它属于典型空间换时间原则的类型。那么它的磁盘空间比普通数据库会浪费一些,而且到目前为止它还没有实现在线压缩功能,
在 MongoDB 中频繁的进行数据增删改时,如果记录变了,例如数据大小发生了变化,这时候容易产生一些数据碎片,出现碎片引发的结果,
一个是索引会出现性能问题,
另外一个就是在一定的时间后,所占空间会莫明其妙地增大,所以要定期把数据库做修复,定期重新做索引,这样会提升MongoDB 的稳定性和效率。
在最新的版本里,它已经在实现在线压缩,估计应该在2.0版左右,应该能够实现在线压缩,可以在后台执行现在repair DataBase 的一些操作。如果那样,就解决了目前困扰我们的大问题。
4、MongoDB 对数据间的事务关系支持比较弱
5、运维不方便
MongoDB 相对于 MySQL 的优势
1. 适合那些对数据库具体数据格式不明确或者数据库数据格式经常变化的需求模型,而且对开发者十分友好。
2. 自带一个分布式文件系统,可以很方便地部署到服务器机群上。
MongoDB 里有一个Shard的概念,就是方便为了服务器分片使用的。每增加一台Shard,MongoDB 的插入性能也会以接近倍数的方式增长,磁盘容量也很可以很方便地扩充。
3. 自带了对map-reduce运算框架的支持,这也很方便进行数据的统计。类似于group by
MongoDB 与 MySQL 命令对比 传统的关系数据库一般由数据库(database)、表(table)、记录(record)三个层次概念组成,
MongoDB 是由数据库(database)、集合(collection)、文档对象(document)三个层次组成。
MongoDB 对于关系型数据库里的表,但是集合中没有列、行和关系概念,这体现了模式*的特点。

MongoDB优点:
1.MongoDB非常容易被扩展,这也为写代码带来了极大的方便。
1.性能优越:快速!在适量级的内存的 MongoDB 的性能是非常迅速的,它将热数据存储在物理内存中,使得热数据的读写变得十分快,
2.高扩展:第三方支持丰富(这是与其他的 No SQL 相比,MongoDB 也具有的优势)
3.自身的 Failover 机制!
4.弱一致性(最终一致),更能保证用户的访问速度
5.文档结构的存储方式,能够更便捷的获取数据: json 的存储格式
6.支持大容量的存储,内置 GridFS
7.内置 Sharding

MongoDB 缺点:
主要是无事物机制!
① MongoDB 不支持事务操作(最主要的缺点)
② MongoDB 占用空间过大
③ MongoDB 没有如 MySQL 那样成熟的维护工具,这对于开发和IT运营都是个值得注意的地方

MongoDB 的应用场景

主要特点:
MongoDB 的提供了一个面向文档存储,操作起来比较简单和容易。
你可以在 MongoDB 记录中设置任何属性的索引 (如:FirstName="Sameer",Address="8 Gandhi Road")来实现更快的排序。
你可以通过本地或者网络创建数据镜像,这使得 MongoDB 有更强的扩展性。
如果负载的增加(需要更多的存储空间和更强的处理能力) ,它可以分布在计算机网络中的其他节点上这就是所谓的分片。
MongoDB支持丰富的查询表达式。查询指令使用 JSON 形式的标记,可轻易查询文档中内嵌的对象及数组。
MongoDB使用update() 命令可以实现替换完成的文档(数据)或者一些指定的数据字段 。
MongoDB中的Map/reduce 主要是用来对数据进行批量处理和聚合操作。
Map和Reduce。Map 函数调用 emit(key,value) 遍历集合中所有的记录,将 key 与 value 传给 Reduce 函数进行处理。
Map 函数和 Reduce 函数是使用 JavaScript 编写的,并可以通过 db.runCommand 或 mapreduce 命令来执行 MapReduce 操作。
GridFS 是 MongoDB 中的一个内置功能,可以用于存放大量小文件。
MongoDB 允许在服务端执行脚本,可以用 Javascript 编写某个函数,直接在服务端执行,也可以把函数的定义存储在服务端,下次直接调用即可。
MongoDB支持各种编程语言:RUBY,PYTHON,JAVA,C++,PHP,C# 等多种语言。

1. 它里面自带了一个名叫 GirdFS 的分布式文件系统,这就为 MongoDB 的部署提供了很大便利。而像 MySQL 这种比较早的数据库,虽然市面上有很多不同的分表部署的方案,但这种终究不如 MongoDB 直接官方支持来得便捷实在。
2. 另外,MongoDB 内部还自建了对 map-reduce运算框架的支持,虽然这种支持从功能上看还算是比较简单的,相当于MySQL里 GroupBy 功能的扩展版,不过也为数据的统计带来了方便。
3. MongoDB 在启动后会将数据库中的数据以文件映射的方式加载到内存中。如果内存资源相当丰富的话,这将极大地提高数据库的查询速度,毕竟内存的 I/O 效率比磁盘高多了。
MongoDB 以 BSON 结构(二进制)进行存储,对海量数据存储有着很明显的优势。

监控
MongoDB提供了网络和系统监控工具Munin,它作为一个插件应用于MongoDB中。
Gangila是MongoDB高性能的系统监视的工具,它作为一个插件应用于MongoDB中。
基于图形界面的开源工具 Cacti, 用于查看CPU负载, 网络带宽利用率,它也提供了一个应用于监控 MongoDB 的插件。
查询语句:是独特的 MongoDB 的查询方式。
适合场景:事件的记录,内容管理或者博客平台等等。
架构特点:可以通过副本集,以及分片来实现高可用。
数据处理:数据是存储在硬盘上的,只不过需要经常读取的数据会被加载到内存中,将数据存储在物理内存中,从而达到高速读写。
成熟度与广泛度:新兴数据库,成熟度较低,No SQL 数据库中最为接近关系型数据库,比较完善的 DB 之一,适用人群不断在增长。

mongodb却是一个“存储数据”的系统,增删改查数据的时候有“与或非”条件,查询数据的方式也能像SQL数据库一样灵活,这是redis所不具备的。
在我的项目中,redis作为session、任务队列的存储器,而mongodb作为数据(包括用户信息等)的存储器。
memcached可以随时执行“save”命令将当前redis的数据保存到硬盘上,另外redis也会根据配置自动存储数据到硬盘上。可以设置让redis再指定时间、指定更改次数时进行备份,生成RDB文件;而设置AOF,可以在操作或时间过程后将“日志”写入一个文件的最末,当操作越来越多,则AOF文件越来越大。

Mongodb与Redis应用指标对比
MongoDB和Redis都是NoSQL,采用结构型数据存储。二者在使用场景中,存在一定的区别,这也主要由于
二者在内存映射的处理过程,持久化的处理方法不同。MongoDB建议集群部署,更多的考虑到集群方案,Redis
更偏重于进程顺序写入,虽然支持集群,也仅限于主-从模式。

在使用Redis过程中,我们发现了不少Redis不同于Memcached,也不同于MySQL的特征。
(本文主要讨论Redis未启用VM支持情况)

1. Schema
MySQL: 需事先设计
Memcached: 无需设计
Redis: 小型系统可以不用,但是如果要合理的规划及使用Redis,需要事先进行类似如下一些规划

数据项: value保存的内容是什么,如用户资料
Redis数据类型: 如String, List
数据大小: 如100字节
记录数: 如100万条(决定是否需要拆分)
⋯⋯
上面的规划就是一种schema,为什么Redis在大型项目需要事先设计schema?因为Redis服务器有容量限制,数据容量不能超出物理内存大小,同时考虑到业务数据的可扩充性,记录数会持续增多、单条记录的内容也都会增长,因此需要提前规划好容量,数据架构师就是通过schema来判断当前业务的Redis是否需要“分库分表”以满足可扩展需求。

2. 容量及带宽规划
容量规划
MySQL: < 硬盘大小
Memcached: < RAM
Redis: < RAM

带宽规划
由于Redis比MySQL快10倍以上,因此带宽也是需要事先规划,避免带宽跑满而出现瓶颈。

3. 性能规划(QPS)
当系统读写出现瓶颈,通常如何解决?
MySQL
写: 拆分到多服务器
读: (1) 拆分 (2) 写少也可以通过增加Slave来解决

Memcached
读写: 都通过hash拆分到更多节点。

Redis:
写:拆分
读: (1) 拆分 (2) 写少也可以通过增加Slave来解决

4. 可扩展性
MySQL: 分库分表
Memcached: hash分布
Redis:也可以分库,也可以hash分布

小结
通过以上分析,Redis在很多方面同时具备MySQL及Memcached使用特征,在某些方面则更像MySQL。
由于Redis数据不能超过内存大小,一方面需要进行事先容量规划,保证容量足够;另外一方面设计上需要防止数据规模无限制增加,进而导致Redis不可扩展。
Redis需要象MySQL一样预先设计好拆分方案。

小问题
在MySQL中,通过预先建立多表或者库可以在业务增长时候将这些表或库一分为二部署到更多服务器上。
在Redis中,“分库分表”应当如何实现?有什么好的设计模式?

redis读写原理:
    Redis只会缓存所有的key的信息,如果Redis发现内存的使用量超过了某一个阀值,将触发swap的操作,Redis根据“swappability = age*log(size_in_memory)”计算出哪些key对应的value需要swap到磁盘。然后再将这些key对应的value持久化到磁盘中,同时在内存中清除。这种特性使得Redis可以保持超过其机器本身内存大小的数据。当然,机器本身的内存必须要能够保持所有的key,毕竟这些数据是不会进行swap操作的。
    当从Redis中读取数据的时候,如果读取的key对应的value不在内存中,那么Redis就需要从swap文件中加载相应数据,然后再返回给请求方。这里就存在一个I/O线程池的问题。在默认的情况下,Redis会出现阻塞,即完成所有的swap文件加载后才会相应。这种策略在客户端的数量较小,进行批量操作的时候比较合适。但是如果将Redis应用在一个大型的网站应用程序中,这显然是无法满足大并发的情况的。所以Redis运行我们设置I/O线程池的大小,对需要从swap文件中加载相应数据的读取请求进行并发操作,减少阻塞的时间。