- 本复习笔记基本来自于网上复制
- 本复习笔记主要用途在于整理后放在手机上听
- 本复习资料主要给博主用
- 博主觉得不重要的、比如python基础语法什么的 、就不会给出了,系统学习请gayhub搜索。
Python
Python中的元类(metaclass)
- 拦截类的创建
- 修改类
- 返回修改之后的类
类变量和实例变量
class Person:
name="aaa"
p1=Person()
p2=Person()
p1.name="bbb"
print(p1.name) # bbb
print(p2.name) # aaa
print(Person.name) # aaa
Python自省
简单一句就是运行时能够获得对象的类型.比如type(),dir(),getattr(),hasattr(),isinstance().
Python中单下划线和双下划线
foo:一种约定,Python内部的名字,用来区别其他用户自定义的命名,以防冲突,就是例如__init__(),del(),call()这些特殊方法
_foo:一种约定,用来指定变量私有.程序员用来指定私有变量的一种方式.不能用from module import * 导入,其他方面和公有一样访问;
__foo:这个有真正的意义:解析器用_classname__foo来代替这个名字,以区别和其他类相同的命名,它无法直接像公有成员一样随便访问,通过对象名._类名__xxx这样的方式可以访问.
迭代器和生成器
问: 将列表生成式中[]改成() 之后数据结构是否改变?
答案:是,从列表变为生成器
迭代器:迭代器是一个可以记住遍历的位置的对象:next(iter([1,2,3,4]))
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
x = self.a
self.a += 1
if self.a> 3:
raise StopIteration
return x
myclass = MyNumbers()
myiter = iter(myclass)
print(next(myiter))
print(next(myiter))
生成器:使用了 yield
的函数被称为生成器(generator
),简单点理解生成器就是一个迭代器。
面向切面编程(AOP)和装饰器
被用于有切面需求的场景:插入日志、性能测试、事务处理等。
装饰器的作用就是为已经存在的对象添加额外的功能。
Python中重载
函数重载主要是为了解决两个问题。
可变参数类型。
可变参数个数。
Python 都不需要
新式类和旧式类
python的多父类继承问题
新式类继承是根据C3算法,旧式类是深度优先。
在Python3.6下,className.mro()查看继承顺序。
slots
__slots__是一个类变量,__slots__属性可以赋值一个包含类属性名的字符串元组, 或者是可迭代变量,或者是一个字符串,只要在类定义的时候, 使用__slots__ = a Tuple来定义该属性就可以了。
__new__和__init__的区别
这个__new__确实很少见到,先做了解吧.
__new__是一个静态方法,而__init__是一个实例方法.
__new__方法会返回一个创建的实例,而__init__什么都不返回.
只有在__new__返回一个cls的实例时后面的__init__才能被调用.
当创建一个新实例时调用__new__,初始化一个实例时用__init__.
ps: __metaclass__是创建类时起作用.所以我们可以分别使用__metaclass__,__new__和__init__来分别在类创建,实例创建和实例初始化的时候做一些小手脚.
单例模式
class Singleton(object):
def __new__(cls, *args, **kw):
if not hasattr(cls, '_instance'):
orig = super(Singleton, cls)
cls._instance = orig.__new__(cls, *args, **kw)
return cls._instance
class MyClass(Singleton):
a = 1
# --------------------
# 装饰器版本
def singleton(cls):
instances = {}
def getinstance(*args, **kw):
if cls not in instances:
instances[cls] = cls(*args, **kw)
return instances[cls]
return getinstance
@singleton
class MyClass:
...
# --------------------
# 作为python的模块是天然的单例模式
# mysingleton.py
class My_Singleton(object):
def foo(self):
pass
my_singleton = My_Singleton()
# to use
from mysingleton import my_singleton
my_singleton.foo()
- 共享属性逻辑上也是单例模式
创建实例时把所有实例的__dict__指向同一个字典,这样它们具有相同的属性和方法。
class Borg(object):
_state = {}
def __new__(cls, *args, **kw):
ob = super(Borg, cls).__new__(cls, *args, **kw)
ob.__dict__ = cls._state
return ob
class MyClass2(Borg):
a = 1
Python中的作用域
Python 中,一个变量的作用域总是由在代码中被赋值的地方所决定的。
当 Python 遇到一个变量的话他会按照这样的顺序进行搜索:
本地作用域(Local)→当前作用域被嵌入的本地作用域(Enclosing locals)→全局/模块作用域(Global)→内置作用域(Built-in)
GIL线程全局锁
线程全局锁(Global Interpreter Lock),即Python为了保证线程安全而采取的独立线程运行的限制, 说白了就是一个核只能在同一时间运行一个线程. 对于io密集型任务,python的多线程起到作用, 但对于cpu密集型任务,python的多线程几乎占不到任何优势,还有可能因为争夺资源而变慢。
在python3.x中,GIL不使用ticks计数, 改为使用计时器(执行时间达到阈值后,当前线程释放GIL), 这样对CPU密集型程序更加友好, 但依然没有解决GIL导致的同一时间只能执行一个线程的问题
闭包
闭包可以保存当前的运行环境 闭包必须满足以下几点:
- 必须有一个内嵌函数
- 内嵌函数必须引用外部函数中的变量
- 外部函数的返回值必须是内嵌函数
Python函数式编程
- filter
>>>a = [1,2,3,4,5,6,7]
>>>b = filter(lambda x: x > 5, a)
>>>print b
>>>[6,7]
- map
>>> a = map(lambda x:x*2,[1,2,3])
>>> list(a)
[2, 4, 6]
- reduce
from functools import reduce
...: def c(x,y):
...: print(x,y)
...: return x*y
...: reduce(c,range(1,5))
1 2
2 3
6 4
Out[10]: 24
Python垃圾回收机制
Python GC主要使用引用计数(reference counting)来跟踪和回收垃圾。 当一个对象有新的引用时,它的ob_refcnt就会增加, 当引用它的对象被删除,它的ob_refcnt就会减少. 引用计数为0时,该对象生命就结束了。
基本思路是先按需分配,等到没有空闲内存的时候从寄存器和程序栈上的引用出发, 遍历以对象为节点、以引用为边构成的图,把所有可以访问到的对象打上标记, 然后清扫一遍内存空间,把所有没标记的对象释放。
Python默认定义了三代对象集合,索引数越大,对象存活时间越长。
当某些内存块M经过了3次垃圾收集的清洗之后还存活时, 我们就将内存块M划到一个集合A中去,而新分配的内存都划分到集合B中去。 当垃圾收集开始工作时,大多数情况都只对集合B进行垃圾回收。
操作系统
select,poll和epoll
select有3个缺点:
- 连接数受限
- 查找配对速度慢
- 数据由内核拷贝到用户态
poll使用pollfd结构而不是select的fd_set结构,poll改善了第一个缺点。
epoll改了三个缺点. poll在“醒着”的时候只要判断一下就绪链表是否为空就行了
调度算法
-
高级调度(作业调度/长程调度)(频率低):将外存作业调入内存
-
低级调度(进程调度/短程调度)(频率高):决定就就绪队列中哪个进程获得处理机并执行
-
什么是调度?本质上就是一种资源分配
-
什么是饥饿?某写进程一直在等待,得不到处理
调度算法的分类
- 抢占式(当前进程可以被抢):可以暂停某个正在执行的进程,将处理及重新分配给其他进程
- 非抢占式(当前进程不能被抢走):一旦处理及分配给了某个进程,他就一直运行下去,直到结束
具体调度算法:
- 1.先来先服务(FCFS):按照到达顺序,非抢占式,不会饥饿
- 2.短作业/进程优先(SJF):抢占/非抢占,会饥饿
- 3.高响应比优先(HRRN):综合考虑等待时间和要求服务事件计算一个优先权,非抢占,不会饥饿
- 4.时间片轮转(RR):轮流为每个进程服务,抢占式,不会饥饿
- 5.优先级:根据优先级,抢占/非抢占,会饥饿
- 6.多级反馈队列:
- 设置多个就绪队列,每个队列的进程按照先来先服务排队,然后按照时间片轮转分配时间片
- 若时间片用完还没有完成,则进入下一级队尾,只有当前队列为空时,才会为下一级队列分配时间片。
- 抢占式,可能会饥饿
作业调度算法:
- 先来先服务调度算法
- 短作业优先调度算法
- 优先级调度算法
进程调度算法:
- 以上6种都可以是进程调度算法
死锁
原因:
- 竞争资源
- 程序推进顺序不当
必要条件:
- 互斥条件
- 请求和保持条件
- 不剥夺条件
- 环路等待条件
处理死锁基本方法:
- 预防死锁(摒弃除1以外的条件)
- 避免死锁(银行家算法)
- 检测死锁(资源分配图)
- 解除死锁: 剥夺资源 or 撤销进程
页面置换算法
- 最佳置换算法OPT:不可能实现
- 先进先出FIFO
- 最近最久未使用算法LRU:最近一段时间里最久没有使用过的页面予以置换.
- clock算法
边沿触发和水平触发
边缘触发是指每当状态变化时发生一个 io 事件,条件触发是只要满足条件就发生一个 io 事件
Python中异步编程关键字都有什么?在Python中异步编程与Generator,协程,线程之间有什么关系?
yeild async await Generator 是一个异步实现的生成器 ,是协程 。 协程是用户态的线程。
Python中装饰器的本质相当于什么?
装饰器的本质是一个闭包函数,而闭包函数的本质是变量作用域的外溢。 (外层函数中包裹的内部函数可使用外层函数的参数,以及接受其值)
怎么获取xx端口对应的进程并杀掉它的linux命令
sudo lsof -i:端口号 //查找对应的进程号
sudo kill -9 进程号 //杀死对应的进程
筛选Linux 10-15k 大小的文件
find -size +10k -15k
怎么查找文件中包含某文字的命令
grep -rn "phpernote" * -C 5
-r 是递归查找 -n 是显示行号 -C number 匹配的上下文分别显示[number]行
docker的底层实现
Linux 上的命名空间(Namespaces)、 控制组(Control groups)、 Union 文件系统(Union file systems) 和容器格式(Container format)。
堆栈与队列的区别
堆栈FILO 队列FIFO
针对用户下订单,订单定时失效的功能,在微服务的设计思路下,应该如何来设计实现?
可以使用redis的定时存储key-value方式 EXPIRE key timeout, 获取key时没有这个key,则认为订单失效,让当前程序拿取订单信息,返回用户提示订单失败。
线程 进程和协程的区别
- 进程:最小分配单元,每个进程都有自己单独的资源区域。进程的环境包括环境变量,进程所掌控的资源,有中央处理器,有内存,打开的文件,映射的网络端口等。
- 线程:cpu最小执行单位,线程共享进程的资源,多个线程可以共享同一地址空间和其他资源,比如共享全局变量。
- 协程:用户态执行,完全是由用户程序所控制。“协程就是你可以暂停执行的函数”。
数据库
事物四特性
- 原子性(Atomicity):要么全部被执行,要么都不执行。
- 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。
- 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
- 持久性(Durability):一个事务一旦提交,他对数据库的修改应该永久保存在数据库中。
mysql 数据库索引
聚集索引,非聚集索引,B-Tree,B+Tree
Redis原理
Redis是一个完全开源免费的key-value内存数据库,通常被认为是一个数据结构服务器,主要是因为其有着丰富的数据结构 strings、map、 list、sets、 sorted sets
- 速度快:使用标准C写,所有数据都在内存中完成,读写速度分别达到10万/20万,
- 持久化:对数据的更新采用Copy-on-write技术,可以异步地保存到磁盘上,主要有两种策略,一是根据时间,更新次数的快照(save 300 10 )二是基于语句追加方式(Append-only file,aof)
- 自动操作:对不同数据类型的操作都是自动的,很安全
- 快速的主--从复制,官方提供了一个数据,Slave在21秒即完成了对Amazon网站10G key set的复制。
- Sharding技术: 很容易将数据分布到多个Redis实例中
缺点:
- 内存贵,只能用于小数据高性能。
- 难支持在线扩容
Multi-Version Concurrent Control
- Read Uncommitted:最低的隔离级别,什么都不需要做,一个事务可以读到另一个事务未提交的结果。所有的并发事务问题都会发生。
- Read Committed:只有在事务提交后,其更新结果才会被其他事务看见。可以解决脏读问题。
- Repeated Read:在一个事务中,对于同一份数据的读取结果总是相同的,无论是否有其他事务对这份数据进行操作,以及这个事务是否提交。可以解决脏读、不可重复读。
- Serialization:事务串行化执行,隔离级别最高,牺牲了系统的并发性。可以解决并发事务的所有问题
MyISAM和InnoDB
MyISAM 适合于一些需要大量查询的应用,但其对于有大量写操作并不是很好。 甚至你只是需要update一个字段,整个表都会被锁起来,而别的进程,就算是读进程都无法操作直到读操作完成。 另外,MyISAM 对于 SELECT COUNT(*) 这类的计算是超快无比的。
InnoDB 的趋势会是一个非常复杂的存储引擎,对于一些小的应用,它会比 MyISAM 还慢。 他是它支持“行锁” ,于是在写操作比较多的时候,会更优秀。并且,他还支持更多的高级应用,比如:事务。
TCP协议中的三次握手和四次挥
注意: 中断连接端可以是客户端,也可以是服务器端. 下面仅以客户端断开连接举例, 反之亦然.
urllib和urllib2的区别
- urllib提供urlencode方法用来GET查询字符串的产生,而urllib2没有。这是为何urllib常和urllib2一起使用的原因。
- urllib2可以接受一个Request类的实例来设置URL请求的headers,urllib仅可以接受URL。这意味着,你不可以伪装你的User Agent字符串等。
Post和Get
HTTP方法的幂等性是指一次和多次请求某一个资源应该具有同样的副作用。(注意是副作用)
GET的URL会被放在浏览器历史和WEB 服务器日志里面。,POST 发完基本就没有了。post可以发送的数据够大,get受某些版本ie限制发不了多少东西。get会被认为是幂等的,也就是请求1次和n次是一样的。
apache和nginx的区别
nginx 相对 apache 的优点:
- 轻量级,同样起web 服务,比apache 占用更少的内存及资源
- 抗并发,nginx 处理请求是异步非阻塞的,支持更多的并发连接,而apache 则是阻塞型的,在高并发下nginx 能保持低资源低消耗高性能
- 配置简洁
- 高度模块化的设计,编写模块相对简单
- 社区活跃
apache 相对nginx 的优点:
- rewrite ,比nginx 的rewrite 强大
- 模块超多,基本想到的都可以找到
- 少bug ,nginx 的bug 相对较多
- 超稳定
APISIX: 和传统 API 网关相比, 具备动态路由和插件热加载,特别适合微服务体系下的 API 管理。
网站用户密码保存
- 明文保存
- 明文hash后保存,如md5
- MD5+Salt方式,这个salt可以随机
- 知乎使用了Bcrypy(好像)加密
XSRF和XSS
CSRF重点在请求,XSS重点在脚本
CGI和WSGI
CGI是通用网关接口,是连接web服务器和应用程序的接口,用户通过CGI来获取动态数据或文件等。 CGI程序是一个独立的程序,它可以用几乎所有语言来写,包括perl,c,lua,python等等。
WSGI, Web Server Gateway Interface,是Python应用程序或框架和Web服务器之间的一种接口,WSGI的其中一个目的就是让用户可以用统一的语言(Python)编写前后端。
Socket
Socket=Ip address+ TCP/UDP + port
浏览器缓存
Cache-control:值可以是public、private、no-cache、no- store、no-transform、must-revalidate、proxy-revalidate、max-age no-cache代表不缓存过期的资源,缓存会向服务器进行有效处理确认之后处理资源 而no-store才是真正的不进行缓存。 304 Not Modified
Ajax
AJAX,Asynchronous JavaScript and XML(异步的 JavaScript 和 XML), 是与在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术。
unix进程间通信方式(IPC)
- 管道 Pipe
from multiprocessing import Process, Pipe
Pipe().send("Hello 11")
- 命名管道 named pipe
import os
fd = os.open('pipetest',os.O_NONBLOCK | os.O_CREAT | os.O_RDWR)
os.write(fd,"hello")
- 信号(Signal)
import signal
signal.signal(signal.SIGTERM,lambda a,b;print(a,b))
- 消息(Message)队列
import Queue
Queue.Queue().put
- 共享内存 / 内存映射(mapped memory)
import mmap
with contextlib.closing(mmap.mmap(-1, 100, tagname='SASU', access=mmap.ACCESS_WRITE)) as m:
m.write()
m.flush()
- 信号量(semaphore)
原理:给定一个数量,对多个进程可见,且多个进程都可以操作。进程通过对数量多少的判断执行各自的行为。(生产者/消费者)
multiprocessing --> Semaphore()
sem = Semaphore(num)
功能:创建信号量
参数:信号量初始值
返回:信号量对象
sem.get_value() 获取信号量值
sem.acquire() 将信号量减1 当信号量为0时会阻塞
sem.release() 将信号量加1
- 套接口(Socket)
import socket
http和tcp的区别
HTTP在应用层,TCP 和 UDP 都位于计算机网络模型中的运输层。 HTTP 中包括许多方法,Get ,Post 等。
时间复杂度
看循环嵌套 增长方式 循环结束条件
# log2 N
for(i=0;i<n:i*2)
a++
解决服务性能瓶颈
- 增加worker
- 预处理数据
- 异步处理io密集型问题
- 多线程处理cpu密集型问题
- 队列
- 燃尽图分析
mongodb索引
MySQL 之所以选择 B+,那是因为出于范围选择考虑的。那么 MongoDB 选择 B 树,可能是因为单一数据查询多,范围查询少。
fastapi 与 flask 的不同
- todo
为什么要用 gunicorn
- WSGI 同步处理模式的, WSGI 采用多线程方式来支持并发
- gunicorn是prefork模式,从nginx每发过来一个请求,它就fork一个进程去处理这个请求,并buffer相关的数据。wsgi服务器都是专门为生产环境
flask 用异步的方法
- gevent
mongo 设置timeout的data
- 关键词: expireAfterSeconds、TTL
- MongoDB的过期 设置依赖索引(TTL-index), 设置过期字段使用的索引后, 插入数据时在该字段指定日期时间, 经过在创建索引时指定的秒数后,该记录会被MongoDB认为已经过期,然后删除。
grpc 与 http 的不同
- grpc 序列化速度快,压缩效率高。传输协议 采用http2,性能比http1.1好了很多。
- http每次请求发送一个request,服务器响应之后就断掉。
bcolz hdf5
- Bcolz文件是一个文件夹
- hdf5是一个.h5文件
- Bcolz存储(压缩)数据的速度是HDF5的10倍以上,并发完成。
rabbitmq 和 kafuka 区别
名称 | 应用场景方面 | 架构模型方面 | 吞吐量方面 | 集群负载均衡方面 |
---|---|---|---|---|
RabbitMQ | 用于实时的,对可靠性要求较高的消息传递上。 | 以broker为中心,有消息的确认机制。 | 支持消息的可靠的传递,支持事务,不支持批量操作,基于存储的可靠性的要求存储可以采用内存或硬盘,吞吐量小。 | 本身不支持负载均衡,需要loadbalancer的支持 |
kafka | 用于处于活跃的流式数据,大数据量的数据处理上。 | 以consumer为中心,无消息的确认机制。 | 内部采用消息的批量处理,数据的存 储和获取是本地磁盘顺序批量操作,消息处理的效率高,吞吐量高。 | 采用zookeeper对集群中的broker,consumer进行管理,可以注册topic到zookeeper上,通过zookeeper的协调机制,producer保存对应的topic的broker信息,可以随机或者轮询发送到broker上,producer可以基于语义指定分片,消息发送到broker的某个分片上。 |
QPS TPS
我拿普罗米斯的日志看的
GET请求的 总请求数量 / 总等待时长 = QPS
668971.0 / 7273.539398193359 = 91.97324
大概92,也不知道时多时少
因为不是纯GET请求,也算数据库写入,所以我觉得也算TPS。
RabbitMQ的结构
- Broker:简单来说就是消息队列服务器实体。
- Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列。
- Queue:消息队列载体,每个消息都会被投入到一个或多个队列。
- Binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来。
- Routing Key:路由关键字,exchange根据这个关键字进行消息投递。
- vhost:虚拟主机,一个broker里可以开设多个vhost,用作不同用户的权限分离。
- producer:消息生产者,就是投递消息的程序。
- consumer:消息消费者,就是接受消息的程序。
- channel:消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务。