epoll、mysql概念及简单操作
epoll
程序阻塞的过程
假设我们目前运行了三个进程A B C ,如果他们都在处于运行态,那就会被加到一个运行队列中
进程A正在运行socket程序
在linux中有句话,万物皆文件,socket对象的读写其实也是创建了文件进行读写
所以阻塞过程为:
1、首先系统会创建一个文件描述符指向一个socket对象,其中包含了读写缓冲区,等待队列
2、当程序执行到阻塞函数(accept、recv)的时候,系统会将进程A 从工作队列中移除
3、将进程A的引用添加到socket对象的等待队列中,这样cpu过来调用就不会调用进程A ,A就进入阻塞状态
进程的唤醒
1、tcp通讯过程中,当网卡接收到数据时,他会先将数据写到系统的缓冲区
2、发送中断信号给cpu,中断信号就是一个可以让cpu提前做你的任务的一个信号(相当于给你的任务提高优先级)
3、cpu执行中断程序,将数据从内核(系统缓冲区)copy到socket的缓冲区(应用程序内存)
4、唤醒进程,即将进程A切换到就绪态,同时从socket的等待队列中移除这个进程的引用
select检测多个socket
select实现的思路比较直接
1、将所有的socket对象放到一个列表当中,例如rlist = [socket1,socket2,...]
2、当遇到阻塞IO的时候,先遍历一遍上述的列表,然后把进程A添加到每一个socket的等待队列中,然后阻塞进程
3、当数据达到时,cpu执行中断程序,将数据copy给socket缓冲区,同时唤醒处于等待队列中的进程A
为了防止重复添加到等待队列,还需要移除已经存在的进程A
4、进程A唤醒后 由于不清楚哪个socket有数据,所以还需要再遍历一遍所有的socket,看看哪个有数据
select的优点与面临的问题
从上面不难看出select其中的优点与缺点
优点:实现方式简单粗暴,所以基本各个平台都有实现的方法
缺点:
1、select需要遍历socket列表,频繁的对等待队列进行添加移除的操作
2、数据到达了也需要遍历一遍socket列表才能知道谁有数据了
随着并发量的增加,这两个操作的耗时时间也大大增加,出于对效率的考虑,select只能同时检测1024个socket
epoll处理select问题的方法
由于select处理并发的并发量不能满足人们的需要,epoll就应运而生了,他能处理的并发量直接就以万级来计
不过epoll只有再linux中可用,这也是为什么服务器基本不采用windows的原因,nginx就是用epoll实现的
1、解决避免频繁的对等待队列进行操作
首先对于第一个问题我们先看select的处理方式
r_list,w_list,_ = select.select(rlist,wlist,xlist)
每次处理完一次读写后,都需要将所有的过程都重复一遍,包括移除进程,添加进程,没有
可处理socket默认就会将进程添加到等待队列,并阻塞住进程。
对于这个第一个问题epoll,采取的方案是,将等待队列的维护和阻塞进程这两个操作进行拆分
先创建一个epoll对象,通过epoll对象的register和unregister方法对等待队列的维护(添加和移除)
通过epoll.epoll()来阻塞进程
(个人见解:epoll对象就相当于对所有的socket对象进行统一管理,
没有socket对象有数据处理时就用epoll.epoll()来阻塞进程
当有socket有数据时,就将进程从epoll对象的等待队列移除,相当于以前需要每个socket对象的等
待队列都需要移除和添加操作,现在只用一个来代替,避免没必要的频繁操作socket对象的等待队列)
2、解决select中进程无法获知哪些socket是有数据所以需要遍历
epoll为了解决这个问题,在内核中维护了一个就绪列表
1、创建epoll对象,epoll对象也会对应一个文件
2、执行register时,也会将epoll对象添加到socket的等待队列中
3、当数据到达后,cpu执行中断程序,将数据copy给socket
4、在epoll中,中断程序接下来回执行epoll对象中的回调函数,传入就绪的socket对象
5、将socket添加到就绪列表中(这样有数据的socket对象都会被单独放到一个队列中)
6、唤醒epoll等待队列中的进程
进程唤醒后,由于存在就绪列表,所以不需要再遍历socket,直接处理就绪列表即可
epoll相关函数
# 创建epoll对象 epoll = select.epoll() # 将socket对象添加到epoll检测队列中 epoll.register(server.fileno(),select.EPOLLIN) # server.fineno() 表示的是socket对象对应的文件描述符,EPOLLIN指的是可读事件、EPOLLOUT是可写事件 epoll.epoll() # 阻塞程序的代码,当检测的事件发生的时候就会接着往下执行 epoll.unregister(server.fileno()) # 将socket对象从检测队列中删除,只需要提供对应的文件描述符即可 epoll.motify(server.fileno(),select.EPOLLIN) # 更改检测队列中某个socket对象的检测事件
MySQL(重点)
数据库相关概念
数据库就是存储数据的仓库
数据库的本质就是一套CS结构的TCP程序,可以远程登录对数据库进行操作
客户端连接到服务器,向服务器发送指令,来完成数据的操作
常见数据库
1、关系型数据库
数据库可以为数据与数据之间建立关联关系,比如人是一条数据,他可能关联着一个工作岗位数据,
双方都可以通过自身找到对方
mysql 免费开源,支持中大型企业
为了防止mysql被闭源,以及担心oracle的优化能力
创始人widenius 另起炉灶 开发了 mariaDB mariaDB完全兼容mysql 使用方式一样
oracle 收费闭源 ,功能强大 ,分布式数据库
SQLserver 微软生态圈,仅支持windows系统 太局限
DB2 IBM 开发的数据库软件,收费闭源,经常与IBM的机器绑定销售
2、非关系型数据库
通过key value存储数据,各个数据之间没有关系,不是通用性数据库,有局限性,通常将
数据存储再内存中以提高速度,所以非关系型数据库多用于缓存,与关系型数据库搭配使用
MongoDB
redis
memcache
数据库与文件系统的对应关系
一个数据项 name = jerry 本质是文件中某一行的一部分数据
一条记录 jerry,18,man 本质是文件里的一行数据
一张表 本质是一个文件
数据库 本质是一个文件夹
DBMS DataBaseManagerSystem 数据库管理系统,数据库的服务器端程序
数据库服务器 运行有DBMS的计算机
数据库安装方式
1、下载解压包 :https://dev.mysql.com/downloads/file/?id=485812
2、解压到某个文件目录下
3、添加环境变量
将解压完的文件中bin文件的绝对路径copy添加到系统环境变量的path中
4、作为服务器应该自启动mysql服务器,需要添加到系统服务
mysql --install 运行完毕,windows查询server,看看server里是否有mysql
sc delete mysql 删除服务(如果需要重装的话,不删除服务的话文件删除不全)
net start mysql 启动服务
net stop mysql 停止服务
连接服务器的指令
本质是TCP程序,所以连接必须指定ip和端口,如果服务器就运行在本机上,可以省略ip
如果端口没改过,也可以省略端口
完整的写法
mysql -h(ip) -P(端口) -u(用户名) -p(密码)
如果刚开始没设置密码的话输入用户名不用输密码就可以直接进入
如果是直接输入mysql进入的话默认是游客模式,游客只能浏览,不能修改
修改管理员的密码
1、如果知道原密码可以使用 mysqladmin 这个工具(直接在终端执行,不需要登录MySQL)
mysqladmin -u用户名 -p旧密码 password 新密码 # 设置新密码和password中间是有空格的
2、不知道原始密码的情况
1、先关闭mysql服务器,直接在终端执行 mysqld --skip-grant-tables
2、无密码登录root账号
3、执行更新语句
update mysql.user set password = password("新密码") where user="要修改的用户名" and host="localhost";
4、刷新访问权限表
flush privileges;
设置远程登录的账号
1、首先使用你的root账号登录到数据库
2、设置访问权限
grant all privileges on *.* to "账号名"@"%" identified by "密码" with grant option;
其中“*.*”代表资源所有权限 ,@后面的%号表示所有的访问地址,也可以使用唯一的访问地址进行替换“localhost”
3、刷新访问权限表
flush privileges;