中国空间站朋友圈,wordpress底部版权,万网,WordPress导出单页1 基础知识
1.1 GC机制
Python的垃圾回收#xff0c;其实高级的语言都有自己的垃圾回收机制简称GC#xff0c;
python当中主要通过三种方式解决垃圾回收的方式#xff0c;引用计数、标记清除、分代回收。引用计数#xff1a;如果有新的引用指向对象#xff0c;对象引用计…1 基础知识
1.1 GC机制
Python的垃圾回收其实高级的语言都有自己的垃圾回收机制简称GC
python当中主要通过三种方式解决垃圾回收的方式引用计数、标记清除、分代回收。引用计数如果有新的引用指向对象对象引用计数就加一引用被销毁时
对象引用计数减一当用户的引用计数为0时该内存被释放标记清除
首先标记对象(垃圾检测)然后清除垃圾(垃圾回收)》首先初始所有对象标记为白色
并确定根节点对象(这些对象是不会被删除)标记它们为黑色(表示对象有效)。将有效对象引用的对象标记为灰色(表示对象可达但它们所引用的对象还没检查)
检查完灰色对象引用的对象后将灰色标记为黑色。重复直到不存在灰色节点为止。
最后白色结点都是需要清除的对象分代回收:垃圾回收器会更频繁的处理新对象。一个新的对象即是你的程序刚刚创建的
而一个老的对象则是经过了几个时间周期之后仍然存在的对象。
Python会在当一个对象从零代移动到一代或是从一代移动到二代的过程中提升(promote)这个对象。1.2 装饰器、生成器、迭代器
装饰器: 写代码要遵循开放封闭原则装饰器本质上是一个嵌套函数(被套着的函数就是闭包)
它接收被装饰的函数(func)作为参数并返回一个包装过的函数。在不改变被装饰函数的
代码情况下给被装饰函数或程序添加新的功能,wrsps可以保证装饰器修饰的函数的name
的值保持不变使装饰器更加的完美加载顺序自下而上执行顺序自上而下应用:当我们记录日志的时候执行某函数、给某个功能添加日志。
闭指的该函数是定义在函数内的函数
包指的就是该函数引用了一个外层函数作用域的名字e作用域的名字
封闭已实现的功能代码块
开放对扩展开发
生成器:yield关键字、那么函数名()结果就是生成器、并且不会执行函数内部代码生成器内置有__iter__和__next__方法所以生成器本身就是一个迭代器
应用爬虫
对比return可以返回多次值、可以挂起保存函数的运行状态
应用:redis缓存
迭代器:不依赖索引取值、__iter__迭代器、__next__生成器通过迭代取值的方案可以节省内存其中迭代器又分为可迭代对象和迭代器对象可迭代对象内置有__iter__的方法的对象都叫可迭代的对象1.3 三元表达式、列表生成式、生成器表达式
1 三元表达式是python为我们提供的一种简化代码的解决方案res 条件成立时返回的值 if 条件 else 条件不成立时返回的值
2 列表生成式就相当于把for循环写到列表中一行代码完成一个功能简化代码但是写的复杂的话会影响阅读一般也不怎么用res [x for x in range(10)]print(res) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
3 生成器表达式将列表生成式的[]换成()即可对比列表生成式返回的是一个列表而生成器表达式返回的是一个生成器对象,对比列表生成式生成器表达式的优点自然是节省内存(一次只产生一个值在内存中)1.4 函数递归
在调用一个函数的内部又调用自己所以递归的本质就是一个循环的过程
它的大前提就是递归调用一定要在某一层结束如果不结束会形成一个死循环。
递归分为两个阶段回溯向下一层一层挖井递推向上一层一层返回
items[[1,2],3,[4,[5,[6,7]]]]
def func(items):
for x in items:
if type(x) is list: # 满足未遍历完items以及if判断成立的条件时一直进行调用
func(x)
else:
print(x,end )
func(items)
匿名函数就是没有名字的函数临时只用一次语法
lambds 参数1参数2...: expression
单例模式:(单一职责原则):保证一个类仅有一个实例并提供一个访问它的全
局访问点、比如桌面上的垃圾回收站2 面向对象
2.1 OOP面向对象编程
面向对象编程的核心是对象二字对象就是一个用来盛放数据与功能的容器基于该思想
编写程序就是创造一个个的容器其优点是扩展性强但是它也有缺点就是提高了编程的
复杂度。在程序中是先定义类后产生对象这里的对象就是容器是用来存放数据与
功能的而类也是容器用在存放同类对象共有的数据与功能面向对象编程有三大特征封装继承多态
1 封装将多个属性和方法封装到一个抽象的类中、所有类的对象都可以对其调用。针对封装到对象或者类中的属性我们还可以严格控制对他们的访问分别是隐藏与开放接口隐藏属性是采用用下划线开头的方式将属性隐藏起来设置成私有的仅仅是一种变形操作类里定义属性就是为了使用隐藏并不是目的而是限制了类外部对数据的直接操作类内应该提供相应的接口来允许类外部间接的操作数据接口之上可以附加额外的逻辑来对数据的操作进行严格的控制2 继承实现代码的重用、继承父类、重用父类的属性和方法、减少代码的冗余。继承描述的是子类与父类之间的关系是一种什么是什么的关系需要先抽象再继承。抽象最主要的作用是划分类别可以隔离关注点降低复杂度抽象即总结相似之处总结对象之间的相似之处得到类总结类与类之间的相似之处就可以得到父类在python2中有经典类和新式类之分没有显式的继承object类的类以及该类的子类都是经典类显示的继承object的类以及该类的子类都是新式类。但是在python3中既是没有显示的继承object也会默认继承该类1 经典类深度优先2 新式类广度优先3 多态多态指的是一类事物有多种形态多态性指的是可以在不用考虑对象具体类型的情况下而直接使用对象、但是需要依赖封装和继承、在python中推崇鸭子类型完全不依赖继承、制造出外观和行为相同对象同样可以实现不考虑对象类型而使用对象鸭子类型是动态类型的一种风格,不管对象属于哪个,也不管声明的具体接口是什么,只要对象实现了相应的方法,函数就可以在对象上执行操作。即忽略对象的真正类型转而关注对象有没有实现所需的方法、签名和语义. 是动态类型的一种风格,不管对象属于哪个,也不管声明的具体接口是什么,只要对象实现了相应的方法,函数就可以在对象上执行操作。即忽略对象的真正类型转而关注对象有没有实现所需的方法、签名和语义.多态(polymorphism)是指同一个方法调用由于对象不同可能会产生不同的行为。
注意
1.多态是方法的多态属性没有多态
2.多态的存在有两个必要条件继承、方法重写(一个类它继承了一个类但是它又改写了它父类的方法这样在调用这个方法时就会因为实例对象的不同而调用的方法不同也就是说看这个实例对象实例化时是用父类实例化的还是子类实例化的是父类实例化的结果就是父类的方法是子类实例化的结果就是子类的方法)2.1 继承原理 MRO方法
菱形问题如果A中有一个方法B和/或C都重写了该方法而D没有重写它那么D继承的是哪个版本的方法B的还是C的对于你定义的每一个类python都会计算出一个方法解析顺序(MRO)列表该MRO列表就是
一个简单的所有基类的线性顺序列表python会在MRO列表上从左往右一次开始查找基类
直到找到第一个匹配这个属性的类为止。MRO列表会遵循如下三条准则
1、子类会先于父类被检查
2、多个父类会根据它们在列表中的顺序被检查
3、如果对下一个类存在两个合法的选择选择第一个父类super()获得父类定义。在子类中如果想要获得父类的方法时我们可以通过super()来做super()代表父类的定义而不是父类对象。2.2 绑定方法和非绑定方法
但凡在类中定义一个函数默认就是绑定给对象的应该由对象来调用
会将对象当作第一个参数自动传入classmethods绑定给类的方法由类来调用自动将类本身当作第一个参数传入
staticmethod非绑定方法不与类和对象绑定类和对象都可以调用普通函数没有自动传值
property一种特殊属性、访问它时会执行一段功能用来绑定给对象的方法将函数对象伪装成数据属性然后返回值
应用django模型类中写子序列化的方法跨表操作2.3 反射、CBV源码简述
python中的反射就是通过字符串的形式操作对象相关的属性python中一切事物都是对象都可以用到反射。**反射机制**指的是在程序的运行状态中对于任意一个类都可以知道这个类的所有属性和方法对于任意一个对象都能够调用他的任意方法和属性。
这种动态获取程序信息以及动态调用对象的功能称为反射机制。
hasattr 检测是否含有某属性
getattr 获取属性
setattr 设置属性
delattr 删除属性好处:反射可以提前定义好接口、接基于类的视图应用场景
CBV源码简述根据前端请求方式的不同自动匹配执行对应的方法在url路由中的views.类 名.as_view()的源码下可以看到是被classonlymethod修饰的类方法内部定义闭包函数传参并返回闭包函数名、在dajong启动的时候会执行urls的as_view()产生变 形为views.view在浏览器提交请求的时候就会触发view方法通过view下的self 使用类的对象返回self.dispatch属性、在父类中的dispathc函数通过反射机制就 通过字符串操作对象属性口只有在被完成后才会真正执行就是可以事先写好逻辑接口事后实现接口功能2.4 元类、魔法方法、猴子补丁
元类创建类的类就叫元类metaclass函数type其实就是一个元类
type就是Python在背后用来创建所有类的元类。魔法方法:__call__,__init__,__new____str__...类加()触发类的元类的__call__方法
__str__ 打印时触发 str函数或者print函数—obj.str()
__init__ 是初始化方法通过类创建对象时自动触发执行
__new__ 是创建对象时为对象分配空间、在初始化init之前被调用当我们创建实例的时候 __new__方法在__init__方法之前被调用并将__new__方法的
返回值将传递给__init__方法作为第一个参数最后__init__给这个实例设置一些参数。猴子补丁:猴子补丁得益于python灵活的语法一切皆对象的思想。
猴子补丁的主要功能就是动态的属性的替换。虽然属性的运行时替换和猴子也没有什么关系所以说猴子补丁的叫法有些莫名其妙但是只要模块运行时替换的功能对应就行了。
猴子补丁允许运行期间动态修改一个类或模块3 常用模块
os模块式与操作系统交互的一个接口
os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回第一个绝对路径之前的参数将被忽略
os.path.splitext() 将文件名和扩展名分开
os.path.split() 返回文件的路径和文件名
os.mkdir(dirname) 生成单级目录相当于shell中mkdir dirname
os.remove() 删除一个文件
sys
sys.path 返回模块的搜索路径初始化时使用PYTHONPATH环境变量的值
sys.exit(n) 退出程序正常退出时exit(0)
sys.version 获取Python解释程序的版本信息
re
正则
\w 匹配数字字母下划线
\W 匹配非字母数字下划线
^ 匹配字符串的开头
$ 匹配字符串的末尾
random
生成随机数
print(random.random())#(0,1)----float 大于0且小于1之间的小数
print(random.randint(1,3)) #[1,3] 大于等于1且小于等于3之间的整
logging
记录日志
日志级别有五种
logging.debug(调试debug)
logging.info(消息info)
logging.warning(警告warn)
logging.error(错误error)
logging.critical(严重critical)
jsonpickle
json是可以在不同语言之间交换数据的而pickle只在python之间使用
json只能序列化最基本的数据类型而pickle可以序列化所有的数据类型包括类函数都可以序列化4 进程线程协程
进程是CPU资源分配的基本单位线程是独立运行和独立调度的基本单位CPU上真正运行的是线程。
进程拥有自己的资源空间一个进程包含若干个线程线程与CPU资源分配无关多个线程共享同一进程内的资源。
线程的调度与切换比进程快很多。
协程是单线程下的并发是一种用户态的轻量级线程即协程是由用户程序自己控制调度的。
对于多核CPU利用多进程协程的方式能充分利用CPU获得极高的性能Gevent 是一个第三方库可以轻松通过gevent实现并发同步或异步编程在gevent中用到的主要模式是Greenlet, 它
是以C扩展模块形式接入Python的轻量级协程。 Greenlet全部运行在主程序操作系统进程的内部但它们被协作式地调
度。5 异步和同步
我们在说同步、异步的时候特指那些需要其他部件协作或者需要一定时间完成的任务同步提交一个任务提交之后在原地等待提交的结果之后再去提交下一个任务。某功能调用时在没有得到结果之前该调用就不会返回
异步提交一个任务提交之后不等提交的任务运行完直接提交下一个任务。异步的概念和同步相对。同步与异步针对的是函数/任务的调用方式同步就是当一个进程发起一个函数任务调用的时候一直等到函数任务完成而进程继续处于激活状态。而异步情况下是当一个进程发起一个函数任务调用的时候不会等函数返回而是继续往下执行当函数返回的时候通过状态、通知、事件等方式通知进程任务完成。6 GIL锁/互斥锁
1、首先明确GIL并不是Python的特性它是在实现Python解析器(CPython)时所引入的一个概念
2、GIL全局解释器锁。每个线程在执行的过程都需要先获取GIL保证同一时刻只有一个线程可以执行代码。
3、当前线程遇到I/O或者字节码执行100行使用计时器时间到达阈值释放GIL才会释放GIL锁。线程的运行仍然是有先后顺序的并不是同时进行。
4、Python使用多进程是可以利用多核的CPU资源的。
5、多线程爬取比单线程性能有提升因为遇到IO阻塞会自动释放GIL锁。 多进程可以充分使用cpu的两个内核而多线程却不能充分使用cpu的两个内核cpython解释器中存在一个GIL(全局解释器锁)它的作用就是保证同一时刻只有一个线程可以执行代码因此造成了我们使用多线程的时候无法实现并行。解决方案:
1更换解释器比如使用jpythonjava实现的python解释器jpython xxx.py
2使用其他语言C语言编写程序
3使用多进程完成多任务的处理多个进程操作同一份数据的时候会出现数据错乱的问题
针对上述问题解决方法就是加锁处理将并发变成串行牺牲效率但是保证了数据的安全扩展
行锁 表锁注意
1、锁不要轻易的使用容易造成死锁现象我们一般写代码不会用到都是内部封装好的
2、锁只在处理数据的部分加起来保证数据安全只在争抢数据的环节加锁处理即可7 HTTP/HTTPS协议
1、什么是HTTP? 数据传输是明文超文本传输协议是一个基于请求响应无状态的作用于tcp/ip应用层的协议之上的协议它规定了浏览器与服务端之间数据交互的格式设计HTTP的初衷是为了提供一种发布和接收HTML页面的方法。绝大多数的Web开发都是构建在HTTP协议之上的Web应用。2、什么是HTTPS 数据传输是密文安全超文本传输协议HTTPS是一种通过计算机网络进行安全通信的传输协议。HTTPS使用的主要目的是提供对网站服务器的身份认证同时保护交换数据的隐私与完整性。3、HTTP vs HTTS
HTTP特点
(1)无状态协议对客户端没有状态存储对事物处理没有“记忆”能力比如访问一个网站需要反复进行登录操作
(2)无连接HTTP/1.1之前由于无状态特点每次请求需要通过TCP三次握手四次挥手和服务器重新建立连接。比如某个客户机在短时间多次请求同一个资源服务器并不能区别是否已经响应过用户的请求所以每次需要重新响应请求需要耗费不必要的时间和流量。
(3)基于请求和响应基本的特性由客户端发起请求服务端响应
(4)简单快速、灵活
(5)通信使用明文、请求和响应不会对通信方进行确认、无法保护数据的完整性HTTPS特点
(1)基于HTTP协议通过SSL或TLS提供加密处理数据、验证对方身份以及数据完整性保护
(2)内容加密采用混合加密技术中间者无法直接查看明文内容
(3)验证身份通过证书认证客户端访问的是自己的服务器
(4)保护数据完整性防止传输的内容被中间人冒充或者篡改websocket协议 数据传输是密文
数据格式请求数据格式
请求首行(请求方法...)
请求头(一大堆K:V键值对)
请求体(并不是所有的请求方法都有 主要用来携带敏感性数据)
响应数据格式
响应首行(响应状态码...)
响应头(一大堆K:V键值对)
响应体(展示给用户的数据)8 tcp/udp协议
1 tcp协议可靠传输TCP数据包没有长度限制理论上可以无限长但是为了保证网络的效率通常TCP数据包的长度不会超过IP数据包的长度以确保单个TCP数据包不必再分割。
2 udp协议不可靠传输”报头”部分一共只有8个字节总长度不超过65,535字节正好放进一个IP数据包。1 为什么连接的时候是三次握手关闭的时候却是四次握手因为当Server端收到Client端的SYN连接请求报文后可以直接发送SYNACK报文。其中ACK报文是用来应答的SYN报文是用来同步的。但是关闭连接时当Server端收到FIN报文时很可能并不会立即关闭SOCKET所以只能先回复一个ACK报文告诉Client端你发的FIN报文我收到了。只有等到我Server端所有的报文都发送完了我才能发送FIN报文因此不能一起发送。故需要四步握手。第一次握手建立连接时客户端发送syn包synj到服务器并进入SYN_SENT状态等待服务器确认SYN同步序列编号Synchronize Sequence Numbers。
第二次握手服务器收到syn包必须确认客户的SYNackj1同时自己也发送一个SYN包synk即SYNACK包此时服务器进入SYN_RECV状态
第三次握手客户端收到服务器的SYNACK包向服务器发送确认包ACK(ackk1此包发送完毕客户端和服务器进入ESTABLISHEDTCP连接成功状态完成三次握手。9 django
9.1 MTV
Django 是一个由 Python 编写的一个开放源代码的 Web 应用框架。
是基于MTV模式的框架需要配合url控制器路径分发使用Django的MTV模式本质上和MVC是一样的也是为了各组件间保持松耦合关系只是定义上有些许不同Django的MTV分别是指
· M 代表模型Model 负责业务对象和数据库的关系映射(ORM)。
· T 代表模板 (Template)负责如何把页面展示给用户(html)。
· V 代表视图View 负责业务逻辑并在适当时候调用Model和Template。除了以上三层之外还需要一个URL分发器它的作用是将一个个URL的页面请求分发给
不同的View处理View再调用相应的Model和Template优势低耦合开发快捷部署方便可重用性高维护成本低。
Python Django 是快速开发、设计、部署网站的最佳组合9.2 ORM
orm:对象关系映射
orm目的就是为了能够让不懂SQL语句的人通过python面向对象的知识点也能够轻松自如的操作数据库
类 ---------- 表
对象 -------- 表里面的数据
对象点属性 -- 字段对应的值
缺陷:sql封装死了 有时候查询速度很慢9.3 forms组件
能够完成的信息
1、渲染html代码2、校验数据3、展示提示信息***为什么数据校验非要去后端不能在前端利用js直接完成呢***
数据校验前端可有可无但是后端必须要有!!!
因为前端的校验是弱不禁风的 你可以直接修改或者利用爬虫程序绕过前端页面直接朝后端提交数据钩子函数钩子函数在form组件中能够让我们自定义校验规则
在froms组件中有两类钩子
1、局部钩子单个字段增加校验规则
2、全局钩子给多个字段增加校验规则9.4 auth模块
Auth模块是Django自带的用户认证模块我们在开发一个网站的时候无可避免的需要设计实现网站的用户系统。此时我们需要实现包括用户注册、用户登录、用户认证、注销、修改密码等功能所以说比较麻烦。Django作为一个完美主义者的终极框架它内置了强大的用户认证系统–auth它默认使用 auth_user 表来存储用户数据。auth模块的常用方法:authenticate()提供了用户认证功能即验证用户名以及密码是否正确一般需要username 、password两个关键字参数,如果认证成功用户名和密码正确有效便会返回一个 User 对象login(HttpRequest, user)该函数接受一HttpRequest对象以及一个经过认证的User对象。该函数实现一个用户登录的功能。它本质上会在后端为该用户生成相关session数据。logout(request) *该函数接受一个HttpRequest对象无返回值。当调用该函数时当前请求的session信息会全部清除。该用户即使没有登录使用该函数也不会报错is_authenticated()用来判断当前请求是否通过了认证。9.5 DTL语法
模板语言主要用于前后端混合开发的项目后端为前端页面传值的语法模版语法之变量在 Django 模板中遍历复杂数据结构的关键是句点字符, 语法变量名模板语言之标签标签看起来像是这样的 {% tag %}标签比变量更加复杂一些在输出中创建文本一些通过循环或逻辑来控制流程一些加载其后的变量将使用到的额外信息到模版中。一些标签需要开始和结束标签(例如{% tag %} ...标签内容 ... {% endtag %})9.6 F、Q查询
F作用两个字段之间作比较专门取对象中某列值的操作
F对象允许Django在未实际链接数据的情况下具有对数据库字段的值的引用。在更新数据时需要先从数据库里将原数据取出后放在内存里然后编辑某些属性最后提交。查询男生比女生多的公司
models.company.filter(c_boy_num__gtF(c_girl_num))Q作用对对象进行复杂查询并支持and,|or~not操作符与或非运算来组合生成不同的Q对象便于在查询操作中灵活地运用。如果Q查询和关键字查询同时存在时Q查询要放在关键字查询的前面查询名字不是红楼梦的书
models.Book.objects.filter(~Q(name红楼梦))9.7 中间件
中间件是一个用来处理Django的请求和响应的框架级别的钩子。
它是一个轻量、低级别的插件系统用于在全局范围内
改变Django的输入和输出。每个中间件组件都负责做一些特定的功能。中间件是帮助我们在视图函数执行之前和执行之后都可以做一些额外的操作它本质上就是
一个自定义类类中定义了几个方法Django框架会在请求的特定的时间去执行这些方法。
但是由于其影响的是全局所以需要谨慎使用使用不当会影响性能。
MIDDLEWARE [
django.middleware.security.SecurityMiddleware, # 安全中间件
django.contrib.sessions.middleware.SessionMiddleware, # 会话中间件处理session
django.middleware.common.CommonMiddleware, # 站点中间件处理是否带斜杠的
django.middleware.csrf.CsrfViewMiddleware, # CSRF保护中间件跨站请求伪造的处理
django.contrib.auth.middleware.AuthenticationMiddleware, # 认证中间件提供用户认证服务
django.contrib.messages.middleware.MessageMiddleware,# 消息中间件基于cookie或者会话的消息功能
django.middleware.clickjacking.XFrameOptionsMiddleware, # X-Frame-Options中间件点击劫持保护
]
MIDDLEWARE配置项是一个列表(列表是有序的)列表中是一个个字符串这些字符串其实
是一个个类也就是一个个中间件。Django默认有七个中间件但是django暴露给用户可以自定义中间件并且里面可以写五种方法
1、process_request : 请求进来时,权限认证 。
2、process_view : 路由匹配之后,能够得到视图函数
3、process_exception : 异常时执行
4、process_template_responseprocess : 模板渲染时执行
5、process_response : 请求有响应时执行process_request方法
1.请求来的时候需要经过每一个中间件里面的 process_request方法经过的顺序是按照配置文件中注册的中间件从上往下的顺序依次执行
2.如果中间件里面没有定义该方法那么直接跳过执行下一个中间件
3.它的返回值可以是None按正常流程继续走交给下一个中间件处理如果该方法返回了Httpresponse对象那么请求将不再继续往后执行而是直接原路返回校验失败不允许访问.process_request方法就是用来做全局相关的所有限制功能process_response方法
1.响应走的时候需要经过每一个中间件里面的 process_response方法该方法有两个额外的参数 request, response
2,该方法必须返回一个 HttpResponse对象:默认返回的就是形参 response,你也可以自己返回自己的
3.顺序是按照配置文件中注册了的中间件从下往上依次经过如果你没有定义的话直接跳过执行下一个总结当前端发来请求Django会执行每个中间件中的process_request,执行顺序按照
配置文件由上至下执行。响应走的时候Django会执行每个中间件中的process_response 方法process_response方法是在视图函数之后执行的执行顺序是按照配置文件中
注册了的中间件从下往上依次执行
9.8 路由分发
当一个url请求过来之后先到项目主目录下的urls内。
然后由这个url做处理分发给其他app内的urls一级路由主目录urls内引入include
二级路由只查找本地urls内的路径
自动生成路由:SimpleRouter、DefaultRouterViewSetMixin9个子类视图才能自动生成路由***Default与Simple的区别是:***
Default会多附带一个默认的API根视图返回一个包含所有列表视图的超链接响应数据。# 1 导入路由类
from rest_framework.routers import SimpleRouter, DefaultRouter
# 2 实例化得到对象
router SimpleRouter()
# 3 注册路由
router.register(books, views.BookView)10 DRF
10.1 Restful 规范
RESTful是一种定义Web API接口的设计风格尤其适用于前后端分离的应用模式中。数据的安全保障url链接一般都采用https协议进行传输(数据交互中安全性)接口特性表现一看就知道是个api接口用api关键字标识接口urlhttps://api.baidu.com多数据版本共存在url链接中标识数据版本https://api.baidu.com/v1数据即是资源
均使用名词可复数尽量不要出现动词资源操作由请求方式决定method
提供请求方式来标识增删改查动作过滤通过在url上传参的形式传递搜索条件:
例如url后面?搜索分页游标10.2 jwt认证
JWTJSON Web Token
JWT 就是一种在用户登录后生成token 并把token 放在前端后端不需要维护用户的
状态信息但是可以验证token 有效性的认证及状态管理方式。JWT的构成base64的使用加码和解码
1. 头部Header存放如何处理token的方式加密的算法、是否有签名等
2. 载荷Payload数据的主体部分用户信息、发行者、过期时间等
3. 签名Signature将header、payload再结合密码盐整体处理一下最后一步签名的过程实际上是对头部以及负载内容进行签名防止内容被篡改。如果有人
对头部以及负载的内容解码之后进行修改再进行编码最后加上之前的签名组合形成新的
JWT的话那么服务器端会判断出新的头部和负载形式的签名和JWT附带上的签名是不一样
的。如果要对新的头部和负载进行签名在不知道服务器加密时用的密钥的话
得出来的签名也是不一样的。11 View家族
两个基类
APIView是RESTframework提供的所有视图的基类继承自Django的View父类
GenericAPIView[通用视图类]继承自APIVIew主要增加了操作序列化器和数据库查询
方法作用是为下面Mixin扩展类的执行提供方法支持。通常在使用时可搭配一个或多个Mixin扩展类。# 5个视图扩展类(rest_framework.mixins)
CreateModelMixincreate方法创建一条
DestroyModelMixindestory方法删除一条
ListModelMixinlist方法获取所有
RetrieveModelMixinretrieve获取一条
UpdateModelMixinupdate修改一条# 9个子类视图(rest_framework.generics)
CreateAPIView:继承CreateModelMixin,GenericAPIView有post方法新增数据
DestroyAPIView继承DestroyModelMixin,GenericAPIView有delete方法删除数据
ListAPIView继承ListModelMixin,GenericAPIView,有get方法获取所有
UpdateAPIView继承UpdateModelMixin,GenericAPIView有put和patch方法修改数据
RetrieveAPIView继承RetrieveModelMixin,GenericAPIView有get方法获取一条
ListCreateAPIView有get获取所有post方法新增
RetrieveDestroyAPIView有get方法获取一条delete方法删除
RetrieveUpdateAPIView有get获取一条putpatch修改
RetrieveUpdateDestroyAPIView有get获取一条putpatch修改delete删除# 视图集
ViewSetMixin重写了as_view
ViewSet继承ViewSetMixin和APIView
GenericViewSet继承ViewSetMixin, generics.GenericAPIView
ModelViewSet继承了GenericViewSet和五个视图扩展类5个接口都有
ReadOnlyModelViewSet继承mixins.RetrieveModelMixin,mixins.ListModelMixin,GenericViewSetaction装饰器:
自动生成路由后使用action装饰器来继续让写在视图类的方法可以被访问到11.1 序列化器、局部全局钩子
前后端不分离项目有form组件帮我们去做数据校验有模板语法从数据库取出queryset对象不需要人为去转格式前后端分离项目
我们需要自己去做数据校验,手动去转数据格式因为跨平台数据传输都用json字符串不能直接jsonqueryset对象
1 序列化把python中的对象转成json格式字符串序列化器会把模型对象转换成字典,经过response以后变成json字符串
2 反序列化把json格式字符串转成python中的对象把客户端发送过来的数据,经过request以后变成字典
source指定要序列化的字段只有一个字段也可以跨表
SerializerMethodField跨表查(来定制返回的字段)要么是列表要么是字典序列化器
-定义一个类继承Serializer
-在类内些字段常用字段和非常用字段字段参数
-在视图类中实例化得到一个序列化类的对象传入要序列化的数据
-对象.data---》就是字典serializer不是只能为数据库模型类定义也可以为非数据库模型类的数据定义。
serializer是独立于数据库之外的存在。如果我们想要使用序列化器对应的是Django的
模型类DRF为我们提供了ModelSerializer模型类序列化器来帮助我们快速创建一个
Serializer类局部钩子全局钩子函数单个字段校验validate_字段名在序列化器中
需要同时对多个字段进行比较验证时可以定义validate方法来验证11.2 rbac模式
RBAC 是基于角色的访问控制(Role-Based Access Control)
在 RBAC 中权限与角色相关联用户通过成为适当角色的成员而得到这些角色的权限。
这就极大地简化了权限的管理。这样管理都是层级相互依赖的权限赋予给角色而把角色又赋予用户这样的权限设计很清楚管理起来很方便。应用:Django的 Auth组件 采用的认证规则就是RBAC
1像专门做人员权限管理的系统CRM系统都是公司内部使用所以数据量都在10w以下一般效率要求也不是很高
2用户量极大的常规项目会分两种用户前台用户(三大认证) 和 后台用户(BRAC来管理)结论没有特殊要求的Django项目可以直接采用Auth组件的权限六表
不需要自定义六个表也不需要断开表关系单可能需要自定义User表11.3 分页
原生django有分页功能也可以自定义封装分页继承Paginator类drf三种分页功能
1 基本分页PageNumberPaginationpage_size 2 # 每页显示两条page_query_param page #查询第几页的参数 ?page3max_page_size 4 #每页最大显示多少条page_size_query_param size #每页显示的条数查询条件默认是page_size显示的条数 # ?page3size32 偏移分页LimitOffsetPaginationdefault_limit2 #默认显示几条limit_query_paramlimit # limit3 表示取3条offset_query_param offset #偏移 ?offset5limit3 #从第5个位置开始取3条数据max_limit 5 #最多显示5条3 游标分页CursorPaginationcursor_query_param cursor # 查询的key值page_size 2 # # 每页显示两条ordering id # 按id字段排序# 配置使用的分页类pagination_class CustomNumberPagination11.4 过滤、排序
过滤
1 过滤针对于 list 获取所有对于列表数据可能需要根据字段进行过滤
2 在请求路径中带过滤条件对查询结果进行过滤# 在视图中配置过滤类局部使用然后配置过滤字段
filter_backends [SearchFilter,]
search_fields [nameprice]第三方过滤类使用django-filter
内置的SearchFilter过滤类功能一般如果想实现更高级的过滤
可以使用第三方通过添加django-fitlter扩展来增强支持自己定义过滤类支持模糊查询排序在类视图中设置filter_backends排序本身也是过滤
对于列表数据REST framework提供了OrderingFilter过滤器来帮助我们快速指明数据按照指定字段进行排序。使用rest_framework.filters.OrderingFilter过滤器
REST framework会在请求的查询字符串参数中检查是否包含了ordering参数
如果包含了ordering参数则按照ordering参数指明的排序字段对数据集进行排序。
前端可以传递的ordering参数的可选字段值需要在ordering_fields中指明。11.5 异常处理、自动生成接口文档
我们在生产环境中需要把全部异常捕获输入到日志中。而且我们也不希望给错误页面给用户看到这时候应该怎么办呢
这时候可以针对 DRF 框架没有处理的一些特殊的异常进行全局的异常处理。drf 提供了异常处理我们可以自定义异常处理函数。
需要在配置文件中声明自定义的异常处理如果未声明会采用默认的方式。DRF 可以自动帮助我们生成接口文档。接口文档以网页的方式呈现。
自动接口文档能生成的是继承自APIView及其子类的视图。生成接口文档需要coreapi库的支持。在总路由中添加接口文档路径。文档路由对应的视图配置为rest_framework.documentation.include_docs_urls
参数title为接口文档网站的标题。
from rest_framework.documentation import include_docs_urls
urlpatterns [url(r^docs/, include_docs_urls(titleMy REST API))
]12 数据库
12.1 索引、索引下推技术
索引是一种数据结构既结构数据换句话说索引就是一种组织数据的方式
hash索引:是基于hash表实现记算出hash值对应的k value适合等值查询不适合范围查询***树索引***
1 二叉树非叶子节点只允许最多两个子节点存在右边的子节点大于当前节点的值每个节点只存储一个键值和数据
2 平衡二叉树左右高度子节点不超过1、在数据量大的时候会进行多次磁盘io降低查找效率
3 B树平衡树每个节点储存更多的键值key和数据data并且每个节点拥有更多的子节点。
4 B树在非叶子节点上不保存数据只存放键值能存储更多的键值所有数据均存储在叶子节点并且是按照顺序排列的。查找数据会减少IO数据查询的效率更快。这使得B树在做范围查找、分段查找、去重查找、分组查找异常简单。***为什么索引结构默认使用B树而不是Hash二叉树红黑树***
1 Hash虽然可以快速定位但是没有顺序IO复杂度高。
2 二叉树树的高度不均匀不能自平衡查找效率跟树的高度有关并且IO代价高。
3 红黑树树的高度随着数据量增加而增加IO代价高。1 普通索引 一张表中可以有多个普通索引随便一个字段都可以建立的索引我们平常建立的索引大部分都是普通索引
2 联合索引 好几个字段联合起来建立的索引
3 唯一索引 业务中唯一的字段适合建立唯一索引一个表中可以有多个唯一索引
4 主键索引 和唯一索引一样主键索引也是唯一的不同的就是一个表只能有一个主键索引***索引下推技术***索引下推index condition pushdown 简称ICP。
在不使用ICP的情况下在使用非主键索引又叫普通索引或者二级索引进行查询时存储引擎通过索引检索到数据然后返回给MySQL服务器服务器然后判断数据是否符合条件。
在使用ICP的情况下如果存在某些被索引的列的判断条件时MySQL服务器将这一部分判断条件传递给存储引擎然后由存储引擎通过判断索引是否符合 MySQL服务器传递的条件只有当索引符合条件时才会将数据检索出来返回给MySQL服务器。
索引条件下推优化可以减少存储引擎查询基础表的次数也可以减少MySQL 服务器从存储引擎接收数据的次数。12.2 explain、事务
explain :索引执行计划查看rows的大小,rows是核心指标、优化语句主要在优化rows事务ACID
数据库事务指的则是作为单个逻辑工作单元执行的一系列操作SQL语句 功能:
1 为数据库操作提供了一个从失败中恢复到正常状态的方法同时提供了数据库即使在异常状态下仍能保持一致性的方法。
2 当多个应用程序在并发访问数据库时可以在这些应用程序之间提供一个隔离方法以防止彼此的操作互相干扰。这些操作要么全部执行要么全部不执行。***事务的四大特性***
1 原子性 Atomicity:事务作为一个整体包含在其中对于数据库的操作要么全部执行要么全部不执行。例如A给B转了100A余额减100刚转完系统崩溃B收到钱款这一操作没有执行则整个事务回滚100元退还到A的余额
2 一致性 Consistency:事务应该确保数据库从一致状态转到另一个一致状态。例如转账行为中一个人减了50元另外一个人就应该加上这50元而不能是40元。其他一致状态的含义是数据库中的数据应满足完整性约束例如字段约束不能为负数事务执行完毕后的该字段也同样不是负数。
3 隔离性 Isolation:多个事务并发执行时一个事务的执行应该不受其他事务执行的影响。举例A给B转100元和C给B转100元是独立的。
4 持久性 Durability:成功执行的事务产生的结果应该被永久保留在数据库中。12.3 触发器、存储过程、视图
1 触发器触发器是一个特殊的存储过程它是MySQL在insert、update、delete 的时候自动执行的代码块。
2 视图视图是由查询结果形成的一张虚拟表是表通过某种运算得到的一个投影create view view_name as select 语句
3 存储过程把一段代码封装起来当要执行这一段代码的时候可以通过调用该存储过程来实现(经过第一次编译后再次调用不需要再次编译比一个个执行sql语句效率高)create procedure 存储过程名(参数,参数,…)12.4 常见约束
约束含义一种限制用于限制表中的数据为了保证表中数据的准确性和可靠性。分类六大约束
1.NOT NULL 非空用于保证该字段的值不能为空。例如学生表的学生姓名及学号等等。
2.DEFAULT默认值用于保证该字段有默认值。例如学生表的学生性别
3.PRIMARY KEY主键用于保证该字段的值具有唯一性并且非空。例如学生表的学生学号等。
4.UNIQUE唯一用于保证该字段的值具有唯一性可以为空。例如注册用户的手机号身份证号等。
5.CHECK检查约束MySql不支持检查字段的值是否为指定的值。
6.FOREIGN KEY外键用于限制两个表的关系用于保证该字段的值必须来自于主表的关联列的值在从表添加外键约束用于引用主表中某些的值。例如学生表的专业编号添加约束的实际
1.创建表时
2.修改表时约束的添加分类
1 列级约束六大约束语法上都支持但外键约束没有效果
2 表级约束除了非空、默认、其它的都支持。12.5 SQL语句、SQL注入
SQL语言主要用于存取数据、查询数据、更新数据和管理关系数据库系统,SQL语言由IBM开发。SQL语言分为3种类型
1 DDL语句 数据库定义语言 数据库、表、视图、索引、存储过程例如CREATE DROP ALTER
2 DML语句 数据库操纵语言 插入数据INSERT、删除数据DELETE、更新数据UPDATE、查询数据SELECT
3 DCL语句 数据库控制语言 例如控制用户的访问权限GRANT、REVOKEsql注入: 利用现有的程序将恶意的sql命令注入到后台的数据库引擎执行的能力。像符号(两横杠--)会注释掉之后的sql根本原理就是字符串的拼接name%s 原生sql中让execute帮做拼接就可以django的orm种就不会存在这个问题12.6 MVCC、事务隔离级别、读现象
多版本控制mvcc:
保证隔离性多版本并发控制保存数据在某个节点的快照读不加锁读写不冲突增加并发创建时间的版本号过期时间的版本号开启新事务、版本号都会递增事务的隔离级别: 未提交读、提交读、可重复读、可序列化锁
1 Read uncommitted(读未提交)在这种事务隔离级别下一个事务可以读到另外一个事务未提交的数据。可能会脏读
2 Read committed(读已提交):在一个事务修改数据过程中如果事务还没提交其他事务不能读该数据。可能会出现不可重复读
3 Repeatable read(可重复读):由于读已提交隔离级别会产生不可重复读的读现象。所以比读已提交更高一个级别的隔离级别就可以解决不可重复读的问题。这种隔离级别就叫可重复读
4 Serializable(可序列化):是最高的隔离级别前面提到的所有的隔离级别都无法解决的幻读在可序列化的隔离级别中可以解决。innoDB 存储引擎默认隔离级别为可重复读Repeatable Read该隔离级别下
避免了脏读、不可重复读现象的产生对于索引的查询采用 next-key locks。
这样做就避免了幻读现象(读已提交未提交读),(读已提交)。**读现象: 脏读、不可重复读、幻读**
1 脏读A事务读取了已经被B事务更新但是还没有提交的字段之后若此时B回滚A读取的内容就是无效的了称之为脏数据
2 不可重复读事务A按一定条件搜索期间事务B删除了符合条件的某一条数据导致A 再次读取时数据少了一条。这种情况归为不可重复读
3 幻读事务A 按照一定条件进行数据读取期间事务B插入了相同搜索条件的新数据事务A再次按照原先条件进行读取时发现了事务B新插入的数据 称为幻读前提数据库的并发场景有三种
1 读-读不存在任何问题、不需要并发控制
2 读-写有隔离性问题可能遇到脏读、幻读、不可重复读
3 写-写可能存在更新丢失的问题12.7 锁机制
首先对mysql锁进行划分
按照锁的粒度划分行锁、表锁、页锁
按照锁的使用方式划分共享锁、排它锁悲观锁的一种实现
还有两种思想上的锁悲观锁、乐观锁。InnoDB中有几种行级锁类型三种算法Record Lock、Gap Lock、Next-key Lock
1 Record Lock在索引记录上加锁
2 Gap Lock间隙锁
3 Next-key LockRecord LockGap Lock--》解决幻读问题**行锁**只针对当前操作的行加锁。行级锁能减少数据库操作的冲突。加锁粒度最小但加锁的开销也最大。有可能会出现死锁的情况。行级锁按照使用方式分为共享锁和排他锁。
**表锁**只针对当前的操作对整张表加锁资源开销比行锁少不会出现死锁的情况但是发生锁冲突的概率很大。被大部分的mysql引擎支持MyISAM和InnoDB都支持表级锁但是InnoDB默认的是行级锁。是mysql锁中粒度最大的一种锁
**页锁**页级锁是MySQL中锁定粒度介于行级和表级中间的一种锁。表级锁速度快冲突多行级冲突少速度慢。所以取了折衷的页级一次锁定相邻的一组记录。BDB(键值对数据库系统)支持页级锁。无论是悲观锁还是乐观锁他们本质上不是数据库中具体的锁概念而是我们定义出来用来描述两种类别的锁的思想。乐观锁和悲观锁的概念不仅仅存在于数据库领域可以说存在线程安全存在并发的场景几乎都有乐观锁和悲观锁的适用场景。悲观锁和乐观锁是一种思想也叫悲观并发控制和乐观并发控制还有MVCC多版本并发控制
悲观锁PCC:见名知意悲观的认为你会修改数据所以在我修改前就加锁再进行修改
乐观锁OCC:1 假设数据不会冲突在数据提交的时候才会进行冲突检测如果发现冲突了则让返回用户错误的信息让用户决定如何去做。2 相对于悲观锁在对数据库进行处理的时候乐观锁并不会使用数据库提供的锁机制。一般的实现乐观锁的方式就是记录数据版本。DBD介绍
BDB 是 Berkeley DBBerkeley Database的缩写是一种嵌入式数据库管理系统
Embedded Database Management System简称 EDBMS。
Berkeley DB 是由 Oracle 公司开发的一种高性能、轻量级、事务处理的键值对数据库系统。以下是 Berkeley DBBDB的一些主要特点和用途
1. **嵌入式数据库**- Berkeley DB 是一种嵌入式数据库它的数据库引擎被直接嵌入到应用程序中而不是作为独立的服务器运行。这样可以方便地在应用程序内部管理数据。2. **键值对存储**- Berkeley DB 使用简单的键值对key-value存储模型。- 每个数据项都由唯一的键标识应用程序可以通过键快速检索数据。3. **事务支持**- Berkeley DB 提供了事务支持允许应用程序在一组操作中定义一个原子的、一致的、持久的工作单元。这确保了数据的一致性和可靠性。4. **高性能**- Berkeley DB 被设计为高性能的数据库引擎。它在处理大量并发读写操作时表现良好适用于需要快速响应时间的应用场景。5. **多种存储引擎**- Berkeley DB 提供了多种存储引擎包括 Btree、Hash、Queue 等以满足不同类型的应用需求。6. **支持 ACID 特性**- Berkeley DB 遵循 ACID原子性、一致性、隔离性、持久性特性确保数据库的可靠性和稳定性。7. **跨平台**- Berkeley DB 提供了跨平台的支持可以在多种操作系统上运行包括 Linux、Windows、macOS 等。8. **广泛应用**- Berkeley DB 在许多领域被广泛应用包括嵌入式系统、网络应用、金融领域等。- 它被用于存储配置数据、缓存、日志文件等。Berkeley DB 提供了 C 语言的 API同时也有其他语言的绑定如 Java、Python 等。
在一些应用场景中Berkeley DB 被认为是一种可靠的、高性能的数据库解决方案。
然而需要注意的是近年来 Berkeley DB 的维护和更新逐渐减少
而且 Oracle 公司已经停止了对开源版本的维护推荐使用其它替代数据库系统。MVCC介绍
MVCCMulti-Version Concurrency Control是一种数据库管理系统DBMS中
用于处理并发访问的技术。它允许多个事务同时对数据库进行读写操作而不会相互干扰从而提高数据库的并发性能。MVCC 的核心思想是为每个事务创建一个数据版本并在事务之间共存而不是阻塞其他事务。
每个事务在读取数据时看到的是一个特定版本的数据而不受其他并发事务的影响。
这有助于确保事务之间的隔离性同时提高了系统的并发性能。MVCC 的主要组成部分包括以下几个概念
1. **数据版本**- 在 MVCC 中每个数据行都可以有多个版本每个版本与一个特定的事务相关联。- 每当对数据行进行修改时都会创建一个新的版本并将该版本关联到执行修改的事务。2. **事务的可见性**- 事务只能看到在它开始之前已经存在的版本。- 当事务开始时系统记录一个时间戳或序列号事务只能看到该时间戳之前已经存在的版本。3. **并发控制**- 当多个事务同时访问相同的数据时MVCC 使用时间戳或其他方式来确定哪个版本的数据是对事务可见的。- 这种方式避免了读写之间的冲突并允许多个事务同时读取相同的数据行。4. **回滚段**- 数据库通常会使用回滚段来存储已提交事务的历史版本。- 这样即使事务已提交其他事务仍然可以查看之前的版本。MVCC 的优势包括
- **高并发性** 允许多个事务同时读取和修改数据提高了数据库的并发性能。- **提高隔离性** 每个事务看到的是一个特定版本的数据而不受其他事务的影响提高了事务之间的隔离性。- **支持长事务** MVCC 支持长事务而不会导致锁的争用因为每个事务操作的是自己的数据版本。MVCC 在一些主流的数据库系统中得到了广泛的应用例如 PostgreSQL、Oracle、
MySQL 的 InnoDB 存储引擎等。这种并发控制的方法对于大规模的高并发数据库系统非常有用。12.8 异步IO和协程的实现
在 Python 中异步 I/O 和协程是通过 asyncio 模块来实现的。
asyncio 提供了对异步编程的支持其中的关键概念包括异步 I/O 操作、协程和事件循环。以下是异步 I/O 和协程的基本概念和实现方式
1. **异步 I/O**- 异步 I/O 是指在进行 I/O 操作时可以在等待结果的同时执行其他任务而不会阻塞整个程序。- 在 Python 中异步 I/O 是通过使用 asyncio 提供的异步 I/O 操作来实现的。import asyncioasync def main():# 异步执行 I/O 操作result await asyncio.sleep(1)print(Async I/O operation completed)asyncio.run(main())2. **协程**- 协程是一种轻量级的线程可以在执行期间暂停和恢复。- 在 Python 中协程通过 async def 关键字定义并使用 await 关键字进行挂起和恢复。import asyncioasync def coroutine_example():print(Start coroutine)await asyncio.sleep(2)print(Coroutine resumed after sleep)asyncio.run(coroutine_example())3. **事件循环**- 事件循环是异步编程的核心负责调度和执行异步任务。- 在 Python 中可以使用 asyncio 的事件循环来管理协程的执行。import asyncioasync def task_one():print(Task One)async def task_two():print(Task Two)async def main():# 创建事件循环loop asyncio.get_event_loop()# 添加异步任务到事件循环loop.create_task(task_one())loop.create_task(task_two())# 运行事件循环await asyncio.sleep(1)asyncio.run(main())以上示例展示了异步 I/O 操作、协程的定义和事件循环的使用。
asyncio 提供了更多丰富的功能包括异步锁、异步队列、协程的并发控制等。
在实际应用中异步编程可以提高程序的并发性能特别是在处理大量 I/O 操作时。12.9 Redis数据类型、链接池、管道、事务缓存设计与优化
1 redis数据库非关系型redis内存数据库所有数据放在内存中
2 数据类型字符串列表字典hash集合有序集合
3 链接池连接池的作用相当于缓存了多个客户端与redis服务端的连接当有新的客户端来进行连接时此时只需要去连接池获取一个连接即可实际上连接池就是把一个连接共享给多个客户端可以说是广播要用的话就去接收。
4 管道非关系型数据库本身不支持事务redis默认在执行每次请求都会创建连接池申请连接和断开归还连接池一次连接操作如果想要在一次请求中指定多个命令则可以使用pipline实现一次请求指定多个命令并且默认情况下一次pipline 是原子性操作。**redis当中如何实现事务集群不支持单机才支持**
具体实现开启管道把命令放进去调用execute依次执行管道中的所有命令它的原理就是要么一次性都执行要么都不执行保证了事务**如果遇到访问的接口新增修改操作比较频繁怎么解决呢如果是访问和新增修改同样频繁呢**
解决1 每次更新修改数据的时候redis就删除一次缓存下次访问的时候再去mysql中取
解决2 在序列化器中重写save方法每次新增修改数据就删除一次缓存这样每次访问该接口的时候再去数据库中获取数据存到缓存中拿到的数据都是最新的首次访问缓存没有就去数据库中拿数据再次访问的时候速度就快了。这种两种解决方式优点
1 好处加速读写
2 降低后端负载后端服务器通过前端缓存降低负载业务端使用redis降低后端mysql负载应用场景
1 降低后端负载对高消耗的sqljoin结果集/分组统计的结果做缓存
2 加速请求响应利用redis优化io响应时间
3 大量写合并为批量写如计数器先redis累加再批量写入db13 Celery进行异步任务、定时任务的处理包结构封装与使用
Celery异步任务框架是一个简单、灵活且可靠的处理大量消息的分布式系统
专注于实时处理的异步任务队列同时也支持任务调度应用场景
异步任务解决耗时任务,将耗时操作任务提交给Celery去异步执行比如发送短信/邮件、消息推送、音视频处理等等
延迟任务解决延迟任务延迟多长时间执行一个任务
定时任务定时执行某件事情比如每天数据统计Celery的架构由三部分组成消息中间件message broker、任务执行单元worker和 任务执行结果存储taskresult store组成
1 消息中间件: Celery本身不提供消息服务但是可以方便的和第三方提供的消息中间件集成。包括RabbitMQ, Redis等等
2 任务执行单元: Worker是Celery提供的任务执行的单元worker并发的运行在分布式的系统节点中。
3 任务结果存储:Task result store用来存储Worker执行的任务的结果Celery支持以不同方式存储任务的结果包括AMQP, redis等14 Git项目版本管理工具、docker部署。
工作中常用的几个git命令:
新增文件的命令
git add file或者git add .提交文件的命令
git commit –m 或者 git commit –a查看工作区状况
git status –s拉取合并远程分支的操作
git fetch/git merge或者git pull查看提交记录命令
git reflog我们公司开发用的gitee有个主分支我们大家开发都用一个分支
所有人共用一个它的好处是不存在合并时发生冲突我们采用敏捷开发的15 linux操作命令
cd 是切换到你要的目录里去
ls 是显示文件夹里面有些什么文件
mkdir 是创建文件夹
touch 是创建文件
mv 是移动某个文件到对应的文件夹下
vim 是用来做文本编辑的
tree 是显示目录层级
echo 相当于python的print是输出的打印的意思
rm 是删除16 生产者消费者模型
什么是生产者消费者模型
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯而通过阻塞队列来进行通讯
所以生产者生产完数据之后不用等待消费者处理直接扔给阻塞队列
消费者不找生产者要数据而是直接从阻塞队列里取
阻塞队列就相当于一个缓冲区平衡了生产者和消费者的处理能力。基于队列实现生产者消费者模型生产者生产/制造东西
消费者消费/处理东西的
该模型除了上述两个之外还需要一个媒介
生活中的例子做包子的将包子做好之后放在蒸笼媒介里面买包子的去蒸笼里面拿
厨师做菜做完之后用盘子装着给消费者端过去
生产者和消费者之间不是直接做交互的而是借助于媒介做交互
生产者做包子的 消息队列蒸笼 消费者吃包子的17 orm可以怎么优化
批量创建 bulk_create()
尽量不要在循环中操作 QuerySet
用values( )或values_list( )只取需要的列的数据
使用iterator()方法来获取数据处理完数据就将其丢弃
select_related 查询外键
prefetch_related 处理一对多、多对多查询18 数据库可以怎么优化
索引、MySQL集群、负载均衡、读写分离19 程序效率可以怎么优化
只加载必要的模块延迟加载
缓存优化
服务器架构优化
后端可以使用uwsgi
前端使用nginx 或者F5做负载均衡20 mysql、redis高级
mysql主从同步 业务、做高可用 两个nginx和两个tomcat两个mysql实现高可用
避免 单点问题、中间使用keepalived监听
1、实现服务器负载均衡
2、通过复制实现数据的异地备份、提高数据库系统的可用性原理:
1.Master 数据库只要发生变化立马记录到Binary log 日志文 件中
2.Slave数据库启动一个I/O thread连接Master数据库请求 Master变化的二进制日志
3.Slave I/O获取到的二进制日志保存到自己的Relay log 日志 文件中。
4.Slave 有一个 SQL thread定时检查Realy log是否变化变化 那么就更新数据主从延迟:
1. 首先就是主库可以并发写入从库只能通过单sql thread完成任务 MySQL5.7之前
2. MySQL主从之间的同步本来就不是时时同步的是异步的同步也就是说主库提交
事务之后从库才再来执行一遍。
3. 在主库上对没有索引大表的列进行delete或者update的操作
4. 从库的硬件配置没有主库的好经常忽略从库的重要性
5. 网络问题 解决: 1. 避免一些无用的IO消耗可以上高转速的磁盘SSD或者PCIE-SSD 设备2. 阵列级别要选择RAID10raid cache策略要使用WB坚决不要WT。3. IO调度要选择deadline模式。4. 适当调整buffer pool的大小redis非关系型键值对NoSQL数据库 AOF和RDB Redis持久化:
RDB方案: 快照某时刻完成备份、写日志、任何草错记录日志要恢复数据、只要把 日志从新走一遍即可AOF方案: 客户端每写入一条命令都记录一条日志放到日志文件中、如果出现宕机、可以将数据完全恢复.三种策略.日志不是直接写到硬盘上而是放在缓冲区缓冲区根据一些策略、写到硬盘 aof重写: 本质就是把过期的无用的可以优化的命令来优化减少磁盘占用量加快恢复速度主从复制: 高可用:
1、副本库通过slaveof 127.0.0.1 6379命令连接主库、并发送sync给主库
2、主库收到sync触发BGSAVE,后台保存RDB发送给副本库
3、副本库接受或会应用RDB快照、
4、主库会陆续将中间产生的新的操作、保存并发送给副本库
5、到此、主复制集就正常工作
6、再此后、主库只要发生新的操作、都会以命令传播形式自动发送给副本库
7. 所有复制相关信息,从info信息中都可以查到.即使重启任何节点,他的主从关 系依然都在.
8. 如果发生主从关系断开时,从库数据没有任何损坏,在下次重连之后,从库发送 PSYNC给主库
9. 主库只会将从库缺失部分的数据同步给从库应用,达到快速恢复主从的目的哨兵高可用:
1 多个sentinel发现并确认master有问题
2 选举触一个sentinel作为领导
3 选取一个slave作为新的master
4 通知其余slave成为新的master的slave
5 通知客户端主从变化
6 等待老的master复活成为新master的slave缓存雪崩: 大量缓存数据在同一时间过期、redis服务宕机、刚好大量用户请求、都无法在 redis中处理都会直接访
问数据库造成高并发、导致数据库宕机形成连锁反应导致服务器崩溃解决方案:
1 缓存数据的过期时间设置随机防止同一时间大量数据过期现象发生。
2 如果缓存数据库是分布式部署将热点数据均匀分布在不同搞得缓存数据库中。
3 设置热点数据永远不过期。缓存预热: 业务刚上线的时候就提前把数据缓存起来、针对缓存雪崩的数据过期的一种方式
缓存击穿业务被频繁访问称为热数据大量请求访问的热数据过期了无法从缓存中读取直接访问数据库引起数
据库压力瞬间增大造成过大压力
解决方案设置热点数据永远不过期。
缓存穿透缓存穿透是用户访问数据不在缓存不在数据库、所有访问缓存的时候缓存缺失、访问数据库、数据库也没有、没办法构建缓存这样大量访问来的时候就会造成缓存穿透这时的用户很可能是攻击者攻击会导致数据库压力过大。解决方案
1 限制非法请求接口层增加校验如用户鉴权校验id做基础校验id0的直接拦截
2 缓存空值将key-value对写为key-null缓存有效时间可以设置短点如30秒
设置太长会导致正常情况也没法使用。这样可以防止攻击用户反复用同一个id暴力攻击
3 利用布隆过滤器、
redis淘汰机制: 用一定的缓存丢失来换取内存的使用效率。21 uWSGI和nginx的理解
uWSGI是一个web服务器它实现了WSGI协议uwsgi、http等协议
Nginx中HttpUwsgiModule的作用是与uWSGI服务器进行交换
WSGI是一种Web服务器网关接口他是一个Web服务器与web应用通信的一种规范
WSGI是一种通信协议
uwsgi是一种线路协议而不是通信协议在此常用语在uWSGI服务器与其他网络服务器的数据通信
uWSGI是实现了uwsgi和WSGI两种协议的Web服务器
nginx是一个开源的高性能的HTTP服务器和反向代理:
1.作为web服务器它处理静态文件和索引文件效果非常高
2.它的设计非常注重效率最大支持5万个并发链接但只占用很少的内存空间
3.稳定性高配置简洁。
4.强大的反向代理和负载均衡功能平衡集群中各个副武器的负载压力应用