【后端开发面试题】每日 3 题(五)

✍个人博客:Pandaconda-CSDN博客

📣专栏地址:https://blog.csdn.net/newin2020/category_12903849.html

📚专栏简介:在这个专栏中,我将会分享后端开发面试中常见的面试题给大家~

❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪

1. 如何优化一个高并发场景下的数据库读写性能?

数据库层面

  • 索引优化

    • 合理创建索引,对经常用于查询条件、排序和连接的字段添加索引,如在用户表的 username 字段上添加索引,可加快按用户名查询的速度。
    • 避免过多索引,因为索引会增加写操作的开销,且占用额外的磁盘空间。定期分析查询语句,删除不必要的索引。
    • 使用复合索引,当多个字段经常一起用于查询条件时,创建复合索引可以提高查询效率。例如,对于经常同时根据 user_id 和 create_time 查询订单的场景,创建 (user_id, create_time) 复合索引。
  • 数据库架构优化

    • 读写分离:采用主从复制架构,主库负责写操作,从库负责读操作。这样可以将读压力分散到多个从库上,提高系统的读性能。例如,在电商系统中,商品信息的查询可以从从库获取,而订单的创建则在主库进行。
    • 分库分表:当数据量非常大时,将数据分散存储在多个数据库或表中。水平分表按照数据的行进行划分,如按时间将订单表拆分为多个表;垂直分表按照数据的列进行划分,将不常用的字段拆分到另一个表中。
  • 数据库参数调整

    • 根据服务器的硬件资源和业务特点,调整数据库的配置参数。例如,调整 innodb_buffer_pool_size 以提高 MySQL 的缓存效率,确保常用数据能在内存中快速访问。
      应用层面
  • 缓存机制

    • 使用内存缓存(如 Redis)来减轻数据库的读压力。将经常访问的数据(如热门商品信息、用户信息等)存储在缓存中,应用程序优先从缓存中获取数据,只有在缓存中不存在时才去查询数据库,并将查询结果更新到缓存中。
    • 缓存更新策略:采用合适的缓存更新策略,如缓存失效、缓存更新和缓存删除等。例如,当数据发生更新时,及时更新缓存中的数据,以保证数据的一致性。
  • 异步处理

    • 将一些非关键的数据库操作(如日志记录、统计信息更新等)进行异步处理。可以使用消息队列(如 Kafka、RabbitMQ)将这些操作发送到队列中,由专门的消费者进行处理,避免阻塞主业务流程。
  • 限流和熔断

    • 实现限流机制,限制对数据库的并发访问量,防止过多的请求压垮数据库。可以使用令牌桶算法或漏桶算法来实现限流。
    • 引入熔断机制,当数据库出现故障或响应时间过长时,自动熔断对数据库的访问,返回默认数据或错误信息,避免系统雪崩。

2. 简述 Go 语言中 goroutine 和线程的区别

内存占用

  • 线程:操作系统线程的栈空间通常较大,一般为几兆字节。这是因为线程需要保存大量的上下文信息,以支持复杂的系统调用和切换操作。较大的栈空间会占用较多的系统内存资源,当创建大量线程时,容易导致内存耗尽。

  • goroutine:Go 语言中的 goroutine 栈空间初始时非常小,通常只有几 KB,并且可以根据需要动态增长和收缩。这使得在 Go 程序中可以轻松创建大量的 goroutine,而不会像线程那样消耗过多的内存。

    调度开销

  • 线程:线程的调度由操作系统内核负责,涉及用户态和内核态的切换,这种切换开销较大,因为需要保存和恢复大量的上下文信息。此外,操作系统线程的调度是全局的,会影响整个系统的性能。

  • goroutine:goroutine 的调度由 Go 运行时(runtime)负责,在用户态进行调度,避免了频繁的内核态切换,调度开销较小。Go 运行时采用了 M:N 调度模型,将 M 个 goroutine 映射到 N 个操作系统线程上,提高了并发性能。

    创建和销毁开销

  • 线程:创建和销毁操作系统线程的开销较大,因为涉及到内核资源的分配和释放。例如,创建一个新线程需要分配栈空间、内核数据结构等,销毁线程时需要回收这些资源。

  • goroutine:goroutine 的创建和销毁开销非常小,Go 运行时可以快速地创建和销毁 goroutine,使得程序可以高效地处理大量的并发任务。

    并发性能

  • 线程:由于线程的调度开销和内存占用问题,在处理大量并发任务时,线程的性能会受到限制。过多的线程会导致上下文切换频繁,增加系统的负载,降低并发性能。

  • goroutine:goroutine 由于其轻量级的特点,可以轻松创建大量的并发任务,并且调度开销小,因此在高并发场景下表现出色。Go 语言的并发模型使得开发者可以更方便地编写高效的并发程序。

3. 在 Node.js 中,如何处理异步操作中的错误?

回调函数方式

在传统的异步操作中,通常使用回调函数来处理结果和错误。回调函数的第一个参数通常用于传递错误信息,如果没有错误则为 null。

javascript 复制代码
const fs = require('fs');

fs.readFile('nonexistentfile.txt', 'utf8', (err, data) => {
    if (err) {
        console.error('读取文件时出错:', err);
        return;
    }
    console.log('文件内容:', data);
});

Promise 方式

使用 Promise 可以更好地管理异步操作和错误处理。Promise 有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。可以使用 .then() 方法处理成功的结果,使用 .catch() 方法处理错误。

javascript 复制代码
const fs = require('fs').promises;

fs.readFile('nonexistentfile.txt', 'utf8')
  .then(data => {
        console.log('文件内容:', data);
    })
  .catch(err => {
        console.error('读取文件时出错:', err);
    });

async/await 方式

async/await 是基于 Promise 的语法糖,使异步代码看起来更像同步代码。可以使用 try...catch 块来捕获和处理异步操作中的错误。

javascript 复制代码
const fs = require('fs').promises;

async function readFileAsync() {
    try {
        const data = await fs.readFile('nonexistentfile.txt', 'utf8');
        console.log('文件内容:', data);
    } catch (err) {
        console.error('读取文件时出错:', err);
    }
}

readFileAsync();

全局错误处理

在 Node.js 中,可以使用 process.on('uncaughtException') 来捕获未被处理的同步错误,使用 process.on('unhandledRejection') 来捕获未被处理的 Promise 拒绝。

javascript 复制代码
process.on('uncaughtException', (err) => {
    console.error('未处理的同步错误:', err);
    // 可以进行一些清理操作,然后退出进程
    process.exit(1);
});

process.on('unhandledRejection', (reason, promise) => {
    console.error('未处理的 Promise 拒绝:', reason);
});
相关推荐
吞掉星星的鲸鱼42 分钟前
使用高德api实现天气查询
前端·javascript·css
....4921 小时前
Vue3 + Element Plus + AntV X6 实现拖拽树组件
javascript·vue.js·elementui·antvx6
徐小黑ACG2 小时前
GO语言 使用protobuf
开发语言·后端·golang·protobuf
花花鱼3 小时前
node-modules-inspector 可视化node_modules
前端·javascript·vue.js
·薯条大王4 小时前
MySQL联合查询
数据库·mysql
TDengine (老段)5 小时前
TDengine 中的关联查询
大数据·javascript·网络·物联网·时序数据库·tdengine·iotdb
morris1316 小时前
【redis】redis实现分布式锁
数据库·redis·缓存·分布式锁
再学一点就睡6 小时前
大文件上传之切片上传以及开发全流程之前端篇
前端·javascript
hycccccch6 小时前
Canal+RabbitMQ实现MySQL数据增量同步
java·数据库·后端·rabbitmq
这个懒人7 小时前
深入解析Translog机制:Elasticsearch的数据守护者
数据库·elasticsearch·nosql·translog