非关系型数据库之 redis

 NoSQL诞生的是为了解决现有关系型数据库所解决不了的问题。云计算时代对技术有了更高的要求,具体总结为4点,读写速度低延迟,可支持海量数据和流量,更简单的部署和管理分布式集群,减小越来越大的运营成本。而现有的主流的存储系统大部分还是采用了关系型数据库,其限制性很难满足以上需求。下面会从 NoSQL 的优势逐步聊到 redis 的一些重要概念,以及如何在分布式系统中应用。

关系型数据库的限制性

  • 扩展困难:Join联合多表查询机制,使得数据库扩展艰难。

  • 读写速度慢:当数据量很大时,由于关系型数据库的系统逻辑非常复杂,使得其很容易发生死锁等并发问题,导致读写速度下滑非常严重。

  • License成本高:企业级数据库的价格惊人,并且随着系统的规模而增加。

  • 有限的支撑容量:现有关系型解决方案无法支撑Google这样海量的数据存储。

NoSQL数据库的特性

为了解决这些需求,很多新类型的数据被开发出来,它们在设计上非常关注对数据高并发地读写和对海量数据的存储,与关系型数据库相比,它们在架构和数据模型方面做了“减法”,而在扩展和并发等方面做了“加法”。 他们有一些共同的特性,而被统称为 NoSQL 数据库。

  • 不再使用SQL语言,比如MongoDB、Cassandra就有自己的查询语言。
  • 通常是开源项目。
  • 为集群运行而生。
  • 弱结构化,不会严格的限制数据结构类型。

现在主流的NoSQL数据库有BigTable、HBase、Cassandra、SimpleDB、CouchDB、MongoDB和Redis等。

NoSQL 数据库分类及适用场景

键值(Key-Value)数据库

键值数据库就像在传统语言中使用的哈希表,可以通过key来添加、查询或者删除数据,鉴于使用主键访问,所以会获得不错的性能及扩展性。

  • 产品:Redis、Memcached、Riak、Amazon’s Dynamo

  • 早期使用公司:GitHub(Riak)、BestBuy(Riak)、Twitter(Redis和Memcached)、StackOverFlow(Redis)、 Instagram(Redis)、Youtube(Memcached)、Wikipedia(Memcached)

键值数据库——适用场景

储存用户信息,比如会话、配置文件、参数、购物车等等。这些信息一般都和ID(键)挂钩,这种情景下键值数据库是个很好的选择。

键值数据库——不适用场景

  1. 取代通过键查询,而是通过值来查询。Key-Value数据库中根本没有通过值查询的途径。

  2. 需要储存数据之间的关系。在Key-Value数据库中不能通过两个或以上的键来关联数据。

  3. 事务的支持。在Key-Value数据库中故障产生时不可以进行回滚。

面向文档(Document-Oriented)数据库

面向文档数据库会将数据以文档的形式储存。每个文档都是自包含的数据单元,是一系列数据项的集合。每个数据项都有一个名称与对应的值,值既可以是简单的数据类型,如字符串、数字和日期等;也可以是复杂的类型,如有序列表和关联对象。数据存储的最小单位是文档,同一个表中存储的文档属性可以是不同的,数据可以使用XML、JSON或者JSONB等多种形式存储。

  • 产品:MongoDB、CouchDB、RavenDB

  • 早期使用公司:SAP(MongoDB)、Codecademy(MongoDB)、Foursquare(MongoDB)、NBC News(RavenDB)

文档数据库——适用场景

  1. 日志。企业环境下,每个应用程序都有不同的日志信息。 Document-Oriented数据库并没有固定的模式,所以我们可以使用它储存不同的信息。

  2. 分析。鉴于它的弱模式结构,不改变模式下就可以储存不同的度量方法及添加新的度量。

文档数据库——不适用场景

在不同的文档上添加事务。Document-Oriented数据库并不支持文档间的事务,如果对这方面有需求则不应该选用这个解决方案。

列存储(Wide Column Store/Column-Family)数据库

列存储数据库将数据储存在列族(column family)中,一个列族存储经常被一起查询的相关数据。举个例子,如果我们有一个Person类,我们通常会一起查询他们的姓名和年龄而不是薪资。这种情况下,姓名和年龄就会被放入一个列族中,而薪资则在另一个列族中。

  • 产品:Cassandra、HBase

  • 早期使用公司:Ebay (Cassandra)、Instagram (Cassandra)、NASA (Cassandra)、Twitter (Cassandra and HBase)、Facebook (HBase)、Yahoo!(HBase)

列族数据库——适用场景

  1. 日志。因为我们可以将数据储存在不同的列中,每个应用程序可以将信息写入自己的列族中。

  2. 博客平台。我们储存每个信息到不同的列族中。举个例子,标签可以储存在一个,类别可以在一个,而文章则在另一个。

列族数据库——不适用场景

  1. 如果我们需要ACID事务。Cassandra就不支持事务。

  2. 原型设计。如果我们分析Cassandra的数据结构,我们就会发现结构是基于我们期望的数据查询方式而定。在模型设计之初,我们根本不可能去预测它的查询方式,而一旦查询方式改变,我们就必须重新设计列族。

图(Graph-Oriented)数据库

图数据库允许我们将数据以图的方式储存。实体会被作为顶点,而实体之间的关系则会被作为边。比如我们有三个实体,Steve Jobs、Apple和Next,则会有两个“Founded by”的边将Apple和Next连接到Steve Jobs。

产品:Neo4J、Infinite Graph、OrientDB

有谁在使用:Adobe (Neo4J)、Cisco (Neo4J)、T-Mobile (Neo4J)

图数据库——适用场景

  1. 在一些关系性强的数据中

  2. 推荐引擎。如果我们将数据以图的形式表现,那么将会非常有益于推荐的制定

图数据库——不适用场景

不适合的数据模型。图数据库的适用范围很小,因为很少有操作涉及到整个图。

言归正传——Redis特点

Redis是一个开源的使用C语言编写、开源、支持网络、可基于内存亦可持久化的日志型、高性能的Key-Value数据库,并提供多种语言的API。

Redis 与其他键值数据库相比,有如下3个特点

  1. Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。

  2. Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。

  3. Redis支持数据的备份,即master-slave模式的数据备份。

Redis优势

  • 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
  • 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
  • 支持事务、单线程、原子性 – Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。
  • 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。

redis相比memcached有哪些优势?

  • memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型

  • redis的速度比memcached快很多

  • redis可以持久化其数据

Redis 数据类型

它通常被称为数据结构服务器,因为值(value)可以是 字符串(String)、哈希(Hash)、 列表(list)、集合(sets)、有序集合(sorted sets/zset)等类型。

Redis 为什么要把所有数据放到内存中?

Redis为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。所以redis具有快速和数据持久化的特征。

如果不将数据放在内存中,磁盘I/O速度为严重影响redis的性能。在内存越来越便宜的今天,redis将会越来越受欢迎。

如果设置了最大使用的内存,则数据已有记录数达到内存限值后不能继续插入新值。

Redis是单进程单线程的

redis利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销

虚拟内存的使用

当你的key很小而value很大时,使用VM的效果会比较好.因为这样节约的内存比较大.

当你的key不小时,可以考虑使用一些非常方法将很大的key变成很大的value,比如你可以考虑将key,value组合成一个新的value.

vm-max-threads这个参数,可以设置访问swap文件的线程数,设置最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的.

可能会造成比较长时间的延迟,但是对数据完整性有很好的保证.

自己测试的时候发现用虚拟内存性能也不错。如果数据量很大,可以考虑分布式或者其他数据库

Redis常见性能问题和解决方案:

  • Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件

  • 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次

  • 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内

  • 尽量避免在压力很大的主库上增加从库

  • 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3…