消息队列

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,得分排行榜,数据结构是一个跳表

redis的持久化

将内存的数据写入磁盘,防止数据丢失。有RDBAOF

RDB:快照,默认持久化方式,一定时间(或手动save)会将内存中的数据存于硬盘中,数据文件卫dump.rdb。这个过程是fork一个子进程完成的不会影响主进程的IO操作,保证了性能,缺点:会丢失一部分数据

AOF:追加。在rdis执行写命令的时候记录到单独的日志文件中,重启redis会重新持久化日志文件以恢复数据。缺点是文件比较大,恢复比较慢

如何选择持久化方式

  • 如果可以承受一定时间的数据丢失,使用RDB持久化方式,因为快
  • 在redis4.0之后支持了混用模式,允许数据丢失。建议一起开启

内存满了,业务还在写数据会怎么样

淘汰不活跃的,将新的加进去,做好监控和扩容,及时提高阈值

什么是缓存雪崩

就是缓存大量失效。请求打到数据库

如何避免

过期时间随机分布,避免同时失效
热点数据不过期
限流熔断,避免后端承受请求压力

怎么做持久化的

RDB全量,AOF增量

RDB原理

fork子进程来进行RDB,cow(copy on write)子进程创建后,父进程继续提供读写服务

redis同步机制了解吗

可以使用主从同步。主节点做一次备份,将后续修改记录到内存buffer,再将RDB全量复制并加载到内存,在通过后续增量AOF进行同步

什么是缓存穿透

非法请求,缓存和数据库中都没有,可能会导致服务瘫痪

如何避免

  • 前端参数校验
  • 布隆过滤器
  • 将空对象也缓存,下次直接返回(设置一个较短的过期时间)
  • 请求限流

缓存与数据库不一致

  • 主动更新缓存、异步更新缓存
  • 缓存失效,重新查询数据库
  • 双写一致性,更新数据库同时更新缓存

说说持久化

有RDB(默认)和AOF

  • RDB快照,隔段时间保存一次硬盘,文件为dump.rdb。fork子进程进行,保证了性能。但数据安全性低,会丢失一部分数据
  • AOP追加,每次写时候记录到单独日志文件中,同时开启优先AOF,解决了数据一致性问题。但带来的问题就是大,恢复比较慢

如何保证热点数据

采取淘汰策略:常见的有LRU

淘汰策略有哪些

out

BloomFilter(布隆过滤器)

概念:70年布隆提出,用于检索一个元素是否在集合中,空间效率和时间效率高于其他算法,但有误伤率和删除困难

原理:当元素加入集合,通过k个散列函数将元素映射为一个位数组的k个点,如果有0则一定存在,如果全1则不一定存在
bloom