Cyan Blog Cyan Blog
首页
  • Java (opens new window)
  • JUC (opens new window)
  • JVM (opens new window)
  • Redis

    • Redis安装 (opens new window)
    • Redis基础 (opens new window)
    • Redis实战 (opens new window)
    • Redis集群安装 (opens new window)
    • Redis分布式缓存 (opens new window)
    • Redis多级缓存 (opens new window)
    • Redis原理 (opens new window)
  • 管理工具

    • Maven (opens new window)
    • Git (opens new window)
  • SSM

    • Spring (opens new window)
    • SpringBoot (opens new window)
    • Mybatis (opens new window)
    • MybatisPlus (opens new window)
  • 微服务

    • Docker (opens new window)
    • RabbitMQ (opens new window)
    • SpringCloud (opens new window)
    • Dubbo (opens new window)
    • MongoDB (opens new window)
    • Zookeeper (opens new window)
  • Java面试题 (opens new window)
  • JUC面试题 (opens new window)
  • JVM面试题 (opens new window)
  • Linux面试题 (opens new window)
  • SQL面试题 (opens new window)
  • Maven面试题 (opens new window)
  • Redis面试题 (opens new window)
  • SSM面试题 (opens new window)
  • SpringCloud面试题 (opens new window)
  • Linux (opens new window)
  • C++ (opens new window)
  • 数据库

    • MySQL (opens new window)
    • NoSQL (opens new window)
  • 软件测试

    • 软件测试 (opens new window)
  • 加密解密 (opens new window)
  • bilibili字幕提取 (opens new window)
  • 道理 (opens new window)
  • 关于博主

    • Github (opens new window)
    • CSDN (opens new window)
  • 关于本站

    • 如何搭建博客网站 (opens new window)
首页
  • Java (opens new window)
  • JUC (opens new window)
  • JVM (opens new window)
  • Redis

    • Redis安装 (opens new window)
    • Redis基础 (opens new window)
    • Redis实战 (opens new window)
    • Redis集群安装 (opens new window)
    • Redis分布式缓存 (opens new window)
    • Redis多级缓存 (opens new window)
    • Redis原理 (opens new window)
  • 管理工具

    • Maven (opens new window)
    • Git (opens new window)
  • SSM

    • Spring (opens new window)
    • SpringBoot (opens new window)
    • Mybatis (opens new window)
    • MybatisPlus (opens new window)
  • 微服务

    • Docker (opens new window)
    • RabbitMQ (opens new window)
    • SpringCloud (opens new window)
    • Dubbo (opens new window)
    • MongoDB (opens new window)
    • Zookeeper (opens new window)
  • Java面试题 (opens new window)
  • JUC面试题 (opens new window)
  • JVM面试题 (opens new window)
  • Linux面试题 (opens new window)
  • SQL面试题 (opens new window)
  • Maven面试题 (opens new window)
  • Redis面试题 (opens new window)
  • SSM面试题 (opens new window)
  • SpringCloud面试题 (opens new window)
  • Linux (opens new window)
  • C++ (opens new window)
  • 数据库

    • MySQL (opens new window)
    • NoSQL (opens new window)
  • 软件测试

    • 软件测试 (opens new window)
  • 加密解密 (opens new window)
  • bilibili字幕提取 (opens new window)
  • 道理 (opens new window)
  • 关于博主

    • Github (opens new window)
    • CSDN (opens new window)
  • 关于本站

    • 如何搭建博客网站 (opens new window)
  • 简历项目
  • Java面试题

  • 后端开发
  • 数据库面试题
  • Maven
  • MyBatis面试题
  • Spring面试题
  • SpringBoot面试题
  • SpringCloud面试题

  • Redis面试题

  • 设计模式
  • 中间件

  • 场景题
  • Other

  • Random

  • 项目面试题

    • 黑马点评面试题
      • 为什么使用Redis+Token来代替session
      • 为什么使用Redis+Token而不用JWT
      • 缓存穿透
      • 缓存雪崩
      • 缓存击穿
      • 为什么使用Redis生成唯一ID,为什么不选择数据库子自增ID、雪花算法呢
      • 为什么使用乐观锁不用悲观锁
      • Redis实现的分布式锁
      • Redisson解决一人一单的问题
      • 阻塞队列(Stream/RabbitMQ)异步完成数据库库存扣减和订单生成
      • RabbitMQ异步完成数据库库存扣减和订单生成
      • ZSET
      • SET
    • 苍穹外卖
    • +
    • 项目linux部署
  • 面试
  • 项目面试题
2025-04-18
0
0
目录

黑马点评面试题


使用Redis+Token解决了在集群模式下的Session共享问题,使用拦截器实现用户的登录校验和权限刷新

# 为什么使用Redis+Token来代替session

由于项目模拟了tomcat集群,用户的请求可能被不同的服务器处理。session是存储在单个服务器的内存中,其他服务器无法访问该Session,导致用户状态丢失,而如果使用服务器间的Session复制,会有延迟,导致数据的不一致,而且Session的复制会占用额内存,影响服务器的性能。

使用Redis+Token可以根据Token为key将用户信息存储在Redis中,所有服务器都可以共享Redis中的用户信息,从而实现SSO。

# 为什么使用Redis+Token而不用JWT

Redis+Token是有状态,用随机的UUID生成Token作为Key,依赖Redis存储用户信息,选择Redis+Token可以在用户登出或者有异常行为时,主动删除Redis中的Token来结束会话

不用JWT主要是因为JWT无法提前失效,只能将其加入Redis的黑名单中,在拦截器中拦截,但是也会违背JWT无状态的特性;而且JWT无法续期,我们的项目主要是用户在每次访问时会续期,如果用JWT,续期需要重新生成JWT,会导致有过多的JWT,增加管理负担;而且JWT通常UUID大,会增加网络传输负担。


通过Redis缓存空数据解决了缓存穿透问题,结合动态TTL机制防止缓存雪崩,缓存失效时使用互斥锁解决缓存击穿

# 缓存穿透

缓存穿透是

# 缓存雪崩

# 布隆过滤器的实现原理

# 缓存击穿

解决方法:互斥锁从数据库中获取数据、使用逻辑过期,数据过期通过异步获取数据,并发线程返回旧数据。

# 为什么用逻辑过期而不用互斥锁

因为我们缓存的数据是商户的信息,一致性要求不高,使用逻辑过期可以保留redis中缓存的数据,数据过期时开启一个异步线程从数据库中获取数据更新,而并发线程可以直接返回缓存的旧数据。其实也可以使用互斥锁,因为从数据库获取商户信息的过程也不费时间,不会导致可用性降低,如果数据重建过程费时间才需要根据一致性要求决定选择方案。


使用Redis实现全局唯一ID生成,并通过乐观锁(CAS机制)进行库存控制,解决超卖问题。

# 为什么使用Redis生成唯一ID,为什么不选择数据库子自增ID、雪花算法呢

因为Redis是基于内存的,适合高并发,可以保证高可用、高性能、唯一性, 而数据库性能瓶颈明显,且分库分表时维护自增ID复杂度高, 雪花算法需要考虑时钟回拨(回拨时id会归零),而且不同机器之间系统时钟可能存在微小偏差,可能导致id不是有序的

# 为什么使用乐观锁不用悲观锁

在高并发情况下,悲观锁竞争激烈,会轮流竞争锁后才进行库存判断减库存,越后的线程阻塞越久,体现在前端显示加载中,用户体验差。

而乐观锁我们是利用了数据库的行锁,通过SQL语句来实现判断和减库存的原子性,这样,只要库存不够,后面的线程都会直接返回库存不足

也就是说乐观锁锁的粒度比悲观锁小,就是悲观锁是所有线程在获取互斥锁的时候串行化,而乐观锁是在数据库更新操作时利用行锁实现串行化,

但是这样对数据库压力大,QPS(吞吐量/秒请求量)有限,所以后面我们使用了Redis来优化,将秒杀优惠券库存预热到Redis中,通过lua脚本来实现判断资格、减库存操作的原子性,由于Redis是基于内存的,能提供更高的QPS

# 高并发下CAS失败率高,如何优化?

我们的SQL语句是通过库存大于0的条件,不是根据版本号或者库存数量来判断的,保证了先来先得,先操作数据库的线程先成功,只有库存不足才会失败,而不会因为版本号不匹配就失败。

不过如果CAS失败率高,可以使用LongAdder类来进行优化,LongAdder类内部维护一个base值和 Cell[] 数组,刚开始会直接CAS修改base值,如果CAS失败次数过多会进行分片,base值被分配到每个Cell中,每个线程优先修改自己对应的 Cell 分片,只有线程间操作同一个 Cell 时才会触发少量 CAS 操作,


使用Redisson分布式锁解决一人一单的问题,Redis+Lua 脚本实现秒杀活动的抢单业务,并使用阻塞队列(Stream/RabbitMQ)异步完成数据库库存扣减和订单生成

# Redis实现的分布式锁

# 如何解决分布式锁误删的

分布式锁误删是因为设置了锁的过期时间,当获得锁的线程被阻塞时,由于锁过期,其他线程获得到锁,但是原来被阻塞的线程又恢复执行完业务后将别的线程的锁释放。

我们是通过Redis的hash结构,将当前获得锁的线程ID存入hash的值中,每次释放锁之前会判断一些锁是否为当前线程所有。

但是在判断和删除锁之间不是原子性的,并发下还是会有误删的可能,所以我们使用了Lua脚本来保证操作的原子性,

# 使用Redisson的优势

Redisson提供了可重入、非阻塞重试、超时续约(看门狗机制)等功能,而且释放锁是原子操作,不需要通过Lua脚本实现防误删

# Redisson解决一人一单的问题

使用了Redisson的分布式锁,保证查询用户订单和创建订单操作的安全性,确保用户不能重复下单,实现一人一单

# Redis+Lua脚本实现的秒杀业务

通过Lua脚本实现库存检查、一人一单判断、完成抢单操作的原子性,再将下单业务放入阻塞队列,利用独立线程异步下单

# 阻塞队列(Stream/RabbitMQ)异步完成数据库库存扣减和订单生成

基于阻塞队列的异步秒杀存在哪些问题?

  • 内存限制问题
  • 数据安全问题

# RabbitMQ异步完成数据库库存扣减和订单生成

使用rabbitMQ代替阻塞队列可以看项目优化

通过消息队列由一个消费者处理订单业务,通过持久化、消费者重试机制保证消息的消费,如果三次失败会进入专门的队列中由人工处理


使用Redis的ZSet实现了点赞排行榜功能, 使用Set集合实现关注、共同关注功能;

# ZSET

以时间为score,实现点赞排行榜功能,显示最早点赞的TOP5

# SET

将用户关注的好友id放入Redis中,通过求交集获取共同关注的好友

#面试#Redis
上次更新: 2025/5/7 00:24:40
随机题01
苍穹外卖

← 随机题01 苍穹外卖→

最近更新
01
项目优化
05-06
02
项目优化
05-06
03
延迟消息
05-05
更多文章>
Theme by Vdoing | Copyright © 2025-2025 Cyan Blog
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式