性能相关
服务器cpu过高
怎么定位和查看:
- top命令 看cpu占用高的进程 , ps 找到cpu高的线程 然后定位代码
- 查看相关日志
内存过高
查看:
free -m 查看服务器内存使用情况,-m的意思是内存显示单位是mb
top 查看服务器所有进程占用内存,为了查看方便,可以使用
日志
原因:
1.内存泄漏
2.缓存使用不当
3.
内存泄漏如何定位和处理
可能发生内存泄漏的场景
- 申请过多的goroutine 例如在for循环中申请过多的goroutine来不及释放导致内存泄漏
- 协程结束时协程中的channel没有关闭,导致一直阻塞;例如协程中有死循环
- 切片截取引起子切片内存泄漏 解决 : append
排查内存泄漏 :pprof 分析工具
pprof 支持四种类型的分析:
CPU分析
Memory内存分析
Block阻塞分析,
Mutex互斥锁分析
抢红包场景
系统架构设计
前端层:负责展示抢红包的页面,处理用户点击抢红包的请求,并将请求发送到后端服务器。使用cdn加速
后端层:接收前端请求,进行业务逻辑处理,包括用户验证、红包分配、记录抢红包结果等。使用nginx发到不同服务器上
数据存储层:存储红包信息、用户信息、抢红包记录等数据。需要选择高性能、高可用的数据库系统,如Redis。
缓存层:使用缓存技术(如Redis)存储热点数据,提高数据访问速度,减轻数据库压力。
消息队列:在抢红包高峰期,使用消息队列(如RabbitMQ、Kafka)进行流量削峰,异步处理抢红包请求。
数据存储设计
红包池:使用Redis列表(List)或有序集合(Sorted Set)作为红包池,存储红包的金额和ID。可以根据红包的总金额和数量,预先生成红包并放入池中。
用户信息:使用Redis哈希(Hash)存储用户的基本信息,如用户ID、昵称、账户余额等。
抢红包记录:使用Redis列表或数据库表记录每次抢红包的结果,包括用户ID、红包ID、抢红包时间等。
3. 并发控制设计
分布式锁:在抢红包过程中,使用Redis的分布式锁(如SETNX命令)来确保同一时间只有一个线程能够修改红包池中的数据。
原子操作:利用Redis的原子操作(如LPOP、RPOP、INCR、DECR等)来确保在抢红包过程中数据的一致性和完整性。
乐观锁:在更新数据库记录时,使用乐观锁(如版本号)来避免并发更新导致的数据冲突。
4. 公平性设计
随机算法:采用随机算法(如线性同余生成器、梅森旋转算法等)来生成红包金额,确保每个人抢到红包的概率相同。
红包分配策略:可以根据红包的总金额和数量,设计不同的分配策略,如平均分配、按概率分配等。
**防作弊机制:通过限制用户抢红包的频率、检测异常行为等方式,防止用户作弊或恶意刷红包。
5. 性能优化设计
批量操作:在可能的情况下,使用Redis的批量操作命令(如MGET、MSET、PIPELINE等)来提高数据访问效率。
异步处理:将非核心的业务逻辑(如记录抢红包结果、更新用户账户余额等)异步处理,以减少主线程的阻塞时间。
水平扩展:通过增加服务器数量、使用负载均衡等方式,提高系统的并发处理能力和可用性。
如何为你的服务设置持续集成/持续部署管道(CI/CD pipeline)
步骤一:版本控制和代码仓库
选择版本控制系统:使用像 Git 这样的版本控制系统来管理代码。
创建代码仓库:在 GitHub、GitLab 或 Bitbucket 等平台上创建一个代码仓库来存储代码。
步骤二:持续集成(CI)
选择 CI 工具:例如 Jenkins、CircleCI、GitLab CI/CD 等。
设置 CI 配置文件:在代码仓库中创建 CI 配置文件(如 .gitlab-ci.yml、Jenkinsfile),定义构建、测试和部署流程。
触发 CI 构建:每当有新的代码推送到代码仓库时,CI 工具会自动触发构建过程。
执行单元测试、集成测试等:确保代码通过各种测试阶段。
步骤三:持续部署(CD)
选择部署工具:使用工具如 Ansible、Docker、Kubernetes 等来自动化部署。
设置部署配置:定义部署流程,包括构建 Docker 镜像、部署到测试环境、执行自动化测试等。
自动化部署到生产环境:确保通过测试的代码能够自动部署到生产环境。
步骤四:监控和日志
集成监控工具:集成监控工具如 Prometheus、Grafana 来监控应用程序性能和健康状况。
收集日志:使用工具如 **ELK Stack(Elasticsearch、Logstash、Kibana)**来收集和分析日志。
什么是微服务(microservice)?你在什么场景下会使用微服务?一个系统分解成多少个微服务合适?
服务(Microservices)是一种软件架构风格,将单一应用程序分解为一组小的、独立的服务。每个服务运行在自己的进程中,并通过轻量级机制(rpc Grpc 等)进行通信。
微服务的特点
独立部署:每个服务可以独立部署和升级。
团队自治:不同的团队可以负责不同的服务。
技术多样性:不同服务可以使用不同的技术栈。
故障隔离:一个服务的故障不会影响整个系统。
适用场景
复杂业务逻辑:适用于具有复杂业务需求的大型应用。
快速迭代:需要频繁更新和部署的系统。
可扩展性:系统需要根据负载水平灵活扩展。
多团队开发:多个团队协作开发,需减少相互依赖。
微服务的划分
按业务功能:将系统按业务领域分解,如用户服务、订单服务、支付服务等。
按团队结构:根据团队的能力和责任分解。
按数据模型:将具有不同数据模型的功能分开。
微服务架构的优点和缺点是什么?什么样的场景不适合使用微服务架构?
微服务架构的优点
灵活性:可以独立开发、部署、扩展服务。
技术多样性:不同服务可以使用最适合的技术栈。
故障隔离:单个服务故障不会影响整个系统。
团队自治:团队可以独立负责某个服务,减少依赖。
微服务架构的缺点
复杂性:服务间通信和数据一致性管理复杂。
运维成本:需要复杂的部署、监控和管理系统。
网络延迟:服务间通信增加了网络延迟和故障风险。
不适合使用微服务的场景
小型应用:业务简单,团队规模小。
开发资源有限:缺乏维护复杂分布式系统的能力。需要服务治理
快速原型:需要快速迭代,微服务的复杂性可能拖慢进度。
如何在数据量大的后端应用程序中进行批处理(batch processing)?
1. 数据分区
分块处理:将数据集划分为多个小块,逐块处理,减少内存占用。
分片并行:将数据分片后使用多线程或多进程并行处理。
2. 使用批量操作
批量插入/更新:使用数据库提供的批量操作接口,减少数据库交互次数。
批量读取:一次读取多条记录,减少 I/O 开销。
3. 异步处理
消息队列:使用 Kafka、RabbitMQ 等,将任务放入队列,异步批量消费。
任务调度:使用调度工具(如 Airflow)定期执行批处理任务。
4. 数据流处理
流式处理框架:使用 Apache Flink、Apache Spark Streaming 等流式处理框架,适合连续数据流的批处理。
5. 资源管理
动态资源分配:根据任务负载动态调整资源,保证批处理任务的效率。
负载均衡:在分布式环境中使用负载均衡器分配任务,防止单点过载。
在高负载的场景中(high-load scenario),你会使用怎样的策略管理数据库连接(DB connection)?为什么?
1. 连接池
使用连接池:如 HikariCP、C3P0、DBCP 等。
原因:减少连接建立和释放的开销,提高性能和响应速度。
2. 连接池配置
最大连接数:设置合理的最大连接数,防止数据库过载。
最小连接数:保持一定数量的空闲连接,减少请求延迟。
连接超时:设定连接的超时时间,释放长期未使用的连接。
3. 读写分离
主从复制:将读操作分配到只读副本,减轻主库压力。
原因:提高读操作的并发能力,提升整体性能。
4. 使用缓存
缓存热点数据:使用 Redis、Memcached 缓存频繁访问的数据。
原因:减少数据库访问次数,降低负载。
5. 分库分表
水平拆分:将数据分布到多个库或表中。
原因:提高数据库的并发处理能力。
6. 优化查询
索引优化:确保查询使用适当的索引。
原因:减少查询时间,降低数据库压力。
7. 异步操作
批量处理:将多个小操作合并为一个批量操作。
异步任务:使用异步机制处理非实时查询。
原因:减轻数据库的瞬时负载。
你通常用哪些方法来管理后台任务(background task)?
1. 使用任务队列
Celery:支持分布式任务调度,适合 Python 应用。
RQ (Redis Queue):简单易用的任务队列,基于 Redis。
Sidekiq:用于 Ruby 应用的高效任务队列。
2. 使用调度器
Cron:在 Unix 系统上定时执行任务。
Celery Beat:与 Celery 配合使用,实现定时任务。
APScheduler:Python 的高级定时任务调度库。
3. 使用消息队列
RabbitMQ:用于异步任务处理和消息传递。
Apache Kafka:适合高吞吐量的任务处理场景。
4. 容器化与编排
Docker:将任务封装在容器中,便于管理和部署。
Kubernetes CronJobs:在 Kubernetes 集群中调度任务。
5. 并发与异步
多线程/多进程:利用 Python 的 concurrent.futures 或 Java 的 ExecutorService。
异步框架:如 Node.js 的 async/await 或 Python 的 asyncio。
如果一个web请求处理时间非常长(long-running process),你会如何处理与优化?
排查过程
监控和日志:使用监控工具和日志分析确定请求的哪个部分最慢。
代码和查询分析:深入分析代码和数据库查询,找出具体的性能瓶颈。
优化和测试:针对瓶颈点进行优化,持续测试和监控效果。
优化策略
a. 异步处理
后台任务:将长时间运行的任务移到后台,使用任务队列(如 Celery、Sidekiq)。
非阻塞 I/O:使用异步框架(如 Node.js,Python 的 asyncio)处理 I/O 操作。
b. 分片和批处理
数据分片:将大数据集分成小块处理,减少单次操作的时间。
批量操作:合并多个数据库操作为一个批处理命令。
慢查询
1. 暂时停止新请求
流量控制:临时减少新请求的流入,使用负载均衡器或防火墙限制访问。
2. 优化慢查询
索引优化:检查并创建缺失的索引。
查询重写:优化查询语句,减少不必要的复杂操作。
3. 增加资源
扩展数据库实例:临时增加数据库的计算资源。
读写分离:将读请求引导到只读副本,减轻主库压力。
4. 缓存策略
结果缓存:使用 Redis 或 Memcached 缓存查询结果,减少数据库负载。
页面缓存:缓存生成的页面或部分页面。
5. 后台处理
异步处理:将长时间查询改为后台任务,异步处理结果。
批量处理:合并多个小查询为批量操作。
6. 清理堆积
优先级调整:调整查询优先级,先处理高优先级任务。
事务管理:在安全的情况下,终止长时间占用的事务。