python技术面试题(九)

本文涉及的产品
传统型负载均衡 CLB,每月750个小时 15LCU
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: python技术面试题(九)

每日分享

Never give up. Never let things out of your control dictate who you are.

永不言弃。不能让那些超出你能力范围的事情干扰到你对自己的判断。

小闫语录

每个人的精力都是有限的,不可能面面俱到,事事精通,那么我们为何不只抓一点,无限延伸呢?不要指望一个数学家熟知中华上下五千年,更不要指望一个历史学家破解哥德巴赫猜想。术业有专攻,你自有属于你的平台。多尝试,多失败,只有这样你才能找到你的舞台,大放异彩,加油。


面试题

1.谈谈你对Nginx中负载均衡的理解。

答:负载均衡简单的来说就是将任务分摊到不同的服务器中,从而使业务处理更加的高效。Nginx中负载均衡策略有轮询,当然这也是默认的方式,就是按顺序向后端的服务器进行任务分发;还有权重,通过设置权重使得一些硬件条件较好的服务器处理的业务多一点; ip_hash则是基于客户端IP分配业务,确保了相同的客户端的请求一直发送到相同的服务器,以上就是一些常见的负载均衡策略。

2.数据库优化的措施,你们项目开发中做过哪些优化?

答:数据库的优化措施有很多,常见的有优化索引、SQL语句;设计表的时候严格根据数据库的设计范式来设计数据库;使用缓存,将经常访问且不需要经常变化的数据放到缓存中,节约磁盘IO;优化硬件,采用固态等;垂直分表,就是将不经常读取的数据放到一张表中,节约磁盘IO;主从分离,读写分离;选择合适的引擎;不采用全文索引等措施。

我们在项目开发过程中尽量少的使用外键,因为外键约束会影响插入和删除性能;使用缓存,减少对数据库的访问;需要多次连接数据库的一个页面,将需要的数据一次性的取出,减少对数据库的查询次数。在我们查询操作中尽量避免全表扫描,避免使用游标,因为游标的效率很差,还避免大事务操作,提高并发能力。

3.redis五种数据类型底层实现?

redis中有五种数据类型:字符串、列表、哈希、集合以及有序集合。

redis底层有简单字符串、链表、字典、跳跃表、整数集合、压缩列表等数据结构,但是,不是直接使用他们构建键值对的,而是基于这些数据结构创建了一个对象系统,这些对象系统就是咱们的五种数据类型。通过这五种不同类型的对象,Redis可以在执行命令之前,根据对象的类型判断一个对象是否可以执行给定的命令,而且可以针对不同的场景,为对象设置多种不同的数据结构,从而优化对象在不同场景下的使用效率。

在Redis中,键总是一个字符串对象,而值可以是字符串、列表、集合等对象,所以我们通常说的键为字符串键,表示的是这个键对应的值为字符串对象,我们说一个键为集合键时,表示的是这个键对应的值为集合对象。

首先是字符串对象,它的编码可以是int,raw或者embstr。其中int 编码是用来保存整数值,raw编码是用来保存长字符串,而embstr是用来保存短字符串。其中的长短字符串以44个字节为界限进行区分,当然这是redis3.2之后的版本才改的。编码的转化中,值得注意的几点是redis中对于浮点数类型作为字符串进行保存,需要的时候再将它转换成浮点数类型;int编码保存的值不是整数或大小超过了long类型(int就是可以用long类型表示的整数)的范围时,自动转化为raw。redis中embstr由于考虑到内存分配时的缺陷,只能用于读。所以修改embstr对象时,会先转化为raw在进行修改。

列表对象编码可以是压缩列表,也可以是双端链表。当列表保存元素个数小于512个且每个元素长度小于64个字节时,采用压缩列表编码;除此之外的所有情况使用双端链表编码。

双端链表:首先解释一下什么是链表,就是存储数据的时候,每一个节点中保存着下一个节点的指针,存储十分灵活,任意添加数据时,节约内存开销。双端链表就是链表具有前置节点和后置节点的引用,获取这两个节点时间复杂度都为O(1)。

压缩列表:由一系列特殊编码的连续内存块组成的顺序性数据结构。一个压缩列表可以包含任意多个节点,每个节点可以保存一个字节数组或者一个整数值。

简单的理解:去电影院买票看电影,压缩列表要的是连号的座位,双端链表只要有座位就行,管它连号不连号。

哈希对象,底层是压缩列表和hashtable实现的。而hashtable 编码的哈希表对象底层使用字典数据结构,哈希对象中的每个键值对都使用一个字典键值对。同样,当列表保存元素个数小于512个且每个元素长度小于64个字节时,采用压缩列表编码;除此之外的所有情况使用hashtable 编码。

集合对象的编码可以是 intset 或者 hashtable。intset 编码的集合对象使用整数集合作为底层实现,集合对象包含的所有元素都被保存在整数集合中。hashtable 编码的集合对象使用 字典作为底层实现,字典的每个键都是一个字符串对象,这里的每个字符串对象就是一个集合中的元素,而字典的值则全部设置为 null。当集合对象中所有元素都是整数,且所有元素数量不超过512时,采用intset编码。除此之外使用hashtable编码。

有序集合的编码可以是 ziplist 或者 skiplist。ziplist 编码的有序集合对象使用压缩列表作为底层实现,每个集合元素使用两个紧挨在一起的压缩列表节点来保存,第一个节点保存元素的成员,第二个节点保存元素的分值。并且压缩列表内的集合元素按分值从小到大的顺序进行排列,小的放置在靠近表头的位置,大的放置在靠近表尾的位置。skiplist 编码的有序集合对象使用 zset 结构作为底层实现,一个 zset 结构同时包含一个字典和一个跳跃表。字典的键保存元素的值,字典的值则保存元素的分值;跳跃表节点的 object 属性保存元素的成员,跳跃表节点的 score 属性保存元素的分值。这两种数据结构会通过指针来共享相同元素的成员和分值,所以不会产生重复成员和分值,造成内存的浪费。压缩列表的使用条件同上,除此之外使用跳跃表。

其实有序集合单独使用字典或跳跃表其中一种数据结构都可以实现,但是这里使用两种数据结构组合起来,原因是假如我们单独使用 字典,虽然能以 O(1) 的时间复杂度查找成员的分值,但是因为字典是以无序的方式来保存集合元素,所以每次进行范围操作的时候都要进行排序;假如我们单独使用跳跃表来实现,虽然能执行范围操作,但是查找操作有 O(1)的复杂度变为了O(logN)。因此Redis使用了两种数据结构来共同实现有序集合。

4.MySQL引擎有哪些了解,用过什么?

答:主流的引擎有两个,分别是InnoDB和MyISAM。其中InnoDB支持事务,支持外键约束,它还支持行锁(比如select…for update语句,会触发行锁,但是锁定的是索引不是记录)。MyISAM不支持事务,不支持外键,它是数据库默认的引擎。InnoDB保存表的行数,如果看这个表有多少行的时候,InnoDB扫描整张表,MyISAM则是直接读取保存的行数即可。删除表的时候InnoDB是一行一行的删,而MyISAM则是重建表。InnoDB适合频繁修改以及安全性要求较高的应用,MyISAM适合查询为主的应用。在我们的项目中使用的是InnoDB。

5.缓存穿透、缓存击穿、缓存雪崩?

答:缓存穿透指的是缓存和数据库中该数据没有,但是用户不断的发起请求(如发起id为-1或者id特别大不存在该数据的请求),从而使得数据库压力过大。这样就要考虑是不是受到了攻击。解决方法就是接口层增加校验,对id进行校验,过滤非法请求;如果对方执着于同一个ID暴力攻击,那么我们可以在缓存中将key-value写成key-null,缓存有效时间设置的短一点。

缓存击穿指的是缓存中没有,但是数据库中有(一般就是缓存时间到期了)的数据,这时并发用户特别多,缓存读不到,同时去数据库读数据,造成数据库压力瞬间增大的现象。解决的方法就是热点数据永远不过期;另一种方法就是牺牲一点用户体验保护数据库,加互斥锁。

缓存雪崩指的是缓存中数据大规模的到期,而查询数据量巨大,引发数据库压力过大。你也许会想,这不是缓存击穿吗?不是的,缓存击穿是用户查询同一条数据,而缓存雪崩则是用户查询不同的数据。解决方案就是缓存数据的时间设置为随机,防止同一时间大量数据过期;如果缓存数据采用分布式部署,那么热点数据给其他缓存数据库中也分点,雨露均沾嘛;还可以将热点数据设置为永不过期。

6.异步任务除了celery还涉及到哪些?为什么选择celery?

异步任务可以使用threading模块实现多线程,进而实现多任务。还可以使用asyncio包实现异步任务,它本质是采用了协程。还有基于redis的异步任务队列RQ等等。但是兼顾性能、功能、实用性、降低耦合以及可扩展等等综合因素采用了celery。

celery是生产者消费者模型,它拥有三个至关重要的模块,一个任务发出者,一个中间人,一个执行者。任务发出者发出任务,放到中间人的消息队列中(项目中使用redis数据库),然后执行者一监听到任务就立马执行。

7.Django中中间件是如何使用的?

1.首先需要定义一个中间件的工厂函数,然后返回一个可以被调用的中间件。其中中间件工厂函数需要接收一个可以调用的 get_response对象,返回的中间件也是一个可以被调用的对象,并且像视图一样接收一个request对象参数,返回一个Response对象。下面是一个实例:

def simple_middleware(get_response):
    # 此处编写的代码仅在Django第一次配置和初始化的时候执行一次。
    def middleware(request):
        # 此处编写的代码会在每个请求处理视图前被调用。
        response = get_response(request)
        # 此处编写的代码会在每个请求处理视图之后被调用。
        return response
    return middleware

2.定义好中间件之后,需要在settings.py文件中添加注册中间件。

MIDDLEWARE = [
    ...
    'users.middleware.simple_middleware',  # 添加中间件
]

8.项目上线后,服务器有没有什么容灾措施?

可以将数据异地备份;将项目部署到不同平台的服务器上等等,防止数据丢失。

9.如何提高并发性能?

答:可以使用动态页面的静态化;增加缓存;垂直分表;数据库的主从分离读写;分库分表;异步读取;异步编程等。数据库的优化其实也是在提高并发性能。

10.利用代码实现一个简单的TCP服务器?

import socket
# 创建套接字
tcp_server_socket = socket(socket.AF_INET,socket.SOCK_STREAM)
# 本地的信息
address = ('', 8888)
# 绑定地址
tcp_server_socket.bind(address)
# 设置监听
# 使用socket创建的套接字默认是属性是主动的,使用listen将其变为被动的,这样就可以接收到别人的连接了
# 最大等待连接数我么设置为128,这是一个经验值,前人趟的坑,我们就不要在进去了
tcp_server_socket.listen(128)
# 如果有新的客户端来连接服务器,那么就产生一个新的套接字专门为这个客户端服务
# client_socket用来为这个客户端服务
# tcp_server_socket就可以省下来专门等待其他新客户端的连接
client_socket,clientAddr = tcp_server_socket.accept()
# 接收对方发送过来的数据
recv_data = client_socket.recv(1024)
print('接收到的数据为:',recv_data.decode('gbk'))
# 发送一些数据到客户端
client_socket.send('welcome to 小闫笔记'.encode('gbk'))
# 关闭为这个客户端服务的套接字,只要关闭了,就意味着不能再为这个客户端服务了,如果还需服务,只能再次进行重新连接。
client_socket.close()

参考文献:https://www.cnblogs.com/ysocean/p/9102811.html

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
6天前
|
存储 网络协议 安全
30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场
本文精选了 30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场。
19 2
|
12天前
|
算法 Python
Python图论探索:从理论到实践,DFS与BFS遍历技巧让你秒变技术大牛
图论在数据结构与算法中占据重要地位,应用广泛。本文通过Python代码实现深度优先搜索(DFS)和广度优先搜索(BFS),帮助读者掌握图的遍历技巧。DFS沿路径深入搜索,BFS逐层向外扩展,两者各具优势。掌握这些技巧,为解决复杂问题打下坚实基础。
24 2
|
13天前
|
开发框架 开发者 Python
探索Python中的装饰器:技术感悟与实践
【10月更文挑战第31天】 在编程世界中,装饰器是Python中一种强大的工具,它允许我们在不修改函数代码的情况下增强函数的功能。本文将通过浅显易懂的方式,带你了解装饰器的概念、实现原理及其在实际开发中的应用。我们将一起探索如何利用装饰器简化代码、提高可读性和复用性,同时也会分享一些个人的技术感悟,帮助你更好地掌握这项技术。
30 2
|
18天前
|
数据采集 Web App开发 iOS开发
如何利用 Python 的爬虫技术获取淘宝天猫商品的价格信息?
本文介绍了使用 Python 爬虫技术获取淘宝天猫商品价格信息的两种方法。方法一使用 Selenium 模拟浏览器操作,通过定位页面元素获取价格;方法二使用 Requests 和正则表达式直接请求页面内容并提取价格。每种方法都有详细步骤和代码示例,但需注意反爬措施和法律法规。
|
18天前
|
数据采集 存储 Web App开发
利用Python 的爬虫技术淘宝天猫销量和库存
使用 Python 爬虫技术获取淘宝天猫商品销量和库存的步骤包括:1. 安装 Python 和相关库(如 selenium、pandas),下载浏览器驱动;2. 使用 selenium 登录淘宝或天猫;3. 访问商品页面,分析网页结构,提取销量和库存信息;4. 处理和存储数据。注意网页结构可能变化,需遵守法律法规。
|
19天前
|
数据库 开发者 Python
“Python异步编程革命:如何从编程新手蜕变为并发大师,掌握未来技术的制胜法宝”
【10月更文挑战第25天】介绍了Python异步编程的基础和高级技巧。文章从同步与异步编程的区别入手,逐步讲解了如何使用`asyncio`库和`async`/`await`关键字进行异步编程。通过对比传统多线程,展示了异步编程在I/O密集型任务中的优势,并提供了最佳实践建议。
16 1
|
27天前
|
机器学习/深度学习 算法 Java
机器学习、基础算法、python常见面试题必知必答系列大全:(面试问题持续更新)
机器学习、基础算法、python常见面试题必知必答系列大全:(面试问题持续更新)
|
1月前
|
人工智能 文字识别 Java
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?
尼恩,一位拥有20年架构经验的老架构师,通过其深厚的架构功力,成功指导了一位9年经验的网易工程师转型为大模型架构师,薪资逆涨50%,年薪近80W。尼恩的指导不仅帮助这位工程师在一年内成为大模型架构师,还让他管理起了10人团队,产品成功应用于多家大中型企业。尼恩因此决定编写《LLM大模型学习圣经》系列,帮助更多人掌握大模型架构,实现职业跃迁。该系列包括《从0到1吃透Transformer技术底座》、《从0到1精通RAG架构》等,旨在系统化、体系化地讲解大模型技术,助力读者实现“offer直提”。此外,尼恩还分享了多个技术圣经,如《NIO圣经》、《Docker圣经》等,帮助读者深入理解核心技术。
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?
|
1月前
|
网络协议 安全 Java
难懂,误点!将多线程技术应用于Python的异步事件循环
难懂,误点!将多线程技术应用于Python的异步事件循环
61 0
|
1月前
|
Java C++ Python
【面试宝典】深入Python高级:直戳痛点的题目演示(下)
【面试宝典】深入Python高级:直戳痛点的题目演示(下)