redis介绍和多路复用的优点

redis介绍

数据是存储在磁盘里的,磁盘有两个维度衡量
1.寻址:寻址的速度是毫秒级的;
2.带宽:单位时间可以有多少个字节流过去,然后基本上是G或者M这种级别;
磁盘里的数据,需要先加载到内存,然后再从内存到CPU进行运算
内存的话也有两个维度
1.寻址:寻址的速度是纳秒级的;
2.带宽:非常大
磁盘比内存慢了10万倍,在寻址上慢了10万倍
在 I/O 过程中,读取磁盘的速度相对内存读取速度要慢的多。因此为了能够加快处理数据的速度,需要将读取过的数据缓存在内存里。而这些缓存在内存里的数据就是高速缓冲区(buffer cache);
磁盘有磁道和扇区,扇区是512bytes
数据在数据库是行级存储的,建表之后要建立索引,否则查询速度不会提升太多。行级存储根据建表约束,即使列数据为空也会提前占位,为后边增加删除修改方便;通过建立索引也可以提升查询速度,where条件查询命中索引之后,通过索引列可以找到对应的数列,从而减少磁盘IO查询;B+Tree索引结构:数据和索引放在磁盘里,树干放在内存里,内存速度快,根据二叉树遍历树干找到索引列对应的数据区间再去磁盘找到具体的索引命中行级数据的索引数据;建立索引之后增删改数据会变慢 因为要维护索引列,索引本质也是数据,不是指针的概念;
数据量变大之后查询速度为什么会变慢:
1.如果是小批量查询,速度不会变的很慢,命中索引之后还是会变得比较快;
2.如果同时又很多查询进来,命中索引会把datapage带到内存,这个时候受硬盘带宽的影响,速度会变慢。

可以看出,数据在磁盘和内存是不一样的,但是内存在操作系统中算是稀有资源,如果作为存储数据的地方,会很昂贵。为了折中处理,所以出现了缓存的概念,即redis,redis是非关系型数据结构,内部存储是以一种K,V键值对。redis value具有类型的概念,memcach的value没有类型概念;

Redis为什么那么快?

redis是在内存上的操作;redis是单进程、单线程、单实例的;还有就是多路复用,非阻塞IO;
多路复用:I/O多路复用指通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。
在Linux世界中,一切皆文件,所有的IO设备都被抽象为一个文件概念;磁盘,网络,终端,甚至进程间通信工具管道都被当做文件对待,所有的IO操作都通过文件读写来实现;文件描述符(File description)就像是每一个文件的唯一标识,用来标注一个特定的文件

BIO/NIO/AIO

BIO:同步阻塞IO,一个进程或者线程对应处理内核的一个FD,当FD变为就绪状态的时候,进行处理,否则就一直阻塞状态,比较耗费连接和线程资源,Socket在这个时期是阻塞的;
NIO:同步非阻塞IO,用户空间中的一个连接循环读取FD,看是否就绪状态,有多少个FD就循环多少次,一个连接不只是为一个FD服务,读取一个不可用就继续读取下一个,不会阻塞;
AIO:异步非阻塞IO,所谓异步就是一个只负责读取看是否就绪状态,如果就绪交给别的处理线程去处理就行;

多路复用的几种实现方式

1. select
select它通过一个select()系统调用来监视多个文件描述符的数组,当select()返回后,该数组中就绪的文件描述符便会被内核修改标志位,使得进程可以获得这些文件描述符从而进行后续的读写操作。
select目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点,事实上从现在看来,这也是它所剩不多的优点之一。
select的一个缺点在于单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024,不过可以通过修改宏定义甚至重新编译内核的方式提升这一限制。另 外,select()所维护的存储大量文件描述符的数据结构,随着文件描述符数量的增大,其复制的开销也线性增长。同时,由于网络响应时间的延迟使得大量 TCP连接处于非活跃状态,但调select()会对所有socket进行一次线性扫描,所以这也浪费了一定的开销。

2. poll

poll和select在本质上没有多大差别,但是poll没有最大文件描述符数量的限制。poll和select同样存在一个缺点就是,包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间,而不论这些文件描述符是否就绪,它的开销随着文件描述符数量的增加而线性增大。
另 外,select()和poll()将就绪的文件描述符告诉进程后,如果进程没有对其进行IO操作,那么下次调用select()和poll()的时候将 再次报告这些文件描述符,所以它们一般不会丢失就绪的消息,这种方式称为水平触发(Level Triggered)。

3. epoll

直到Linux2.6才出现了由内核直接支持的实现方法,那就是epoll,它几乎具备了之前所说的一切优点,被公认为Linux2.6下性能最好的多路I/O就绪通知方法。
epoll可以同时支持水平触发和边缘触发(Edge Triggered,只告诉进程哪些文件描述符刚刚变为就绪状态,它只说一遍,如果我们没有采取行动,那么它将不会再次告知,这种方式称为边缘触发),理论上边缘触发的性能要更高一些,但是代码实现相当复杂。
epoll 同样只告知那些就绪的文件描述符,而且当我们调用epoll_wait()获得就绪文件描述符时,返回的不是实际的描述符,而是一个代表就绪描述符数量的值,你只需要去epoll指定的一个数组中依次取得相应数量的文件描述符即可,这里也使用了内存映射(mmap)技术,这样便彻底省掉了这些文件描述符在 系统调用时复制的开销。
另一个本质的改进在于epoll采用基于事件的就绪通知方式。在select/poll中,进程只有在调用一定的方法后, 内核才对所有监视的文件描述符进行扫描,而epoll事先通过epoll_ctl()来注册一个文件描述符,一旦基于某个文件描述符就绪时,内核会采用类 似callback的回调机制,迅速激活这个文件描述符,当进程调用epoll_wait()时便得到通知。

总结一下:select是Linux内核的一个系统调用,从用户空间到内核携带所有FD去内核请求系统调用,select把就绪态返回回去,这样FD来回拷贝比较浪费资源,并且select数据结构是数组,携带最大FD是定值1024可以通过修改Linux内核重新编译进行修改,于是poll出现,poll只是不限制数量,其他和select一样,最后出来的是epoll,epoll让内核和用户空间有一片共享空间,不用把FD搬来搬去了,因此效率提升了,这里使用了内存映射(mmap)技术。
多路复用epoll的有关过程:
线程从用户态调用内核的epoll函数实际上是调用了三个函数:
1、epoll_create函数
函数声明:int epoll_create(int size)
该 函数生成一个epoll专用的文件描述符。它其实是在内核申请一空间,用来存放你想关注的socket fd上是否发生以及发生了什么事件。size就是你在这个epoll fd上能关注的最大socket fd数。这里内核申请的空间就是mmap内存映射供内核和用户空间共享的一块存储空间,减少文件描述符在用户空间和内核来回复制的一个弊端。
2、epoll_ctl函数
函数声明:int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
该函数用于控制某个epoll文件描述符上的事件,可以注册事件,修改事件,删除事件。
参数:
epfd:由 epoll_create 生成的epoll专用的文件描述符;
op:要进行的操作例如注册事件,可能的取值EPOLL_CTL_ADD 注册、EPOLL_CTL_MOD 修 改、EPOLL_CTL_DEL 删除
3、epoll_wait函数
函数声明:int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout)
该函数用于轮询I/O事件的发生;
参数:
epfd:由epoll_create 生成的epoll专用的文件描述符;
epoll_event:用于回传代处理事件的数组;
maxevents:每次能处理的事件数;
timeout:等待I/O事件发生的超时值(单位我也不太清楚);-1相当于阻塞,0相当于非阻塞。一般用-1即可
返回发生事件数。

整个epoll实现多路复用的一个历程是:
用户空间调用内核的系统调用epoll中的epoll_create函数做的一件事就是开辟空共享内存空间,将所有文件描述符放在共享空间的红黑树;用户空间还会调用epoll_wait函数,有处于就绪状态可读可写的文件描述符了,文件描述符会转移到共享内存的链表上,epoll_wait停止阻塞,返回给用户空间,用户空间对文件描述符进行操作。epoll_ctl可以对文件描述符进行增删改操作。

redis运行原理
当有多个redis客户端连接到redis所在服务器的时候就是多个socket连接到redis服务器的内核上了,redis就是一个线程,调用epoll系统调用来找到就绪的文件描述符fd,然后进行处理;reids是单线程单进程的一个实例,但是redis不是只有一个进程线程,而是只有一个进程线程来处理redis客户端请求的;
单进程单线程的处理请求有一个好处就是保证了顺序的一致性,在分布式的系统中是很有好处的,保证的顺序性是每个连接内的顺序是有顺序的,一个连接请求内,即使是多线程的,只要这个请求内部是可以控制的,redis服务内部只有一个线程来处理请求,就可以保证,只要进入的连接内是有序的,那么redis就是有序处理的;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值