设计模式
工厂模式
将对象的创建逻辑封装在一个工厂类中,而不是直接实例化,使得创建对象的过程与使用对象的过程分离
使用场景:
- 日志记录:选择记录位置 本地、网络存储
- 数据库访问:切换数据库
- 协议选择
单例模式
一个类只有一个实例,并且提供访问这个对象的方式
- 生成唯一ID
- 计数器
代理模式
通过引入一个代理对象来控制对原对象的访问,代理对象在客户端和目标对象之间充当中介,负责将客户端的请求转发给目标对象,同时在转发请求前后进行额外的处理。
- AOP
- 火车票代售
与适配器模式区别:适配器改变接口,代理不改变
与装饰器模式区别:装饰器用于增强功能,代理用于控制访问
适配器模式
充当两个不兼容接口之间的桥梁,通过适配器将一个类的接口转换成客户期望的另一个接口,使原本不能一起工作的类能够协同工作
- 跨平台运行
- xml转json
装饰器模式
向一个现有的对象添加新功能,同时不改变其结构
模板模式
抽象类定义方法模板,子类按需重写方法实现,调用方式按抽象类定义执行
场景题
设计秒杀
静态资源放cdn
F5
↓
nginx
↓
open feign
↓ sentinel和mq 限流
服务
预热:把商品放入redis
库存:lua脚本操作
放重:setnx token或IP同一时间一个有效
分布式锁:请求原子性
↓
数据库读写分离
订单超时自动取消
JDK自带延迟队列 DelayQueue 简单 不适合分布式
MQ延时消费 MQ接到消息会在指定时间通知消费端去处理 支持分布式 24小时内
redis过期监听 不可靠
定时任务分布式批处理 批量捞取
防重复下单
网页按钮置灰
redis setnx 过期3-5s 用户token+商品URL+key(下单)
防刷单
用风控
提高门槛:实名认证,消费门槛
限制用户参与、中奖次数
根据用户历史行为,提供不同的优惠
限流,自动扩容伸缩
黑名单
大数据用户画像
扫码登录
- 生成QR:生成二维码ID,保存二维码ID状态到redis,设置过期时间,用轮询或长连接查询二维码状态
- 扫码:APP扫码,校验用户token,变更二维码状态,绑定二维码ID和临时token
- 确认登录:检验临时token,执行登录,生成PC token
redis 记录连续登录几天
redis bitmap
key:日期 位:用户ID
key:用户 位:日期
一亿个redis key 统计共同好友
SINTERSTORE 取交集
Neo4j
Hbase+Hadoop
拆微服务
- 微服务之间不要有业务交叉
- 微服务之间用接口访问
- 高内聚 低耦合
DDD 面对软件复杂之道
MQ保证消息不丢失
生产者发送:发送+回调 事务消息 手动事务
主从同步:1.同步-收到消息立即同步到从节点 2.异步-收到消息先响应生产者,后同步从节点
写入磁盘:同步、异步刷盘
消费者消费:事务完成后,提交offset
设计一个高效的会议室预订方案,快速返回一间空的会议室
数据结构
使用HashMap<Integer, List
判断一个会议室是否空闲
- 新请求的开始时间 >= 已有时间段的结束时间
- 新请求的结束时间 <= 已有时间段的开始时间
对每个会议室的预定时间进行排序,利用 二分查找 提高查询效率
如何保证redis和mysql的一致性
延迟双删策略
- 先删除缓存
- 更新数据库
- 等待一段时间,再次删除缓存(确保脏数据不会回写)
基于MySQL binlog订阅
- MySQL主库更新数据后,binlog记录变更日志
- Redis监听binlog,并同步更新缓存
事务+消息队列(MQ)保证最终一致性
- 数据库更新和消息队列发送放入同一个事务,保证数据库变更后一定会有一个同步消息。
- 消息队列消费后,再更新Redis,保证最终一致性。
小内存如何排序大数据
分组查询数据,每一组单独排序后存入文件,同时读取各组文件,将每组文件的数据按顺序放入败者树中,每一个叶子节点对应一个文件,若该节点的数据胜出,则读取下一个数据,胜出的数据放入一个新文件,直到各组文件读取完毕。