Redis 漫谈

2020-02-23  本文已影响0人  Robin92

从文件存储到数据库存储

文件存储

在计算机中,一切信息的存储都是以文件的方式固化在磁盘上。这是最基本、最简单的存储方式。

很早之前,我们的所有数据只能用文件来存储,查询数据就来读取文件。如 linux 系统中命令 grep、awk。

但有一些约束严重限制了这种存储方式查询的效率。这种限制主要来自于磁盘的读取效率。

磁盘的常识:

磁盘寻址:磁头先找到 0 磁道 -> 找到分区表 -> 根据偏移量找到文件 -> 读取文件数据。
带宽/吞吐,磁盘到内存的一秒的吞吐量。一般磁盘是 百兆 级别

随着文件的变大,查询速度急剧下降。其主要原因就是:数据文件需要全部读入内存,数据需要进行全量扫描(全量 IO)。

数据库的出现

datapage 的概念

如 Redis 的 datapage 默认为 4k,将一个数据文件每 4k 分为一个 datapage 进而实现“分治”。内存在读取数据时,会以 4k 为单位进行数据读取。这个单位可调,太大索引效率会变低,太小索引占内存太大,造成浪费。

关系型数据库建表 Schema

关系型数据库建表必须给出 Schema,给出类型。这时即使插入数据行只有一个字段有值,其他空值仍会占用空间。数据二维对齐,便于搜索。

SQL 中的约束

约束:这个表中的某一个数据,只能是其他表中的某一个字段。这就是一个小对大的一个参照。能让搜索更有效率。将部分热数据放在内存,而冷数据放在磁盘上。

索引

索引,索引也是数据,也存在 datapage 中。索引将查询的关键字(id)和数据所在 datapage 的位置(内存)存储起来。所以我们可以先遍历索引,找到数据存在的大致位置,再查询。但随着数据量变大,索引也会变大。

B+ 树存索引利用内存

B+ 树,树干在内存,叶子节点是在磁盘。从而利用内存搜索更快,从而完成了整个索引。

至此为止,思考一个问题:在使用数据库时,是不是表起来越大,搜索越慢?
答:不一定。
应该这样想:数据很大,同样也维护了很大的索引,但索引主干是在内存中的。所以:

  • 如果你的搜索恰好命中索引,那数据量很大对查询不会影响很大;
  • 若未命中索引,查询一定会很慢;
  • 而对于写的话,因为每次插入数据,都需要重新维护索引,所以将导致写的速度会变慢;
  • 而对于复杂查询,又在高并发场景下,查询可能就会有问题了(Query Cache)。

Query Cache 是数据库做的一个优化,参考。它会缓存查询结果,当相同的 select 语句到来时直接从缓存中返回数据。

插曲:db-engines 网站,查看数据库排名,并参考做数据库选型。Redis 是 Key-Value 型数据库的第一名。


Redis 与 Memcache

相同点:他们都是基于 Key-Value 类型的内存型数据库。

不同点:memcache 只能存 string,而 Redis 基于 string 有其他类型,且基于类型有了方法。

注意:Redis 和 Memcache 最大的不同不只是在于支持类型的不同,而是在于 Redis 基于类型有了方法,有了方法后就可以操作各类型中具体的元素。

他们的具体区别:虽说有 String 就能存 json 格式的数据,但 memcache 无法取出所存数据的某一部分数据,即 memcache 只能取出了其全量数据(数据向计算移动)。而 Redis 可以(计算向数据移动)。

比如用 memcache 用 json 的字符串表示一个 list,但它无法取出指定的一个元素的数据(如 k[1])。

数据向计算移动:拿到数据再计算。数据全量取出后,再由客户端来计算。
计算向数据移动:先计算好拿哪个,再去拿数据。客户端只需要指明公式,由数据库取数据时自己计算要取的值并返回。


Linux 实用技术

strace 工具:抓取进程对内核的系统调用

linux strace 工具,可以抓取进程运行时对系统调用的日志。

使用方法:

strace -ff -o path/to/filename ./server_name

程序将会把 server_name 进程执行的所有系统调用日志,输出到 path/to/filename.PID 文件中。

在进程运行的同时,你可以到 /proc/PID/ 目录下看各 PID 的运行情况。

如在已经监听的 redis-server 中,用一客户端执行 BGSAVE(一个持久化命令),则会发现日志文件会多出一个。而此时(未执行命令时),在主线程中可以看到一个频繁执行的函数,即 epoll 函数(引出正文 Epoll 讲解)。

由此可以看到 Redis 启动了多个线程。那为什么我们广泛得说 Redis 是单线程的呢?这是因为我们常说的单线程是指 在业务处理时 是单线程来处理的。

其实在 linux 系统中没有线程的概念,其实都是进程,而在 linux 中是轻量级的进程。

Linux /proc/PID 目录

Linux 中 /proc/ 目录中存了各个进程运行的相关日志。运行的进程以进程号(PID)为文件夹名存放。


后续见:从 BIO 到 NIO 最后到 Epoll

附:

上一篇下一篇

猜你喜欢

热点阅读