学习python挺久了根据主要百度的面试题总结了一下面试可能问到的知识点,总之还差很多很多...还需要不断地添加修正。如果有大神看了评论、点赞一下给我一点信心。
输入url后发生什么:
- 查询查询浏览器缓存、检查系统缓存、检查路由器缓存、查询ISP DNS 缓存、递归查询(从根域名服务器到顶级域名服务器再到极限域名服务器依次搜索哦对应目标域名的IP)
- 三次握手(SYN、ACK,SYN、ACK),tcp封装数据包送到网络层。
- 请求、传输数据:方法、地址、ip、状态码、http版本
- nginx接受请求后判断url,静态资源直接返回,动态给uwsg服务器。
- 动态找django/flask框架,框架返回数据给uqsgi。再传给nginx
- 返回相应,释放tcp(挥手)
- 渲染页面:解析html、css代码。构建渲染树展示到页面
- arp地址解析,dns域名解析
状态码:
- 200 ok请求成功
- 301/302 重定向
- 404 未找到资源
- 204 请求成功但服务器无返回
- 400 请求错误
- 401未授权
- 403 禁止访问
- 405 请求方法错误
- 408 请求超时
- 500 服务器错误
- 501 请求方法未识别
- 502 网关错误 504 网关超时
- 503 服务器不可用 505 http版本不支持
redis缓存
需求:(memcached)
- 访问量大,要求速度快,依赖数据库
- 数据变化小|变化大是产品核心
缓存架构:
- 多级缓存
- 本地缓存
- 构建全局变量(数据受限,只限访问最频繁的数据)
- orm本身的缓存(例queryset、sqlalchemy)
- 外部缓存(多级:根据计算机体系结构的缓存分级)
- 本地缓存
缓存数据:
- 缓存一个数据
- 缓存一组数据数据库视角
-
- 每个缓存对应数据库一张表或几张相关的表(对象)
- 保存数据库查询操作的结果(数据库查询角度,一般缓存复杂查询)
- 视图视角
- 将视图处理结果
- 页面视角
- 前后端不分离(缓存页面,静态化)
-
缓存保存形式:
- 字符串:
- 优点:通用、占用空间小
- 缺点:数据只能作为整体
- (list、set、hash、zset)
- 优点:可以针对字段查询
- 缺点:占用空间比字符串大
缓存有效期:
- 原因:节省空间,同步数据库数据使得不一致不会一直存在
- 有效期策略:
- 定时过期:设置定时器,定时清理
- 惰性过期:处理时才会查询是否过期
- 定期过期:定期检查过期时间
- reids使用惰性+定期(一部分)
内存淘汰策略:
- LRU(最近最少使用)
- LFU(最近访问频率最少):定期衰减。
- redis4.x存在lfu
- redis缓存时不用持久化需要配置内存淘汰。
- redis存储是,配置持久化,不要内存淘汰
缓存使用模式:
先更新数据库,在存入缓存。
- 读缓存:
- 写缓存:将数据先保存缓存,同步数据库
缓存穿透:
- 直接查询不存在数据库无法缓存的数据,导致数据库压力过大产生异常。
- 缓存不存在数据到缓存。(常用)
- 使用过滤器。(布龙过滤器)
缓存雪崩:
- 同一时刻大量缓存数据集中过期失效,造成数据库异常。
- 对过期时间设置偏差,错开过期时间。(常用)
- 多级缓存且有效期不同,相互补充。
- 修改数据库,引入锁/队列。
+++
Redis底层原理(C):
-
自己封装的简单动态字符串(SDS),不用c的字符串:
-
len总长度,free剩余长度,buf当前字符串
C字符串 SDS 获取字符串长度的复杂度为O(N) 获取字符串长度的复杂度为O(1) API 是不安全的,可能会造成缓冲区溢出 API 是安全的,不会造成缓冲区溢出 修改字符串长度N次必然需要执行N次内存重分配 修改字符串长度N次最多执行N次内存重分配 只能保存文本数据 可以保存二进制数据和文本文数据 可以使用所有<String.h>库中的函数 可以使用一部分<string.h>库中的函数
-
-
哈希表(字典/符号表):
- Redis 中采用了连地址法(separate chaining)来解决哈希冲突。
-
跳跃表(链表和节点组成,有序集合/集群节点):
-
节点:
1、层:level 数组可以包含多个元素,每个元素都包含一个指向其他节点的指针。
2、前进指针:用于指向表尾方向的前进指针
3、跨度:用于记录两个节点之间的距离
4、后退指针:用于从表尾向表头方向访问节点
5、分值和成员:跳跃表中的所有节点都按分值从小到大排序。成员对象指向一个字符串,这个字符串对象保存着一个SDS值
- 链表: header,tail分别指向跳跃表的头结点和尾节点。level 用于记录最大的层数,length 用于记录我们的节点数量。
-
-
整数集合:为全是数字且数据量小的集合的底层实现,由数组实现。
-
压缩列表:是列表和哈希的底层之一
- 当列表中数据小且每个值都步长的时候用压缩列表。
-
链表:列表的底层之一
数据库索引底层(B-tree)
B-tree是多叉平衡查找树(多分支):
- 节点的子女等于节点中元素个数+1(最小度数即内节点中节点最小孩子数目)
- B-tree高度l - 1 = log┌m/2┐((N+1)/2 )+1
B±tree(取消指针,底部指针连接【根据顺序】):
- 孩子中有父节点的数据
- 所有的非终端结点可以看成是索引部分
- 磁盘读写代价比B-tree低,查询效率稳定
- B树在提高了磁盘IO性能的同时并没有解决元素遍历的效率低下的问题
B-tree(非根和非叶子结点再增加指向兄弟的指针):*
- B+树的分裂:当一个结点满时,分配一个新的结点,并将原结点中1/2的数据复制到新结点,最后在父结点中增加新结点的指针;B+树的分裂只影响原结点和父结点,而不会影响兄弟结点,所以它不需要指向兄弟的指针
- B*树的分裂:当一个结点满时,如果它的下一个兄弟结点未满,那么将一部分数据移到兄弟结点中,再在原结点插入关键字,最后修改父结点中兄弟结点的关键字(因为兄弟结点的关键字范围改变了);如果兄弟也满了,则在原结点与兄弟结点之间增加新结点,并各复制1/3的数据到新结点,最后在父,结点增加新结点的指针
- 所以,B*树分配新结点的概率比B+树要低,空间使用率更高。
三树区别:
-
B树:有序数组+平衡多叉树;
B+树:有序数组链表+平衡多叉树;
B*树:一棵丰满的B+树。
-
B树必须用中序遍历的方法按序扫库,而B+树直接从叶子结点扫就可以,B+树支持range-query非常方便,而B树不支持。
-
B树也好B+树也好,根或者上面几层因为被反复query,所以这几块基本都在内存中,不会出现读磁盘IO,一般已启动的时候,就会主动换入内存。
+++
python常用库:
os,time,random,pymysql,threading,multiprocessing,queue,django,flask,requests,virtualenv,selenium,scapy,xadmin,celery,re,hashlib,md5
###init和new的区别:
- init 是对对象的初始化,
- new是新建一个对象,new在init之前执行。
随机数的生成:
rnadom.random():生成0-1之间的随机浮点数
rnadom.uniform(a,b):生成a,b见的浮点数
rnadom.randint(a,b):生成a,b见的整数
rnadom.choice(sequence):特定序列随机取数
rnadom.shuffle(list):打乱列表
判断日期:
detatime.data(year=,month=,day=)
(date1-date2).days
网络七层模型:
-
物理层(中继器(也叫放大器)和集线器):
-
数据链路层(帧):
- 数据链路层为网络层提供可靠的数据传输;
- 主要的协议:以太网协议;
- 网桥和交换机.
-
传输层(IP数据报):
- IP协议的主要功能有:无连接数据报传输、数据报路由选择和差错控制。
- 网络层负责对子网间的数据包进行路由选择。此外,网络层还可以实现拥塞控制、网际互连等功能;
- 包含的主要协议:
- IP协议(Internet Protocol,因特网互联协议);
- ICMP协议(Internet Control Message Protocol,因特网控制报文协议);
- ARP协议(Address Resolution Protocol,地址解析协议);
- RARP协议(Reverse Address Resolution Protocol,逆地址解析协议)
-
网络层(tcp,udp):
- 为何挥手:数据丢失资源浪费。
SYN:"synchronize"请求同步标志;;ACK:“acknowledge"确认标志”;
FIN:"Finally"结束标志。
-
会话层:
-
表示层:
-
应用层:
- http:
- Get是从服务器上获取数据,Post是向服务器传送数据
- Get传送的数据量小,不能大于2KB;Post传送的数据量较大,一般被默认为不受限制
- 根据HTTP规范,GET用于信息获取,而且应该是安全的和幂等的
- http:
unittest:
- 是python中的单元测试框架,可以共享搭建,自动测试,在测试中暂停代码,将不同代码迭代成一组。
PEP8规范:
常量:大写+’_’ 私有变量:‘下划线’+小写
内置变量:前后都加双下划线
类:大驼峰命名法
内存泄露:
- 浪费内存资源
- 可通过sys.getrefcount(对象)查看引用计数是否为0
Tcp:
- 创建套接字、bind、阻塞监听、连接客户,recv/send、关闭套接字。
什么叫2MSL:
- 主动发送fin的以后,在4次挥手后要等待一段时间确认对方不会再有数据传送过来,这段时间称之为2MSL。(无法进行超时重传)
HTTP与s:
- http需要证书,且收费;
- http未加密不安全,s加密安全;
- 端口不同一个80一个443。
- socket(类型,应用场景)
###css初始化:
重设浏览器样式,防止页面差异。使得开发简洁方便,减少CSS代码量。
请求上下文&应用上下文:
请求上下文保存交互数据:
- 全局可访问
应用上下文保存配置信息:
- request context中的一个对app代理人,伴随request而活
mysql下SQL的导入导出:
- 导出:
- mysqldump -u用户 -p密码(可不写) 数据库名>导出文件名(当前目录下)
- mysqldump -u用户 -p密码(可不写) 数据库名 表名>导出文件名(当前目录下)
- 导出一个数据库结构:
- mysqldump -u dbuser -p -d --add-drop-table dbname >d:/dbname_db.sql
-d 没有数据 --add-drop-table 在每个create语句之前增加一个drop table(没用过)
- mysqldump -u dbuser -p -d --add-drop-table dbname >d:/dbname_db.sql
- 导入:
- 数据库名字需自己创建,通过use进入对应数据库,然后输入source 文件名(不是当前目录写绝对路径)
###Django过滤:
-
模糊查询:
- 对象.objects.filter(字段名__contains=…)
-
空查询(字段名__usnull=False)
-
范围查询(字段名__in=【】)
-
比较查询(gt大于lt小于加e包含等于)
-
查询不满足条件的数据:
- 对象.objects.exclude(条件)
-
F对象(类属性之间的比较):需要导入
from django.db.models import F
对象.objiects.filter(字段__gt=F(‘另一个字段’))
-
Q对象(与或非&|~)
- 导入
from django.db.models import F
对象.objiects.filter(Q(字段__gt=30)&Q(字段2_gt=30))
对象.objiects.filter(Q(字段__gt=30)|Q(字段2_gt=30))
对象.objiects.filter(~Q(字段__gt=30))
-
聚合函数:
from django.db.models import Sum.Count.Max,Min,Avg
对象.objiects.aggregate(Sum(字段__gt=30))
对象.objiects.aggregate(Sum(字段__gt=30)).count()
Django中间件:有六种
def __init__(): #初始化,不需要参数,只在服务器第一个响应执行
def process_reuqest():每个请求之前
def process_view():每个视图之前
def process_template_response():渲染模板前
def process_response():响应返回浏览器之前
def process_exception():视图出现异常是
uWSGI与nginx的理解:
- uwsgi是web服务器,nginx中的httpywsgimoule就是与uwsgi交互。
- wsgi是通信协议网关接口,只允许python与web交互。
- uwsgi是线路协议,用做数据通信
- nginx是高性能http服务器和反向代理:
- 处理静态文件、索引文件效率高
- 占用内存小,支持高并发5W
- 可以反向代理、负载均衡
Django数据库优化:
- 减少外键使用;
- 建立缓存机制;
- 优化sql语句(如varchar(3))
- 合理创建索引;
- 减少查询次数;
- 分库分表。读写分离
定时任务:
- crontab:
- 是linux系统自带的定时任务命令;
- 是django-crontab 拓展 封装了使用系统crontab命令的方法;
- 优点:不需要程序自己维护定时器,不占用程序的资源。
- 缺点:不太灵活,crontab是操作系统的命令,独立于系统运行,所以在程序还未运行时以确定有那些定时任务需要执行,并且交代给linux系统,在程序运行时,发现新的定时需求是,不是很方便。
- APScheduler:
- python开发的定时工具;
- 定时的计时,需要python开启单独线程/进程来计时
- 缺点:需要独立维护,占用程序资源
- 优点:灵活,不仅能做程序启动前确定的定是认为,与python程序集成方便,程序中产生的新定时任务可以方便的交给APScheduler,进行定时任务。
RPC(远程过程调用):
- web与系统间进行网络调用
- 传递的参数为必要的二进制,加快传输效率
- 通用性不高,只能连接专用客户端服务器
- 调用方式为函数调用,支持多语言
- python通用的Rpc:
- facebook开发的thrift
- Google gRPC
- gRPC:
- 封装了底层网络通信
- 二进制协议 Protocol Buffers
- 传输使用HTTP/2
- 支持多语言、多平台
数据集:
特征值+目标值
Nginx&Apache:
nginx:
- nginx占用内存资源少,
- nginx是异步非阻塞,支持高并发,Apache是阻塞性
apache:
- 模块多,bug少,稳定
####查询集的特性:惰性执行,缓存。
tornado:
ioloop&iosteram前者封装了高效io事件循环,后封装了无阻塞的soket,可以达到高效异步请求。
HTTPs:
- 优点:
- 加密传输,安全SSl+HTTP
- 缺点:
- 影响加载速度。收费
- sml:报文最大生存时间
- ttl:生存时间 msl大于ttl ip数据报最大路由数
- rtt:客户到服务器往返所花事件
代理ip:
- 透明代理:客户不需要知道代理服务器的存在
- 普通匿名代理:隐藏客户真实ip
- 高级匿名代理:不会改变客户的请求
MYSQL:
- 优化
- InnoDB有事物,MyISAM没事物
- 分裤分表,查询优化(过滤,分组)
- 分页查询limit
- 读写分离
- 减少访问次数(缓存)
- 集群优点
- 高可用,失效自动快速切换
- 分布式
- 集群缺点:
- 不支持外键
- 部署管理复杂
- 占用空间大
定义二叉树:
class TreeNode(object):
def __init__(self,left=None,right=None,value=None)
self.value = value
self.left = left
self.right = right
def preorder(root):
if value is None:
return
else:
print(root.value)
preorder(root.left)
preorder(root.right)
二分查找:
def two_search(alist,item):
n = len(alist)
if n == 0:
return False
mid = n // 2
if alist[mid] == item:
return True
elif alist[mid] > item:
return two_search( alist[:mid],item)
else:
return two_search( alist[mid+1:],item)
快速排序:
def quick_sort(alist):
if len(alist) < 2 and not alist:
return alist
a = 0
b = alist[0]
llist = [alist[i] for i in range(1, len(alist)) if alist[i] <= b]
rlist = [alist[i] for i in range(1, len(alist)) if alist[i] > b]
return quick_sort(llist) + [b] + quick_sort(rlist)
归并排序:
def merge_main_sort(alist):
if len(alist) <= 1:
return alist
mid = len(alist) // 2
llist = merge_main_sort(alist[:mid])
rlist = merge_main_sort(alist[mid:])
return merge_sort(llist,rlist)
def merge_sort(llist,rlist):
a = b = 0
len_a, len_b = len(llist), len(rlist)
c = []
while a < len_a and b < len_b:
if llist[a] < rlist[b]:
c.append(llist[a])
a += 1
else:
c.append(rlist[b])
b += 1
if a < len_a:
c.extend(llist[a:])
else:
c.extend(rlist[b:])
return c
进程线程协成:
- 进程:
- 进程的切换是内存地址空间大切换,用户态到内核态的切换,和上下文的切换。有操作系统内核完成,切换时清除上一个进程的缓存,保存上一个进程的状态,并开辟出下一个进程的环境。
- 线程:
- 是cpu分布时间片,在一个进程内完成,主要是上下文的切换和上一个状态的保持。内核完成。
- 协成:
- 轮询调用协成函数完成切换,是由用户主动操作的切换,不需要内核的参与。
- 多路io复用:
- select:轮询的方式socket,最大1024
- poll:不限制数量
- epoll:做回调函数,只观察加入Ready队列的socket
云平台存储图片:
- 注册账号
- 新建存储空间
- 查看官方文档
- 安装对应python包
- 参考官方文档代码作出修改,将隐私设置放入配置文件中。
- 封装上传文件的函数
- 构建对象,生成token
- 执行上传
- 返回上传后的文件路径,方便调用
CDN:
- 提高用户访问速度、成功率、保护数据完整性
- cdn服务器会选择用户请求的最近的,有数据,且可承载的服务器ip返回给用户
cdn是对域名加速
CDN部署简单,对原站基本不做任何改动即可生效。
CDN因为其流量分流到各节点的原理,天然获得抵抗网络攻击的能力。
CDN采用各节点缓存的机制,网站的静态网页和图片修改后,如果CDN缓存没有做相应更新,则看到的还是旧的网页。