场景题
# 单点登录这块怎么实现的
1,先解释什么是单点登录
单点登录的英文名叫做:Single Sign On(简称SSO)
2,介绍自己项目中涉及到的单点登录(即使没涉及过,也可以说实现的思路)
3,介绍单点登录的解决方案,以JWT为例
I. 用户访问其他系统,会在网关判断token是否有效
II. 如果token无效则会返回401(认证失败)前端跳转到登录页面
III. 用户发送登录请求,返回浏览器一个token,浏览器把token保存到cookie
IV. 再去访问其他服务的时候,都需要携带token,由网关统一验证后路由到目标服务
# 权限认证是如何实现的
- 后台管理系统的开发经验
- 介绍RBAC权限模型5张表的关系(用户、角色、权限)
- 权限框架:Spring security
# 上传数据的安全性你们怎么控制?
- 使用非对称加密(或对称加密),给前端一个公钥让他把数据加密后传到后台,后台解密后处理数据
- 传输的数据很大建议使用对称加密,不过不能保存敏感信息
- 传输的数据较小,要求安全性高,建议采用非对称加密
# 如何判断几十亿个数 是否存在某个数?
对于几十亿个数的查找问题
- “对于几十亿个数的查找问题,首先可以考虑直接查找,但时间复杂度是O(n),效率较低。
- 如果数据允许排序,可以先排序再使用二分查找,排序的时间复杂度是O(n log n),而查找的时间复杂度是O(log n),但整体性能仍然可能不够理想。
- 为了提高查找效率,可以考虑使用哈希表或布隆过滤器,哈希表的查找时间复杂度是O(1),但需要较大的内存空间;而布隆过滤器则是一种空间效率更高的数据结构,不过布隆过滤器会有误判,只能用于快速判断某个数不存在或可能存在。
- 如果数据量太大,无法一次性加载到内存中,可以采用分片处理方法,将数据分成多个小文件进行处理。如果数据存储在分布式系统中,可以使用分布式计算框架(如Hadoop或Spark)来并行处理查找请求。
- 此外,如果数据范围有限且密集,可以使用位图法来节省空间,因为每个数只需要一个bit来表示。但位图法需要预先将数据加载到位图中,适合数据范围较小的场景。
- 对于频繁查找的场景,可以考虑使用缓存或预处理(如建立索引)来优化查找效率。
# 如何防止超卖
最简单的方式是直接通过SQL语句判断库存大于0,通过数据库行锁,完成查询扣库存的原子性操作,实现防止超卖,适用于用户、并发量小的情况。 并发大的,可以将库存预热到redis中,通过Lua脚本查询库存、通过用户ID作为Key来避免重复下单、扣库存、生成订单号,再通过消息队列异步操作数据库和具体订单的生成
# 设计30分钟未支付自动取消功能(考察延时队列实现)
有多种方式可以实现
- 对数据库轮询,通过定时任务扫描数据库,取消超时订单,但是对数据库压力大,而且有延迟性
- 使用时间轮算法,可以使用Netty 的HashedWheelTimer,按时间槽调度任务,这种方式实现代码简单,但是缺点是重启后消息会丢失。
- 使用RabbitMQ的延迟队列,可以设置消息的存活时间,如果超时未消费就会变成死信,进入死信队列,再通过从死信队列中拿消息进行处理。由RabbitMQ保证消息的不丢失和不重复消费
# 高并发下如何保证Redis和MySQL库存数据一致性?
若允许短暂不一致,采用 Canal 异步监听数据库binlog日志 并延迟删除缓存 + 如果删除失败,MQ异步重试 实现最终一致。 若要求强一致,使用 Redisson 实现的读写锁,在读的时候添加共享锁,当我们更新数据的时候,添加排他锁。
# 用户连续点击支付按钮,如何保证只扣款一次?
首先前端肯定是要设置按钮只允许点击一次,后端可以通过Redis,使用setnx,将当前用户和商品id为key来保证生成订单业务只执行一次。
如果是用户重复支付,可以在订单支付成功回调时先判断订单是否已经支付,支付过执行退款业务。
# 千万级数据表如何优化深分页?(ES scroll vs游标方案对比)
Elasticsearch Scroll:适合离线大批量拉取,牺牲实时性换取吞吐量。
数据库游标分页:适合用户实时操作,需业务侧配合传递游标参数。
避免深分页
# MySQL到ES的数据一致性如何保障?(Binlog+CDC方案)
# 如何防止恶意用户批量调用注册接口
# AQ
公司对这个岗位的期待是什么,您认为我和这个期待还有哪些差距
个人优势和未来规划