初识Redis

一、一些常识

1、磁盘

寻址:速度毫秒级别

带宽:带宽速度G或M的级别

2、内存

寻址:速度ns。在寻址上:磁盘比内存慢10w倍

带宽:很大

3、IO

磁盘有磁道和扇区,一扇区512Byte,如果每次读取512Byte,那么索引成本会变大。所以磁盘每次返回4K的数据(4k对齐),操作系统无论读取多少都是最少4k从磁盘拿。

4、随着文件变大,取数据速度会变慢,磁盘IO成为瓶颈

二、Redis的出现

1、如果数据只是存储在磁盘的话,检索速度肯定是很慢的。为了提高查找速度,数据库出现了,数据库的data page大小4k(刚好和磁盘的4k对齐对应上,定义小了浪费,定义大不影响),但是此时如果没有建索引的话,查询速度并不会快很多。

2、数据和索引都是存储在磁盘里的,内存里面存储了B+树的树干,查询的SQL中where条件命中了索引时,会经过B+数的树干查询到叶子节点,把叶子节点读到内存对应就能把数据查询到内存里。

3、那么,有个问题。数据库的表很大,性能一定会下降??

(1)如果表有索引,增删改会变慢;

(2)查询数据呢?一个或少量查询依然很快;并发大时会受硬盘带宽影响查询速度。

如何解决这个问题???

一个极端:SAP HANA 内存级别的关系型数据库,所有数据都是放到内存中的,自然不会受磁盘瓶颈的影响。但是,唯一缺点就是太贵,一般的公司都买不起。

这时,问题就很明显了。关系型数据库在数据量大并发大时,增删改查会变慢;同时内存级别的HANA数据库又用不起,咋办,折中方案,缓存出现了。比如Redis、memcached。

当然,Redis的出现是由于所有信息系统的两个基础设施所制约

1、冯洛伊曼体系的硬件制约

2、以太网,tcp/ip的网络(不稳定)

这两个基础设施无法改变,才导致Redis的出现。如果硬件不是冯洛伊曼体系,出现了量子计算机,硬盘IO和带宽问题解决了,就没有人用Redis、memcached做缓存了;另外以太网,tcp/ip的网络不稳定。

三、Redis和memcached对比

1、Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

2、memcached:也是key-value类型,而value没有类型的概念。此时就能想到value是json类型的。json:可以表示很复杂的数据结构。

3、如果客户端想通过一个缓存系统取回value中的某一个元素。

memcached会返回value所有的数据到客户端,此时服务端网卡和IO成为瓶颈,同时客户端要有自己的代码去解析数据。

而Redis有类型的概念,并且更重要的是Redis的server中对每种类型都有自己的方法,可以直接返回需要的数据,此时网卡不会成为瓶颈,同时客户端的代码也简单。(这就有点计算向数据移动的感觉了,计算不是在客户端完成的,直接在服务端取数据时就完成了计算,直接返回需要的数据)

四、Redis为啥这么快

我们知道Redis也只是部分数据存放在内存中(内存很快,IO很慢),那为啥,Redis能够做到如此快呢,因为Redis所有IO的数据放到了epoll,然后再单进程挨个处理这里面的数据。

那啥是epoll?这就得说说整个Linux的发展进程了。

1、BIO:

BIO
例如有两个client连接到计算机(一个连接就是一个fd,假设为fd8和fd9);此时有两个进程,一个要read fd8,一个要read fd9。而早期的socket是Blocking的(如果只有一个CPU),也就是当read fd8的进程在读取时client没有数据返回时会Blocking,这时即使read fd9的进程有数据返回也无法执行read fd9,那么就会造成cpu资源的浪费。此时称为BIO。

2、NIO

NIO
socket 可以是nonblock(非阻塞)。

此时就可以用一个线程来read fd8、read fd9,先读fd8,再读fd9(因为是非阻塞,会返回有数据还是没数据),轮流读取直到有数据返回(即轮询),轮询是发生在用户空间的。而此时遍历取出数据来处理都是同一个线程来处理,即是同步。也就是同步非阻塞时期。NIO

但是存在一个问题:如果有1000个fd,代表用户进程轮询调用1000次kernel,成本很大(查询一次fd,调用一次kernel,一直在用户态和内核态不断切换,CPU不断保护现场恢复现场换来换去)

而用户解决不了这个问题,此时内核就得发展

3、多路复用NIO

多路复用NIO
内核空间增加了一个系统调用select。

此时不需要用户进程轮询调用1000次,直接调用select方法,把1000个fd传给内核,内核再把结果返回给用户,用户再判断哪些有数据,调用有数据的fd的read方法。减少了用户态和内核态的切换(以前1000个fd需要切换1000次,现在只需要一次切换),多路复用的NIO(1000个连接复用一个线程)

但是还是存在问题:用户每次需要传1000个fd,内核再返回1000个fd的结果,用户再判断内核返回的结果哪些可以用,去调用其对应的read方法,还是有点复杂。也就是内核和用户需要把fd相关的数据拷来拷去

4、epoll

epoll
内核有自己的空间,用户有自己的空间,用户不能直接访问内核空间,所以需要拷来拷去。如何解决?

共享空间(用户和内核都可以访问的空间,通过mmap来调用)里面有红黑树和链表。

用户直接把新增的fd放到共享空间的红黑树里,此时就少了拷贝的过程,用户执行系统调用;内核就能直接看到,然后内核通过fd去看谁的数据来了,将到达的数据放到链表里;此时链表就有数据了,用户就能直接读取链表的fd。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值