服务器学习心得


redis原理、安装

<h1>redis安装总结</h1> <ul> <li><a href="https://www.bilibili.com/video/BV1go4y1m7Fd?p=6">https://www.bilibili.com/video/BV1go4y1m7Fd?p=6</a></li> </ul> <pre><code class="language-shell">yum install wget cd ~ mkdir soft &amp;&amp; cd soft wget http://download.redis.io/releases/redis-5.0.5tar.gz tar xf redis-5.0.5tar.gz &amp;&amp; cd redis-src # 看readme.md文件 yum install gcc make distclean make cd src # 生成了可执行程序 cd .. make install PREFIX=/opt/mashibing/redis5 vi /etc/profile #编写内容 export REDIS_HOME=/opt/mashibing/redis5 export PATH=$PATH:$REDIS_HOME/bin #保存文件 cd utils ./install serve.sh # 可执行一次或多次 service redis_6379 start/stop/stauts &gt; /etc/init.d/***</code></pre> <ul> <li>一个物理机中可以有多个redis实例(进程),通过端口区分</li> <li>可执行程序就一份,在目录中,但是内存中未来的多个实例,需要各自的配置文件,持久化目录等资源</li> </ul> <h2>redis原理</h2> <ul> <li> <p>处理用户对数据的操作是单进程,单线程,单实例。</p> <ul> <li>还有其他操作调用线程,这个些线程和处理用户数据操作没有关系。</li> </ul> </li> <li>多个客户端的一个或多个连接(socket),通过TCP握手,到达linux内核(kemel)</li> <li>redis进程和linux内核之间使用的epoll模型,非阻塞多路复用I/O,在内存中处理速度非常快</li> <li>分布式情况下,只能保证每个连接内,是用户操作数据的顺序,在单进程的单线程内,户对数据的操作是按顺序处理的。 <ul> <li>在分布式情况下,数据的一致性是最头疼问题。</li> </ul></li> </ul> <h2>nginx启动原理</h2> <ul> <li>按照多少个CPU启动多少个进程worker</li> <li>一个worker进程可以把数据压到CPU的一二三级缓存</li> <li>每个nginx进程,使用多路复用epoll模型</li> <li>linux内核kemel的epoll,是同步,非阻塞机制下的多路复用</li> </ul> <h2>epoll介绍</h2> <ul> <li><a href="https://www.bilibili.com/video/BV1go4y1m7Fd?p=7">https://www.bilibili.com/video/BV1go4y1m7Fd?p=7</a></li> <li>linux内核kemel的epoll,是同步,非阻塞机制下的多路复用</li> </ul> <h2>linux man 命令查看几类文档</h2> <ul> <li><a href="https://www.cnblogs.com/chenmingjun/p/8352478.html">https://www.cnblogs.com/chenmingjun/p/8352478.html</a></li> </ul> <pre><code class="language-shell">man ls # 标准用户命令 man 1 cd # 标准用户命令 man 2 cd # 系统调用命令 man 4 tty # 设备文件</code></pre> <h2>Linux操作系统中基础的概念</h2> <h4>用户空间 / 内核空间</h4> <ul> <li>现在操作系统都是采用虚拟存储器,对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方)。</li> <li>操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限。</li> <li>为保证用户进程不能直接操作内核(kernel),保证内核的安全,操作系统将虚拟空间划分为两部分,一部分为内核空间,一部分为用户空间。</li> </ul> <h4>进程切换</h4> <ul> <li>为控制进程执行,内核必须有能力挂起正在CPU上运行的进程,并恢复以前挂起的某个进程的执行。这种行为被称为进程切换。</li> <li>任何进程都是在操作系统内核的支持下运行的,是与内核紧密相关的,并且进程切换是非常耗费资源的。</li> </ul> <h4>进程阻塞</h4> <ul> <li>正在执行的进程,由于期待的某些事件未发生,如请求系统资源失败、等待某种操作的完成、新数据尚未到达或无新工作做等,则由系统自动执行阻塞原语(Block),使自己由运行状态变为阻塞状态。</li> <li>进程的阻塞是进程自身的一种主动行为,只有处于运行态的进程(获得了CPU资源),才可能将其转为阻塞状态。当进程进入阻塞状态,是不占用CPU资源的。</li> </ul> <h4>文件描述符</h4> <ul> <li>文件描述符(File descriptor),用于表述指向文件的引用的抽象化概念。</li> <li>文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。</li> <li>当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。</li> <li>在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。</li> <li>文件描述符这一概念只适用于UNIX、Linux这样的操作系统。</li> </ul> <h4>缓存I/O</h4> <ul> <li>缓存I/O又称为标准I/O,大多数文件系统的默认I/O操作都是缓存I/O。</li> <li>在Linux的缓存I/O机制中,操作系统会将I/O的数据缓存在文件系统的页缓存中,即数据会先被拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。</li> </ul> <h2>I/O多路复用(multiplexing)</h2> <ul> <li><a href="https://www.jianshu.com/p/397449cadc9a">https://www.jianshu.com/p/397449cadc9a</a></li> <li>可以理解为事件循环</li> <li>事件驱动模型,另一个名字是I/O多路复用 <ul> <li><a href="https://www.zhihu.com/question/28594409/answer/345897182">https://www.zhihu.com/question/28594409/answer/345897182</a></li> </ul></li> <li>本质是通过一种机制(系统内核缓冲I/O数据),让单个进程可以监视多个文件描述符,一旦某个描述符就绪(一般是读就绪或写就绪),能够通知程序进行相应的读写操作</li> <li>与多进程和多线程技术相比,I/O多路复用技术的最大优势是系统开销小,系统不必创建进程/线程,也不必维护这些进程/线程,从而大大减小了系统的开销。</li> </ul> <h2>Unix五种IO模型</h2> <table> <thead> <tr> <th>序号</th> <th>IO模型</th> <th>同步异步</th> <th>说明</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>blocking IO</td> <td>同步</td> <td>阻塞IO</td> </tr> <tr> <td>2</td> <td>nonblocking IO</td> <td>同步</td> <td>非阻塞IO</td> </tr> <tr> <td>3</td> <td>IO multiplexing</td> <td>同步</td> <td>IO多路复用</td> </tr> <tr> <td>4</td> <td>signal driven IO</td> <td>同步</td> <td>信号驱动IO</td> </tr> <tr> <td>5</td> <td>asynchronous IO</td> <td>异步</td> <td>异步IO</td> </tr> </tbody> </table> <h2>常用的I/O复用模型</h2> <ul> <li> <p><a href="https://blog.csdn.net/wteruiycbqqvwt/article/details/90299610">https://blog.csdn.net/wteruiycbqqvwt/article/details/90299610</a></p> </li> <li> <p>select,poll,epoll,都是 Linux API 提供的 IO 复用方式。</p> </li> <li> <p>select</p> <ul> <li>仅知道有I/O事件发生,并不知道是哪几个流(可能有一个,多个,甚至全部)</li> <li>只能无差别轮询所有流,找出能读出数据,或者写入数据的流,对他们进行操作</li> <li>具有O(n)的无差别轮询复杂度,同时处理的流越多,无差别轮询时间就越长</li> </ul> </li> <li>poll <ul> <li>poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个fd(文件描述符)对应的设备状态</li> <li>fd(文件描述符) File descriptor</li> <li>没有最大连接数的限制,是基于链表来存储的</li> </ul></li> <li>epoll <ul> <li>可以理解为event poll,就是事件驱动</li> <li>不同于忙轮询和无差别轮询,epoll会把哪个流发生了怎样的I/O事件通知我们</li> <li>epoll实际上是事件驱动(每个事件关联上fd)的,对这些流的操作都是有意义的</li> <li>文件描述符(fd),也就是新来的连接,通过等待事件(事件驱动),放到epoll的共享空间红黑树中,此时等待事件还是阻塞状态。</li> <li>再通过等待事件,放到链表中,维护这个事件是可写还是可读,返回到用户共享空间中,此时等待事件非阻塞状态。</li> </ul></li> </ul> <h2>select,poll,epoll的区别</h2> <table> <thead> <tr> <th></th> <th>select</th> <th>poll</th> <th>epoll</th> </tr> </thead> <tbody> <tr> <td>操作方式</td> <td>遍历</td> <td>遍历</td> <td>回调</td> </tr> <tr> <td>底层实现</td> <td>数组</td> <td>链表</td> <td>红黑树</td> </tr> <tr> <td>I/O效率</td> <td>每次调用都进行线性遍历</td> <td>每次调用都进行线性遍历</td> <td>事件通知方式,<br />每当fd就绪,系统注册的回调函数就会被调用,<br />将就绪fd放到readyList里面</td> </tr> <tr> <td>时间复杂度</td> <td>O(n)</td> <td>O(n)</td> <td>O(1)</td> </tr> <tr> <td>最大连接数</td> <td>1024(x86)或2048(x64)</td> <td>无上限</td> <td>无上限</td> </tr> <tr> <td>fd拷贝</td> <td>每次调用select,<br />都需要把fd集合从用户态拷贝到内核态</td> <td>每次调用poll,<br />都需要把fd集合从用户态拷贝到内核态</td> <td>调用epoll_ctl时拷贝进内核并保存,<br />之后每次epoll_wait不拷贝</td> </tr> </tbody> </table>

页面列表

ITEM_HTML