一问一答之中间件
消息队列
mq就是消息队列,在队列中的成为生产者,取数据的叫消费者
为什么要用
解耦
:比如对象A依赖B,C,如果不用会频繁改动源码,不便于维护,如果将A与其余对象之间加入消息队列,A只需要给mq,其余对象也只需要从mq中取。不需要在改A的代码
异步
:假设A调B,C,D的方法,总时长为A+B+C+D,如果A为核心业务,其余的为非核心,用户体验会很不好,主要的已经完了,将非核心业务交给mq去做,加大吞吐量和用户体验
削峰/限流
:请求多的时候,每台服务器承受能力有限,如果过多,容易把系统搞掉,这时候消息队列可以将多余请求加入队列中,来避免这种情况
什么是redis
c语言编写,高性能nosql数据库,基于内存,读写快,可做缓存,分布式锁
为什么用redis
传统的关系型数据库无法满足所有的场景,无法应对并发高的情况,容易将db打崩。
查的快,并发高,支持持久化
为什么快:
- 内存操作,访问数据库是从硬盘读取的
- 基于hashmap的数据结构
- 单线程避免多线程的上下文切换,不用考虑线程竞争,不用考虑锁的问题
- 使用多路复用IO模型,非阻塞IO
单线程不应该很耗时吗?会fork子进程来处理,不影响当前线程,保证性能
redis的数据结构
string、list、hash、set、zset、HyperLogLog、Geo、Pub/Sub。
- String:字符串,简单的k-v,v可以是字符也可以是数字,v是2进制安全的,可以存图片或序列化的对象,最大512M
- Hash:hget / hset / hgetall字典,多用于存储一个对象
- List:链表,双端队列实现一个list,多用于存储消息队列,关注列表,支持正反遍历:lpush+lpop=Stack(栈),lpush+rpop=Queue(队列)
- Set:无序,不可重复集合,求交集并集,比如共同好友
- Zset:有序的set,得分排行榜,数据结构是一个跳表
相较于memcached的优势
- 更丰富的数据类型
- 更快
- 可以持久化
redis的持久化
将内存的数据写入磁盘,防止数据丢失。有RDB
和AOF
。
RDB:快照,默认持久化方式,一定时间(或手动save)会将内存中的数据存于硬盘中,数据文件卫dump.rdb。这个过程是fork一个子进程完成的不会影响主进程的IO操作,保证了性能,缺点:会丢失一部分数据
AOF:追加。在rdis执行写命令的时候记录到单独的日志文件中,重启redis会重新持久化日志文件以恢复数据。缺点是文件比较大,恢复比较慢
如何选择持久化方式
- 如果可以承受一定时间的数据丢失,使用RDB持久化方式,因为快
- 在redis4.0之后支持了混用模式,允许数据丢失。建议一起开启
内存满了,业务还在写数据会怎么样
淘汰不活跃的,将新的加进去,做好监控和扩容,及时提高阈值
什么是缓存雪崩
缓存大量失效,导致请求打到数据库,可能是到期了,也可能是redis挂了
如何避免
缓存过期时间设置一个随机值,redis集群部署。
如果redis挂了,使用本地缓存加限流措施
redis分布式锁
先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。
怎么做持久化的
RDB全量,AOF增量
RDB原理
fork子进程来进行RDB,cow指copy on write 子进程创建后,父进程继续提供读写服务,写脏的页面数据会逐渐和子进程分离开来。
redis同步机制了解吗
可以使用主从同步。主节点做一次备份,将后续修改记录到内存buffer,再将RDB全量复制并加载到内存,在通过后续增量AOF进行同步
什么是缓存穿透
非法请求,缓存和数据库中都没有,可能会导致服务瘫痪
如何避免
- 前端参数校验
- 布隆过滤器
- 将空对象也缓存,下次直接返回(设置一个较短的过期时间)
缓存与数据库不一致
- 键过期之后,会保持一致
- 先操作数据库,再缓存或先操作缓存,在数据库,我们希望它能同时成功与失败,于是就用到了分布式事务
- 相对于更新与删除来说,一般采取删除策略,查不到再从数据库查,更新所需性能更高(懒加载)
- 在高并发场景下,先更新数据库在删除缓存
说说持久化
有RDB(默认)和AOF
- RDB快照,隔段时间保存一次硬盘,文件为dump.rdb。fork子进程进行,保证了性能。但数据安全性低,会丢失一部分数据
- AOP追加,每次写时候记录到单独日志文件中,同时开启优先AOF,解决了数据一致性问题。但带来的问题就是大,恢复比较慢
如何保证热点数据
采取淘汰策略:常见的有LRU
淘汰策略有哪些
BloomFilter(布隆过滤器)
概念:70年布隆提出,用于检索一个元素是否在集合中,空间效率和时间效率高于其他算法,但有误伤率和删除困难
原理:当元素加入集合,通过k个散列函数将元素映射为一个位数组的k个点,如果有0则一定存在,如果全1则不一定存在