怎样让百度搜不到自己的网站,wordpress 火箭,热门网站,网站开发技能介绍一、基础部分
1、什么是Python#xff1f;为什么它会如此流行#xff1f;Python是一种解释的、高级的、通用的编程语言。Python的设计理念是通过使用必要的空格与空行#xff0c;增强代码的可读性。它之所以受欢迎#xff0c;就是因为它具有简单易用的语法
2、为什么Pytho…一、基础部分
1、什么是Python为什么它会如此流行Python是一种解释的、高级的、通用的编程语言。Python的设计理念是通过使用必要的空格与空行增强代码的可读性。它之所以受欢迎就是因为它具有简单易用的语法
2、为什么Python执行速度慢我们如何改进它Python代码执行缓慢的原因是因为它是一种解释型语言。它的代码在运行时进行解释而不是编译为本地语言。为了提高Python代码的速度我们可以使用CPython、Numba或者我们也可以对代码进行一些修改。1. 减少内存占用。2. 使用内置函数和库。3. 将计算移到循环外。4. 保持小的代码库。5. 避免不必要的循环3、Python有什么特点1. 易于编码2. 免费和开源语言3. 高级语言4. 易于调试5. OOPS支持6. 大量的标准库和第三方模块7. 可扩展性(我们可以用C或C编写Python代码)8. 用户友好的数据结构4、Python有哪些应用1. Web开发2. 桌面GUI开发3. 人工智能和机器学习4. 软件开发5. 业务应用程序开发6. 基于控制台的应用程序7. 软件测试8. Web自动化9. 基于音频或视频的应用程序10. 图像处理应用程序5、Python的局限性1. 速度2. 移动开发3. 内存消耗(与其他语言相比非常高)4. 两个版本的不兼容(23)5. 运行错误(需要更多测试并且错误仅在运行时显示)6. 简单性
6、如何在Python中管理内存Python内存由Python的私有headspace管理。所有的Python对象和数据结构都位于一个私有堆中。私用堆的分配由Python内存管理器负责。Python还内置了一个的垃圾收集器可以回收未使用的内存并释放内存使其可用于headspace。7、解释Python的内置数据结构Python中主要有四种类型的数据结构列表列表是从整数到字符串甚至另一个列表的异构数据项的集合。列表是可变的。列表完成了其他语言中大多数集合数据结构的工作。列表在[ ]方括号中定义。例如a [1,2,3,4]集合集合是唯一元素的无序集合。集合运算如联合|交集和差异可以应用于集合。{}用于表示一个集合。例如a {1,2,3,4}元组Python元组的工作方式与Python列表完全相同只是它们是不可变的。()用于定义元组。例如a 1,2,3,4字典字典是键值对的集合。它类似于其他语言中的hash map。在字典里键是唯一且不可变的对象。例如a {number[1,2,3,4]}
8、Python中的单引号和双引号有什么区别在Python中使用单引号( )或双引号( )是没有区别的都可以用来表示一个字符串。这两种通用的表达方式除了可以简化程序员的开发避免出错之外还有一种好处就是可以减少转义字符的使用使程序看起来更简洁更清晰。
9、Python中appendinsert和extend的区别?append在列表末尾添加新元素。insert在列表的特定位置添加元素。extend通过添加新列表来扩展列表。
10、break、continue、pass是什么break在满足条件时它将导致程序退出循环。continue将返回到循环的开头它使程序在当前循环迭代中的跳过所有剩余语句。pass使程序传递所有剩余语句而不执行。
11、区分Python中的removedel和popremove将删除列表中的第一个匹配值它以值作为参数。del使用索引删除元素它不返回任何值。pop将删除列表中顶部的元素并返回列表的顶部元素。12、和is的区别是比较两个对象或值的相等性。is运算符用于检查两个对象是否属于同一内存对象。list1[1,2,3,4]list2[1,2,3,4]print(id(list1))print(id(list2))print(list1list2)print(**50)print(list1 is list2)140105464266496140105464277120True**************************************************False
13、!和is not运算符的区别!如果两个变量或对象的值不相等则返回true。is not是用来检查两个对象是否属于同一内存对象。14、什么是lambda函数Lambda函数是不带名称的单行函数可以具有n个参数但只能有一个表达式。也称为匿名函数。eg: alambda x,y:xyprint(a(5,6))1115、 Python中的Map Function是什么map函数在对可迭代对象的每一项应用特定函数后会返回map对象。16、如何使用索引来反转Python中的字符串?strhelloprint(str[::-1])17、类和对象有什么区别类(Class)被视为对象的蓝图。类中的第一行字符串称为doc字符串包含该类的简短描述。在Python中使用class关键字可以创建了一个类。一个类包含变量和成员组合称为类成员。对象(Object)是真实存在的实体。在Python中为类创建一个对象我们可以使用obj CLASS_NAME()例如obj num()使用类的对象我们可以访问类的所有成员并对其进行操作。
18、你对Python类中的self有什么了解self表示类的实例。通过使用self关键字我们可以在Python中访问类的属性和方法。注意在类的函数当中必须使用self因为类中没有用于声明变量的显式语法。19、Python中OOPS是什么面向对象编程抽象(Abstraction)、封装(Encapsulation)、继承(Inheritance)、多态(Polymorphism)抽象(Abstraction):将一个对象的本质或必要特征向外界展示并隐藏所有其他无关信息的过程。封装(Encapsulation)意味着将数据和成员函数包装在一起成为一个单元。它还实现了数据隐藏的概念。多态(Polymorphism):子类可以定义自己的独特行为并且仍然共享其父类/基类的相同功能或行为。
20、Python支持多重继承吗Python可以支持多重继承。多重继承意味着一个类可以从多个父类派生。
21、Python中使用的zip函数是什么zip函数获取可迭代对象将它们聚合到一个元组中然后返回结果。zip()函数的语法是zip(*iterables)numbers [1, 2, 3]string [one, two, three] result zip(numbers,string)print(set(result))-------------------------------------{(3, three), (2, two), (1, one)}
**22、Python中的装饰器是什么**面试几乎必问之一要求能手写装饰器装饰器(Decorator)是Python中一个有趣的功能。它用于向现有代码添加功能。这也称为元编程因为程序的一部分在编译时会尝试修改程序的另一部分。def addition(func):def inner(a,b):print(numbers are,a,and,b)return func(a,b)return inneradditiondef add(a,b):print(ab)add(5,6)---------------------------------numbers are 5 and 6sum: 11
23、用一行Python代码从给定列表中取出所有的偶数和奇数a [1,2,3,4,5,6,7,8,9,10]odd, even [el for el in a if el % 21], [el for el in a if el % 20]print(odd,even) ([1, 3, 5, 7, 9], [2, 4, 6, 8, 10])24、谈下python的GILGIL 是python的全局解释器锁同一进程中假如有多个线程运行一个线程在运行python程序的时候会霸占python解释器加了一把锁即GIL使该进程内的其他线程无法运行等该线程运行完后其他线程才能运行。如果线程运行过程中遇到耗时操作则解释器锁解开使其他线程运行。所以在多线程中线程的运行仍是有先后顺序的并不是同时进行。多进程中因为每个进程都能被系统分配资源相当于每个进程有了一个python解释器所以多进程可以实现多个进程的同时运行缺点是进程系统资源开销大25、、简述面向对象中__new__和__init__区别__init__是初始化方法创建对象后就立刻被默认调用了可接收参数1、__new__至少要有一个参数cls代表当前类此参数在实例化时由Python解释器自动识别2、__new__必须要有返回值返回实例化出来的实例这点在自己实现__new__时要特别注意可以return父类通过super(当前类名, cls)__new__出来的实例或者直接是object的__new__出来的实例3、__init__有一个参数self就是这个__new__返回的实例__init__在__new__的基础上可以完成一些其它初始化的动作__init__不需要返回值4、如果__new__创建的是当前类的实例会自动调用__init__函数通过return语句里面调用的__new__函数的第一个参数是cls来保证是当前类实例如果是其他类的类名那么实际创建返回的就是其他类的实例其实就不会调用当前类的__init__函数也不会调用其他类的__init__函数。26、字典根据键从小到大排序dic{name:zs,age:18,city:深圳,tel:1362626627}print(dict(sorted(dic.items(),keylambda x:x[0],reverseFalse)))
27、[[1,2],[3,4],[5,6]]一行代码展开该列表得出[1,2,3,4,5,6]列表推导式print([j for i in li for j in i])numpy方法import numpy as npprint(np.array(li).flatten().tolist())
28、遇到bug如何处理?1、细节上的错误通过print打印能执行到print说明一般上面的代码没有问题分段检测程序是否有问题如果是js的话可以alert或console.log2、如果涉及一些第三方框架会去查官方文档或者一些技术博客。3、对于bug的管理与归类总结一般测试将测试出的bug用teambin等bug管理工具进行记录然后我们会一条一条进行修改修改的过程也是理解业务逻辑和提高自己编程逻辑缜密性的方法我也都会收藏做一些笔记记录。4、导包问题、城市定位多音字造成的显示错误问题
**29、写一个单例模式**因为创建对象时__new__方法执行并且必须return 返回实例化出来的对象所cls.__instance是否存在不存在的话就创建对象存在的话就返回该对象来保证只有一个实例对象存在单列打印ID值一样说明对象同一个class Singleton(object):__instanceNonedef __new__(cls, *args, **kwargs):if cls.__instance is None:cls.__instance object.__new__(cls)return cls.__instanceaSingleton(18,A)bSingleton(22,B)print(id(a))print(id(b))
30 python 内存泄漏Python 有自动垃圾回收但还是会有内存泄漏的情况现在总结一下三种常见的内存泄漏场景。1、无穷大导致内存泄漏如果把内存泄漏定义成只申请不释放那么借着 Python 中整数可以无穷大的这个特点我们一行代码就可以完成内存泄漏了。i 1024 ** 1024 ** 10242、循环引用导致内存泄漏引用记数器 是 Python 垃圾回收机制的基础如果一个对象的引用数量不为 0 那么是不会被垃圾回收的我们可以通过 sys.getrefcount 来得到给定对象的引用数量。3、外面库导致内存泄漏这种情况我也只遇到过一次之前 mysql-connector-python 的内存泄漏导致我的程序跑着跑着占用的内存就越来越大最后我们返的 C 语言扩展禁用之后就没有问题了。
31、内存泄漏和内存溢出的区别内存溢出是指向JVM申请内存空间时没有足够的可用内存了就会抛出OOM即内存溢出。内存泄漏是指向JVM申请了一块内存空间使用完后没有释放由于没有释放这块内存区域其他类加载的时候无法申请同时当前类又没有这块内存空间的内存地址了也无法使用相当于丢了一块内存这就是内存泄漏。值得注意的是内存泄漏最终会导致内存溢出很好理解内存丢了很多最后当然内存不够用了。
32、Python 字典实现 对象.属性 调用class dict(dict):def __new__(cls, *args, **kwargs):return super().__new__(cls)def __getattr__(self, name):if name.startswith(__):raise AttributeErrorreturn self.get(name)def __setattr__(self, name, val):self[name] valdef __hash__(self):return id(self)**33、多线程、多进程和协程的区别与联系**多线程线程是进程的一个实体是CPU进行调度的最小单位他是比进程更小能独立运行的基本单位。线程基本不拥有系统资源只占用一点运行中的资源如程序计数器,一组寄存器和栈但是它可以与同属于一个进程的其他线程共享全部的资源。提高程序的运行速率上下文切换快开销比较少但是不够稳定容易丢失数据形成死锁。多进程进程是系统进行资源分配的最小单位每个进程都有自己的独立内存空间不用进程通过进程间通信来通信。但是进程占据独立空间比较重量级所以上下文进程间的切换开销比较大但是比较稳定安全。协程协程是更小的执行单位是一种轻量级的线程协程的切换只是单纯的操作CPU的上下文所以切换速度特别快且耗能小。gevent是第三方库通过greenlet实现协程其基本思想是当一个greenlet遇到IO操作时比如访问网络就自动切换到其他的greenlet等到IO操作完成再在适当的时候切换回来继续执行。由于IO操作非常耗时经常使程序处于等待状态有了gevent为我们自动切换协程就保证总有greenlet在运行而不是等待IO。
**34、元组是不可变的元组中存一个列表列表中元素是否可以改变可以**
35、浅拷贝与深拷贝的区别浅拷贝创建新对象其内容是原对象的引用只拷贝一层。深拷贝和浅拷贝对应深拷贝拷贝了对象的所有元素包括多层嵌套的元素。深拷贝出来的对象是一个全新的对象不再与原来的对象有任何关联。
36、什么是RESTfulREST指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是RESTful。37、如何设计 restful API 1、协议API与用户的通信协议总是使用HTTPs协议。2、域名应该尽量将API部署在专用域名之下3、版本应该将API的版本号放入URL。4、路径路径又称终点endpoint表示API的具体网址。在RESTful架构中每个网址代表一种资源resource所以网址中不能有动词只能有名词而且所用的名词往往与数据库的表格名对应。一般来说数据库中的表都是同种记录的集合collection所以API中的名词也应该使用复数。5、http 动词常用的HTTP动词有下面五个GETSELECT从服务器取出资源一项或多项。POSTCREATE在服务器新建一个资源。PUTUPDATE在服务器更新资源客户端提供改变后的完整资源。PATCHUPDATE在服务器更新资源客户端提供改变的属性。DELETEDELETE从服务器删除资源。6、过滤信息如果记录数量很多服务器不可能都将它们返回给用户。API应该提供参数过滤返回结果。7、状态码服务器向用户返回的状态码和提示信息8、错误处理如果状态码是4xx就应该向用户返回出错信息9、返回结果针对不同操作服务器向用户返回的结果应该符合以下规范。GET /collection返回资源对象的列表数组GET /collection/resource返回单个资源对象POST /collection返回新生成的资源对象PUT /collection/resource返回完整的资源对象PATCH /collection/resource返回完整的资源对象DELETE /collection/resource返回一个空文档10、Hypermedia APIRESTful API最好做到Hypermedia即返回结果中提供链接连向其他API方法使得用户不查文档也知道下一步应该做什么。11、其他服务器返回的数据格式应该尽量使用JSON避免使用XML38、python 中字典的底层实现原理在Python中字典是通过散列表哈希表实现的。字典也叫哈希数组或关联数组所以其本质是数组。
39、如何解决哈希碰撞或者哈希冲突1、开放寻址法2、再哈希法3、链地址法4、公共溢出区5、装填因子
40、python 装饰器函数装饰器与类装饰器函数装饰器函数能作为参数传递给其他函数可以被赋值给其他变量可以作为返回值可以被定义在另外一个函数内类装饰器类具有__call__方法当使用 形式将装饰器附加到函数上时就会调用此方法 应用场景 插入日志、性能测试、事务处理、缓存、权限校验等
41 token和jwt-token存在什么区别
相同 都是访问资源的令牌 都可以记录用户信息都是只有验证成功后
不同点服务端验证客户端发来的token信息要进行数据的查询操作JWT验证客户端发来的token信息就不用 在服务端使用密钥校验就可以不用数据库的查询。
42、浏览器请求相应全过程详解
- 在浏览器中输入URL 或者IP 或者域名
- 如果输入的是域名就需要进行DNS解析成IP地址通过IP来确认是哪个服务器
- 建立TCP 请求即三次握手
- 发送http请求
- 服务器处理请求并将处理结果返回给浏览器
- 最后断开连接即四次挥手
- 浏览器根据返回结果进行处理以及页面渲染
43、为什么是三次握手 而不是两次呢
防止出现请求超时脏链接
44、python 常见的魔法方法__init____new____call____str____repr__
45、python slots 在类中的作用主要用于避免动态创建属性它用于节省对象中的内存空间。静态结构不允许在任何时候动态创建对象而是在初始创建之后不允许这样做。 如果要实例化数百个数千个同一类的对象则 需要使用 __slots__ 。__slots__ 仅作为内存优化工具存在。**警告**不幸的是插槽有副作用。 不要过早优化并在各处使用它 它对代码维护不是很好它实际上只有在拥有数千个实例时才能为您节省
二、数据库部分 ## mysql 相关1、数据库优化查询方法外键、索引、联合查询、选择特定字段等等
2、简述mysql和redis区别redis 内存型非关系数据库数据保存在内存中速度快mysql关系型数据库数据保存在磁盘中检索的话会有一定的Io操作访问速度相对慢
3、列出常见MYSQL数据存储引擎InnoDB支持事务处理支持外键支持崩溃修复能力和并发控制。如果需要对事务的完整性要求比较高比如银行要求实现并发控制比如售票那选择InnoDB有很大的优势。如果需要频繁的更新、删除操作的数据库也可以选择InnoDB因为支持事务的提交commit和回滚rollback。MyISAM插入数据快空间和内存使用比较低。如果表主要是用于插入新记录和读出记录那么选择MyISAM能实现处理高效率。如果应用的完整性、并发性要求比 较低也可以使用。MEMORY所有的数据都在内存中数据的处理速度快但是安全性不高。如果需要很快的读写速度对数据的安全性要求较低可以选择MEMOEY。它对表的大小有要求不能建立太大的表。所以这类数据库只使用在相对较小的数据库表。
4、日常工作中你是怎么优化SQL的加索引--避免返回不必要的数据--适当分批量进行--优化sql结构--分库分表--读写分离
5、说说分库与分表的设计水平分库以字段为依据按照一定策略hash、range等将一个库中的数据拆分到多个库中水平分表以字段为依据按照一定策略hash、range等将一个表中的数据拆分到多个表中。垂直分库以表为依据按照业务归属不同将不同的表拆分到不同的库中。垂直分表以字段为依据按照字段的活跃性将表中字段拆到不同的表主表和扩展表中。
6、事务的隔离级别有哪些MySQL的默认隔离级别是什么读未提交Read Uncommitted读已提交Read Committed可重复读Repeatable Read串行化SerializableMysql默认的事务隔离级别是可重复读(Repeatable Read)其他数据库一般默认为读已提交。我们可以把mysql的默认隔离级别修改为读已提交这句话面试官不问不要说不要给自己挖坑
7、什么是幻读脏读不可重复读呢事务A、B交替执行事务A被事务B干扰到了因为事务A读取到事务B未提交的数据,这就是脏读在一个事务范围内两个相同的查询读取同一条记录却返回了不同的数据这就是不可重复读。事务A查询一个范围的结果集另一个并发事务B往这个范围中插入/删除了数据并静悄悄地提交然后事务A再次查询相同的范围两次读取得到的结果集不一样了这就是幻读。
**8、说一下数据库的三大范式**第一范式数据表中的每一列每个字段都不可以再拆分第二范式在第一范式的基础上分主键列完全依赖于主键而不能是依赖于主键的一部分第三范式在满足第二范式的基础上表中的非主键只依赖于主键而不依赖于其他非主键
**9、索引有哪几种类型**主键索引: 数据列不允许重复不允许为NULL一个表只能有一个主键。唯一索引: 数据列不允许重复允许为NULL值一个表允许多个列创建唯一索引。普通索引: 基本的索引类型没有唯一性的限制允许为NULL值。全文索引是目前搜索引擎使用的一种关键技术对文本的内容进行分词、搜索覆盖索引查询列要被所建的索引覆盖不必读取数据行组合索引多列值组成一个索引用于组合搜索效率大于索引合并
10、创建索引有什么原则呢最左前缀匹配原则频繁作为查询条件的字段才去创建索引频繁更新的字段不适合创建索引索引列不能参与计算不能有函数操作优先考虑扩展索引而不是新建索引避免不必要的索引在order by或者group by子句中创建索引需要注意顺序区分度低的数据列不适合做索引列(如性别定义有外键的数据列一定要建立索引。对于定义为text、image数据类型的列不要建立索引。删除不再使用或者很少使用的索引
11、什么是数据库事务数据库事务简称事务是数据库管理系统执行过程中的一个逻辑单位由一个有限的数据库操作序列构成这些操作要么全部执行,要么全部不执行是一个不可分割的工作单位。
12、mysql 事务的特性ACID原子性、一致性、隔离性、持久性
13、B树和B树的区别1、B-树是一类树包括B-树、B树、B*树等是一棵自平衡的搜索树它类似普通的平衡二叉树不同的一点是B-树允许每个节点有更多的子节点。
B-树是专门为外部存储器设计的如磁盘它对于读取和写入大块数据有良好的性能所以一般被用在文件系统及数据库中。2、B树是B-树的变体也是一种多路搜索树, 它与 B- 树的不同之处在于:所有关键字存储在叶子节点出现,内部节点(非叶子节点并不存储真正的 data)为所有叶子结点增加了一个链指针因为内节点并不存储 data所以一般B树的叶节点和内节点大小不同而B-树的每个节点大小一般是相同的为一页
14、mysql 行锁MySQL的行锁又分为共享锁S锁和排他锁X锁。一般普通的select语句InnoDB不加任何锁我们称之为快照读select * from test;通过加S锁和X锁的select语句或者插入/更新/删除操作我们称之为当前读select * from test lock in share mode;select * from test for update;insert into test values(…);update test set …;delete from test …;以上的当前读读取的都是记录的最新版本。对读取记录都会加锁除了第一条语句lock in share mode是对记录加S锁共享锁外其他的操作都是加X锁排他锁。
15、什么是死锁怎么解决
死锁是指两个或多个事务在同一资源上相互占用并请求锁定对方的资源从而导致恶性循环的现象
常见的解决死锁的方法如果不同程序会并发存取多个表 尽量约定以相同的顺序访问表可以大大降低死锁机会。
在同一个事务中尽可能做到一次锁定所需要的所有资源减少死锁产生概率
对于非常容易产生死锁的业务部分可以尝试使用升级锁定颗粒度通过表级锁定来减少死锁产生的概率16、什么是脏读幻读不可重复读
脏读(Drity Read)某个事务已更新一份数据另一个事务在此时读取了同一份数据 由于某些原因前一个RollBack了操作则后一个事务所读取的数据就会是不正确的。不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致 这可能是两次查询过程中间插入了一个事务更新的原有的数据。幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致 例如有一个事务查询了几列(Row)数据 而另一个事务却在此时插入了新的几列数据先前的事务在接下来的查询中 就会发现有几列数据是它先前所没有的。17、索引有哪些使用场景
1)、应该创建索引的场景主键应该创建主键索引。
频繁作为查询条件的字段应该创建索引。
查询中需要与其他表进行关联的字段应该创建索引。
需要排序的字段应该创建索引。
需要统计或分组的字段应该创建索引。
优先考虑创建复合索引。
2)、不应创建索引的场景
数据记录较少的表。
经常需要增删改操作的字段。
数据记录重复较多且分布平均的字段如性别、状态等。## redis 相关
1、redis 是单线程还是多线程
大家所熟知的 Redis 确实是单线程模型指的是执行 Redis 命令的核心模块是单线程的而不是整个 Redis 实例就一个线程Redis 其他模块还有各自模块的线程的
2、Redis 不仅仅是单线程
一般来说 Redis 的瓶颈并不在 CPU而在内存和网络。如果要使用 CPU 多核可以搭建多个 Redis 实例来解决。
其实Redis 4.0 开始就有多线程的概念了比如 Redis 通过多线程方式在后台删除对象、以及通过 Redis 模块实现的阻塞命令等。
3、Redis系列 | 缓存穿透、击穿、雪崩、预热、更新、降级
缓存穿透
当查询Redis中没有的数据时该查询会下沉到数据库层同时数据库层也没有该数据当这种情况大量出现或被恶意攻击时接口的访问全部透过Redis访问数据库而数据库中也没有这些数据我们称这种现象为缓存穿透。
解决方案
在接口访问层对用户做校验如接口传参、登陆状态、n秒内访问接口的次数
利用布隆过滤器将数据库层有的数据key存储在位数组中以判断访问的key在底层数据库中是否存在
缓存击穿
缓存击穿和缓存穿透从名词上可能很难区分开来它们的区别是穿透表示底层数据库没有数据且缓存内也没有数据击穿表示底层数据库有数据而缓存内没有数据。当热点数据key从缓存内失效时大量访问同时请求这个数据就会将查询下沉到数据库层此时数据库层的负载压力会骤增我们称这种现象为缓存击穿。
解决方案
延长热点key的过期时间或者设置永不过期如排行榜首页等一定会有高并发的接口
利用互斥锁保证同一时刻只有一个客户端可以查询底层数据库的这个数据一旦查到数据就缓存至Redis内避免其他大量请求同时穿过Redis访问底层数据库
缓存雪崩
缓存雪崩是缓存击穿的大面积版缓存击穿是数据库缓存到Redis内的热点数据失效导致大量并发查询穿过redis直接击打到底层数据库而缓存雪崩是指Redis中大量的key几乎同时过期然后大量并发查询穿过redis击打到底层数据库上此时数据库层的负载压力会骤增我们称这种现象为缓存雪崩。
解决方案
在可接受的时间范围内随机设置key的过期时间分散key的过期时间以防止大量的key在同一时刻过期
对于一定要在固定时间让key失效的场景(例如每日12点准时更新所有最新排名)可以在固定的失效时间时在接口服务端设置随机延时将请求的时间打散让一部分查询先将数据缓存起来
延长热点key的过期时间或者设置永不过期这一点和缓存击穿中的方案一样
缓存预热
缓存预热如字面意思当系统上线时缓存内还没有数据如果直接提供给用户使用每个请求都会穿过缓存去访问底层数据库如果并发大的话很有可能在上线当天就会宕机因此我们需要在上线前先将数据库内的热点数据缓存至Redis内再提供出去使用这种操作就成为缓存预热。
缓存预热的实现方式有很多比较通用的方式是写个批任务在启动项目时或定时去触发将底层数据库内的热点数据加载到缓存内。
缓存更新
缓存服务Redis和数据服务底层数据库是相互独立且异构的系统在更新缓存或更新数据的时候无法做到原子性的同时更新两边的数据因此在并发读写或第二步操作异常时会遇到各种数据不一致的问题。
缓存更新的设计模式有四种
Cache aside查询先查缓存缓存没有就查数据库然后加载至缓存内更新先更新数据库然后让缓存失效或者先失效缓存然后更新数据库
Read through在查询操作中更新缓存即当缓存失效时Cache Aside 模式是由调用方负责把数据加载入缓存而 Read Through 则用缓存服务自己来加载
Write through在更新数据时发生。当有数据更新的时候如果没有命中缓存直接更新数据库然后返回。如果命中了缓存则更新缓存然后由缓存自己更新数据库
Write behind caching俗称write back在更新数据的时候只更新缓存不更新数据库缓存会异步地定时批量更新数据库
缓存降级
缓存降级是指当访问量剧增、服务出现问题如响应时间慢或不响应或非核心服务影响到核心流程的性能时即使是有损部分其他服务仍然需要保证主服务可用。可以将其他次要服务的数据进行缓存降级从而提升主服务的稳定性。Redis 能够处理速度快的原因主要有以下几个方面1、内存数据库Redis是一种内存数据库数据存储在内存中因此读写速度非常快。2、单线程Redis是单线程的避免了多线程带来的上下文切换和锁竞争的开销因此可以更高效地利用CPU资源。3、非阻塞式IORedis使用了非阻塞式IO当执行一个IO操作时它不会被阻塞而是会立即返回这样就可以执行其他操作提高了Redis的响应速度。4、基于事件驱动Redis采用了基于事件驱动的模型通过监听socket事件当事件发生时执行相应的操作避免了轮询的开销提高了Redis的性能。5、轻量级Redis的代码量相对较小且没有复杂的依赖关系因此它的启动速度非常快这也是它处理速度快的重要原因之一。综上所述Redis之所以能够处理速度快是因为它采用了多种优化策略和技术从而实现了高效的数据存储和快速的读写操作。
三、数据结构与算法
1、基本的算法有哪些怎么评价一个算法的好坏?基本的算法有: 排序算法(简单排序 快速排序 归并排序) 搜索(二分搜索) 对于其他基本数 据结构 栈 队列树都有一些基本的操作。评价算法的好坏一般有两种: 时间复杂度和空间复杂度。时间复杂度:同样的输入规模(问题规模)花费多少时间。空间复杂度:同样的输入规模花费多少空间(主要是内存)。以上两点越小越好。稳定性:不会引文输入的不同而导致不稳定的情况发生。算法的思路是否简单:越简单越容易实现的越好。
2、斐波那契数列斐波那契数列:简单地说起始两项为 0 和 1此后的项分别为它的前两项之和。def fibo(num):numList [0, 1]for i in range(num - 2):numList.append(numList[-2] numList[-1])return numList
四、web框架
1、Django 的生命周期
前端发起请求nginxuwsgi中间件URLview视图通过orm与model层进行数据交互拿到数据返回给view试图将数据渲染到模板中拿到字符串中间件uwsginginx前端渲染
2、中间件的五种方法
process_requestprocess_responseProcess_viewProcess_exceptionProcess_render_template
3、django 自带的中间件
SecurityMiddlewareSessionMiddlewareCommmonMiddlewareCsrfViewMiddlewareAuthenticationMiddlewareMessageMiddlewareXFrameOptionMiddleware
4、csrf 攻击、危害与防御 csrf 攻击全称为Cross-site request forgery 中文名称 跨站请求伪造 也被称为“One Click Attack”或者“Session Riding”通常缩写为CSRF或者XSRF是一种对网站的恶意利用。
XSS主要是利用站点内的信任用户而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS相比CSRF更具危险性。
主要的危害来自于攻击者盗用用户身份发送恶意请求。比如模拟用户发送邮件发消息以及支付、转账等。
如何防御CSRF攻击?
1、重要数据交互采用POST进行接收当然POST也不是万能的伪造一个form表单即可破解。
2、使用验证码只要是涉及到数据交互就先进行验证码验证这个方法可以完全解决CSRF。
3、出于用户体验考虑网站不能给所有的操作都加上验证码因此验证码只能作为一种辅助手段不能作为主要解决方案。
4、验证HTTP Referer字段该字段记录了此次HTTP请求的来源地址最常见的应用是图片防盗链。
5、为每个表单添加令牌token并验证。