Redis面试合集

概念

Redis是一种key-value型非关系数据库。

特点:

1、速度快,存在于内存中,类似于HashMap,HashMap的操作和查找的时间复杂度都是O(1)

2、支持丰富的数据类型,包括字符串、哈希、列表、集合、有序集合五种数据类型。

3、支持事务,操作都是原子性的,要么都执行要么都不执行。

4、memcached所有值都是简单的字符串,Redis可以持久化数据(RDB、AOF)。

过期策略

定时过期(定时器)、惰性过期(访问时判断)、定期过期(每隔一段时间扫描)

如何保证Redis都是热点数据?(数据回收)

最近最少使用/随机/最近最少使用/更早过期时间的

持久化(RDB和AOF)

RDB:一定时间将内存数据以快照形式保存到硬盘dump.rdb。通过save参数配置快照周期。

保存成一个文件,更安全。数据量大时,启动效率更高。子进程单独进行持久化保证Redis高性能。持久化过程中发生事故数据容易丢失。

AOF:将Redis执行命令写到单独日志文件中。

数据安全。通过append追加到日志,即使服务器宕机也可通过redis-check-aof工具解决数据一致问题。AOF文件更大,恢复更慢,启动效率低。

保证Redis和MYSQL数据一致

缓存单删: 更新DB前先删除缓存,再更新库,查询缓存无数据则直接访问DB。
延时双删: 为了解决缓存单删,在高并发读情况下数据不一致问题。操作数据前,先删除缓存,接着操作DB,然后延迟一段时间,再删除缓存。

定时+增量更新: 主要是利用库里行数据的更新时间字段+定时增量查询。具体为:每次更新库里的行数据,记录当前行的更新时间;然后把更新时间做为一个索引字段(加快查询速度)

定时任务: 每隔几秒,比如5秒(自定义),把库里最近5秒钟的数据查询出来,写入缓存并记录查询结束时间。查询过程和放入缓存都是单线程不存在并发问题。每次同步成功,下次执行把结束时间作为开始时间,当前时间作为结束时间实现增量查询。

优点:架构简单、逻辑和业务解耦、依赖少,最多加个分布式定时任务或者Redis分布式锁。

监听binlog+MQ: 监听MYSQL binlog把数据库的更新插入删除操作通过MQ同步给下游消费者,下游拿到日志和业务数据再放入缓存。

优点:缓存和业务解耦,减少业务代码的侵入性。

缺点:技术和架构复杂,中间件的运维,引入MQ后带来的问题,比如数据乱序:同一条数据先发后至,后发先至到达消费者,通过redis lua+数据的时间戳比较方案,解决并发问题和数据乱序问题

redis缓存三兄弟问题

PHP+Redis分布式锁

Redis分布式锁是通过线程锁来实现,同时只允许一个线程执行,其他线程进入等待状态。

优点:降低MySQL压力,比队列的并发量高。缺点:线程需要排队等待,并发量也不是特别高。

php 复制代码
$key = "test:lock:".$id;$uuid = Uuid::uuid1()->getHex();try {
    $ret = Redis::set($key, $uuid, 'EX', 10, 'NX');
    if (!$ret) {
        usleep(10);
        return $this->test($id);
    }
    $stock = Skill::query()->where('id', $id)->value('stock');
    if ($stock > 0) {
        Skill::query()->where('id', $id)->decrement('stock');
        $msg = '抢购成功';
    } else {
        $msg = '库存不足,抢购失败';
    }
    if (Redis::get($key) == $uuid) {
        Redis::del($key);
    }
    return $msg;} catch (\Exception $exception) {
    return '抢购失败';}

PHP+Redis乐观锁

Redis的乐观锁就是借助Redis事务和watch监控,采用事务打断的方式实现

优点:并没有锁定任何资源,多线程可以并行。缺点:这是PHP层面的控制,而PHP是有性能瓶颈的。

php 复制代码
$key = 'stock:'.$id;Redis::watch($key);$stock = Redis::get($key);
if (is_null($stock)) {
 return '没有商品';
}
if ($stock == 0) {
 return '库存不足';
}
Redis::multi();Redis::decr($key);
$res = Redis::exec();
if ($res) {
 Skill::query()->where('id', $id)->decrement('stock');
 return '抢购成功';
} else {
 return '抢购失败';}

Nginx结合Lua做桶限流+Redis乐观锁(最优方案)

这种方案是最优方案,直接绕过应用层,在接入层实现限流和防止超卖的操作,只消耗很少的服务器性能,但是可抗并发量级特别大,性能上远超上述几种方案。

逻辑分析:先使用 Nginx+Lua 漏桶算法过滤掉大部分请求,再使用Lua连接Redis,使用Redis乐观锁的方式控制库存。假设只有10个秒杀商品,那这里只保留10个请求进入应用层(PHP和MysqL),应用层不需要进行其他操作,直接操作数据库就可以。

项目应用

1、ERP的商品报表模块,API接口处理好数据,序列化成字符串后给定过期时间存储到Redis中。

2、序列号生成器,我们又很多单号,像订单、生产、调拨,但需求层面要求我们的订单尾号按照顺序来,我们生成器中会根据类别将对应序列号hash进行自增。

3、订单提取模块,

持续更新,未完待续~

相关推荐
KIDULT°6 小时前
MySQL系列 (1):数据库原理
运维·数据库·mysql·云计算
我不是程序员三三7 小时前
透明加密软件偶发解密异常排错实录:文件时能打开时乱码
数据库·域智盾
snhna7 小时前
向量数据库深度实战:从 HNSW 到 pgvector、Milvus 选型与 RAG 落地
数据库·人工智能·python·postgresql·milvus
天行健,君子而铎7 小时前
数据分类分级的范式转换:从规则匹配到场景化高准确率一键部署
网络·数据库·安全
牛战士coding8 小时前
MySQL 读写分离完整链路:主从复制、多数据源与 @DS 路由
数据库·mysql
goehou9 小时前
MCP 查数实战:让 LLM 安全地查数据库(只读账号、SQL 校验、参数漂移)
数据库·ai·llm·教程·mcp·function calling
我不会插花弄玉9 小时前
7.函数【由浅入深-MySQL】
android·数据库·mysql
考研保研资料分享9 小时前
新闻传播保研经验:中传预推免面试、广告学代表作与实习准备(2025)
面试·职场和发展
周小董9 小时前
[1369]Windows上安装PostgreSQL
数据库·windows·postgresql
一只积极向上的小咸鱼11 小时前
第一性原理思考:从拆解问题到用实验检验答案
数据库