Loading

【Redis】线程框架和性能辩思

【Redis】线程框架和性能辩思

Redis是什么

REmote DIctionary Server

当缓存当数据库都行

image

与内存KV相比拓展性更强

image

相较于传统的MySQL等较为简单,可以通过Lua脚本完成复杂的操作

线程模型

服务器做的事情: 以TCP服务器为例,一般做法就是监听一个端口,然后接收连接,从连接上收请求,收到连接后处理,处理完了再把回复写回去

服务器内部的线程模型:怎么在进程中去分配线程的执行流,去把上面的事情完全做完

image

redis是一个单线程的程序,redis所有网络的操作:接受新连接,处理请求等在一个线程内部处理

线程和性能的关系

image

Redis开20个进程可能效果比20个线程的X效果要好,避免了加锁以及用户内核态的切换

Q:内核态命令比较慢?

A:用户可以有多个,内核只有一个,比如你和你同学是两个线程,你们自己的桌子就是用户态,各自看书可以互不影响,假设公共书架是内核,要去书架拿书到桌子上则是到内核态做事,这时候就会有冲突,而且你要去书架取书也需要做更多事情,耗费更长时间

Q:不同进程也是共用一个内核吗?共用4g内存的高1g地址空间,在内核空间的这1g中,一定是共享的同一块内存是不?

A:不确定,linux 32bit的低端内存的确只有700多M,理论上直接映射没关系,但是FD之类的信息理论上可以每个进程映射不同内存的

怎样做到高性能

image

当CPU执行时,所需的数据不在寄存器或cache中。需要去内存加载数据,这期间CPU没有工作,等待,称stall。

这里泛指:后面有任务去做,但卡在了等待阻塞的系统调用上

Redis里的线程模型

image

redis怎么工作

有很多的socket要去监听,一个线程不可能阻塞多个socket,所以把socket放在一个多路复用的一个对象里。

以epoll为例,把socket全部放在epoll里面,调用epollwait操作,假设当前这些socket上没有事件可以做,epollwait对象就会一直阻塞,一直等到某个socket上有事件可以触发时,(事件就是对socket做read或write操作),epollwait返回成功,某个socket可读。这个请求就会就会进入线程的流程,readQueryFromClient。。在数据库中处理请求,把回复组织好,调用sendReplyToClient进行回复的发送(不是调用socketwrite直接写到socket里面,而是记录在io多路复用的框架内)(直接写可能阻塞),io多路复用去监控,如果socket是可写的,把积攒在队列里的数据一点点写到socket里

在整个流程中唯一可能阻塞的情况就是epollwait,在等事件时可能是阻塞的,这时候阻塞是应该阻塞的。

定时器:ae,在一定事件内触发任务,通过epollwait的超时实现

非阻塞IO

fd的缓冲队列:一个文件描述字在内核中会准备一个读或者写的buffer(可以理解为一个队列)

tcp栈:负责传输层的组包

内核负责把组好的包放在队列里面

业务层去做read或者recv时只是把数据从缓冲区拷贝出去。做write或者send时也只是把数据拷贝到缓冲区中。

image

一般用非阻塞IO结合epoll

辅助线程

往磁盘上写日志是不能使用多路复用的

原因:操作系统认为往磁盘写文件是一个高速IO,认为不会阻塞

低速IO(socket、管道):如果一时半会写不进去,就会进入阻塞状态,操作系统会把线程让出来同时进入到一个sleep状态(可被中断的interruptable)。

高速IO:不可被打断 ==》远端挂载可能出问题

image

image

多核环境

image

两种方式优劣

image

R1访问较多,数据量大并且单个核使用率高

image

image

image

posted @ 2023-03-29 21:20  ydssx  阅读(12)  评论(0编辑  收藏  举报