面试笔记(python)

代码量85000,核心业务代码30000
处理问题:224个
现网变更:配合252 变更428 B:94

需求:
1、cps-hub分集群部署
cps-hub有两个功能
,一个是状态通道,另一个是维护通道,之前的状态通道是cps-server的有个子进程叫status_server,这些生态是cps-client的agent类型组件上报到status_server并由status_server储存在内存中的,但随着华为云规模的增大,内存无法支撑。cps-client和status-server是通过sokcet通信(udp);且cps-client都直连zk造成zk存在压力大。为解决以上问题将状态上报通道拆分出来,同时为了功能归一和方便集群化将维护通道也拆分出来和状态通道统一归入Hub.cps-hub也解决了边缘云厂家下,cps-client与server通信的安全问题,cps-client与cps-hub使用https+用户名密码认证,同时可针对某一边缘云,通过配置cps-hub-nginx.进行网络隔离。状态和配置数据归位redis和gaussdb
2、CPS支持Grid架构
一个管控面 grid  集群里包含原架构下的所有组件(如 quasar_server、nova_api、nova_DB等),可以部署出多个 grid  集群,每个 grid  处理不同同租户的相同请求,不同 grid  之前数据隔离。不同 grid  中的各个组件,用同一套安装包,同一个组件的多个实例之间共享配置项和控制脚本,各个 grid ,升级变更独立,独立运维互不干扰。grid  内部遵循以前的可靠性的部署升级策略方案设计研发经验
3、python23切换
4、云平台容灾改造及自动化
5、云平台档位扩容
6、SD卡日志写内存

做的最失败的项目:
新建大云2000及以上档位部署redis-cps,之前是HCSO只有500及以下档位,2000及以上档位都是大云的,后来有个HCSO的需求,HCSO档位升级,由500升到了2000,新建的HCSO局点就有了2000档位,标准化部署工部和标准化部署json是和大云一起的,标准化部署的虚拟机发放档位表是单独维护的,上TMG评审后,HCSO的也加上了,阻塞了两天时间


离职动机:
1、身体吃不消,夜班经常要搞到很晚,现在是大概一个月轮一次,正常3点左右,有时候会搞到7点半
2、项目基本开发完成,后面没有什么大的项目需求,更多的转到维护上去,不是很想做运维的工作
3、对容器比较感兴趣,在这边没时间学习,还有就是我们这边的容器感觉比较lower

云平台(CPS)提供的能力:
安装、部署、配置管理、服务生命周期管理。

容器:
当前解决方案是:租户管理区虚拟化,openstack平台分为管理区底座和租户管理区,管理区底座是三个被级联层,里面包含控制节点和计算节点,能够发放虚拟机,使用管理区底座发放的虚拟机再搭建一个单层的openstack系统称为租户管理区。租户管理区管理的计算节点用于给租户发放ECS虚拟机。
容器解决方案:k8部署在管理区底座,使用新版本的服务制作镜像,利用计算节点发放容器,白天现将高版本容器发放出来,晚上实现切流,然后将老版本容器下线,对于服务的心跳、监控还是利用的CPS的能力,在CPS的能力外套了一层容器的外壳。
java:

python基础:
(1)Python 3 和 Python 2 有什么区别
Python 3是Python语言的最新版本,与Python 2相比,Python 3具有许多改进和升级,例如更好的语法、更好的Unicode支持、更好的异常处理和更高的性能。
(1)pdb
非侵入式方法:
python3 -m pdb filename.py
# 导入
import pdb
# 设置断点
pdb.set_trace()
# -------------------
# 断点命令
p + 变量名 # 打印变量  或者直接变量名
n # 执行下一行
s # 进入函数
r # 执行函数到结束
c # 停止调试并继续运行
q # 退出调试
# enter 重复上一次命令
侵入式方法:
import pdb pdb.set_trace()
(2)list底层实现
Python中的列表(list)是一种非常常用的内置数据类型,它可以存储任意类型的元素值,而且其大小可以动态地变化
结构体:双向链表前后指针(python内部管理内存的方式)、引用计数器、动态指针数组、列表容量、当前大小
切片是创建了新的列表对象
插入复杂度是O(n)是将对象的地址指针存到动态数组中,当大小不够时会动态扩展,扩展的是连续的存储空间,如果不够,就要做整体迁移
append复杂度是O(1)
pop(0)的时间复杂度为O(n),pop()的时间复杂度为O(1),删除元素,空的比较多的时候会动态回收
clear就是将list结构体中相关变量的值重置为零
销毁列表del,引用计数器-1,如果引用计数器>0,表示还有其他变量使用此列表,之后不做任何操作:如果引用计数器=0,表示没人使用此列表,之后需要做如下事宜,如果列表中有数据,则先处理元素,其实就是找到每个元素,将元素的引用计数器-1,处理完元素后,ob_item=NULL 、ob_size=0 、ob_allocated=0,将列表从管理内存的双向环状链表中移除,认为这个对象没人使用了,现在可以被销毁了
extend:将元素一个一个添加到指定list复杂度是O(n)
(3)dict底层实现
字典的查询、添加、删除的平均时间复杂度都是O(1)
Python字典的底层原理是使用哈希表实现的,它使用哈希函数将键映射到一个唯一的索引,然后将值存储在该索引处,时间复杂度在常数级别O(1),使用开放地址法解决冲突
数据结构:键、值、hash值
字典添加:如果使用的插槽数+虚拟插槽数大于数组大小的2/3,则会调用insertdict()以添加新的键/值对,并调整字典的大小
移除字典:请注意,如果使用的插槽数比插槽总数少得多,则删除项操作不会触发数组调整大小。但是,当添加键/值对时,需要根据使用的插槽数+虚拟插槽数来调整大小,因此也可以缩小数组
(4)set底层实现
remove:如果删除的元素不在集合,会抛出异常
discard:即使元素不存在,也不会抛出异常
在Python 3中,set的哈希表采用开放寻址(open addressing)的方式来解决哈希冲突,而不是使用链表。
Python 3中的哈希表采用稀疏化(sparseness)技术(一个基于行的压缩矩阵来进行处理),使得哈希表可以使用更少的空间来存储元素,从而减少空间占用。
如果哈希表中已经存在了一个具有相同哈希值的元素,则使用等价性测试检查这两个元素是否相等。如果它们不相等,就在这个桶中继续寻找下一个空闲的位置。如果桶中没有空闲的位置,则需要重新哈希,这会增加哈希表的大小并将所有元素重新分配到新的桶中。
(5)元组
Py_ssize_t,一个整型数据类型。
ob_refcnt,表示对象的引用记数的个数,这个对于垃圾回收很有用处,后面我们分析虚拟机中垃圾回收部分在深入分析。
ob_type,表示这个对象的数据类型是什么,在 python 当中有时候需要对数据的数据类型进行判断比如 isinstance, type 这两个关键字就会使用到这个字段。
ob_size,这个字段表示这个元组当中有多少个元素。
ob_item,这是一个指针,指向真正保存 python 对象数据的地址
(5)UT
Unittest库的执行先后顺序
setUp() ——每个用例执行前清理环境
tearDown() ——每个用例执行后清理环境
setUpClass() ——所有用例执行前运行一次
tearDownClass() ——所有用例执行后运行一次
顺序:setUpClass() -> setUp() -> test1() -> tearDown() -> setUp() -> test2() -> tearDown() ->…-> tearDownClass
a. test fixture:setUp(前置条件)、tearDown(后置条件),用于初始化测试用例及清理和释放资源
b. test case:测试用例,通过集成 unttest.TestCase,来实现用例的继承,在 Unitfest 中,测试用例都是通过 test 来识别的,测试用例命名 test_xxx
c. test suite:测试套件,也称之为测试用例集
d. test runner:运行器,一般通过 runner 来调用 suite 去执行测试
TestCase-->由TestLoader加载TestCase到TestSuit-->由TestRunner来运行TestSuite,将运行结果保存在TextTestResult中
测试用例执行顺序由用例的字典序决定,如果要改变执行顺序需要通过
# 创建一个测试套件 list
suite = unittest.TestSuite()
# 方法一,添加测试用例(子元素)到测试套件(集合)
suite.addTest(MyTestCase('test_3'))
suite.addTest(MyTestCase("test_1"))
UT用例技巧
判断 是否被调用一次,而且调用时的参数是否一致
mock_set.assert_called_once_with("test", operation_info=xxx)
判断是否被调用多次,参数是期望调用的列表
from mock import call
expect_create_args_list = [call("/cps/switch"),
                           call("/cps/switch/enable_cps_hub",
                                data={'value': 'True', 'hub_proxy_instance': 'cps-hub-nginx2'})]
mock_createZkNode.assert_has_calls(expect_create_args_list)
判断被调用次数
real_call_count_list = []
for mock_obj in check_obj_list:
    real_call_count_list.append(mock_obj.call_count)
当函数的入参是个类实例时,由于实例id不一致,我们先通过ANY判断,再解析调用的时的参数拿到实例,通过isinstance,以及判断实例内属性是否一致来达到目的
mock_delete_software_package.assert_called_once_with("fpl_test.tar.gz", mock.ANY)
捕获异常用例
with self.assertRaises(Exception) as context:
    self.component_host_zkao.list_instance_id_by_component_name("cps.cps-client", False)
# Then
self.assertEqual(error_msg, str(context.exception))
(6)用例覆盖
语句覆盖:每条语句至少执行一次。
判定覆盖:每个判定的所有可能结果至少出现一次。(又称“分支覆盖”)
条件覆盖:每个条件的所有可能结果至少执行一次。
判定/条件覆盖:一个判定中的每个条件的所有可能结果至少执行一次,并且每个判断本身的所有可能结果至少执行一次。
多重条件覆盖(组合覆盖):每个判定中的所有可能的条件结果的组合,以及所有的入口点都至少执行一次。(注意“可能”二字,因为有些组合的情况难以生成。)
完全路径覆盖:每条路径至少执行一次。
基本路径覆盖:根据流图计算环复杂度,得到基本路径覆盖的用例数。
分割后的完全路径覆盖:每条路径至少执行一次,每个条件的所有可能结果至少执行一次。
路径覆盖 > 多重条件覆盖 > 判定/条件覆盖 > 条件覆盖 > 判定覆盖 > 语句覆盖
1. 路径覆盖是覆盖率最高的。语句覆盖最弱。
2. 满足多重条件覆盖准则的测试用例集,同样满足判定覆盖准则、条件覆盖准则和判定/条件覆盖准则。
(7)迭代器、迭代对象
可迭代对象包含迭代器。
如果一个对象拥有__iter__方法,其是可迭代对象;如果一个对象拥有__next__方法,其是迭代器。
定义可迭代对象,必须实现__iter__方法;定义迭代器,必须实现__iter__和__next__方法。
Next()是初始化创建一个实例,该实例可以被调用,也就是 Next()()时会调用 Next().call()
列表,元组,集合,字典,字符串都是可迭代对象,所有可以用for循环遍历的对象,都是可迭代对象,甚至包括文件对象
(8)多线程
面向对象 vs. 面向过程:threading是面向对象的多线程模块,而thread是面向过程的多线程模块。使用threading模块创建线程更加方便,使用起来也更加简单。
功能更丰富:threading模块提供了许多thread模块不具备的功能,如线程锁、信号量、事件等。这些功能的引入使得在使用线程时更加方便和灵活。
兼容性:threading模块可以在Python 2和Python 3中使用,而thread模块只能在Python 2中使用。这使得使用threading模块更加具有通用性
https://zhuanlan.zhihu.com/p/428786719
https://www.ngui.cc/zz/2431225.html?action=onClick
(9)多进程
https://www.php.cn/faq/557361.html
https://zhuanlan.zhihu.com/p/604064435
multiprocessing
(9)python底层是用C写的,不是C++。
Python 在执行代码时,会使用到解释器。Python 有三种解释器 CPython、JPython、Pypy。
其中 CPython 就是使用 C 语言编写的,解释器的实现方式可以有很多种。
(10)deque
(11)OrderedDict
(12)sort
(13)cleancode
(14)手写装饰器
(15)作用域
local->enclosed->global->builtin
(16)高阶函数
zip:接受一系列可迭代对象作为参数,将对象中对应的元素打包成一个个tuple(元组),然后返回由这些tuples组成的list(列表)。若传入参数的长度不等,则返回list的长度和参数中长度最短的对象相同
map:map函数会根据提供的函数对指定序列做映射。map(lambda x: x ** 2, [1, 2, 3, 4, 5]) 返回结果为:[1, 4, 9, 16, 25],map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10]),当函数为None时,操作和zip相似:map(None, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])返回结果为:[(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]
filter:filter函数会对序列参数sequence中的每个元素调用function函数,最后返回的结果包含调用结果为True的元素
reduce:function参数是一个有两个参数的函数,reduce依次从sequence中取一个元素,和上一次调用function的结果做参数再次调用function。reduce(lambda x, y: x + y, [2, 3, 4, 5, 6], 1),结果为21(  (((((1+2)+3)+4)+5)+6)  ),reduce(lambda x, y: x + y, [2, 3, 4, 5, 6])

常用设计模式:
单例模式:只有一个实例,通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。线程安全,没有加任何锁、执行效率比较高。类加载的时候就初始化,不管后期用不用都占着空间,浪费了内存。
工厂模式:通过将创建对象的代码和使用对象的代码解耦,工厂能够降低应用维护的复杂度。工厂方法(Factory Method),它是一个方法(或以Python术语来说,是一个函数),对不同的输入参数返回不同的对象,它是一组用于创建一系列相关事物对象的工厂方法。
优点:工厂模式可以提高代码的灵活性和可维护性,客户端代码和具体类的实现之间松耦合,当需要新增或更改某个具体类时,只需要修改工厂类即可,无需修改客户端代码。缺点:由于增加了工厂类的复杂性,会增加代码的复杂性和理解难度。应用场景:当需要实例化多个相似的对象时,可以使用工厂模式来封装实例化过程。同时,工厂模式还可以用于隐藏对象的实现细节,提高程序的安全性
抽象工厂模式(Abstract Factory Pattern):提供一个接口或基类,用于创建一系列相关或依赖的对象,而无需指定具体的类。‍
观察者模式:观察者模式是一种行为型模式,用于在对象之间建立一种依赖关系,使得当一个对象的状态发生变化时,所有依赖于它的对象都会收到通知并自动更新
模板方法模式:模板方法模式是一种行为型模式,用于定义一个算法的骨架,而将一些步骤延迟到子类中实现。在Python中,可以使用抽象基类来实现模板方法模式
适配器模式(Adapter Pattern):将一个类的接口转换为客户端所期望的另一个接口,使得原本不兼容的接口能够一起工作。
装饰器模式(Decorator Pattern):动态地为对象添加额外的功能,不改变其接口。
代理模式(Proxy Pattern):为其他对象提供一种代理,控制对该对象的访问,并在访问前后进行一些额外的操作。
策略模式(Strategy Pattern):定义一系列的算法,并将其封装成独立的类,使得它们可以互相替换,使算法的变化独立于使用算法的客户端。
迭代器模式(Iterator Pattern):提供一种方法来顺序访问聚合对象中的各个元素,而无需暴露其内部表示。
责任链模式(Chain of Responsibility Pattern):将请求的发送者和接收者解耦,通过一条责任链传递请求,直到有一个对象能够处理它为止。
状态模式(State Pattern):允许对象在其内部状态发生改变时改变其行为,使其看起来像是改变了类。

数据库:
mysql:
https://blog.csdn.net/YJ000312/article/details/123790957
https://baijiahao.baidu.com/s?id=1761402527311101533&wfr=spider&for=pc
gaussdb:
https://blog.csdn.net/weixin_39598796/article/details/113720737

中间件:
redis:与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。Redis是一个开源,内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。它支持字符串、哈希表、列表、集合、有序集合,位图,hyperloglogs等数据类型。内置复制、Lua脚本、LRU收回、事务以及不同级别磁盘持久化功能,同时通过Redis Sentinel提供高可用,通过Redis Cluster提供自动分区。
redis内部整体的存储结构是一个大的hashmap,内部是数组实现的hash,key冲突通过挂链表去实现,每个dictEntry为一个key/value对象,value为定义的redisObject
https://www.zhihu.com/tardis/bd/art/487583440?source_id=1001
https://zhuanlan.zhihu.com/p/427496556
kafka:
优点:控制了流量 缺点:会让流程变慢
生产者:Producer 往Kafka集群生成数据
消费者:Consumer 往Kafka里面去获取数据,处理数据、消费数据 Kafka的数据是由消费者自己去拉去Kafka里面的数据
主题:topic
分区:partition 默认一个topic有一个分区(partition),自己可设置多个分区(分区分散存储在服务器不同节点上)
https://zhuanlan.zhihu.com/p/446774729
https://blog.csdn.net/wudidahuanggua/article/details/127086186
mq
zookeeper
https://baijiahao.baidu.com/s?id=1765960923918704613&wfr=spider&for=pc
算法:
2、动态规划
3、背包
(1)01背包
(2)完全背包
(3)多重背包
4、树
(1)中序遍历
(2)后续遍历
(3)前序遍历
(4)层次遍历
(5)二叉搜索树
(6)平衡二叉树
(7)完全二叉树
(8)红黑树(Java的TreeMap实现,C++的STL,map和set都是用红黑树实现的、著名的linux进程调度Completely Fair Scheduler,用红黑树管理进程控制块)
    每个结点是黑色或者红色。
    根结点是黑色。
    每个叶子结点(NIL)是黑色。 [注意:这里叶子结点,是指为空(NIL或NULL)的叶子结点!]
    如果一个结点是红色的,则它的子结点必须是黑色的。
    每个结点到叶子结点NIL所经过的黑色结点的个数一样的。[确保没有一条路径会比其他路径长出俩倍,所以红黑树是相对接近平衡的二叉树的!]
(9)深度遍历
(10)B+树
5、图
(1)并查集
(2)深搜
(3)广搜
(4)最短路径(dijkstra、Bellman-Ford)
(5)最小生成树(Prim、kruskal)
(6)关键路径
6、排序
(1)归并排序
(2)堆排序
(3)插入排序
(4)冒泡排序
(5)二分查找
7、哈希
8、链表
(1)双指针
(2)快慢指针
9、栈
(1)前缀表达式、中缀表达式、后缀表达式
(2)后缀表达式求值
10、队列
11、常用函数
heapq.heappop()、heapq.heappush() 优先队列]


9月7日阿里巴巴晚8点面试 
9月6日字节跳动晚8点面试 (下载飞书)
9月2日和罗荣敏吃饭

周六下午两点:滨安路1199好

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值