java进阶知识

这里写自定义目录标题

    • 消息队列
      • 优缺点
      • 高可用
      • 消息不被重复消费(保证消息的幂等性)
      • 消息的可靠性传输(处理消息丢失)
      • 消息的顺序性
    • 搜索引擎
      • 提高查询效率
    • 缓存
      • 用途
      • redis 和 memcached 有啥区别?
      • 为啥 redis 单线程模型也能效率这么高?
      • redis 主要有以下几种数据类型:
      • redis 的过期策略
      • 如何保证redis高并发
      • redis持久化
      • redis cluster 介绍
      • 节点间的内部基本通信原理
      • gossip 协议
      • 分布式寻址算法
      • 缓存雪崩
            • 缓存雪崩的事前事中事后的解决方案如下。
      • 缓存穿透
            • 解决方式
      • 缓存与数据库的双写一致性
      • redis 的并发竞争问题

消息队列

优缺点

核心: 解耦,异步,削峰

  1. 系统可用性降低
    系统引入的外部依赖越多,越容易挂掉。本来你就是 A 系统调用 BCD 三个系统的接口就好了,人 ABCD 四个系统好好的,没啥问题,你偏加个 MQ 进来,万一 MQ 挂了咋整,MQ 一挂,整套系统崩溃的,你不就完了?如何保证消息队列的高可用,可以点击这里查看。
  2. 系统复杂度提高
    硬生生加个 MQ 进来,你怎么保证消息没有重复消费?怎么处理消息丢失的情况?怎么保证消息传递的顺序性?头大头大,问题一大堆,痛苦不已。
  3. 一致性问题
    A 系统处理完了直接返回成功了,人都以为你这个请求就成功了;但是问题是,要是 BCD 三个系统那里,BD 两个系统写库成功了,结果 C 系统写库失败了,咋整?你这数据就不一致了。

高可用

  1. RabbitMQ 有三种模式:单机模式、普通集群模式、镜像集群模式。
  2. Kafka 的高可用性,分散放在多个机器上的,每个机器就放一部分数据。

消息不被重复消费(保证消息的幂等性)

  1. 比如你拿个数据要写库,你先根据主键查一下,如果这数据都有了,你就别插入了,update 一下好吧。
  2. 比如你是写 Redis,那没问题了,反正每次都是 set,天然幂等性。
  3. 比如你不是上面两个场景,那做的稍微复杂一点,你需要让生产者发送每条数据的时候,里面加一个全局唯一的 id,类似订单 id 之类的东西,然后你这里消费到了之后,先根据这个 id 去比如 Redis 里查一下,之前消费过吗?如果没有消费过,你就处理,然后这个 id 写 Redis。如果消费过了,那你就别处理了,保证别重复处理相同的消息即可。
  4. 比如基于数据库的唯一键来保证重复数据不会重复插入多条。因为有唯一键约束了,重复数据插入只会报错,不会导致数据库中出现脏数据。

消息的可靠性传输(处理消息丢失)

java进阶知识_第1张图片

消息的顺序性

RabbitMQ : 拆分多个 queue,每个 queue 一个 consumer,就是多一些 queue ;
kafka: 一个 topic,一个 partition,一个 consumer,内部单线程消费;

搜索引擎

ElasticSearch 设计的理念就是分布式搜索引擎,底层其实还是基于 lucene 的。核心思想就是在多台机器上启动多个 es 进程实例,组成了一个 es 集群。

提高查询效率

  1. 性能优化的杀手锏——filesystem cache
  2. 数据预热
  3. 冷热分离
  4. document 模型设计
  5. 分页性能优化
  6. 不允许深度分页/默认深度分页性能很惨

缓存

用途

高性能,高并发

redis 和 memcached 有啥区别?

  1. redis 支持复杂的数据结构
    redis 相比 memcached 来说,拥有更多的数据结构,能支持更丰富的数据操作。如果需要缓存能够支持更复杂的结构和操作, redis 会是不错的选择。

  2. redis 原生支持集群模式
    在 redis3.x 版本中,便能支持 cluster 模式,而 memcached 没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据。

  3. 性能对比
    由于 redis 只使用单核,而 memcached 可以使用多核,所以平均每一个核上 redis 在存储小数据时比 memcached 性能更高。而在 100k 以上的数据中,memcached 性能要高于 redis,虽然 redis 最近也在存储大数据的性能上进行优化,但是比起 memcached,还是稍有逊色。

为啥 redis 单线程模型也能效率这么高?

  1. 纯内存操作
  2. 核心是基于非阻塞的 IO 多路复用机制
  3. 单线程反而避免了多线程的频繁上下文切换问题

redis 主要有以下几种数据类型:

  1. string
  2. hash
  3. list
  4. set
  5. sorted set

redis 的过期策略

redis 过期策略是:定期删除+惰性删除。
如果定期删除漏掉了很多过期 key,然后你也没及时去查,也就没走惰性删除,此时会怎么样?如果大量过期 key 堆积在内存里,导致 redis 内存块耗尽了,咋整?
答案是:走内存淘汰机制。
allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(这个是最常用的)

如何保证redis高并发

redis 实现高并发主要依靠主从架构,一主多从,一般来说,很多项目其实就足够了,单主用来写入数据,单机几万 QPS,多从用来查询数据,多个从实例可以提供每秒 10w 的 QPS。
如果想要在实现高并发的同时,容纳大量的数据,那么就需要 redis 集群,使用 redis 集群之后,可以提供每秒几十万的读写并发。
redis 高可用,如果是做主从架构部署,那么加上哨兵就可以了,就可以实现,任何一个实例宕机,可以进行主备切换。

redis持久化

  1. RDB:RDB 持久化机制,是对 redis 中的数据执行周期性的持久化。
  2. AOF:AOF 机制对每条写入命令作为日志,以 append-only 的模式写入一个日志文件中,在 redis 重启的时候,可以通过回放 AOF 日志中的写入指令来重新构建整个数据集。

redis cluster 介绍

  1. 自动将数据进行分片,每个 master 上放一部分数据
  2. 提供内置的高可用支持,部分 master 不可用时,还是可以继续工作的

节点间的内部基本通信原理

redis cluster 节点间采用 gossip 协议进行通信 集中式是将集群元数据(节点信息、故障等等)几种存储在某个节点上。集中式元数据集中存储的一个典型代表,就是大数据领域的 storm。它是分布式的大数据实时计算引擎,是集中式的元数据存储的结构,底层基于 zookeeper(分布式协调的中间件)对所有元数据进行存储维护。

gossip 协议

gossip 协议包含多种消息,包含 ping,pong,meet,fail 等等。

分布式寻址算法

  1. hash 算法(大量缓存重建)
  2. 一致性 hash 算法(自动缓存迁移)+ 虚拟节点(自动负载均衡)
  3. redis cluster 的 hash slot 算法

缓存雪崩

对于系统 A,假设每天高峰期每秒 5000 个请求,本来缓存在高峰期可以扛住每秒 4000 个请求,但是缓存机器意外发生了全盘宕机。缓存挂了,此时 1 秒 5000 个请求全部落数据库,数据库必然扛不住,它会报一下警,然后就挂了。此时,如果没用什么特别的方案来处理这个故障,DBA 很着急,重启数据库,但是数据库立马又被新的流量给打死了。
这就是缓存雪崩。

缓存雪崩的事前事中事后的解决方案如下。
  1. 事前:redis 高可用,主从+哨兵,redis cluster,避免全盘崩溃。
  2. 事中:本地 ehcache 缓存 + hystrix 限流&降级,避免 MySQL 被打死。
  3. 事后:redis 持久化,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据。

缓存穿透

对于系统A,假设一秒 5000 个请求,结果其中 4000 个请求是黑客发出的恶意攻击。
黑客发出的那 4000 个攻击,缓存中查不到,每次你去数据库里查,也查不到。
举个栗子。数据库 id 是从 1 开始的,结果黑客发过来的请求 id 全部都是负数。这样的话,缓存中不会有,请求每次都“视缓存于无物”,直接查询数据库。这种恶意攻击场景的缓存穿透就会直接把数据库给打死。

解决方式

很简单,每次系统 A 从数据库中只要没查到,就写一个空值到缓存里去,比如 set -999 UNKNOWN。这样的话,下次便能走缓存了。

缓存与数据库的双写一致性

一般来说,如果允许缓存可以稍微的跟数据库偶尔有不一致的情况,也就是说如果你的系统不是严格要求 “缓存+数据库” 必须保持一致性的话,最好不要做这个方案,即:读请求和写请求串行化,串到一个内存队列里去。

redis 的并发竞争问题

多个系统实例都去更新某个 key。可以基于 zookeeper 实现分布式锁。每个系统通过 zookeeper 获取分布式锁,确保同一时间,只能有一个系统实例在操作某个 key,别人都不允许读和写。

你可能感兴趣的:(面试题或笔试题收集)