高性能NoSQL缓存介绍
什么是NoSQL
NoSQL(NoSQL = Not Only SQL ),意即”不仅仅是SQL”。
NoSQL的演变:
- 1970: NoSQL = We have no SQL
- 1980: NoSQL = Know SQL
- 2000: NoSQL = No SQL
- 2005: NoSQL = Not only SQL
- 2013: NoSQL = No, SQL
NoSQL的优缺点
优点:
- 高可扩展性
- 分布式计算
- 低成本
- 架构的灵活性,半结构化数据
- 没有复杂的关系
缺点:
- 没有数据标准
- 查询功能受限
- 模糊的一致性
- 不能进行关联查询
NoSQL 分类
K-V存储:
K-V 存储的全称是Key-Value
存储,其中Key
是数据的标识,和关系数据库中的主键含义一样,Value
就是具体的数据。
K-V存储主要可以解决关系型数据库无法存储数据结构的问题。
常见的K-V存储的有:
Redis
MemcacheDB
Redis可以支持的数据结构有: string
、hash
、list
、set
、sorted set
、bitmap
和 hyperloglog
文档数据库:
文档数据库可以存储和读取任意数据,目前大部分的文档数据库的数据格式为JSON
。
文档数据库主要解决关系型数据库schema约束的问题。
常见的文档数据库主要有:
MongoDB
列式数据库:
列式数据库就是按照列来存储数据的数据库,与之对应的传统关系数据库被称为“行式数据库”(关系数据库是按照行来存储数据的)。
优点:
统计分析时节省
I/O
消耗更高的存储压缩比,能够节省更多的存储空间
缺点:
- 存储数据时效率低下
全文搜索引擎:
3. 列式数据库
顾名思义,列式数据库就是按照列来存储数据的数据库,与之对应的传统关系数据库被称为“行式数据库”,因为关系数据库是按照行来存储数据的。
关系数据库按照行式来存储数据,主要有以下几个优势:
- 业务同时读取多个列时效率高,因为这些列都是按行存储在一起的,一次磁盘操作就能够把一行数据中的各个列都读取到内存中。
- 能够一次性完成对一行中的多个列的写操作,保证了针对行数据写操作的原子性和一致性;否则如果采用列存储,可能会出现某次写操作,有的列成功了,有的列失败了,导致数据不一致。
我们可以看到,行式存储的优势是在特定的业务场景下才能体现,如果不存在这样的业务场景,那么行式存储的优势也将不复存在,甚至成为劣势,典型的场景就是海量数据进行统计。例如,计算某个城市体重超重的人员数据,实际上只需要读取每个人的体重这一列并进行统计即可,而行式存储即使最终只使用一列,也会将所有行数据都读取出来。如果单行用户信息有1KB
,其中体重只有4
个字节,行式存储还是会将整行1KB
数据全部读取到内存中,这是明显的浪费。而如果采用列式存储,每个用户只需要读取4
字节的体重数据即可,I/O
将大大减少。
除了节省I/O
,列式存储还具备更高的存储压缩比,能够节省更多的存储空间。普通的行式数据库一般压缩率在3:1
到5:1
左右,而列式数据库的压缩率一般在8:1
到30:1
左右,因为单个列的数据相似度相比行来说更高,能够达到更高的压缩率。
同样,如果场景发生变化,列式存储的优势又会变成劣势。典型的场景是需要频繁地更新多个列。因为列式存储将不同列存储在磁盘上不连续的空间,导致更新多个列时磁盘是随机写操作;而行式存储时同一行多个列都存储在连续的空间,一次磁盘写操作就可以完成,列式存储的随机写效率要远远低于行式存储的写效率。此外,列式存储高压缩率在更新场景下也会成为劣势,因为更新时需要将存储数据解压后更新,然后再压缩,最后写入磁盘。
基于上述列式存储的优缺点,一般将列式存储应用在离线的大数据分析和统计场景中,因为这种场景主要是针对部分列单列进行操作,且数据写入后就无须再更新删除。
4. 全文搜索引擎
传统的关系型数据库通过索引来达到快速查询的目的,但是在全文搜索的业务场景下,索引也无能为力,主要体现在:
- 全文搜索的条件可以随意排列组合,如果通过索引来满足,则索引的数量会非常多。
- 全文搜索的模糊匹配方式,索引无法满足,只能用
like
查询,而like
查询是整表扫描,效率非常低。
我举一个具体的例子来看看关系型数据库为何无法满足全文搜索的要求。假设我们做一个婚恋网站,其主要目的是帮助程序员找朋友,但模式与传统婚恋网站不同,是“程序员发布自己的信息,用户来搜索程序员”。程序员的信息表设计如下:
ID | 姓名 | 性别 | 地点 | 单位 | 爱好 | 语言 | 自我介绍 |
---|---|---|---|---|---|---|---|
1 | 多隆 | 男 | 北京 | 猫厂 | 写代码、旅游、马拉松 | Java、C++、PHP | 技术专家,简单,为人热情 |
2 | 如花 | 女 | 上海 | 鹅厂 | 旅游、美食、唱歌 | PHP、Java | 美女如花,风华绝代,貌美如花 |
3 | 小宝 | 男 | 广州 | 熊厂 | 泡吧、踢球 | Python、Go、C | 我是一匹来自北方的狼 |
我们来看一下这个简单业务的搜索场景:
- 美女 1:听说
PHP
是世界上最好的语言,那么PHP
的程序员肯定是钱最多的,而且我妈一定要我找一个上海的。
美女 1 的搜索条件是“性别 + PHP
+ 上海”,其中“PHP”要用模糊匹配查询“语言”列,“上海”要查询“地点”列,如果用索引支撑,则需要建立“地点”这个索引。
- 美女 2:我好崇拜这些技术哥哥啊,要是能找一个鹅厂技术哥哥陪我旅游就更好了。
美女 2 的搜索条件是“性别 + 鹅厂 + 旅游”,其中“旅游”要用模糊匹配查询“爱好”列,“鹅厂”需要查询“单位”列,如果要用索引支撑,则需要建立“单位”索引。
- 美女 3:我是一个“女程序员”,想在北京找一个猫厂的 Java 技术专家。
美女 3 的搜索条件是“性别 + 猫厂 + 北京 + Java
+ 技术专家”,其中“猫厂 + 北京”可以通过索引来查询,但“Java”“技术专家”都只能通过模糊匹配来查询。
- 帅哥 4:程序员妹子有没有漂亮的呢?试试看看。
帅哥 4 的搜索条件是“性别 + 美丽 + 美女”,只能通过模糊匹配搜索“自我介绍”列。
以上只是简单举个例子,实际上搜索条件是无法列举完全的,各种排列组合非常多,通过这个简单的样例我们就可以看出关系数据库在支撑全文搜索时的不足。
(1). 全文搜索基本原理
全文搜索引擎的技术原理被称为“倒排索引”(Inverted index),也常被称为反向索引、置入档案或反向档案,是一种索引方法,其基本原理是建立单词到文档的索引。之所以被称为“倒排”索引,是和“正排“索引相对的,“正排索引”的基本原理是建立文档到单词的索引。我们通过一个简单的样例来说明这两种索引的差异。
假设我们有一个技术文章的网站,里面收集了各种技术文章,用户可以在网站浏览或者搜索文章。
正排索引示例:
文章 ID | 文章名称 | 文章内容 |
---|---|---|
1 | 敏捷架构设计原则 | 省略具体内容,文档内容包含:架构、设计、架构师等单词 |
2 | Java 编程必知必会 | 省略具体内容,文档内容包含:Java、编程、面向对象、类、架构、设计等单词 |
3 | 面向对象葵花宝典是什么 | 省略具体内容,文档内容包含:设计、模式、对象、类、Java 等单词 |
注:文章内容仅为示范,文章内容实际上存储的是几千字的内容。
正排索引适用于根据文档名称来查询文档内容。例如,用户在网站上单击了“面向对象葵花宝典是什么”,网站根据文章标题查询文章的内容展示给用户。
倒排索引示例:
单词 | 文档 ID 列表 |
---|---|
架构 | 1,2 |
设计 | 1,2,3 |
Java | 2,3 |
注:表格仅为示范,不是完整的倒排索引表格,实际上的倒排索引有成千上万行,因为每个单词就是一个索引。
倒排索引适用于根据关键词来查询文档内容。例如,用户只是想看“设计”相关的文章,网站需要将文章内容中包含“设计”一词的文章都搜索出来展示给用户。
(2). 全文搜索的使用方式
全文搜索引擎的索引对象是单词和文档,而关系数据库的索引对象是键和行,两者的术语差异很大,不能简单地等同起来。因此,为了让全文搜索引擎支持关系型数据的全文搜索,需要做一些转换操作,即将关系型数据转换为文档数据。
目前常用的转换方式是将关系型数据按照对象的形式转换为JSON
文档,然后将JSON
文档输入全文搜索引擎进行索引。我同样以程序员的基本信息表为例,看看如何转换。
将前面样例中的程序员表格转换为JSON
文档,可以得到3
个程序员信息相关的文档,我以程序员1
为例:
{
"id": 1,
" 姓名 ": " 多隆 ",
" 性别 ": " 男 ",
" 地点 ": " 北京 ",
" 单位 ": " 猫厂 ",
" 爱好 ": " 写代码,旅游,马拉松 ",
" 语言 ": "Java、C++、PHP",
" 自我介绍 ": " 技术专家,简单,为人热情 "
}
全文搜索引擎能够基于JSON
文档建立全文索引,然后快速进行全文搜索。以Elastic Search为例,其索引基本原理如下:
Elastcisearch 是分布式的文档存储方式。它能存储和检索复杂的数据结构——序列化成为JSON
文档——以实时的方式。
在 Elasticsearch 中,每个字段的所有数据都是默认被索引的。即每个字段都有为了快速检索设置的专用倒排索引。而且,不像其他多数的数据库,它能在相同的查询中使用所有倒排索引,并以惊人的速度返回结果。可参考这里查看。
小结
今天我为你讲了为了弥补关系型数据库缺陷而产生的NoSQL
技术,希望对你有所帮助。
这就是今天的全部内容,留一道思考题给你吧,因为 NoSQL 的方案功能都很强大,有人认为 NoSQL = No SQL,架构设计的时候无需再使用关系数据库,对此你怎么看?
精选留言
鹅米豆发
关于 NoSQL,看过一张图,挺形象:“1970,We have no SQL” -> “1980,Know SQL” -> “2000,NoSQL” -> “2005,Not only SQL” -> “2015,No,SQL”。目前,一些新型数据库,同时具备了 NoSQL 的扩展性和关系型数据库的很多特性。
关系型和 NoSQL 数据库的选型。考虑几个指标,数据量、并发量、实时性、一致性要求、读写分布和类型、安全性、运维性等。根据这些指标,软件系统可分成几类。
- 管理型系统,如运营类系统,首选关系型。
- 大流量系统,如电商单品页的某个服务,后台选关系型,前台选内存型。
- 日志型系统,原始数据选列式,日志搜索选倒排索引。
- 搜索型系统,指站内搜索,非通用搜索,如商品搜索,后台选关系型,前台选倒排索引。
- 事务型系统,如库存、交易、记账,选关系型+缓存+一致性协议,或新型关系数据库。
- 离线计算,如大量数据分析,首选列式,关系型也可以。
- 实时计算,如实时监控,可以选时序数据库,或列式数据库。
代码荣耀
需求驱动架构,无论选用RDB/NoSQL/DRDB,一定是以需求为导向,最终的数据存储方案也必然是各种权衡的设计妥协。
没有银弹,因为不同的应用需求对数据的要求也各不相同。当前我们不可能找到一个存储方案能满足所有的应用需求,但是我们可以通过认识到各种存储方案的优点与缺点(陷阱),在实际应用中,根据应用场景的不同要求(比如对可用性、一致性、易用性、支持事务、响应延迟、伸缩性等),按照上述特性要求的优先级排序,找到最合适的方案并“混合搭配”使用各种数据存储方案。
多种方案搭配混用必然会增加应用的复杂性与增加运维成本,但同时也带来了系统更多的灵活性。
举例:传统/互联网金融领域目前就不可能离开RDB。