【后端开发面试题】每日 3 题(六)
✍个人博客:Pandaconda-CSDN博客
📣专栏地址:https://blog.csdn.net/newin2020/category_12903849.html
📚专栏简介:在这个专栏中,我将会分享后端开发面试中常见的面试题给大家~
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪
1. 在 Spring Boot 中,如何实现定时任务?
在 Spring Boot 中实现定时任务有多种方式,这里主要介绍常用的两种:
使用 @Scheduled 注解
@Scheduled 是 Spring 框架提供的一个注解,可用于方法上,将该方法标记为定时任务。使用步骤如下:
- 在主应用类上添加 @EnableScheduling 注解,开启定时任务功能。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- 创建一个组件类,在其中定义带有 @Scheduled 注解的方法。
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class ScheduledTasks {
// 固定延迟,上一次任务执行结束后,延迟 5000 毫秒执行下一次任务
@Scheduled(fixedDelay = 5000)
public void fixedDelayTask() {
System.out.println("Fixed delay task executed.");
}
// 固定速率,每隔 3000 毫秒执行一次任务
@Scheduled(fixedRate = 3000)
public void fixedRateTask() {
System.out.println("Fixed rate task executed.");
}
// 使用 cron 表达式,每天凌晨 2 点执行任务
@Scheduled(cron = "0 0 2 * * ?")
public void cronTask() {
System.out.println("Cron task executed.");
}
}
使用 SchedulingConfigurer 接口
如果需要更灵活地配置定时任务,可以实现 SchedulingConfigurer 接口。
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskExecutor());
taskRegistrar.addFixedRateTask(() -> {
System.out.println("Custom scheduled task executed.");
}, 5000);
}
public Executor taskExecutor() {
return Executors.newScheduledThreadPool(10);
}
}
2. redis 中,如何实现分布式锁?
基本思路
- 使用 SET 命令设置一个特定的键值对,同时设置过期时间,确保即使持有锁的客户端崩溃,锁也能在一定时间后自动释放。
- 通过判断 SET 命令的返回结果来确定是否成功获取锁。
- 释放锁时,需要确保只有持有锁的客户端才能释放锁,通常使用 Lua 脚本来保证操作的原子性。
示例代码(Python + Redis)
import redis
import time
# 连接 Redis
redis_client = redis.Redis(host='localhost', port=6379, db=0)
def acquire_lock(lock_name, acquire_timeout=10, lock_timeout=10):
end_time = time.time() + acquire_timeout
while time.time() < end_time:
# 使用 SET 命令尝试获取锁
result = redis_client.set(lock_name, "locked", nx=True, ex=lock_timeout)
if result:
return True
time.sleep(0.1)
return False
def release_lock(lock_name):
# 使用 Lua 脚本释放锁,保证操作的原子性
lua_script = """
if redis.call("get", KEYS[1]) == ARGV[1] then
return redis.call("del", KEYS[1])
else
return 0
end
"""
result = redis_client.eval(lua_script, 1, lock_name, "locked")
return result
# 使用示例
lock_name = "my_distributed_lock"
if acquire_lock(lock_name):
try:
print("获取到锁,开始执行任务...")
time.sleep(5) # 模拟任务执行
finally:
release_lock(lock_name)
print("任务执行完毕,释放锁。")
else:
print("未能获取到锁。")
3. 简述如何在 MySQL 中实现数据库备份与恢复
备份
-
使用 mysqldump 工具(逻辑备份)
mysqldump 是 MySQL 自带的一个命令行工具,可用于备份数据库、表或整个 MySQL 实例。
- 备份单个数据库:
其中,username 是 MySQL 用户名,database_name 是要备份的数据库名,执行该命令后会提示输入密码,输入正确密码后,会将指定数据库的结构和数据备份到 backup.sql 文件中。mysqldump -u username -p database_name > backup.sql
- 备份单个数据库:
-
备份多个数据库:
mysqldump -u username -p --databases database1 database2 > backup.sql
-
只备份数据库结构(不包含数据):
mysqldump -u username -p --no-data database_name > structure_backup.sql
-
物理备份
可以直接复制 MySQL 数据目录下的文件来进行物理备份,但这种方法需要停止 MySQL 服务,且对文件的管理和恢复要求较高。一般适用于 InnoDB 存储引擎,可使用 xtrabackup 工具进行热备份。
恢复
-
使用 mysql 命令恢复(逻辑备份恢复)
如果之前使用 mysqldump 进行了备份,可以使用 mysql 命令将备份文件恢复到数据库中。
mysql -u username -p database_name < backup.sql
该命令会将 backup.sql 文件中的 SQL 语句执行,从而恢复数据库的结构和数据。
-
物理备份恢复
对于物理备份,需要将备份的文件复制到 MySQL 数据目录下,并根据具体情况进行配置和启动 MySQL 服务。如果使用 xtrabackup 进行备份,可使用其提供的恢复命令进行恢复。例如:
xtrabackup --prepare --target-dir=/path/to/backup xtrabackup --copy-back --target-dir=/path/to/backup