1.当进程被唤醒不清楚到底哪个socket有数据,只能遍历一遍
2.每一次select的执行,都需要将这进程,再加入到等待队列中
为了防止重复添加等待队列,当某一次操作完成时,也必须从等待队列中删除进程
所以select最大限制被设置为了1024 ,如此看来select连多线程都比不上
于是推出了poll 和 epoll
poll只是简单对select进行了优化,但是还不够完美 ,epoll才是最后的解决方案
案例:
import socket
import select
s = socket.socket()
s.bind(("127.0.0.1",1689))
s.listen()
# 创建一个epoll对象
epoll = select.epoll()
# 注册读就绪事件 (有数据可以读取了)
# s.fileno()用于获取文件描述符
epoll.register(s.fileno(),select.EPOLLIN)
# 存储文件描述符与socket的对应关系
fd_sockets = {s.fileno():s}
while True:
# 该函数是阻塞会直到你关注的事件发生
# 返回值为文件描述符与发生的事件类型 是一个列表 列表中是元组 第一个是描述符 第二个是事件
for fd,event in epoll.poll():
print("有socket 搞事情了!")
sock = fd_sockets[fd] # 取出对应的socket对象
# 判断socket是服务器还是客户端
if sock == s:
# 执行对应的接收或发送
client,addr = sock.accept()
# 注册客户端的事件
epoll.register(client.fileno(),select.EPOLLIN)
# 将对应关系存储到字典中
fd_sockets[client.fileno()] = client
print("来了一个客户端....")
elif event == select.EPOLLIN: #客户端的处理
data = sock.recv(1024)
if not data:
epoll.unregister(fd) # 注销事件
fd_sockets.pop(fd) # 从字典中删除
sock.close() # 关闭socket
continue
print("%s 发来问候:%s" % (sock,data.decode("utf-8")))
#将事件转换为可写
epoll.modify(fd,select.EPOLLOUT)
else:
sock.send("我是服务器 你丫是谁?".encode("utf-8"))
# 将事件转换为可读
epoll.modify(fd, select.EPOLLIN)
epoll 如何解决select的两个问题
1.epoll 把对于等待队列的操作 与阻塞进程分开了
2.epoll 自己维护了一个等待队列 避免了遍历所有socket
并发:
多进程 开销大
多线程 开销小于进程 但是不能无限开
协程 避免线程数量达到上线的问题 本质上属于非阻塞IO模型
IO模型 多路复用 是最好的解决方案
面试官如果问到高并发,从进程开始介绍
数据库是什么
存储数据的仓库
1.列表 字典....等等 都是内存中的 缺点:断电丢失 优点:速度快
2.文件存储 缺点:速度慢 优点:可以实现永久保存
本质就是一套基于CS结构的 客户端和服务器程序,最终的数据存储在服务器端的磁盘中
为什么要使用数据库
直接使用文件存储带来的问题
1.速度慢
2.我们的程序将来 可能后分布在不同的机器上
单台机器 性能肯定有上限,如果一台机器不能够满足,你可以用多个机器共同完成任务
分布式 每个服务器提供不同的服务,有时候某个业务流程可能会涉及到多个服务器
优点: 耦合度降低 易维护,缺点:通讯繁琐,容灾性没有集群好
集群 所有服务器提供的服务是一模一样的, 其优点:容灾性强,易扩展 可插拔
问题:数据分布在不同机器上 如何访问? 通过网络 访问
-
用户权限管理
-
多个客户端并发访问 数据要保证安全
数据库的分类
分为
1.关系型数据库
数据之间可以村存在关联关系 数据库会帮我们维护这种关系
通常存储介质都是磁盘
常见的关系型:
mysql
是我们学习的重点: 是目前最流行的关系型数据库,因为其免费开源,性能不错
目前已经被oracle收购了, 适用于中小型企业
sqlserver
是微软推出的, 因为其只能运行在windows平台所以发展不咋地
oracle sun
目前最强大的关系型数据库,主要是在集群,和用户管理上,非常适合大型企业
db2
IBM的产品,主要面向企业级用户,不差钱的用户 捆绑硬件销售
2.非关系型数据库
没有能帮我们维护数据之间的关系,
通常存储介质都是内存
常见的非关系型:
mongoDB
redis
memcache
数据库重要概念
数据(Column) 文件中的某个字符串
记录(Row) 文件中的某一行
表(Table) 某个文件
库(DataBase) 就是一个文件夹
DBMS 数据库管理系统 (指的就是数据库软件)
数据库服务器 运行DBMS的计算机
安装数据库
采用压缩包的方式来安装,解压到本地即可
bin 存储所有执行文件
data 存储数据的位置
简单的使用步骤:
bin下有 mysqld.exe 是服务器端程序 mysql.exe是客户端程序
需要先运行mysqld.exe
运行客户端时,如果直接双击运行进入游客模式
正确的运行方式 是在终端里指定 用户名密码等参数
常见的参数 -h 主机名称 如果是本机 可以忽略
-P 指定端口 默认3306 可以不写
-u 指定用户名
-p 指定密码
添加环境变量
注册系统服务
注册 mysqld --install
删除 sc delete mysql (注意 是服务名称不是文件名称)
启动服务 net start mysql;
停止 服务 net stop mysql;
查找某个进程
tasklist | findstr mysqld
杀死进程
taskkill /f /pid 111111
mysql 5.6管理员密码的设置
1.知道原始密码
1.1登录到mysql 执行更新语句来修改
update user set password = password("123") where host="localhost" and user="root";
刷新全新 flush privileges; 或者重启mysqld
2.2 mysqladmin小工具
mysqladmin -uroot -p123 password 321
-p是原始密码
2.不知道原始密码
2.2 跳过授权表
手动启动mysqld 指定参数
mysqld --skip-grant-tables
update user set password = password("111") where host="localhost" and user="root";
重启mysqld 即可
简单的使用
数据必须找个文件存起来 也就是表 , 表必须存在于库中也就是文件夹
第一步应该创建数据库 创建表
库的操作
#切换数据库
use 数据库名称 可以不加分号
#查看所有数据库
show databases;
show create databases; #查看数据库详细信息
#创建新的数据库
create database 数据库名称;
create database 数据库名称 charset utf8; # 指定编码方式
# 删除数据库
drop database 数据库名称;
#修改数据库编码 可以进入到数据库文件夹中修改db.opt
#第一行是编码 第二行是排序规则 自己搜索一个
#修改数据库名 可以直接修改对应的文件夹名称
命名规范:
1.不区分大小写
2.不要使用关键字 例如create select 等.....
3.不能使用纯数字
4.可以下滑线 通常字符下滑线数字的组合
表的操作
#创建表
create table 表名称(列名称 列的数据类型,列名称2 类型2,....) charset gbk;
# 指定编码
create table 表名称(列名称 列的数据类型,列名称2 类型2,....) charset gbk;
#查看当前库下所有表
show tables;
#查看表结构
desc 表名称;
#查看表的创建语句
show create table 表名称;
# 删除表
drop table 名称;
# 清空表数据 重建表
truncate table 名称;
# 修改表结构
# 添加字段
alter table 表名 add 列名称 数据类型;
# 删除字段
alter table 表名 drop 列名称;
# 修改数据类型
alter table 表名 modify 列名称 新的数据类型;
# 修改列名
alter table 表名 change 旧的列名 新的列名称 新的类型;
# 修改表的名称
rename table 旧名称 to 新名称;
# 修改编码
alter table 表名 charset utf8;