前言
这篇来讲解java各种各样组件,例如数据库mysql、缓存redis、分布式搜索等等的题目

一、redis篇

1、redis和ehcache区别
答:1.ehcache直接在jvm虚拟机中缓存,速度快,效率高;但是缓存共享麻烦,集群分布式应用不方便。2.redis可缓存共享、分布式部署,可持久化

2、redis应用场景
答:1.热点数据。2.计数器。3.排行榜。4.分布式锁。5.队列。6.点赞。7.token令牌。8.延时操作

3、为啥效率那么高
答::1.完全基于内存,持久化。
    2.单线程。
    3.redis使用多路复用技术。
    4.基于跳跃表数据增删改,效率高

4、redis线程安全吗?为啥效率那么高?
答:采用NIO多路复用,一个线程处理多个请求,线程安全类似无锁机制

5、redis分为多少个库,为啥有这么多个
答:16个库,没个库不准许出现相同key,不同业务连接同一个redis,所以区分

6、redis五种类型:
答:1.String(常规key-value缓存应用,最大512M。常规计数: 微博数, 粉丝数。)
   2.List(双向链表,字符串列表。最新消息排行,消息队列)
   3.Hash(键值(key => value)对集合。场景:存储部分变更数据,如用户信息、存储、读取、修改用户属性等。)
   4.set(string类型的无序集合。场景:共同好友、交集)
   5.zset(sorted set:有序集合。场景:1.排行榜 2.带权重的消息队列)

7、redis如何存放数据
答:1.基于json序列化。2.基于String二进制存放对象

8、mysql和redis保证数据唯一性
答:1.手动清除缓存。2.订阅mysql的binlog日志通过MQ推送

9、全量和增量区别
答:1.全量:每天定时对所有数据数据同步。2.增量:发生操作同步数据,效率低,低延迟

10、内存满了如何处理?
答:1.扩展内存,治标不治本。2.采用redis淘汰机制。3.设置过期key

11、redis宕机会丢失?
答:不会,因为会持久化

12、redis持久化有哪些方案?
答:RDB增量同步。存放文件格式,恢复速度快。AOF增量同步,日志存放

13、redis支持回滚吗?
答:没有回滚。mysql开启事务,其他线程不能做写操作,回滚相当于对该行锁释放。redis开启对key的事务,其他线程还是可以对key做操作

14、redis主从复制
答:单台redis情况下,如果redis宕机会导致数据丢失,故使用复制备份数据
多台分为主从关系,请求会转发主节点。在同步到每子字节点负责读,哨兵会重启节点,单机要手动

15、redis主从实现
答:1.数据备份。2.集群。3.读写分离

16、redis分布式锁思路
答:采用setn。2.redis框架

17、redis的set和setnx区别
setnx可以返回key是否存在。存在返回0,不能修改,不存在返回1

18、分布式锁超时如何处理
答:1.续时。2.回滚当前事务,同时释放锁

19、redis缓存穿透,缓存穿击、缓存雪崩原因及解决方案
答:缓存穿透
   缓存穿击
   缓存雪崩

二、Mysql

2.1、Mysql数据库优化层面

  • 1、需求优化(需求无用功能,不合理。论坛实时更新)
  • 2、系统架构(二进制多媒体功能、流水、活跃缓存数据)
  • 3、SQL以及索引
  • 4、数据库表结构(表规范、分表分库)
  • 5、系统配置优化(Tcp连接、打开文件限制、安全性优化)
  • 6、硬件(IO、CPU、网络)

2.2、SQL查询慢如何优化

  • 1、慢查询日志是否打开
set global slow_query_log=on;
  • 2、检查慢日志路径
show variables like '%slow_query_log%';
  • 3、慢日志判断标准(默认大于10秒)
show variables like 'slong_query_time';

2.3、Explain执行计划

idselect_typetablepartitionstypepossible_keyskey_lenrefrowsfilteredExtra
越大越先执行表示查询的类型,什么语句查询的表匹配的分区表的连接类型可能使用索引实际使用索引索引长度列与索引比较估算的行数条件过滤的百分比

2.4、慢查询优化思路

  • 优化更需要优化的SQL
  • 了解性能瓶颈
  • 明确优化目标
  • explan执行计划
  • 小结果集驱动大结果集
  • 尽可能在索引中完成排序
  • *禁用所有列查询,使用需要的列
  • 只使用最有效的过滤条件
  • *尽可能避免使用复杂的join和子查询
  • 尽可能使用三张以内表
  • 小心使用order by、group by、distinct函数
  • **合理使用索引

2.5、索引种类

  • B-tree索引(mysql中最频繁的索引类型)
    • B树:三个节点,三次IO,键值、指针、数据组合
    • B+树:1、数据全部在第三节点。2、第三节点双向
  • Hash索引(检索效率高于B-tree索引,可以一次定位)
  • Fulltext索引(目前仅支持char、varchar、text)
  • R-tree索引(少见,主要用于空间数据检索)

2.6、什么时候需要创建索引

  • 字段查询比较频繁
  • 字段更改不是很频繁
  • where里面的字段才可以创建索引

2.7、索引失效与优化

  • 复合索引尽量写全
  • 最佳前缀法则(中间索引不能断)
  • 不要在索引上做任何操作(计算、函数等)
  • mysql存储引擎不能继续使用索引中范围条件(bettween、in等)右边列
  • 尽量使用覆盖索引(只查询索引的列)
  • is null 或者 is not nul也会失效
  • !=或 > <判断时,也会失效
  • like通配符也会失效
  • 索引字段是字符串,查询时候不加单引号也会失效
  • or也会导致失效

2.8、优化终极奥义

  • 针对百万数据,放弃join操作。推荐分别根据索引单表取数据,然后在java代码里面join、merge操作
  • 解决IO问题,读IO尽量使用nosql来防控热点数据。写IO使用消息中间件来抗压
    • 解决读IO、热点数据存放redis读IO,从而减轻数据库物理压力
    • 解决写IO、使用消息队列慢慢依次对mysql进行写操作
    • 拓展:多级缓存、redis集群、mq、tomcat、mysql集群

一个单节点(1服务器、1数据库)不可能使系统达到百万级别
mysql最多曾在3500-4500QPS

2.9、其他优化

  • 不能在数据库做运算,运算务必移到业务层
  • 数据库命名简洁明了(长度不能超过30字符)
  • 控制列数量(字段少而精、字段数控制20个以内)
  • 平衡范式与冗余(效率优先,往往牺牲范式)
  • 拒接3B(拒接大sql语句、大事物、大批量)
  • 合理数值类型(合适的字段节省空间)
  • 字符转化数字(例如类型、节省空间、性能)
  • 避免NULL字段(NULL难查询优化、NULL字段索引需要额外空间、复合索引失效)
  • 少用text类型(尽量varchar)
  • 合理使用索引(改善查询、减慢更新)
  • 字符字段建立前缀索引
  • innodb主键推荐自增列(字符串不应该做主键、不用外键)
  • sql尽量简单(一条sql只能在一个cpu运算,大语句拆小语句,减少锁时间,一条大sql可以堵死整个数据库)
  • 简单事物(最好不要有事物)
  • 避免trig/func(不用触发器、函数、客户端程序代替取而代之)

2.10、常见面试题

  • 1、mylSAM和InnoDb区别
1、InnoDb支持事物
2、InnoDb支持外键
3、InnoDb是聚集索引,使用B+Tree作为索引结构。MyISAM是非聚集索引
4、MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,所以查询速度很快
5、InnoDB支持表、行(默认)级锁,而MyISAM支持表级锁
6、InnoDB表必须有唯一索引(如主键)(用户没有指定的话会自己找/生产一个隐藏列Row_id来充当默认主键)
7、Innodb存储文件有frm、ibd,而Myisam是frm、MYD、MYI
	- Innodb:frm是表定义文件,ibd是数据文件
        - Myisam:frm是表定义文件,myd是数据文件,myi是索引文件
  • 2、为啥InnoDb引擎表必须有主键、并且推荐整数自增方式
如果不是自增id,例如uuid。此时你将不能够范围查询
  • 3、云数据库如何定位慢查询
  • 4、执行计划EXPLAIN如何使用
  • 5、EXPLAIN Type需要达到什么级别
    • rang
ALL:全表扫描
index:全表扫描索引数、接近ALL
range:检索范围查询
ref:表示上述表的连接匹配条件、就是那些列、常量用于查询索引列上的值
eq_ref:主键或者唯一索引关联查询、最多只返回一条符合条件记录。
const:对查询某部分进行优化,并转换为一个常量
NULL
  • 6、mysql索引为什么遵循最佳左前缀法则
查询条件尽量用 联合索引前面的列,这样就可以走索引树
  • 7、mysql索引为什么需要避免回表查询
因为索引树上找不到需要的内容,需要借用主键ID再回表查询第二次(利用复合索引)
  • 8、超过多少张表需要禁止join
  • 9、为啥阿里巴巴需要禁止存储过程
  • 10、一张表达到多少级别需要分库分表

三、rabbitMq篇

3.1、项目那些场景运用到MQ

执行比较耗时的代码操作,交给mq异步实现接口

  • 异步发送优惠券
  • 异步发送短信
  • 异步扣除库存

3.2、为什么使用MQ

  • 异步处理(多线程和MQ)【耗时程序移步异步处理】
  • 实现解耦
  • 流量削峰(抗高并发)

3.3、MQ与多线程实现异步区别

  • 多线程实现异步请求可能会消耗cpu资源,频繁上下文切换,从而影响业务线程会发生cpu竞争问题
  • MQ异步是解耦,适合大型互联网项目
  • 小项目可以使用多线程实现异步,大项目建议MQ实现

3.4、MQ如何避免消息堆积问题

  • 背景
    • 生产者投递速率与消费者速率完全不匹配
  • 注意
    • rabbitmq消息被消费立即删除。kafka和rocketMq不会
      立即删除

image.png

  • 解决办法
    • 提高消费者速率,例如消费者集群
    • 消费者批量获取消息、减少网络传输次数
  • 同一个组中,消息不会重复消费

3.5、如何保证消息不丢失

  • MQ服务器端【消息持久化到硬盘】
  • 生产者【ACK响应状态投递 确保我们消息投递到MQ】
  • 消费者【消费者确认消息消费成功,rabbitmq会删除信息】

3.6、生产投递服务器宕机如何处理

使用一个redis或者mysql保存msg记录,如果发生失败,使用定时器根据日志补偿投递。

3.7、如何保证MQ顺序一致性

  • 背景:
    MQ集群或者MQ分区存放消息,每个分区对应一个消费者
  • 解决:
    同一类消息投递到同一个MQ、同一分区、被同一消费者消费
  • 实现:
    根据消息key%分区模型总数投递到同一分区

3.8、如何保证MQ消息幂等性问题

  • 背景:
    消费失败、重复消费
  • 解决:
    • 间隔重复执行消费
    • 业务方面保证幂等性,不被重复执行
    • 设置全局id,消费前先查询是否已经执行
    • 数据库层:设置唯一约束、乐观锁

3.9、MQ与Redis如何保证一致性

  • 解决:
    • 删除redis缓存,可能会出现延迟双删。适合小项目
    • 基于MQ异步处理。update数据--〉MQ发送消息--〉消费--〉redis
    • 订阅binlog。update数据--〉cannal订阅binlog--〉cannal客户端解析成json--〉发送到kafka--〉消费消息--〉redis