王者段位java模式

参考视频

hystrix 降级 限流

配置 中心 阿波罗,config 等

微服务网关 zuul

rbac模型

用户和角色是多对多的 一个 角色 多个用户,一个用户 多个 角色

权限 和 角色关系,一个权限 多个 角色,一个 角色可以多个权限

常见分布式解决方案

  1. tcc
  2. 最大努力尝试
  3. 最终一致性

rabbitMQ 重复消息

rabbitMQ重复消息参考博客

redis 和 mysql 双写一致性的问题

先更新 数据库 再删除缓存

【可能出现的问题,更新完成后, 缓存 还没有删除,可能导致

短暂的数据不一致问题】

你直接回答: 没有十全十美的解决方案

redis 分布式锁

  1. setnx 的问题:
    • 还没有操作完, 这个锁已经过期了
      • 解决方案: watchdog 看门狗机制

mybatis 二级缓存, hashMap redis 缓存的区别

redis 做分布式缓存, 允许别的服务 同时去使用

数据库的优化

  • 分库分表
  • 集群
  • explain 解释 优化
    • 覆盖索引
    • 回表

分表策略

  1. 设置步长
  2. 按照时间
    1. 今年的放一张表
    2. 这个月的放一张表
  3. hash算法
    1. 算出 在哪张表

union 的问题

  1. union 会导致临时表产生
  2. union和 union all 区别
    1. union 会去重 【去重的话 会导致效率低】
    2. union all 不去重

索引

直接回答 b + 树,

b+ 树 和 二叉树 的区别

b+ 树 有多个子节点, 这样压低了 层数 ,如果是 二叉树的话,数据量比较多

层数就比较深, b+ 数压低层数,查询效率就会比较高 (层数越小, 计算机的 Io 次数越少,效率就越高)

myisam 和 innodb 索引上面的区别

my 分为2部分 索引 和 数据文件 是 不一样的 ,数据分离,

查询的话 是先查索引再查数据,会有个回表操作

这里 我直接 说 myisam 是非聚集索引 查询会回表

innodb 如果是 主键索引的话,直接 就是 可以 一次查询出来、

因为 索引和数据是存 一起的,叫做聚集索引

那 innodb 普通索引是非聚集索引, 索引存的是 主键,查询 会有个回表操作。也就是查询2次回表效率低

覆盖索引: 查询的列全部都在命中的索引的条件里面,可以直接从索引里面读取出来,如果触发覆盖索引,就不用回表查询。

innodb 可以支持事务, myisam 不支持事务,只能锁表,更新操作 锁表,导致效率太低

mysql 默认使用 innodb , innodb 和 myisam 区别是 innodb 行锁,myisam 表锁

innodb 锁表怎么解决
1. 更新的时候没有走上索引,导致了全表扫描,就会导致锁表问题,会阻塞后续 读写操作
2. 走索引了,但是没全走上,会有 范围更新的问题,导致 锁住一个比较大的区间【 这样 近似看成是锁表了】
3. 数据库备份的时候,线上的DDL 会导致锁表,

是的,**间隙锁(Gap Lock)**可能导致死锁,但需要具体的场景来触发。为了更清楚了解,以下是相关概念和可能导致死锁的场景:


间隙锁(Gap Lock)的作用

  1. 范围保护:间隙锁用于保护一个范围内的记录,防止其他事务插入数据,确保事务隔离性。
  2. 锁定条件:间隙锁在 InnoDB 的 可重复读(REPEATABLE READ) 或更高隔离级别中会被使用,通常在范围查询(>, <, BETWEEN 等)中出现。

间隙锁导致死锁的典型场景

间隙锁引发死锁,通常是由于多个事务在访问同一范围但操作不同数据时发生。例如:

场景 1:两个事务竞争同一范围内不同的插入

假设 table1 有一列 id,事务 A 和事务 B 的执行顺序如下:

  1. 事务 A

    1
    2
    
    BEGIN;
    SELECT * FROM table1 WHERE id > 10 FOR UPDATE;
    

    (获取 id > 10 范围的间隙锁)

  2. 事务 B

    1
    2
    
    BEGIN;
    SELECT * FROM table1 WHERE id > 20 FOR UPDATE;
    

    (获取 id > 20 范围的间隙锁)

  3. 如果 事务 A 尝试插入一条 id = 25 的记录,而 事务 B 同时尝试插入一条 id = 15 的记录,两者会互相等待,最终导致死锁。


场景 2:不同事务更新或删除时引发范围冲突

假设 table1 中的 id 列已存在记录 10, 20, 30,事务 A 和事务 B 的操作如下:

  1. 事务 A

    1
    2
    
    BEGIN;
    DELETE FROM table1 WHERE id = 20;
    

    (间隙锁保护范围 (10, 20)(20, 30)

  2. 事务 B

    1
    2
    
    BEGIN;
    DELETE FROM table1 WHERE id = 10;
    

    (间隙锁保护范围 (null, 10)(10, 20)

  3. 两者都需要对方释放锁才能完成操作,从而造成死锁。


如何避免间隙锁导致死锁

  1. 使用合适的事务隔离级别

    • 在不需要间隙锁的场景下,降低隔离级别到 读已提交(READ COMMITTED) 可以减少锁争用。
  2. 明确访问顺序

    • 在多个事务中,尽量保证对资源的访问顺序一致,避免互相等待。
  3. 优化查询条件

    • 尽量避免范围查询(><BETWEEN 等)在频繁插入、更新的场景下使用。
  4. 使用索引

    • 在查询条件中尽量使用唯一索引,减少间隙锁的范围。

如何检测和分析死锁

  1. 查看死锁日志: 在 MySQL 中可以通过以下命令查看最近的死锁信息:

    1
    
    SHOW ENGINE INNODB STATUS\G;
    
  2. 分析事务冲突: 根据日志中的锁等待链,找到产生死锁的事务及其操作,优化对应的 SQL。


间隙锁虽能提高事务隔离性,但需要注意它可能带来的锁争用和死锁风险,特别是在高并发环境下。

你说得对,两个事务分别获取 id > 10id > 20 的间隙锁时,确实不会直接互相阻塞。但为什么仍可能出现死锁?这需要结合 MySQL 间隙锁的特性和操作场景来分析。


原因:间隙锁不只锁住范围,还涉及插入意向锁

在 MySQL 的 InnoDB 引擎中,**间隙锁(Gap Lock)**通常与插入意向锁(Insert Intention Lock)结合使用,这种组合可能引发死锁。以下是两种常见的死锁触发机制:


场景 1:间隙锁 + 插入意向锁引发死锁

假设表 table1id 列已经存在数据 10, 20, 30,事务 A 和事务 B 的操作如下:

  1. 事务 A

    1
    2
    
    BEGIN;
    SELECT * FROM table1 WHERE id > 10 FOR UPDATE;
    
    • 锁住范围 (10, +∞) 的间隙,并对现有记录(如 20, 30)加行锁。
  2. 事务 B

    1
    2
    
    BEGIN;
    SELECT * FROM table1 WHERE id > 20 FOR UPDATE;
    
    • 锁住范围 (20, +∞) 的间隙,并对现有记录(如 30)加行锁。
  3. 接下来,事务 A 和 B 各自尝试插入一条新记录:

    • 事务 A 插入 id = 25,需要检查 (20, +∞) 的间隙锁(被事务 B 锁住)。
    • 事务 B 插入 id = 15,需要检查 (10, 20) 的间隙锁(被事务 A 锁住)。
  4. 结果:两者互相等待对方释放锁,从而死锁。


场景 2:间隙锁范围重叠引发死锁

虽然事务分别请求 id > 10id > 20 的锁,但由于 InnoDB 间隙锁的实现方式,可能会出现范围锁重叠,从而导致死锁。假设表中已有记录 10, 20, 30,事务 A 和事务 B 的操作如下:

  1. 事务 A

    1
    2
    
    BEGIN;
    SELECT * FROM table1 WHERE id > 10 FOR UPDATE;
    
    • 锁住范围 (10, +∞),包括 (10, 20)(20, +∞) 两段间隙。
  2. 事务 B

    1
    2
    
    BEGIN;
    SELECT * FROM table1 WHERE id > 20 FOR UPDATE;
    
    • 理论上锁住范围 (20, +∞)
  3. 关键点:锁范围的实际实现
    InnoDB 会在请求范围锁时,将操作扩展到整个范围的一部分(包括锁住相关行),因此:

    • 事务 A 锁住了 (10, 20)(20, 30)
    • 事务 B 锁住了 (20, 30)(30, +∞)
  4. 发生冲突

    • 如果事务 A 试图访问 id = 30 或尝试插入记录到 (20, 30),而事务 B 试图访问 id = 20 或插入到 (10, 20),两者就会陷入等待。

为什么范围锁会扩展?

这是 MySQL InnoDB 为了确保事务隔离性的一种策略。在间隙锁的场景下,InnoDB 通常会锁住查询范围涉及的行以及相关的间隙,而这些范围有时会相互重叠,从而产生冲突。


如何避免这种死锁?

  1. 明确索引范围

    • 如果可以,避免使用范围查询(>< 等)直接加锁;考虑具体的记录加锁,或通过唯一索引精确定位行。
  2. 调整事务操作顺序

    • 设计事务时,尽量保持一致的操作顺序,避免不同事务互相抢占资源。
  3. 使用更低的隔离级别

    • 在业务允许的情况下,降低隔离级别到 READ COMMITTED,此时 InnoDB 会减少间隙锁的使用。
  4. 使用间隙锁诊断工具

    • 通过 SHOW ENGINE INNODB STATUS\G 检查死锁日志,找出具体冲突位置,优化 SQL 语句。

总结来说,虽然两个事务锁住的范围是 id > 10id > 20,看似没有直接冲突,但由于间隙锁的实际实现以及可能的插入操作,两者会间接引发死锁。这也是为什么即使范围不同,死锁仍会发生。