zoukankan      html  css  js  c++  java
  • Redis、Memcache和MongoDB的区别

    Redis、Memcache和MongoDB的区别

     

    1.Memcached

    Memcached的优点:
    Memcached可以利用多核优势,单实例吞吐量极高,可以达到几十万QPS(取决于key、value的字节大小以及服务器硬件性能,日常环境中QPS高峰大约在4-6w左右)。适用于最大程度扛量。(适合多用户同时访问,显然,超出我们的要求)
    支持直接配置为session handle。
    Memcached的局限性:
    只支持简单的key/value数据结构,不像Redis可以支持丰富的数据类型。
    无法进行持久化,数据不能备份,只能用于缓存使用,且重启后数据全部丢失。
    无法进行数据同步,不能将MC中的数据迁移到其他MC实例中。
    Memcached内存分配采用Slab Allocation机制管理内存,value大小分布差异较大时会造成内存利用率降低,并引发低利用率时依然出现踢出等问题。需要用户注重value设计。

    2.Redis

    Redis的优点:
    支持多种数据结构,如 string(字符串)、 list(双向链表)、dict(hash表)、set(集合)、zset(排序set)、hyperloglog(基数估算)
    支持持久化操作,可以进行aof及rdb数据持久化到磁盘,从而进行数据备份或数据恢复等操作,较好的防止数据丢失的手段。
    支持通过Replication进行数据复制,通过master-slave机制,可以实时进行数据的同步复制,支持多级复制和增量复制,master-slave机制是Redis进行HA的重要手段。
    单线程请求,所有命令串行执行,并发情况下不需要考虑数据一致性问题。
    支持pub/sub消息订阅机制,可以用来进行消息订阅与通知。
    支持简单的事务需求,但业界使用场景很少,并不成熟。

    Redis的局限性:
    Redis只能使用单线程,性能受限于CPU性能,故单实例CPU最高才可能达到5-6wQPS每秒(取决于数据结构,数据大小以及服务器硬件性能,日常环境中QPS高峰大约在1-2w左右)(网站追求的是搜索效率,数据的存储,这局限性和要求没有多大的关系)。
    支持简单的事务需求,但业界使用场景很少,并不成熟,既是优点也是缺点。
    Redis在string类型上会消耗较多内存,可以使用dict(hash表)压缩存储以降低内存耗用。

    Mc和Redis都是Key-Value类型,不适合在不同数据集之间建立关系,也不适合进行查询搜索。比如redis的keys pattern这种匹配操作,对redis的性能是灾难。

     

    同时redis的key 与value存储时可以达到512M,比mongDB大了很多,同时也可以支持切片处理,存储更大的数据。

    3.mongoDB 

    mongoDB 是一种文档性的数据库。先解释一下文档的数据库,即可以存放xml、json、bson类型系那个的数据。

    这些数据具备自述性(self-describing),呈现分层的树状数据结构。redis可以用hash存放简单关系型数据。

    mongoDB 存放json格式数据。

    适合场景:事件记录、内容管理或者博客平台,比如评论系统。

    1.mongodb持久化原理

    mongodb与mysql不同,mysql的每一次更新操作都会直接写入硬盘,但是mongo不会,做为内存型数据库,数据操作会先写入内存,然后再会持久化到硬盘中去,那么mongo是如何持久化的呢
    mongodb在启动时,专门初始化一个线程不断循环(除非应用crash掉),用于在一定时间周期内来从defer队列中获取要持久化的数据并写入到磁盘的journal(日志)和mongofile(数据)处,当然因为它不是在用户添加记录时就写到磁盘上,所以按mongodb开发者说,它不会造成性能上的损耗,因为看过代码发现,当进行CUD操作时,记录(Record类型)都被放入到defer队列中以供延时批量(groupcommit)提交写入,但相信其中时间周期参数是个要认真考量的参数,系统为90毫秒,如果该值更低的话,可能会造成频繁磁盘操作,过高又会造成系统宕机时数据丢失过。

    2.什么是NoSQL数据库?NoSQL和RDBMS有什么区别?在哪些情况下使用和不使用NoSQL数据库?
    NoSQL是非关系型数据库,NoSQL = Not Only SQL。
    关系型数据库采用的结构化的数据,NoSQL采用的是键值对的方式存储数据。
    在处理非结构化/半结构化的大数据时;在水平方向上进行扩展时;随时应对动态增加的数据项时可以优先考虑使用NoSQL数据库。
    在考虑数据库的成熟度;支持;分析和商业智能;管理及专业性等问题时,应优先考虑关系型数据库。

    3.MySQLMongoDB之间最基本的区别是什么?
    关系型数据库与非关系型数据库的区别,即数据存储结构的不同。

    4.MongoDB的特点是什么?
    1)面向文档(2)高性能(3)高可用(4)易扩展(5)丰富的查询语言

    5.MongoDB支持存储过程吗?如果支持的话,怎么用?
    MongoDB支持存储过程,它是javascript写的,保存在db.system.js表中。

    6.如何理解MongoDB中的GridFS机制,MongoDB为何使用GridFS来存储文件?
    GridFS是一种将大型文件存储在MongoDB中的文件规范。使用GridFS可以将大文件分隔成多个小文档存放,这样我们能够有效的保存大文档,而且解决了BSON对象有限制的问题。

    7.为什么MongoDB的数据文件很大?
    MongoDB采用的预分配空间的方式来防止文件碎片。

    8.当更新一个正在被迁移的块(Chunk)上的文档时会发生什么?
    更新操作会立即发生在旧的块(Chunk)上,然后更改才会在所有权转移前复制到新的分片上。

    9.MongoDBA:{B,C}上建立索引,查询A:{B,C}和A:{C,B}都会使用索引吗?
    不会,只会在A:{B,C}上使用索引。

    10.如果一个分片(Shard)停止或很慢的时候,发起一个查询会怎样?
    如果一个分片停止了,除非查询设置了“Partial”选项,否则查询会返回一个错误。如果一个分片响应很慢,MongoDB会等待它的响应。

     

    4.Redis、Memcache和MongoDB的区别

    从以下几个维度,对redis、memcache、mongoDB 做了对比,

    1、性能

    都比较高,性能对我们来说应该都不是瓶颈

    总体来讲,TPS方面redis和memcache差不多,要大于mongodb

    TPS:Transactions Per Second(每秒传输的事物处理个数),即服务器每秒处理的事务数。TPS包括一条消息入和一条消息出,加上一次用户数据库访问。(业务TPS = CAPS × 每个呼叫平均TPS)

    2、操作的便利性

    memcache数据结构单一

    redis丰富一些,数据操作方面,redis更好一些,较少的网络IO次数

    mongodb支持丰富的数据表达,索引,最类似关系型数据库,支持的查询语言非常丰富

    3、内存空间的大小和数据量的大小

    redis在2.0版本后增加了自己的VM特性,突破物理内存的限制;可以对key value设置过期时间(类似memcache)

    memcache可以修改最大可用内存,采用LRU算法

    mongoDB适合大数据量的存储,依赖操作系统VM做内存管理,吃内存也比较厉害,服务不要和别的服务在一起

    4、可用性(单点问题)

    对於单点问题,

    redis,依赖客户端来实现分布式读写;主从复制时,每次从节点重新连接主节点都要依赖整个快照,无增量复制,因性能和效率问题,

    所以单点问题比较复杂;不支持自动sharding,需要依赖程序设定一致hash 机制。

    一种替代方案是,不用redis本身的复制机制,采用自己做主动复制(多份存储),或者改成增量复制的方式(需要自己实现),一致性问题和性能的权衡

    Memcache本身没有数据冗余机制,也没必要;对于故障预防,采用依赖成熟的hash或者环状的算法,解决单点故障引起的抖动问题。

    mongoDB支持master-slave,replicaset(内部采用paxos选举算法,自动故障恢复),auto sharding机制,对客户端屏蔽了故障转移和切分机制。

    5、可靠性(持久化)

    对于数据持久化和数据恢复,

    redis支持(快照、AOF):依赖快照进行持久化,aof增强了可靠性的同时,对性能有所影响

    memcache不支持,通常用在做缓存,提升性能;

    MongoDB从1.8版本开始采用binlog方式支持持久化的可靠性

    6、数据一致性(事务支持)

    Memcache 在并发场景下,用cas保证一致性

    redis事务支持比较弱,只能保证事务中的每个操作连续执行

    mongoDB不支持事务

    7、数据分析

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

    8、应用场景

    redis:数据量较小的更性能操作和运算上

    memcache:用于在动态系统中减少数据库负载,提升性能;做缓存,提高性能(适合读多写少,对于数据量比较大,可以采用sharding)

    MongoDB:主要解决海量数据的访问效率问题

    9. redis残酷性

    Redis 是个好东西,提供了很多好用的功能,而且大部分实现的都还既可靠又高效(主从复制除外)。所以一开始我们犯了一个天真的用法错误:把所有不同类型的数据都放在了一组 Redis 集群中。

    ·         长生命周期的用户状态数据

    ·         临时缓存数据

    ·         后台统计用的流水数据

    导致的问题就是当你想扩分片的时候,客户端 Hash 映射就变了,这是要迁移数据的。而所有数据放在一组 Redis 里,要把它们分开就麻烦了,每个 Redis 实例里面都是千万级的 key。

    而另外一个问题是单个 Redis 的性能上限带来的瓶颈问题。由于 CPU 的单核频率都发展到了瓶颈,都在往多核发展,一个 PC Server 一般 24或32 核。但 Redis 的单线程设计机制只能利用一个核,导致单核 CPU 的最大处理能力就是 Redis 单实例处理能力的天花板了。

    举个具体的案例,新功能上线又有点不放心,于是做了个开关放在 Redis,所有应用可以很方便的共享。通过读取 Redis 中的开关 key 来判断是否启用某个功能,对每个请求做判断。这里的问题是什么?这个 key 只能放在一个实例上,而所有的流量进入都要去这个 Redis GET 一下,导致该分片实例压力山大。而它的极限在我们的环境上不过 4 万 OPS,这个天花板其实并不高。

           总结

    认识清楚了现实的残酷性,了解了你所在环境 Redis 的真实性能指标,区分清幻想和现实。我们才能真正考虑好如何合理的利用 Redis 的多功能特性,并有效规避的它的弱项,再给出一些 Redis 的使用建议:

    -根据数据性质把 Redis 集群分类;我的经验是分三类:cache、buffer 和 db
    - cache:临时缓存数据,加分片扩容容易,一般无持久化需要。
    - buffer:用作缓冲区,平滑后端数据库的写操作,根据数据重要性可能有持久化需求。
    - db:替代数据库的用法,有持久化需求。

    ·         规避在单实例上放热点 key。

    ·         同一系统下的不同子应用或服务使用的 Redis 也要隔离开

    另外,有一种观点认为用作缓存 Memcache 更合适,这里可以独立分析下其中的优劣取舍吧。Memcache 是设计为多线程的,所以在多核机器上单实例对 CPU 的利用更有效,所以它的性能天花板也更高。(见下图)要达到同样的效果,对于一个 32 核机器,你可能需要部署 32 个 Redis 实例,对运维也是一种负担。

    https://images2015.cnblogs.com/blog/815275/201512/815275-20151222194959609-767184416.png

    除此,Redis 还有个 10k 问题,当缓存数据大于 10k(用作静态页面的缓存,就可能超过这个大小)延迟会明显增加,这也是单线程机制带来的问题。如果你的应用业务量离 Redis 的性能天花板还比较远而且也没有 10k 需求,那么用 Redis 作缓存也是合理的,可以让应用减少多依赖一种外部技术栈。最后,搞清楚现阶段你的应用到底需要什么,是多样的数据结构和功能、更好的扩展能力还是更敏感的性能需求,然后再来选择合适的工具吧。别只看到个基准测试的性能数据,就欢呼雀跃起来了。

     

    10. mongodb存储数据不能大于16M的解决方法

    GridFS是用于存储和检索超过BSON文档大小限16 MB的文件的规范。

    GridFS不是将文件存储在单个文档中,而是将文件分成多个部分或块[1] ,并将每个块存储为单独的文档。 默认情况下,GridFS使用默认的块大小255 kB; 也就是说,GridFS将文件分成255 kB的块,但最后一个块除外。最后一个块只有必要的大小。 类似地,不大于块大小的文件仅具有最终块,仅使用所需的空间加上一些额外的元数据。

    GridFS使用两个集合来存储文件。 一个集合存储文件块,另一个存储文件元数据。 GridFS部分详细描述了每个集合。

    在为文件查询GridFS时,驱动程序将根据需要重新组合块。 您可以对通过GridFS存储的文件执行范围查询。您还可以从文件的任意部分访问信息,例如“跳过”到视频或音频文件的中间。

    GridFS不仅可用于存储超过16 MB的文件,还可用于存储您想要访问的任何文件,而无需将整个文件加载到内存中。 另请参见何时使用GridFS 。

    何时使用GridFS¶

    MongoDB中,使用GridFS存储大于16 MB的文件。

    在某些情况下,在MongoDB数据库中存储大文件可能比在系统级文件系统上更高效。

    • 如果文件系统限制目录中的文件数,则可以使用GridFS根据需要存储任意数量的文件。
    • 如果要从大型文件的各个部分访问信息而无需将整个文件加载到内存中,可以使用GridFS调用文件的各个部分,而无需将整个文件读入内存。
    • 如果要在多个系统和设施中自动同步和部署文件和元数据,可以使用GridFS。 使用地理位置分散的副本集 ,MongoDB可以自动将文件及其元数据分发到许多mongod实例和工具。

    如果需要以原子方式更新整个文件的内容,请不要使用GridFS。 作为替代方案,您可以存储每个文件的多个版本,并在元数据中指定文件的当前版本。 您可以在上载新版本的文件后更新在原子更新中指示“最新”状态的元数据字段,并在以后删除以前版本(如果需要)。

    此外,如果您的文件都小于16 MB BSON Document Size限制,请考虑将每个文件存储在单个文档中,而不是使用GridFS。 您可以使用BinData数据类型来存储二进制数据。 有关使用BinData的详细信息,请参阅驱动程文档。

    解决办法小结:

    1: 更改数据表结构, 避免单个文档超过16M, 将数据分开存储, 反正mongodb也比较适合用冗余换取效率. 不妨在同一个集合中多建立几个文档, 分开存储信息

    2: 使用GridFS存储大数据量信息.

     

    10、应用场景

    redis:数据量较小的更性能操作和运算上

    MongoDB:主要解决海量数据的访问效率问题

    11.mongodb内置数据分析功能(mapreduce)

     

     

     

  • 相关阅读:
    RHEL7.2安装及配置实验环境
    VMwareworkstation 12安装
    Iterator主要有三个方法:hasNext()、next()、remove()详解
    httpclient
    http接口测试——Jmeter接口测试实例讲解
    java获取Excel的导出
    java获取Excel的导入
    java的post请求
    java的get请求
    Python3 列表(List)基础
  • 原文地址:https://www.cnblogs.com/wangshicheng/p/9885926.html
Copyright © 2011-2022 走看看