一、Redis简介
redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。
Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。
是一个完全开源免费的 key-value 内存数据库 。通常被认为是一个数据结构服务器,主要是因为其有着丰富的数据结构 strings、map、 list、sets、 sorted sets。
- Redis 使用最佳方式是全部数据 in-memory。
- Redis 更多场景是作为 Memcached 的替代者来使用。
- 当需要除 key/value 之外的更多数据类型支持时,使用 Redis 更合适。
- 当存储的数据不能被剔除时,使用 Redis 更合适。
Redis(管道,哈希):
- Redis 不仅仅支持简单的 k/v 类型的数据,同时还提供 list,set,zset,hash 等数据结构的存储。
- Redis 支持数据的备份,即 master-slave 模式的数据备份。
- Redis 支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
二、Redis 实现原理或机制
Redis 是一个 key-value 存储系统。和 Memcached 类似,但是解决了断电后数据完全丢失的情况,而且她支持更多元化的 value 类型,除了和 string 外,还支持lists(链表)、sets(集合)和 zsets(有序集合)几种数据类型。这些数据类型都支持 push/pop、add/remove 及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。
Redis 是一种基于客户端 - 服务端模型以及请求 / 响应协议的 TCP 服务。这意味着通常情况下一个请求会遵循以下步骤:
- 客户端向服务端发送一个查询请求,并监听 Socket 返回,通常是以阻塞模式,等待
- 服务端响应。服务端处理命令,并将结果返回给客户端。
- 在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应。
Redis 管道技术最显著的优势是提高了 Redis 服务的性能。
分区是分割数据到多个 Redis 实例的处理过程,因此每个实例只保存 key 的一个子集。
Redis 有两种类型分区:
- 最简单的分区方式是按范围分区,就是映射一定范围的对象到特定的 Redis 实例。比如,ID 从 0 到 10000 的用户会保存到实例 R0,ID 从 10001 到 20000 的用户会保存到 R1,以此类推。
这种方式是可行的,并且在实际中使用,不足就是要有一个区间范围到实例的映射表。这个表要被管理,同时还需要各 种对象的映射表,通常对 Redis 来说并非是好的方法。 - 哈希分区:另外一种分区方法是 hash 分区。这对任何 key 都适用,也无需是object_name: 这种形式,像下面描述的一样简单:用一个 hash 函数将 key 转换为一个数字,比如使用 crc32 hash 函数。对 keyfoobar 执行 crc32(foobar) 会输出类似 93024922 的整数。
对这个整数取模,将其转化为 0-3 之间的数字,就可以将这个整数映射到 4 个Redis 实例中的一个了。93024922 % 4 = 2,就是说 key foobar 应该被存到 R2实例中。注意:取模操作是取除的余数,通常在多种编程语言中用 % 操作符实现。
三、Redis集群模式存在的问题
3.1 扩容问题
因为使用了一致性哈希进行分片,那么不同的 key 分布到不同的 Redis Server 上,当我们需要扩容时,需要增加机器到分片列表中,这时候会使得同样的 key 算出来落到跟原来不同的机器上,这样如果要取某一个值,会出现取不到的情况,对于这种情况,Redis 的作者提出了一种名为 Pre-Sharding 的方式:Pre-Sharding 方法是将每一个台物理机上,运行多个不同端口的 Redis 实例,假如有三个物理机,每个物理机运行三个 Redis 实例,那么我们的分片列表中实际有 9 个 Redis 实例,当我们需要扩容时,增加一台物理机,步骤如下:
- 在新的物理机上运行 Redis-Server;
- 该 Redis-Server 从属于 (slaveof) 分片列表中的某一 Redis-Server(假设叫 RedisA);
- 等主从复制 (Replication) 完成后,将客户端分片列表中 RedisA 的IP 和端口改为新物理机上 Redis-Server 的 IP 和端口;
- 停止 RedisA。这样相当于将某一 Redis-Server 转移到了一台新机器上。Prd-Sharding 实际上是一种在线扩容的办法,但还是很依赖 Redis 本身的复制功能的,如果主库快照数据文件过大,这个复制的过程也会很久,同时会给主库带来压力。所以做这个拆分的过程最好选择为业务访问低峰时段进行。
3.2 单点故障问题
还是用到 Redis 主从复制的功能,两台物理主机上分别都运行有Redis Server,其中一个 Redis-Server 是另一个的从库,采用双机热备技术,客户端通过虚拟 IP 访问主库的物理 IP,当主库宕机时,切换到从库的物理 IP。只是事后修复主库时,应该将之前的从库改为主库(使用命令 slaveof noone),主库变为其从库(使命令 slaveof IP PORT),这样才能保证修复期间新增数据的一致性。
3.3 Redis 有什么用?
- 速度快:使用标准 C 写,所有数据都在内存中完成,读写速度分别达到 10万 / 20 万。
- 持久化:对数据的更新采用 Copy-on-write 技术,可以异步地保存到磁盘上,主要有两种策略,一是根据时间,更新次数的快照(save 300 10 )二是基于语句追加方式 (Append-only file,aof) 。
- 自动操作:对不同数据类型的操作都是自动的,很安全。
- 快速的主 – 从复制,官方提供了一个数据,Slave 在 21 秒即完成了对Amazon 网站 10G key set 的复制。
- Sharding 技术: 很容易将数据分布到多个 Redis 实例中,数据库的扩展是个永恒的话题,在关系型数据库中,主要是以添加硬件、以分区为主要技术形式的纵向扩展解决了很多的应用场景,但随着 web2.0、移动互联网、云计算等应用的兴起,这种扩展模式已经不太适合了,所以近年来,像采用主从配置、数据库复制形式的,Sharding 这种技术把负载分布到多个特理节点上去的横向扩展方式用处越来越多。
3.4 小结
- 提高了 DB 的可扩展性,只需要将新加的数据放到新加的服务器上就可以了
- 提高了 DB 的可用性,只影响到需要访问的 shard 服务器上的数据的用户
- 提高了 DB 的可维护性,对系统的升级和配置可以按 shard 一个个来搞,对服务产生的影响较小
- 小的数据库存的查询压力小,查询更快,性能更好
四、MongoDB简介
MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
非关系型数据库 (NoSql),Mongo DB 很好的实现了面向对象的思想 (OO 思想), 在Mongo DB 中 每一条记录都是一个 Document 对象。Mongo DB 最大的优势在于所有的数据持久操作都无需开发人员手动编写 SQL 语句, 直接调用方法就可以轻松的实现 CRUD 操作.
4.1 MongoDB 的特点
- 高性能、易部署、易使用,存储数据非常方便。主要功能特性有:
- 面向集合存储,易存储对象类型的数据。
- 模式自由。
- 支持动态查询。
- 支持完全索引,包含内部对象。
- 支持查询。
- 支持复制和故障恢复。
- 使用高效的二进制数据存储,包括大型对象(如视频等)。
- 自动处理碎片,以支持云计算层次的扩展性
- 支持 Python,PHP,Ruby,Java,C,C#,Javascript,Perl 及 C++ 语言的驱动程序,社区中也提供了对 Erlang 及. NET 等平台的驱动程序。
- 文件存储格式为 BSON(一种 JSON 的扩展)。
- 可通过网络访问。
4.2 MongoDB 的功能
- 面向集合的存储:适合存储对象及 JSON 形式的数据。
- 动态查询:Mongo 支持丰富的查询表达式。查询指令使用 JSON 形式的标记,可轻易查询文档中内嵌的对象及数组。
- 完整的索引支持:包括文档内嵌对象及数组。Mongo 的查询优化器会分析查询表达式,并生成一个高效的查询计划。
- 查询监视:Mongo 包含一个监视工具用于分析数据库操作的性能。
- 复制及自动故障转移:Mongo 数据库支持服务器之间的数据复制,支持主 - 从模式及服务器之间的相互复制。复制的主要目标是提供冗余及自动故障转移。
- 高效的传统存储方式:支持二进制数据及大型对象(如照片或图片)
- 自动分片以支持云级别的伸缩性:自动分片功能支持水平的数据库集群,可动态添加额外的机器。
4.3 MongoDB 的适用场景
- 网站数据:Mongo 非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。
- 缓存:由于性能很高,Mongo 也适合作为信息基础设施的缓存层。在系统重启之后,由 Mongo 搭建的持久化缓存层可以避免下层的数据源 过载。
- 大尺寸,低价值的数据:使用传统的关系型数据库存储一些数据时可能会比较昂贵,在此之前,很多时候程序员往往会选择传统的文件进行存储。
- 高伸缩性的场景:Mongo 非常适合由数十或数百台服务器组成的数据库。Mongo的路线图中已经包含对 MapReduce 引擎的内置支持。
- 用于对象及 JSON 数据的存储:Mongo 的 BSON 数据格式非常适合文档化格式的存储及查询。
五、Redis、memcache、MongoDB 对比
mongodb 和 memcached 不是一个范畴内的东西。mongodb 是文档型的非关系型数据库,其优势在于查询功能比较强大,能存储海量数据。和 memcached 更为接近的是 Redis。它们都是内存型数据库,数据保存在内存中,通过 tcp 直接存取,优势是速度快,并发高,缺点是数据类型有限,查询功能不强,一般用作缓存。
5.1 性能
Redis 和 memcache 差不多,要大于 mongodb。
5.2 操作的便利性
- memcache 数据结构单一。
- Redis 丰富一些,数据操作方面,Redis 更好一些,较少的网络 IO 次数。
- mongodb 支持丰富的数据表达,索引,最类似关系型数据库,支持的查询语言非常丰富。
5.3 内存空间的大小和数据量的大小
- Redis 在 2.0 版本后增加了自己的 VM 特性,突破物理内存的限制;可以对key value 设置过期时间(类似 memcache)。
- memcache 可以修改最大可用内存, 采用 LRU 算法。
- mongoDB 适合大数据量的存储,依赖操作系统 VM 做内存管理,吃内存也比较厉害,服务不要和别的服务在一起。
5.4 可用性(单点问题)
- Redis 对于单点问题,依赖客户端来实现分布式读写;主从复制时,每次从节点重新连接主节点都要依赖整个快照, 无增量复制,因性能和效率问题,所以单点问题比较复杂;不支持自动 sharding, 需要依赖程序设定一致 hash 机制。一种替代方案是,不用 Redis 本身的复制机制,采用自己做主动复制(多份存储),或者改成增量复制的方式(需要自己实现),一致性问题和性能的权衡。
- Memcache 本身没有数据冗余机制,也没必要;对于故障预防,采用依赖成熟的 hash 或者环状的算法,解决单点故障引起的抖动问题。
- mongoDB 支持 master-slave,replicaset(内部采用 paxos 选举算法,自动故障恢复),auto sharding 机制,对客户端屏蔽了故障转移和切分机制。
5.5 可靠性(持久化)
- 对于数据持久化和数据恢复,Redis 支持(快照、AOF):依赖快照进行持久化,aof 增强了可靠性的同时,对性能有所影响。
- memcache 不支持,通常用在做缓存, 提升性能;
- MongoDB 从 1.8 版本开始采用 binlog 方式支持持久化的可靠性。
5.6 数据一致性(事务支持)
- Memcache 在并发场景下,用 cas 保证一致性。
- Redis 事务支持比较弱,只能保证事务中的每个操作连续执行。
- mongoDB 不支持事务。
5.7 数据分析
mongoDB 内置了数据分析的功能 (mapreduce), 其他不支持。
5.8 应用场景
- Redis:数据量较小的更性能操作和运算上。
- memcache:用于在动态系统中减少数据库负载,提升性能; 做缓存,提高性能(适合读多写少,对于数据量比较大,可以采用 sharding)。
- MongoDB: 主要解决海量数据的访问效率问题。