面试官:Redis 中大 Key 怎么删除?
首先来看一下该岗位的职责和要求:
岗位职责
负责公司旗下产品的全新需求开发
负责公司中台系统管理系统开发
开发临时性工具和数据处理工作
设计开发可复用模块,提高开发效率节省维护成本
保质保量的完成上级领导安排的技术相关工作
任职要求
本科以上学历,计算机相关专业优先,3 年左右 Golang 开发经验,有 PHP 转 Go 项目经验者优先
熟练掌握 Golang/PHP 语言,熟悉至少一种 Golang 框架
熟练掌握关系型数据库 Mysql 及部分 Nosql
熟练掌握 Redis 缓存技术及 Rabbitmq 等常用消息队列
熟悉 Svn/Git,熟悉 Shell,Python 等至少一种脚本语言
基础扎实,对数据结构有较为深刻的理解
具备良好的分析解决问题能力,能独立承担任务和有系统进度把控能力,注重结果导向
良好的代码书写、注释习惯,能写出高质量的代码,对自己开发的代码负责
面试问题
自我介绍
项目介绍
八股
1. Redis 大 key 删除
问题背景:在 Redis 中,删除大 key(如大型哈希表、列表、集合或有序集合)时,直接使用DEL
命令会导致 Redis 阻塞,影响性能。
解决方案:
使用
UNLINK
命令:UNLINK
命令从 Redis 4.0 开始引入,它的工作原理是异步删除 key。UNLINK
命令会立即将 key 从数据库中删除,但实际的内存释放工作会在后台线程中进行,不会阻塞主线程。示例:
分批删除:
使用
SCAN
、HSCAN
、SSCAN
、ZSCAN
等命令分批删除大 key 中的元素,减少每次操作的负载。示例:
选择在业务低峰期执行删除操作:
在业务低峰期执行删除操作,可以减少对正常业务的影响。
例如,可以选择在夜间或周末进行大 key 的删除操作。
使用
RENAME
命令:先将大 key 重命名,使其不再被业务访问,然后再逐步删除。
示例:
2. MySQL 什么时候会回表
问题背景:在 MySQL 中,回表是指在查询过程中,如果索引不能完全覆盖查询所需的所有列,MySQL 需要通过主键索引回表获取完整的行数据。
具体场景:
非覆盖索引:当查询条件命中了索引,但查询结果需要的列不在索引中时,MySQL 需要回表获取这些列的数据。
示例:
非唯一索引:即使查询条件能够唯一确定一行,但如果使用的是非唯一索引,MySQL 也需要回表确认这一行是否满足查询条件。
示例:
多表联接:在多表联接查询中,如果使用了非覆盖索引,MySQL 可能需要回表获取额外的数据。
示例:
3. MySQL explain type 类型 ref 和 index 的区别
问题背景:EXPLAIN
命令用于显示 MySQL 如何执行查询计划,其中type
列显示了访问类型。
具体区别:
ref:
表示使用了非唯一索引或唯一索引的一部分。
对于每个索引值,MySQL 需要进行一次查询,以找到符合条件的行。
适用于等值查询(如
=
、IN
、<=>
)。示例:
index:
表示全索引扫描,即 MySQL 会遍历整个索引来查找匹配的行。
这通常用于索引覆盖查询,即查询的所有列都包含在索引中,无需回表。
适用于范围查询(如
>
、<
、BETWEEN
、LIKE
)。示例:
4. 对已经关闭的 chan 进行读写会怎么样?
问题背景:在 Go 语言中,channel 是一种同步机制,用于在 goroutine 之间传递数据。
具体行为:
读取已关闭的 channel:
从已关闭的 channel 读取数据时,会立即返回零值,并且关闭标志位会被设置,表明 channel 已经关闭。
向已关闭的 channel 写入数据:
向已关闭的 channel 写入数据会触发 panic,因为不允许向已关闭的 channel 写入数据。
5. 如何保证多个 goroutine 的全部执行
问题背景:在 Go 语言中,goroutine 是轻量级的线程,用于并发执行任务。确保多个 goroutine 全部执行完毕是常见的需求。
具体方法:
使用
sync.WaitGroup
:在启动 goroutine 前增加 WaitGroup 的计数,goroutine 完成后调用 Done()方法减少计数,最后在主 goroutine 中调用 Wait()等待所有 goroutine 完成。
使用通道:
可以创建一个通道,每个 goroutine 完成任务后向通道发送一个信号,主 goroutine 接收这些信号直到所有 goroutine 完成。
使用上下文:
通过 context 管理 goroutine 的生命周期,可以取消或超时等待。
6. string 转 bytes 是否会重新分配内存
问题背景:在 Go 语言中,字符串是不可变的,而字节切片是可变的。
具体行为:
转换过程:
[]byte(s)
将字符串转换为字节切片时,通常不会重新分配内存,而是共享字符串的底层内存。例如:
修改字节切片:
如果对字节切片进行了修改,会触发内存拷贝,因为字符串是不可变的。
例如:
7. goframe 和 gozero 的区别
问题背景:goframe 和 gozero 都是 Go 语言的开发框架,但它们有不同的设计理念和应用场景。
具体区别:
goframe:
特点:企业级开发框架,提供了一整套的 Web 开发、数据库操作、缓存、日志等组件。
适用场景:适合快速构建企业级应用,特别是需要复杂功能和高性能的应用。
优势:
完善的文档和社区支持。
提供丰富的中间件和插件。
支持多种数据库和缓存系统。
gozero:
特点:轻量级的微服务框架,专注于微服务架构,提供了 API 生成器、服务注册与发现、配置中心等功能。
适用场景:适合构建微服务应用,特别是需要高可扩展性和高可用性的应用。
优势:
轻量级,启动速度快。
内置了服务发现和配置管理功能。
支持自动代码生成,提高开发效率。
8. 逃逸分析有哪些场景
问题背景:逃逸分析是编译器的一种优化技术,用于确定变量的作用域和生命周期,以决定变量是否可以在栈上分配,从而减少堆上的内存分配,提高程序性能。
具体场景:
全局变量:
作用域超出函数范围的变量。
函数返回值:
如果函数返回了局部变量的引用或指针,该变量需要逃逸到堆上。
闭包:
如果一个函数返回了一个闭包,而闭包引用了外部函数的局部变量,那么这些变量需要逃逸到堆上。
例如:
循环中的变量:
在循环中创建的变量,如果在循环外被引用,也会逃逸到堆上。
9. Kafka 如何实现有序
问题背景:Kafka 是一个分布式流处理平台,用于构建实时数据管道和流应用。
具体实现:
分区:
每个主题可以被划分为多个分区,每个分区内的消息是有序的。
生产者可以指定消息的分区键,确保相同键的消息被发送到同一个分区。
单一消费者:
对于每个分区,如果有多个消费者订阅了同一个消费者组,那么每个分区的消息只会被一个消费者消费,确保了消息的顺序。
事务:
Kafka 支持事务,可以确保消息的生产者发送的消息按照发送顺序被提交。
10. 项目中常用的设计模式
问题背景:设计模式是解决常见问题的模板,可以帮助开发者编写更高效、更可维护的代码。
单例模式:
描述:确保一个类只有一个实例,并提供一个全局访问点。
优点:节省资源,避免重复创建对象。
缺点:单例对象通常是全局可访问的,容易引起耦合。
工厂模式:
描述:提供一个创建对象的接口,但由子类决定实例化哪一个类。
优点:将对象的创建和使用分离,提高代码的灵活性。
缺点:增加了代码的复杂性。
观察者模式:
描述:定义了对象之间的一对多依赖关系,当一个对象的状态改变时,所有依赖于它的对象都会得到通知。
优点:实现了对象之间的松耦合。
缺点:如果观察者数量过多,通知过程可能会变得复杂。
策略模式:
描述:定义一系列算法,把它们一个个封装起来,并且使它们可以互相替换。
优点:算法的变化独立于使用算法的客户。
缺点:增加了代码的复杂性。
装饰者模式:
描述:动态地给一个对象添加一些额外的职责,而不必修改对象结构。
优点:增加了代码的灵活性和可扩展性。
缺点:增加了代码的复杂性。
代理模式:
描述:为其他对象提供一种代理以控制对这个对象的访问。
优点:增加了安全性和灵活性。
缺点:增加了代码的复杂性。
欢迎关注 ❤
我们搞了一个免费的面试真题共享群,互通有无,一起刷题进步。
没准能让你能刷到自己意向公司的最新面试题呢。
感兴趣的朋友们可以加我微信:wangzhongyang1993,备注:infoq 面试群。
评论