一、为什么会出现 Redis
想理解这个的话,我们需要一些计组的前置知识,有了的话可以跳过。
1.为什么内存读取比硬盘读取快?
内存读取至少比硬盘读取快10万倍,我们先下这个结论完事往下聊。
首先机械硬盘基本上的速度都在 100MB-200MB 之间,SSD硬盘快一点但是也是在 500MB 左右的水准,但是现在 DDR4 内存基本上都是 50GB-100GB 之间看频率。不信可以 AIDA64 测一下。
那这是为什么呢?
我们拿机械硬盘举例,如果cpu要到硬盘里面去拿数据,它得走 I/O,完事机械硬盘还得搁哪转着找资源,找到了之后把数据写到内存然后 cpu 才去内存里面读。
但是cpu如果要的数据在内存里面呢?它先读一级缓存,然后二级缓存,然后三级缓存,最后到内存里面去找。虽然它得走四步,硬盘读取也只比它多了两部调用,但是你得知道一级缓存的速度那基本上都是 1000G/s 这三个缓存用的时间和硬盘读取那都不是一个故事了,差距太大了。
2.为什么数据库比硬盘快?
数据库也比单纯读磁盘强很多。磁盘读取的话有磁道和扇区的一个概念,一个扇区是 512byte 然后每次读东西的时候都是 512byte 往外拿的,你就算只读一个字节的东西一样会给你 512 ,和缓存行的概念是一样的。
但是后来硬盘变大了,操作系统就搞了一个 4K 对齐,就是说每次读取 4k,那为什么呢?为什么硬盘变大每次读取的东西就变多了呢,因为硬盘大了放的东西也就多了
例子:
如果一个学校里面有2000个学生
那么我给学号的话是不是只需要4位数就能表示哪个学号是哪个学生了
但是如果我有2000000个学生了呢?我4位数的学号还够用吗?我就得扩大位数了
以前512byte的时候,我索引4个字节就能搞定了,
但是现在硬盘变大了东西变多了4个字节搞不定了,要么我就减少存储空间,
要么就扩大每次读取的数量。
但是 4k 对齐只是解决的了存储问题,并没有解决读取速度的问题,因为是有带宽限制的,你今天就把那个机械臂给我转到冒烟,它的速度还是有上限的(相当于你进厂打螺丝,平常人一天打 2000 颗螺丝,你就算在熟练最多也就2500,你十年经验也不好使,因为你还是人)然后就出现了 SSD,当然这个我们不扯。
4K 对齐之后还是全量 IO 速度比一开始也快不了多少,那我想让读取速度变快的关键在于解决全量 IO 的问题。
例子:
如果我一个盘里面放了一千个文档我想要找到其中的一个文档这很困难,
那如果我们用一百个文件夹去分类呢?每个文件夹里面只放部分相似的文档,
比如说 Redis 的文件夹就放 Redis 的文档这样找文档的效率就大大提升了,
同理如果后面文档数量又变大了,变成了 100W 个那就可以采用文件夹套文件夹的方式去解决。
你可以理解为我们将数据存放在表里,在表中建立了索引,然后将这一系列索引又放到索引表中,又将一系列的索引表放到了一个B+树中,然后将B+树放到了内存,这样效率就大大提升了。
因为在主要讲 Redis 关于数据库只是简单描述一下,大概概念是这样子的。
因为操作系统每次读取数据都是 4k 所以目前数据库的设计为数据表和索引表的大小都是 4K 。
例子:
比如说你现在查一个数据,它就先判断在那个区间,然后通过区间去找索引表,然后通过索引找到你真正的数据表拿数据。
但是硬盘读取就不一样了,它得随机I/O去找数据,有了数据库索引之后,直接就能通过找索引表就能命中数据了。效率大不一样。
小总结:
1.硬盘和数据库的读取差距在于索引
2.数据表 -> 索引表 -> B+树
3.关系型数据库
有了数据库的概念之后,那什么是关系型数据库呢?
关系型数据库在建表的时候,必须给出这个表有多少个字段也就是多少列,而且要给出列的类型,给出列的类型之后它在硬盘开辟的空间就已经被定死了。如果存储的时候,你建表是 5 个字段,然后只有 1 个字段有值,另外 4 个字段为空,那么其他 4 个字段就会被 0 填满。
那么如果表的数据很多的时候,性能会降低吗?
这个分两个情况:
- 并发高的时候,会受硬盘带宽的影响,这个的话和数据多不多没关系,主要是带宽问题
- 要看 sql 的复杂程度,取决于你的 sql ,如果说你是个行式数据库,完事你查 sum 或者是 age 这种,本来就很慢,数据越多越慢
小总结:关系型数据库倾向于行级存储
4.内存数据库对比
后面因为 IO 是有瓶颈的虽然它优化的很好了但是速度还是不够用,所以出现了内存数据库,顾名思义就是把数据存储到内存上的数据库,常见的有 Memcached 和 redis 等
MongoDB 不是 KV 所以不管它,主要是讲 Redis 和它的优势。
Memcached 是 03 年出来的,Redis 是 09 年。
Redis 优势在哪里?为什么用 Redis 呢?
虽然两者都是KV存储但是有一个区别,在于Memcached的value是没有类型的,而 Redis 有五个基本数据类型。但是这有关系吗?那我只能说没有关系,因为 json 能替代这五种数据类型呀。啥类型都能用 json 来代替。
但是 Redis 给不同类型提供了很多方法。那这个有关系吗?那我只能说关系大了。
例如:
我存了一个list 1,2,3,4,5,6,7 然后我要把4拿出来计算
如果是 Memcached 需要返回一整个 json,然后我把 json 转成 list,然后拿 list 去 get 到 4
那redis呢?我直接就可以在 Redis 里面 get 了
也就是计算向数据移动了,不需要 Client 计算, Redis 直接返回给我了,效率就不一样了。
并且 Redis 是可以做持久化的而 Memcached 没有提供持久化方案。
这两点也是我觉得他们之间最重要的区别了。
小总结:
- Redis 的优势不在于提供了不同的数据类型,而是给不同的数据类型提供了便捷的方法,这使得计算向数据移动。
- Redis 可以持久化