面试(三)

流年不利,这个月我被裁员了,让我猝不及防。

一、异步接口怎么做自动化

异步就检查下游逻辑,如果耗时就需要睡一会(2023-03-08,个人认为可以开启线程池ThreadPoolExecutor,轮询终态结果就行);

调用方式上来看,可分为三类:
同步调用:同步调用是一种阻塞式调用,即在函数A的函数体里通过书写函数B的函数名来调用之,使内存中对应函数B的代码得以执行。
异步调用:异步调用是一种类似消息或事件的机制解决了同步阻塞的问题,例如A通知B后,他们各走各的路,互不影响,不用像同步调用那样,A通知B后,非得等到B走完后,A才继续走。
回调:回调是一种双向的调用模式,也就是说,被调用的接口被调用时也会调用对方的接口,例如A要调用B,B在执行完又要调用A。

二、瀑布流、scrum、devops

瀑布模型是将软件项目划分为不同阶段,从一个阶段流动到下一阶段,每个阶段输出一个或多个评审通过的文档,后续阶段在上一阶段结束前不应该开始,每一个阶段的输出是下一个阶段工作的输入,典型的计划驱动软件过程。

 Scrum是一种兼顾计划性和灵活性的敏捷开发过程,它将这个开发过程分为若干次更小的迭代,每一个迭代周期称为一个冲刺,能应对快速变化的需求。

 DevOps就是让各个部门更好地沟通合作,通过自动化流程来使得软件整体过程更加快捷和可靠。

三、python的内存管理机制

(1)引用计数
  引用计数增加
    1.对象被创建:x=4
    2.被别人引用:y=x
    3.被作为参数传递给函数:foo(x)
    4.作为容器对象的一个元素:a=[1,x,'33']
  引用计数减少
    1.一个本地引用离开了它的作用域。比如上面的foo(x)函数结束时,x指向的对象引用减1。
    2.对象的别名被显式的销毁:del x ;或者del y
    3.对象的一个别名被赋值给其他对象:x=789
    4.对象从一个窗口对象中移除:myList.remove(x)
    5.窗口对象本身被销毁:del myList,或者窗口对象本身离开了作用域
(2)垃圾回收
  a、它会去检查那些引用计数为0的对象,然后清除其在内存的空间
  b、循环垃圾回收器, 确保释放循环引用对象
(3)内存池机制
  分为大内存和小内存,以256字节为界限,对于大内存使用Malloc进行分配,而对于小内存则使用内存池进行分配

四、处理器有多少个进程?
假设处理器4个核心,同一时刻最多只会有4个进程。1个进程可以包含多个线程

五、为什么说pyhton是假的多线程?
在 Cpython 解释器(Python语言的主流解释器)中,有一把全局解释锁(Global Interpreter Lock),
在解释器解释执行 Python 代码时,先要得到这把锁,意味着,任何时候只可能有一个线程在执行代码
其它线程要想获得 CPU 执行代码指令,就必须先获得这把锁,如果锁被其它线程占用了,那么该线程就只能等待,
直到占有该锁的线程释放锁才有执行代码指令的可能。

虽然说任何时候可能有一个线程在执行代码,但并不是需要等该线程执行完代码才释放锁
比如说资源的调度策略切换周期是1秒(默认是0.005秒),然后有2个线程,那么第一秒给A线程,第二秒给B线程,第三秒又给到了A线程,如此循环。
在不使用互斥锁的情况下,只要切换周期设置的足够大,就不会导致数据因为多线程出现数据不安全的情况

六、迭代器、生成器
  1、可迭代对象(for循环中,会自动调用 iter()将我们要迭代的对象转化为可迭代对象,每次循环都会调用 .next() 方法获取新元素,当引发StopIteration错误的时候自动退出循环
    可迭代对象需要实现__iter__方法,常见三类可迭代对象如下

from collections.abc import Iterable
# 判断是不是可迭代对象,python3.7之前collections不需要.abc
print(isinstance(range(10),Iterable))

    (1)迭代器(生成器)
    (2)序列(数组、字符串、元组、集合)
    (3)字典
  2、迭代器
    (1)迭代器不仅要实现__iter__方法,还需要实现__next__方法;
    (2)可以通过Python内置的iter函数把可迭代对象转化为迭代器;
    (3)迭代器能够记住遍历位置,能够通过next方法不断从前往后访问,直到引发StopIteration
  优点:每次只从对象中读取一条数据,不会造成内存的过大开销

class Iterator(object):
    def __init__(self, array):
        self.x = array
        self.index = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.index < len(self.x):
            value = self.x[self.index]
            self.index += 1
        else:
            raise StopIteration
        return value


it = Iterator([1, 2, 3, 4, 5])
print(type(it))
print(next(it))
# 循环会从2开始
for i in it:
    print(i)
View Code

  3、生成器(迭代器的子集)
    (1)在Python中一个函数可以用yiled替代return返回值,这样的话这个函数就变成了一个生成器对象
    (2)推导式来创建生成器

   gen = (i for i in [1, 2, 3, 4, 5])
   print(type(gen))
   print(next(gen))
   print(next(gen))
View Code

、网络协议7层、5层模型

应用层协议:FTP、Telnet、SMTP、HTTP、RIP、NFS、DNS、RSTP
传输层协议:TCP协议、UDP协议
网络层协议:IP协议、ICMP协议、ARP协议、RARP协议

八、TCP三次握手

(1)首先客户端向服务器端发送一段TCP报文:
  a、标记位为SYN,表示“请求建立新连接”;
  b、序号为Seq=x(x一般为1);
(2)服务器端接收到来自客户端的TCP报文之后,并返回一段TCP报文:
  a、标志位为SYN和ACK,表示“确认客户端的报文Seq序号有效,服务器能正常接收客户端发送的数据,并同意创建新连接”
  b、序号为Seq=y;
  c、确认号为ack=x+1,表示收到客户端的序号Seq并将其值加1作为自己确认号Ack的值
(3)客户端接收到来自服务器端的确认收到数据的TCP报文之后,明确了从客户端到服务器的数据传输是正常的;
  a、标志位为ACK,表示“确认收到服务器端同意连接的信号”(即告诉服务器,我知道你收到我发的数据了)
  b、序号为Seq=x+1,表示收到服务器端的确认号Ack,并将其值作为自己的序号值
  c、确认号为ack=y+1,表示收到服务器端序号Seq,并将其值加1作为自己的确认号ack的值

九、幂等

高并发或重复调用导致数据出现问题,这个时候则需要接口做幂等来保证我们数据的正确性。
常用方案如下,参考 https://blog.csdn.net/nonage_bread/article/details/114764227
  1、全局唯一ID
  生成一个全局ID,在执行操作前先根据这个全局唯一ID是否存在,来判断这个操作是否已经执行
  2、唯一索引
  把唯一标识作为唯一索引,在我们实现时,把创建支付单据写入去重表,放在一个事务中,如果重复创建,数据库会抛出唯一约束异常,操作就会回滚
  3、状态控制

十、事务

概念:
  事务由事务开始与事务结束之间执行的全部数据库操作组成。这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。
  如果sql语句执行出现问题,会调用rollback,回滚所有已经执行成功的sql语句。
特性
  原子性(Atomicity):事务中的全部操作在数据库中是不可分割的,要么全部完成,要么全部不执行。
  一致性(Consistency):几个并行执行的事务,其执行结果必须与按某一顺序 串行执行的结果相一致。
  隔离性(Isolation):事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的。
  持久性(Durability):对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障。
关于mysql
  MySQL中默认采用的是自动提交(autocommit)模式,在自动提交模式下,如果没有start transaction显式地开始一个事务,那么每个sql语句都会被当做一个事务执行提交操作

posted @ 2022-06-24 18:03  whitewall  阅读(95)  评论(0编辑  收藏  举报