Skip to content

Python后端面试知识梳理(基于简历)

#1 基础后端概念

Q: 什么是后端开发?它和前端有什么区别? A:

  • 后端 (Backend): 指的是应用程序中用户看不见的部分,负责处理业务逻辑、数据存储、与数据库交互、API接口提供等。可以想象成餐厅的厨房,负责准备菜肴(数据处理)和管理食材(数据库)。简历中提到的 Flask, Django, Node.js, Python, MySQL, PostgreSQL, Redis 都属于后端范畴。
  • 前端 (Frontend): 指的是用户可以直接交互的部分,通常是网站页面或App界面,负责展示数据和接收用户输入。就像餐厅的前台和餐桌,负责点餐和呈现菜肴。简历中的 Vue.js, React, ECharts, Electron, Uniapp 属于前端范畴。
  • 区别: 前端关注用户体验和界面展示,后端关注业务逻辑、数据安全和性能。两者通过 API (应用程序接口) 进行通信。

Q: 什么是API?简历中提到的RESTful API是什么意思? A:

  • API (Application Programming Interface): 应用程序接口,像是一个约定或合同,规定了不同软件组件之间如何进行通信和数据交换。你可以把它想象成餐厅服务员,前端(顾客)通过服务员(API)向后端(厨房)下单(请求数据),后端(厨房)准备好后通过服务员(API)把菜(数据)送到前端(顾客)。
  • RESTful API: 是目前最常用的一种API设计风格(Representational State Transfer)。它有几个核心特点:
    • 资源 (Resource): 网络上的所有事物都被视为资源(比如用户信息、订单列表)。每个资源都有一个唯一的标识符(通常是URL,如 /users/123)。
    • 表现层状态转化 (Representational State Transfer): 客户端通过HTTP动词(GET, POST, PUT, DELETE等)对资源进行操作,导致资源状态发生变化。
      • GET: 获取资源(如获取用户信息)。
      • POST: 创建新资源(如注册新用户)。
      • PUT: 更新或替换整个资源(如更新用户所有信息)。
      • DELETE: 删除资源(如删除用户)。
    • 无状态 (Stateless): 服务器不保存客户端的状态。每次请求都必须包含所有必要信息,服务器才能处理。这使得系统更容易扩展。
  • 简历中提到“主导设计高可用RESTful API”,意味着他设计了遵循REST风格、稳定可靠(高可用)的接口供前端或其他服务调用。

Q: 简历中提到了微服务架构,它和传统的单体架构有什么不同? A:

  • 单体架构 (Monolithic Architecture): 把应用程序的所有功能模块(如用户管理、商品管理、订单管理)都打包在一个独立的应用中部署。
    • 优点: 开发简单,初期部署容易。
    • 缺点: 随着功能增加,代码库变得庞大复杂,修改一小部分可能影响全局,技术栈单一,不易扩展和维护。
  • 微服务架构 (Microservices Architecture): 把一个大型应用程序拆分成一组小而独立的服务,每个服务负责一个具体的业务功能(如用户服务、订单服务)。服务之间通过API(通常是RESTful API或RPC)进行通信。
    • 优点: 每个服务可以独立开发、部署、扩展;可以使用不同的技术栈;单个服务故障影响范围小;团队可以并行开发。
    • 缺点: 系统复杂度增加(服务间通信、分布式事务、服务发现等),运维成本更高,需要更强的基础设施支持。
  • 简历中提到熟悉微服务架构,表明他理解这种现代化的架构设计思想,这在大型项目中很有价值。

#2 核心技术栈 (Python & Web框架)

Q: 为什么选择Python作为后端开发语言? A:

  • 语法简洁,开发效率高: Python语法清晰易懂,接近自然语言,能让开发者快速编写代码,提高开发效率。
  • 强大的生态系统: Python拥有庞大且活跃的社区,提供了丰富的库和框架(如Flask, Django用于Web开发,NumPy/Pandas用于数据分析,Scrapy/Selenium用于爬虫),可以快速构建各种应用。
  • 胶水语言特性: Python很容易与其他语言(如C/C++)编写的模块集成,方便调用底层库或优化性能瓶颈。
  • 广泛的应用领域: 除了Web开发,Python在数据科学、人工智能(简历中AI实践经验部分)、自动化运维、爬虫等领域都有广泛应用。

Q: Flask 和 Django 都是Python的Web框架,它们有什么区别?面试时可能会怎么问? A:

  • Flask:
    • 定位: 微框架 (Microframework)。它核心非常轻量,只提供路由、请求处理、模板渲染等基本功能。
    • 特点: 灵活、自由度高,开发者可以根据需要选择和集成各种扩展(如数据库ORM、表单验证、用户认证等)。适合小型项目、API开发或需要高度定制化的场景。
    • 学习曲线: 相对平缓,容易上手。
    • 简历体现: 简历中多个项目(燃气云平台后端、知识管理系统、房产数据可视化平台、AI文本改写服务)都使用了Flask,表明他精通Flask并能用它构建实际应用。
  • Django:
    • 定位: 全功能框架 (Batteries-included)。它自带了大量常用组件,如ORM(对象关系映射)、Admin后台管理、用户认证系统、表单处理、安全防护等。
    • 特点: 功能完善,约定优于配置,开发大型项目效率高,结构规范。适合需要快速开发功能齐全的Web应用的场景。
    • 学习曲线: 相对陡峭,需要理解其整体架构和设计哲学。
  • 面试可能问法:
    • "请比较一下Flask和Django的优缺点,以及它们的适用场景。"
    • "你在项目中为什么选择使用Flask而不是Django?(反之亦然)"
    • "Flask的核心组件有哪些?(如Werkzeug, Jinja2)"
    • "Django的MTV/MVT模式是什么?(Model-Template-View / Model-View-Template)"
    • "如何在Flask/Django中处理请求?中间件/请求钩子是什么?"
    • "如何在Flask/Django中使用ORM进行数据库操作?"

#3 数据库 (MySQL, PostgreSQL, Redis)

Q: 什么是数据库?为什么需要数据库? A:

  • 数据库 (Database): 是一个长期存储、有组织、可共享、统一管理的数据集合。可以把它想象成一个电子化的文件柜,可以高效地存储、检索、管理大量信息。
  • 为什么需要:
    • 持久化存储: 程序运行结束或服务器关闭后,数据不会丢失。
    • 高效查询: 可以快速地根据条件查找所需数据。
    • 数据共享与一致性: 多用户或多应用可以访问同一份数据,并保证数据的一致性。
    • 数据管理: 提供数据备份、恢复、安全控制等管理功能。

Q: MySQL 和 PostgreSQL 都是关系型数据库,它们有什么异同?什么时候选择哪个? A:

  • 共同点:
    • 都是开源的关系型数据库管理系统 (RDBMS)。
    • 都使用SQL (Structured Query Language) 作为查询语言。
    • 都支持事务 (ACID特性)。
    • 都有广泛的社区支持和应用。
  • 主要区别:
    • 标准符合性: PostgreSQL 对 SQL 标准的实现比 MySQL 更严格和完整。
    • 功能特性: PostgreSQL 在高级特性上更丰富,如更复杂的数据类型(数组、JSONB)、更强大的索引类型、地理空间数据支持(PostGIS扩展)等。
    • 并发控制: PostgreSQL 使用 MVCC (多版本并发控制) 处理并发读写,通常在高并发读写混合场景下表现更好。MySQL (InnoDB引擎) 也使用MVCC,但在某些方面实现不同。
    • 扩展性: PostgreSQL 的扩展机制更灵活强大。
    • 流行度: MySQL 由于历史原因和易用性,在Web开发领域(尤其是LAMP/LEMP栈)更为流行,文档和社区资源相对更多。PostgreSQL 在需要更强数据一致性、复杂查询和高级功能的场景下更受青睐。
  • 选择:
    • 选择MySQL: 如果你需要一个简单易用、社区庞大、与常用Web框架集成良好的数据库,或者对性能要求极高且主要是读操作或简单写操作的场景。
    • 选择PostgreSQL: 如果你需要严格的SQL标准符合性、复杂的数据类型、高级查询功能、更好的并发处理能力、或者地理空间数据处理能力。简历中燃气云平台后端重构使用了PostgreSQL,可能是看中了其在高并发和数据处理方面的稳定性或特定功能。

#3.1 深入解读 Redis

Q: 什么是 Redis?它和MySQL/PostgreSQL有什么本质区别? A:

  • Redis (Remote Dictionary Server): 是一个开源的、基于内存的、键值 (Key-Value) 存储系统。它通常被用作缓存、消息队列、会话存储、排行榜、计数器等。
  • 本质区别:
    • 存储介质: Redis 主要将数据存储在 内存 中,读写速度极快(因为内存读写远快于磁盘)。MySQL/PostgreSQL 主要将数据存储在 磁盘 上,读写速度相对较慢,但可以存储远超内存容量的数据。
    • 数据模型: Redis 是 NoSQL (非关系型) 数据库的一种,最基本的是键值对模型,但也支持更丰富的数据结构(String, List, Hash, Set, Sorted Set等)。MySQL/PostgreSQL 是 关系型 数据库,数据存储在结构化的表中(行和列)。
    • 用途定位: Redis 适用于对 速度 要求极高、数据结构相对简单的场景,常作为关系型数据库的 补充(如缓存)。MySQL/PostgreSQL 适用于需要 持久化存储、复杂查询、事务保证、数据关系复杂的场景。

Q: 简历中提到“实施多级Redis缓存策略(热点数据、查询结果)”,这是什么意思?为什么要用缓存? A:

  • 缓存 (Cache): 是一种存储技术,用于临时保存经常访问的数据副本,以便后续请求能更快地获取数据。就像你把常用的书放在书桌上(缓存),而不是每次都去书架(数据库)找。
  • 为什么用缓存:
    • 提升性能: 从内存读取数据远快于从磁盘数据库读取,可以大幅降低接口响应时间(简历中提到从800ms降至120ms)。
    • 减轻数据库压力: 大量请求可以直接由缓存处理,减少对后端数据库的访问压力,保护数据库。
  • 多级缓存策略: 指的是根据数据的特性(如访问频率、重要性)将其存储在不同层级或类型的缓存中。
    • 热点数据缓存: 将访问频率非常高的数据(如首页商品、配置信息)放入缓存。
    • 查询结果缓存: 将一些计算复杂或查询耗时的数据库查询结果放入缓存,后续相同查询直接返回缓存结果。
    • “多级”可能还意味着使用了不同粒度的缓存,比如应用内缓存(如内存变量、LRU Cache)和分布式缓存(Redis)。
  • 简历体现: 这展示了开发者具备性能优化意识和能力,能通过缓存技术解决实际问题。

Q: 使用Redis缓存会遇到哪些常见问题?如何解决? A:

  • 缓存穿透 (Cache Penetration):
    • 现象: 查询一个数据库 肯定不存在 的数据,导致请求每次都绕过缓存,直接打到数据库,失去缓存保护意义。恶意攻击者可能利用这点频繁请求不存在的数据,拖垮数据库。
    • 解决:
      • 缓存空值: 如果数据库查询结果为空,也将这个“空结果”缓存起来(设置较短的过期时间)。
      • 布隆过滤器 (Bloom Filter): 在访问缓存前,先通过布隆过滤器判断数据是否存在。布隆过滤器可以快速判断一个元素 肯定不存在 或者 可能存在。如果判断肯定不存在,就直接返回,不再查询缓存和数据库。
  • 缓存击穿 (Cache Breakdown):
    • 现象: 一个 热点Key 在缓存中失效(过期)的瞬间,大量并发请求同时涌入,都要去查询数据库并回写缓存,导致数据库压力瞬时增大。
    • 解决:
      • 加锁更新: 只允许一个线程去查询数据库并重建缓存,其他线程等待结果。可以使用分布式锁(如Redis的SETNX命令或RedLock算法)来实现。
      • 热点数据永不过期(逻辑过期): 不给热点Key设置物理过期时间,而是在Value中存储一个逻辑过期时间。当发现数据逻辑过期时,由一个线程异步去更新缓存,其他线程仍然返回旧数据。
  • 缓存雪崩 (Cache Avalanche):
    • 现象: 大量缓存Key在 同一时间 集体失效(比如Redis服务器宕机,或者大量Key设置了相同的过期时间),导致所有请求瞬间全部涌向数据库,造成数据库崩溃。
    • 解决:
      • 过期时间打散: 在设置缓存Key的过期时间时,增加一个随机值,避免大量Key同时过期。
      • 高可用部署: 使用Redis集群或哨兵模式,保证Redis服务的高可用性,避免单点故障。
      • 多级缓存: 使用应用内缓存+分布式缓存等多级策略。
      • 限流降级: 在缓存失效时,通过限流组件(如Sentinel、Nginx)限制访问数据库的请求数量,或者对非核心业务进行降级处理(如返回默认值或提示)。

Q: Redis除了做缓存,还能做什么?(拓展知识) A:

  • 分布式锁: 利用Redis命令(如 SETNX - SET if Not eXists)的原子性,可以实现在分布式环境下多个进程或服务器之间的互斥访问控制。简历中房产爬虫使用Selenium+Redis构建分布式爬虫架构,可能就用到了Redis的某些特性来协调不同爬虫节点的工作(比如任务分配、URL去重,甚至可能用作简单的分布式锁来避免重复抓取)。
  • 消息队列: Redis的List数据结构(LPUSH, RPOP)或更专业的Pub/Sub(发布/订阅)功能,可以实现简单的异步消息队列,用于任务解耦和流量削峰。简历中自动化报表系统使用Celery执行定时任务,Celery通常需要一个消息中间件(Broker),Redis就是常用的Broker之一。
  • 计数器/限流器: Redis的原子自增命令 (INCR, INCRBY) 非常适合实现高并发场景下的计数功能(如文章阅读数、点赞数)或API访问频率限制。
  • 排行榜/延迟队列: Sorted Set (有序集合) 数据结构根据分数排序,非常适合实现排行榜功能。也可以利用其分数特性实现延迟队列(将时间戳作为分数)。
  • Session共享: 在分布式Web应用中,可以将用户的Session信息存储在Redis中,实现不同服务器之间的Session共享。
  • 数据去重: 利用Set数据结构的唯一性,可以快速判断某个元素是否存在,用于URL去重(爬虫场景)、用户签到判断等。

Q: Redis的数据持久化是怎么做的? A: Redis提供了两种主要的持久化方式,将内存中的数据保存到磁盘,防止服务器宕机导致数据丢失:

  • RDB (Redis Database Backup):
    • 方式: 在指定的时间间隔内,将内存中数据集的 快照 (snapshot) 写入磁盘上的一个二进制文件 (dump.rdb)。可以手动触发 (SAVE, BGSAVE) 或配置自动触发。
    • 优点: 恢复速度快(直接加载快照文件),对性能影响小(BGSAVE 由子进程执行)。
    • 缺点: 如果在两次快照之间Redis宕机,会丢失最后一次快照后的所有数据。数据量大时,fork()子进程可能阻塞主进程。
  • AOF (Append Only File):
    • 方式: 将Redis服务器接收到的 每一个写命令(增、删、改)都以追加的方式记录到一个日志文件 (appendonly.aof) 中。Redis重启时,会重新执行AOF文件中的命令来恢复数据。
    • 优点: 数据安全性更高,丢失数据的风险更小(根据同步策略,最多丢失1秒的数据)。
    • 缺点: AOF文件通常比RDB文件大,恢复速度相对较慢(需要逐条执行命令),在高并发写场景下对性能有一定影响。
  • 混合持久化 (Redis 4.0+): 结合了RDB和AOF的优点。在进行快照(RDB)的同时,将快照之后接收到的写命令继续追加到AOF文件中(增量部分)。这样既能快速恢复,又能减少数据丢失。
  • 选择: 通常建议同时开启RDB和AOF,或者使用混合持久化,以兼顾性能和数据安全。

#4 深入解读 爬虫与数据清洗

Q: 什么是网络爬虫 (Web Crawler/Spider)?简历中提到的 Selenium 和 Scrapy 有什么区别? A:

  • 网络爬虫: 是一种按照一定规则自动抓取互联网信息的程序或脚本。它们模拟浏览器行为,访问网页,提取所需数据,并进行存储或处理。就像一只蜘蛛在互联网这张大网上爬行,收集信息。
  • Selenium:
    • 定位: 主要是 浏览器自动化测试 工具。
    • 原理: 通过驱动真实的浏览器(如Chrome, Firefox)执行操作(点击、输入、滚动等),可以加载并执行JavaScript,处理动态渲染的网页内容。
    • 爬虫应用: 非常适合爬取那些需要用户交互、或者内容是通过JavaScript动态加载生成的网站。
    • 优点: 可以处理复杂的前端逻辑和动态内容,所见即所得。
    • 缺点: 速度相对较慢(需要启动和控制真实浏览器),资源消耗较大。
    • 简历体现: 房产数据爬虫中台项目使用了 Selenium+Redis构建分布式爬虫架构,说明他有处理复杂动态网页采集和构建分布式爬虫系统的经验。baitengReptile 开源项目也使用了Selenium。
  • Scrapy:
    • 定位: 是一个专门为 爬取网站数据、提取结构性数据 而设计的 Python应用框架
    • 原理: 基于异步网络库(Twisted)构建,通过发送HTTP请求获取网页源代码,然后使用选择器(如CSS选择器、XPath)从中提取数据。
    • 优点: 爬取效率高(异步非阻塞),高度可扩展(中间件、管道),功能强大(内置请求调度、去重、数据处理管道等),适合构建大型、高效的爬虫项目。
    • 缺点: 对于JavaScript动态渲染的页面处理能力较弱(需要配合Selenium或Splash等工具)。
    • 简历体现: 技术栈中提到了Scrapy,虽然具体项目没细说,但表明他了解并可能使用过这个专业的爬虫框架。
  • 选择: 如果目标网站内容是静态的或者通过简单API加载,优先考虑Scrapy(效率高)。如果网站内容是动态生成的、需要复杂交互,或者反爬机制严格(需要模拟真实浏览器行为),则使用Selenium。有时也会结合使用。

Q: 爬虫会遇到哪些挑战?简历中提到的“反爬虫对抗模块”、“动态IP代理池”、“请求指纹混淆”是什么意思? A:

  • 常见挑战:
    • IP封禁: 网站检测到来自同一IP的访问频率过高,会暂时或永久封禁该IP。
    • User-Agent检测: 网站检查请求头中的User-Agent字段,拒绝非浏览器来源的请求。
    • 验证码: 弹出图片、滑动或点选验证码,阻止自动化程序。
    • JavaScript动态加载/加密: 数据通过JS异步加载,或关键信息被JS加密,直接抓取HTML源码无法获取。
    • 登录/Cookie限制: 某些页面需要登录后才能访问。
    • 请求频率限制: 限制单位时间内来自同一用户的请求次数。
    • Robots.txt协议: 网站通过robots.txt文件声明哪些页面允许或禁止爬虫访问。
  • 反爬虫对抗策略 (简历中提到的):
    • 动态IP代理池: 维护一个包含大量可用代理IP的池子。每次发送请求时,随机选择一个代理IP发出,避免因使用单一IP而被封禁。需要定期检测代理IP的可用性。
    • 请求指纹混淆: 网站可能会根据请求的特征(如请求头顺序、TLS指纹、浏览器特有属性等)来识别爬虫。指纹混淆就是通过模拟不同浏览器、随机化请求头等方式,让爬虫的请求看起来更像真实的、多样化的用户访问,降低被识别的风险。
    • 其他常见策略:
      • 修改User-Agent: 伪装成常见的浏览器User-Agent。
      • 处理Cookie: 模拟登录,维护Cookie状态。
      • 降低请求频率/随机延迟: 避免过快访问,模拟人类操作间隔。
      • 验证码处理: 使用OCR技术识别简单验证码,或接入打码平台处理复杂验证码。
      • 处理动态加载: 使用Selenium/Puppeteer等工具执行JS,或分析Ajax请求接口直接抓取数据。
  • 简历体现: 这部分展示了他在爬虫领域的深入实践,具备应对复杂反爬机制的能力,这对于需要稳定获取数据的业务非常重要。

Q: 爬虫需要注意哪些道德和法律规范? A:

  • 遵守 Robots.txt: 尊重网站所有者通过robots.txt文件设置的爬取规则。虽然不是强制法律,但这是行业普遍遵守的规范。
  • 控制爬取频率: 避免过于频繁的请求给目标网站服务器造成过大压力,影响其正常服务。设置合理的请求间隔。
  • 明确爬取目的和数据使用范围: 不得用于非法目的,尊重数据版权和用户隐私。特别是涉及个人信息的数据,需遵守相关法律法规(如GDPR、个人信息保护法)。
  • 表明身份 (User-Agent): 有时可以在User-Agent中包含联系方式或爬虫标识,方便网站管理员识别和沟通。
  • 避免敏感信息: 不爬取、存储、传播受保护的敏感信息。

Q: 什么是数据清洗 (Data Cleaning)?为什么它很重要?一般步骤有哪些? A:

  • 数据清洗: 是数据预处理的一个关键步骤,指的是识别并纠正(或删除)原始数据中错误、不完整、不准确、不一致或不相关部分的过程。目的是提高数据质量,使其适用于后续的分析、建模或应用。
  • 重要性:
    • 保证数据质量: "Garbage in, garbage out." 低质量的数据会导致错误的分析结果和决策。
    • 提高分析准确性: 清洗后的数据更可靠,能提升模型训练效果和分析结论的准确度。
    • 提升应用效果: 在数据驱动的应用中(如推荐系统、风控模型),高质量的数据是良好效果的基础。
    • 简历体现: 爬虫项目提到“成功采集并结构化处理超过50万条房源数据”,以及燃气平台项目开发“数据质量监控脚本”,都隐含了数据清洗和保证数据质量的工作。结构化处理本身就包含了清洗和转换的步骤。
  • 一般步骤:
    • 处理缺失值 (Missing Values):
      • 删除: 删除含有缺失值的记录或特征列(谨慎使用,可能丢失信息)。
      • 填充: 使用均值、中位数、众数、固定值或通过模型预测来填充缺失值。
    • 处理重复值 (Duplicate Values): 识别并删除完全重复的记录。
    • 处理异常值/离群点 (Outliers): 识别(如使用统计方法3σ原则、箱线图)并处理(删除、替换、或单独分析)那些显著偏离正常范围的数据点。
    • 处理格式/类型错误: 统一日期格式、转换数据类型(如文本型数字转为数值型)、去除多余空格或特殊字符。
    • 处理不一致性: 比如同一含义但写法不同("北京" vs "北京市"),需要统一为标准格式。
    • 数据验证与校验: 检查数据是否符合预定义的规则或约束(如邮箱格式是否正确、数值是否在合理范围内)。

#5 重要后端概念拓展

Q: 简历中提到“解决了高并发下的数据一致性问题”,什么是数据一致性?为什么在高并发下会出问题? A:

  • 数据一致性 (Data Consistency): 指的是在数据库系统或分布式系统中,数据在任何时刻都处于一种有意义的、正确的、符合业务规则的状态。简单来说,就是数据不能自相矛盾或出现错误。
  • 为什么重要: 保证业务逻辑的正确执行,提供可靠的数据基础,维护系统稳定性和用户信任。
  • 高并发下的问题: 当多个用户或进程同时对同一份数据进行读写操作时,如果没有适当的控制机制,就可能出现问题,破坏数据一致性。常见问题包括:
    • 脏读 (Dirty Read): 一个事务读取到了另一个事务尚未提交的数据。如果后一个事务回滚了,那么第一个事务读到的就是“脏”数据。
    • 不可重复读 (Non-Repeatable Read): 一个事务内,多次读取同一数据,但由于其他事务在此期间修改并提交了该数据,导致两次读取结果不同。
    • 幻读 (Phantom Read): 一个事务内,多次按相同条件查询,但由于其他事务在此期间插入或删除了符合条件的记录并提交,导致后续查询看到了之前不存在的“幻影”行或少了行。
  • 简历体现: 在医疗SaaS系统的核心模块(病历管理、预约挂号)开发中解决此问题,表明他有处理并发场景下数据完整性的经验,这对于交易、库存、预约等核心业务至关重要。

Q: 如何保证数据一致性?什么是数据库事务?什么是锁? A: 保证数据一致性的常用机制包括数据库事务和锁。

  • 数据库事务 (Database Transaction):
    • 定义: 是数据库管理系统执行过程中的一个 逻辑单元,它由一个或多个数据库操作(增删改查)组成,这些操作要么 全部成功执行,要么 全部不执行(回滚)。事务是保证数据一致性的基本单位。
    • ACID 特性: 事务必须具备四个核心特性:
      • 原子性 (Atomicity): 事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
      • 一致性 (Consistency): 事务执行前后,数据库都必须从一个一致性状态转移到另一个一致性状态。事务的执行不能破坏数据库的完整性约束。
      • 隔离性 (Isolation): 多个事务并发执行时,一个事务的执行不应被其他事务干扰。事务之间好像是隔离的。数据库通过设置不同的 事务隔离级别(读未提交、读已提交、可重复读、串行化)来控制隔离程度,以平衡性能和一致性(隔离级别越高,并发性能越差)。
      • 持久性 (Durability): 一旦事务成功提交,它对数据库所做的更改就是永久性的,即使系统崩溃也不会丢失。 好的,我们来详细解释一下你提到的各种锁的概念、原理和使用场景。

锁 (Lock) - 核心概念回顾

  • 定义: 锁是一种并发控制机制,用于管理对共享资源的访问。
  • 目的: 保证在多用户/多事务并发环境下,对共享资源的操作(特别是写操作)能够有序进行,防止数据不一致、丢失更新等问题,维护数据的完整性和一致性。
  • 基本原理: 当一个事务(或线程)想要访问资源时,它会尝试获取该资源的锁。
    • 如果资源未被锁定或被兼容的锁锁定,则获取成功,事务可以访问资源。
    • 如果资源已被不兼容的锁锁定,则事务需要等待,直到持有锁的事务释放该锁。

数据库层面的常见锁

数据库管理系统(DBMS)内部实现了复杂的锁机制来处理并发事务。

  1. 共享锁 (Shared Lock / 读锁 / S Lock)

    • 概念:允许多个事务同时读取同一个资源,但不允许任何事务修改它。
    • 原理: 如果事务 T1 持有资源 R 的 S 锁,那么其他事务 T2:
      • 可以再获取资源 R 的 S 锁(读读不互斥)。
      • 不能获取资源 R 的 X 锁,必须等待 T1 释放 S 锁(读写互斥)。
    • 使用场景: 当事务需要读取数据,并确保在读取期间数据不会被其他事务修改时使用。例如,生成报表、数据查询分析。SELECT ... LOCK IN SHARE MODE (MySQL InnoDB) 或 SELECT ... FOR SHARE (PostgreSQL, MySQL 8+) 通常会加 S 锁。
  2. 排他锁 (Exclusive Lock / 写锁 / X Lock)

    • 概念: 只允许持有该锁的事务访问(读取和修改)资源,其他任何事务都不能再获取该资源的任何锁(S 或 X)。
    • 原理: 如果事务 T1 持有资源 R 的 X 锁,那么其他事务 T2:
      • 不能获取资源 R 的 S 锁,必须等待(写读互斥)。
      • 不能获取资源 R 的 X 锁,必须等待(写写互斥)。
    • 使用场景: 当事务需要修改或删除数据时使用,以防止其他事务读取到中间状态或同时修改导致冲突。例如,UPDATE, DELETE, INSERT 操作会自动加 X 锁。SELECT ... FOR UPDATE 显式加 X 锁,用于读取后准备更新的场景(防止其他事务在我读取和更新之间修改数据)。
  3. 行锁 (Row Lock)

    • 概念: 锁定的粒度是数据表中的某一行或多行。
    • 原理: 只锁定事务实际需要操作的行,其他事务可以访问或修改表中的其他行。行锁可以是共享的(S)或排他的(X)。
    • 优点: 并发度高。不同事务操作不同行时,几乎没有冲突。
    • 缺点: 开销相对较大。需要更多的锁管理(内存、CPU),并且可能更复杂(例如需要处理间隙锁以防止幻读)。
    • 使用场景: 大多数支持事务的现代关系型数据库(如 InnoDB 存储引擎的 MySQL, PostgreSQL, SQL Server, Oracle)默认使用的锁粒度。适用于高并发、事务操作数据行比较分散的场景。
  4. 表锁 (Table Lock)

    • 概念: 锁定的粒度是整个数据表。
    • 原理: 锁定整个表后,根据锁类型(S 或 X)限制其他事务对该表的访问。表锁也可以是共享的(S)或排他的(X)。
    • 优点: 开销小。锁管理简单,消耗资源少。
    • 缺点: 并发度低。即使事务只操作表中的一小部分数据,也会阻止其他事务访问整个表,容易造成阻塞。
    • 使用场景:
      • 执行 DDL 操作(如 ALTER TABLE)时,通常需要获取表级排他锁。
      • 进行全表更新或大量数据导入/导出时,有时显式使用表锁可以提高效率(避免管理大量行锁的开销)。
      • 一些存储引擎(如 MySQL 的 MyISAM)主要使用表锁。
  5. 意向锁 (Intention Lock)

    • 概念: 表级锁,但它并不直接锁定表数据,而是“意图”的表示。它表明事务 打算 在表中的某些行上加行锁(共享或排他)。
    • 类型:
      • 意向共享锁 (Intention Shared Lock / IS Lock): 事务打算在表中的某些行上设置 S 锁。
      • 意向排他锁 (Intention Exclusive Lock / IX Lock): 事务打算在表中的某些行上设置 X 锁。
    • 原理与目的: 提高效率。想象一下,如果事务 T1 想对整个表加 X 锁,它需要确保表里没有任何行被其他事务锁定。如果没有意向锁,T1 就必须检查表中的每一行是否有锁。有了意向锁,T1 只需要检查表上是否有 IS 或 IX 锁即可。
      • 事务在获取行级 S 锁之前,必须先获取表级 IS 锁。
      • 事务在获取行级 X 锁之前,必须先获取表级 IX 锁。
    • 兼容性:
      • 意向锁之间(IS vs IS, IS vs IX, IX vs IX)是兼容的。多个事务可以同时持有不同类型的意向锁。
      • 意向锁与行锁无关,它只与表级锁(S 和 X)交互。
      • IS 锁 与 表级 S 锁 兼容,与 表级 X 锁 互斥。
      • IX 锁 与 表级 S 锁 和 表级 X 锁互斥
    • 使用场景: 由数据库系统(如 InnoDB)自动管理,用户通常不需要直接操作。它是实现行锁和表锁共存并高效判断锁冲突的关键机制。

概念层面的常见锁

这是从并发控制的策略角度划分的,不特指数据库中的具体实现,也可以应用于应用程序代码等其他场景。

  1. 悲观锁 (Pessimistic Lock)

    • 概念: 对数据被并发修改持悲观态度,认为冲突总是会发生。因此,在每次操作数据(特别是读取数据用于后续修改)之前,都会先尝试获取锁。如果获取不到锁,就会阻塞等待。
    • 原理: "先锁定,再操作"。利用数据库提供的锁机制(如行锁、表锁,SELECT ... FOR UPDATE, SELECT ... FOR SHARE)或其他同步原语(如编程语言中的 Mutex, synchronized 关键字)。
    • 优点:
      • 实现简单,逻辑清晰。一旦获得锁,就可以确定在操作期间数据不会被修改。
      • 数据一致性强,不易出错。
    • 缺点:
      • 并发性能较低。因为即使冲突实际很少发生,也会加锁,可能导致不必要的等待。
      • 持有锁的时间如果过长,会严重影响其他事务/线程的性能。
      • 容易产生死锁。
    • 使用场景:
      • 写多读少的场景,并发冲突的概率较高。
      • 对数据一致性要求非常高,不允许出现更新失败或需要重试的情况。
      • 事务涉及的操作比较复杂或耗时,不希望在操作过程中数据被改变。
      • 例如:金融交易(扣款、转账)、库存扣减(且不允许超卖)、抢购场景。
  2. 乐观锁 (Optimistic Lock)

    • 概念: 对数据被并发修改持乐观态度,认为冲突很少发生。因此,操作数据时不加锁,而是在提交更新时去检查,看在读取数据到提交更新这段时间内,数据是否被其他事务修改过。
    • 原理: "先操作,后检查"。通常不依赖数据库的锁机制,而是在业务逻辑中实现。常见实现方式:
      • 版本号 (Versioning): 在数据表中增加一个 version 字段。
        1. 读取数据时,同时读取 version 值。
        2. 执行业务逻辑,计算新值。
        3. 提交更新时,UPDATE ... SET data = new_value, version = version + 1 WHERE id = ? AND version = old_version
        4. 检查 UPDATE 语句影响的行数。如果为 1,表示更新成功;如果为 0,表示在我读取数据后、提交更新前,数据已被其他事务修改(version 值已改变),本次更新失败。
      • 时间戳 (Timestamp): 类似版本号,使用时间戳字段。更新时检查时间戳是否匹配。缺点是可能不如版本号精确可靠(例如时钟回拨、并发精度问题)。
      • CAS (Compare-and-Swap): 原子操作,常用于内存对象。比较内存位置的值与预期值是否相符,如果相符则更新为新值。数据库中的版本号机制是类似 CAS 的思想。
    • 优点:
      • 并发性能高。读取数据时不加锁,允许多个事务同时读取和操作数据,只有在最后提交更新时才可能发生冲突。
      • 避免了死锁问题(因为它不持有数据库锁)。
    • 缺点:
      • 需要应用程序自己处理冲突(如重试、报错、合并等),实现逻辑相对复杂。
      • 如果冲突频繁发生,重试成本会很高,性能反而可能不如悲观锁。
      • 存在 "ABA 问题":如果一个值从 A 变成 B,又变回 A,使用简单版本号或时间戳检查会认为没有变化,但实际上中间发生过修改。可以通过更复杂的版本控制解决。
    • 使用场景:
      • 读多写少的场景,并发冲突的概率较低。
      • 允许更新失败和重试的场景。
      • 对并发性能要求很高的系统。
      • 例如:编辑文档(如 Wiki)、更新用户信息、点赞/收藏操作(冲突概率低)。 总结:
  • 数据库锁 (S, X, Row, Table, Intention) 是数据库内部用于保证事务隔离性和数据一致性的具体机制。它们关注的是锁的类型粒度

  • 概念锁 (Pessimistic, Optimistic) 是并发控制的策略哲学。它们关注的是何时以及如何处理并发冲突。

  • 通常,数据库的锁机制(行锁、表锁等)是实现悲观锁策略的基础。而乐观锁更多地在应用层面通过版本号等机制实现,或者利用数据库提供的特定 CAS 功能。

  • 如何解决一致性问题:

    • 合理使用数据库事务,将需要保证原子性的操作放在一个事务中。
    • 选择合适的事务隔离级别(通常是“读已提交”或“可重复读”)。
    • 在必要时(如防止超卖),显式使用数据库锁(如 SELECT ... FOR UPDATE 获取写锁)或应用层锁(如Redis分布式锁)。
    • 在某些场景下使用乐观锁机制。

#6 DevOps & 运维知识

Q: 简历中提到了 Docker, GitLab CI/CD, Jenkins, Shell, Linux,这些是做什么的?它们和DevOps有什么关系? A:

  • Linux: 开源的、免费的类Unix操作系统内核。是目前服务器端最主流的操作系统。后端服务通常部署在Linux服务器上。熟悉Linux常用命令和Shell脚本是后端开发的基本功。
  • Shell: Linux/Unix系统的命令解释器,也是一种脚本语言。可以通过编写Shell脚本来自动化执行一系列Linux命令,用于部署、监控、管理服务器等。
  • Docker: 一个开源的应用容器引擎。可以将应用程序及其所有依赖(库、环境等)打包到一个轻量级、可移植的 容器 (Container) 中,然后在任何支持Docker的机器上运行,保证了环境的一致性。极大地简化了应用的部署和管理。
    • 优点: 环境隔离、快速部署、易于扩展、资源利用率高。
  • CI/CD (Continuous Integration / Continuous Delivery or Deployment):
    • 持续集成 (CI): 开发人员频繁地将代码合并到主干(通常每天多次)。每次合并后,自动进行构建、运行单元测试和集成测试,以快速发现和修复错误。
    • 持续交付 (CD - Delivery): 在CI的基础上,将通过测试的代码自动部署到 预发布环境 (Staging/UAT)。部署到生产环境通常需要手动确认。
    • 持续部署 (CD - Deployment): 在持续交付的基础上,将通过所有测试和检查的代码 自动部署生产环境
    • 目的: 加快软件交付速度,提高软件质量,减少部署风险。
  • GitLab CI/CD: GitLab是一个集代码托管、项目管理、CI/CD等功能于一体的平台。GitLab CI/CD是其内置的CI/CD工具,通过在代码仓库中定义 .gitlab-ci.yml 文件来配置自动化流程。
  • Jenkins: 一个老牌、功能强大的开源自动化服务器,广泛用于实现CI/CD流程。可以通过安装各种插件来支持不同的构建、测试、部署任务。
  • DevOps (Development & Operations): 是一种文化、运动或实践,强调软件开发(Dev)和信息技术运维(Ops)之间的协作和沟通,以及通过自动化(CI/CD、配置管理、监控等)来更快、更可靠地构建、测试和发布软件。上述工具(Docker, CI/CD工具, Shell, Linux)都是实践DevOps理念的重要工具。

Q: 对于一个后端开发者,需要了解哪些基础的运维知识?(针对新人) A: 了解以下基础运维知识能让你更好地理解应用部署环境、排查问题,并与运维同事更顺畅地协作:

# 数据防护与安全

  • Q: 什么是数据防护?为什么重要? A: 数据防护是指采取一系列措施来保护数据免遭未经授权的访问、泄露、篡改或破坏。这对于保护公司资产、用户隐私、遵守法律法规至关重要。
  • Q: 服务器防火墙是做什么的? A: 服务器防火墙(如 iptables, firewalld, ufw in Linux, 或云服务商提供的安全组)是一个网络安全系统,用于 控制进出服务器的网络流量。它根据预设的规则(如允许哪些IP访问哪些端口)来允许或阻止网络连接,是服务器安全的第一道防线。例如,可以配置防火墙只允许来自特定IP的SSH(端口22)连接,只允许公网访问Web服务(端口80/443)。
  • Q: 常见的Web安全漏洞有哪些?如何防护? A:
    • SQL注入 (SQL Injection): 攻击者将恶意的SQL代码插入到应用的输入参数中,欺骗服务器执行非预期的数据库操作(如窃取数据、删除数据)。
      • 防护: 使用 参数化查询 (Parameterized Queries)预编译语句 (Prepared Statements)(这是最有效的防护手段);对用户输入进行严格验证和过滤;使用ORM框架(它们通常内置了防护机制);最小权限原则(数据库用户只授予必要的权限)。
    • 跨站脚本攻击 (XSS - Cross-Site Scripting): 攻击者将恶意脚本注入到网页中,当其他用户访问该网页时,恶意脚本会在用户的浏览器中执行,可能窃取Cookie、会话信息或进行其他恶意操作。
      • 防护: 对用户输入和输出到HTML的内容进行 严格的转义 (Escaping)(如将 <, >, " 转义为 &lt;, &gt;, &quot;);设置 HttpOnly 标记的Cookie(防止脚本读取);使用内容安全策略 (CSP - Content Security Policy)。
    • 跨站请求伪造 (CSRF - Cross-Site Request Forgery): 攻击者诱导已登录的用户访问一个恶意网站或点击一个链接,该网站或链接会向用户已登录的目标网站发送一个伪造的请求(如修改密码、转账),利用用户的身份执行非预期的操作。
      • 防护: 使用 CSRF Token(在表单或请求头中加入一个随机生成的、与用户会话绑定的令牌,服务器验证该令牌);检查HTTP请求的 Referer 头(有局限性);使用SameSite Cookie属性。
    • 其他: 文件上传漏洞、未授权访问、敏感信息泄露等。
    • 通用防护: 保持框架和库的更新;进行安全编码培训;使用Web应用防火墙 (WAF);定期进行安全扫描和渗透测试。
  • Q: 如何进行漏洞防护? A: 除了针对具体漏洞的防护措施外,还包括:
    • 及时更新: 保持操作系统、Web服务器(Nginx/Apache)、数据库、编程语言运行时(Python)、框架(Flask/Django)和第三方库到最新稳定版本,修复已知漏洞。
    • 最小权限原则: 应用程序、数据库用户、系统服务都应该只拥有完成其任务所必需的最小权限。
    • 输入验证: 永远不要信任用户输入,对所有外部输入进行严格的格式、类型、长度校验和过滤。
    • 安全配置: 对服务器、数据库、Web服务进行安全加固配置。
    • 日志审计: 记录关键操作日志,定期审计,以便发现异常行为。

# 服务器与运维操作

  • Q: 什么是虚拟服务器 (VPS/VM)?它和物理服务器有什么区别? A:
    • 物理服务器 (Dedicated Server): 一台完整的、独立的物理计算机硬件,所有资源(CPU、内存、硬盘、带宽)都归你独享。性能最好,但成本高,管理复杂。
    • 虚拟服务器 (Virtual Server / Virtual Machine / VPS): 通过 虚拟化技术 (如 KVM, VMware, Hyper-V) 在一台物理服务器上划分出来的多个相互隔离的虚拟环境。每个虚拟服务器拥有自己独立的操作系统、CPU资源、内存、硬盘空间和网络配置,看起来就像一台独立的服务器。
    • 区别: 虚拟服务器共享物理服务器的硬件资源,成本更低,易于扩展和管理(可以快速创建、销毁、迁移),但性能可能受“邻居”影响(超售情况)。云服务商(如AWS EC2,阿里云ECS,腾讯云CVM)提供的通常就是虚拟服务器。
  • Q: 为什么要进行数据备份?常见的备份策略有哪些? A:
    • 原因: 防止数据丢失(硬件故障、人为误操作、软件Bug、恶意攻击、自然灾害等),保证业务连续性。
    • 常见策略:
      • 全量备份 (Full Backup): 备份所有数据。恢复简单,但备份时间和存储空间消耗大。
      • 增量备份 (Incremental Backup): 只备份自 上一次备份(全量或增量)以来发生变化的数据。备份快,节省空间,但恢复时需要基于上一次全量备份和之后的所有增量备份,过程复杂且耗时。
      • 差分备份 (Differential Backup): 只备份自 上一次全量备份 以来发生变化的数据。备份时间和空间介于全量和增量之间,恢复时只需要上一次全量备份和最后一次差分备份,比增量恢复简单。
    • 备份频率: 根据数据的重要性和变化频率决定(如每天、每小时)。
    • 备份存储: 应将备份存储在与原始数据 不同的物理位置(异地备份),甚至使用不同的存储介质(如磁带、对象存储)。
    • 备份验证: 定期进行恢复演练,确保备份文件可用。
  • Q: 如何追踪服务器的数据流量? A: 追踪数据流量有助于了解应用的网络负载、排查网络问题、监控带宽使用情况。常用工具和方法:
    • 基础工具 (Linux):
      • iftop: 实时显示网络接口的带宽使用情况(按连接)。
      • nethogs: 按进程显示网络带宽占用情况。
      • iptraf: 实时网络监控工具,提供多种统计视图。
      • vnStat: 基于接口的流量日志记录和统计工具。
    • Web服务器日志: Nginx/Apache的访问日志记录了每次HTTP请求的来源IP、请求URL、响应状态码、传输字节数等信息,可以分析流量来源和分布。
    • 云服务商监控: AWS CloudWatch, 阿里云云监控等提供了详细的网络流入/流出流量监控图表。
    • 网络监控系统: 使用专业的网络监控工具(如 Zabbix, Nagios, Prometheus + Grafana)收集和展示更详细的网络性能指标。
  • Q: 如果线上服务挂了,一般怎么排查和重启? A:
    • 排查步骤 (通用思路):
      1. 确认问题: 服务是否真的无法访问?是部分用户还是所有用户?影响范围是?(使用监控系统、ping、telnet、curl等工具初步判断)
      2. 检查应用日志: 查看应用程序(如Flask/Django应用)的错误日志,通常能直接定位到代码层面的问题(如空指针、数据库连接失败、配置错误等)。
      3. 检查系统资源: 查看服务器的CPU、内存、磁盘空间、网络连接数是否耗尽或异常飙升 (top, htop, free -m, df -h, netstat -anp)。
      4. 检查依赖服务: 检查数据库、缓存(Redis)、消息队列等依赖的服务是否正常运行。
      5. 检查Web服务器/网关: 查看Nginx/Apache或应用网关(如uWSGI, Gunicorn)的日志,检查是否有配置错误、连接超时、资源限制等问题。
      6. 检查网络: 检查服务器网络配置、防火墙规则、DNS解析是否正常。
      7. 查看系统日志: 查看操作系统的核心日志(如 /var/log/messagesjournalctl)是否有硬件错误、内核问题等信息。
    • 服务重启:
      • 使用Systemd (现代Linux发行版):
        • 查看服务状态: sudo systemctl status <service_name> (如 sudo systemctl status myapp.service)
        • 停止服务: sudo systemctl stop <service_name>
        • 启动服务: sudo systemctl start <service_name>
        • 重启服务: sudo systemctl restart <service_name>
        • 查看服务日志: journalctl -u <service_name>
      • 使用Supervisor (常用的进程管理工具):
        • 进入控制台: sudo supervisorctl
        • 查看状态: status
        • 停止: stop <process_name>
        • 启动: start <process_name>
        • 重启: restart <process_name>
      • 直接运行 (不推荐用于生产): 如果是前台运行的,Ctrl+C 停止,然后重新执行启动命令。如果是后台运行 (&),需要找到进程ID (ps aux | grep <process_name>, pgrep <process_name>) 然后 kill <pid> (尝试先用 kill -15 <pid> 发送TERM信号,不行再用 kill -9 <pid> 强制杀死),然后重新启动。
    • 注意: 重启前最好先尝试排查原因,避免重启后问题依旧。重启是快速恢复服务的手段,但解决根本问题更重要。

#7 AI & LLM 相关

Q: 简历里提到了很多AI相关的实践,后端开发为什么会接触AI? A: AI,特别是大语言模型(LLM),正在越来越多地融入软件开发和业务流程中:

  • 提升开发效率: AI编程助手(如Copilot, ChatGPT)可以辅助编写代码、生成测试用例、解释代码、调试Bug,提高开发者的生产力(简历提到效率提升超50%)。
  • 赋能业务功能:
    • 智能客服/对话机器人: 对接AI模型(如OpenAI API, Claude)提供智能问答、对话服务(如 wechat-bot 开源项目)。
    • 内容生成/处理: 利用AI生成文本(如自动生成报告、营销文案)、改写文本(如 ParaphrasingToolServer 项目)、总结文档、翻译等。
    • 数据分析与洞察: AI可以辅助分析数据,发现模式,生成可视化报告。
    • 图像生成: 利用Stable Diffusion等模型生成图片,用于设计、内容创作等(简历有提及)。
  • 自动化任务:
    • 文档自动化: 自动生成API文档、技术文档,减少人工编写工作量。
    • 代码分析/审查: 利用AI进行代码质量分析、安全漏洞扫描。
  • 优化基础设施:
    • 服务访问: 使用Cloudflare Workers等边缘计算方案优化对海外AI服务的访问(简历有提及)。
    • 模型管理: 搭建统一平台(如NextChat)管理和调用多种AI模型,进行成本优化和灵活切换。
  • 后端是AI能力的落地者: AI模型本身通常需要后端服务来封装、部署、提供API接口,并将其与现有业务系统集成。因此,后端开发者需要了解如何调用AI API、处理AI模型的输入输出、以及将AI能力整合到产品中。

Q: 什么是大语言模型 (LLM)?Prompt Engineering 是什么意思? A:

  • 大语言模型 (LLM - Large Language Model): 是一种基于深度学习(特别是Transformer架构)训练出来的、拥有海量参数(通常数十亿甚至万亿级别)的人工智能模型。它们通过在极大规模的文本数据上进行训练,学会了理解和生成人类语言的能力。常见的LLM包括GPT系列(如GPT-3.5, GPT-4)、Claude、LLaMA等。它们可以执行各种自然语言处理任务,如问答、翻译、摘要、写作、代码生成等。
  • Prompt Engineering (提示工程): 指的是 设计和优化输入文本(即“提示”,Prompt) 的艺术和科学,以便更好地引导大语言模型生成期望的、高质量的输出。因为LLM的输出高度依赖于输入提示的质量和表达方式,Prompt Engineering的目标就是找到最有效的提问方式或指令,来激发模型的潜力,使其准确、相关、有用地完成特定任务。这包括:
    • 明确指令: 清晰地告诉模型要做什么。
    • 提供上下文: 给出必要的背景信息。
    • 指定格式: 要求模型按特定格式输出(如JSON、Markdown)。
    • 示例学习 (Few-shot Learning): 在提示中给出几个输入输出的例子,让模型学习模式。
    • 思维链 (Chain-of-Thought): 引导模型分步骤思考,提高复杂推理任务的准确性。
    • 迭代优化: 不断尝试和调整提示,直到获得满意的结果。
  • 简历体现: 熟练掌握Prompt Engineering意味着他知道如何有效地与LLM交互,以获得最佳结果,这在应用AI技术的项目中非常关键。

#8 面试建议 (针对新人)

  • 基础扎实: 掌握Python语法、常用数据结构与算法、计算机网络(HTTP协议)、操作系统(Linux)基础。
  • 框架理解: 至少深入理解一个Web框架(如Flask或Django),包括其工作原理、请求生命周期、核心组件。能动手写简单的CRUD应用。
  • 数据库: 掌握SQL基本语法,理解关系型数据库的基本概念(表、索引、事务),了解至少一种数据库(如MySQL)的基本使用和优化。了解Redis的基本概念和常用场景(缓存)。
  • 项目经验: 如果没有实际工作经验,可以做一些个人项目(如简历中的开源项目),并能清晰地介绍项目目标、技术选型、遇到的困难及解决方法。重点突出你学到了什么,解决了什么问题。
  • 学习能力: 面试中展现出你的学习热情和快速学习新知识的能力。可以谈谈你最近在学什么新技术。
  • 沟通表达: 清晰、有条理地回答问题,遇到不懂的可以坦诚说明,并表达学习意愿。
  • 针对性准备: 仔细研究目标公司的技术栈和业务,思考你的技能和经验如何匹配。准备一些与职位要求相关的常见面试题。
  • 加分项: 了解Docker、CI/CD、基本的运维知识、爬虫技术、或者对AI有初步了解,都会是加分项。