最近有粉丝私信说被 oppo 的后端面试问麻了, 所以明天给大家举荐一篇整顿了 16 道 oppo 面试真题答案的文章。心愿对大家有帮忙哈,一起学习,一起提高。
- 聊聊你印象最粗浅的我的项目,或者做了什么优化。
- 我的项目提到分布式锁,你们是怎么应用分布式锁的?
- 常见的分布式事务解决方案
- 你们的接口幂等是如何保障的?
- 你们的 MySQL 架构是怎么的?
- 常见的索引构造有?哈希表构造属于哪种场景?
- 给你 ab,ac,abc 字段,你是如何加索引的?
- 数据库隔离级别是否理解?你们的数据库默认隔离级别是?为什么选它?
- RR 隔离级别实现原理,它是如何解决不可反复读的?
- 你们我的项目应用了 RocketMQ 对吧?那你晓得如何保障音讯不失落吗?
- 事务音讯是否理解?场景题:比方下单清空购物车,你是如何设计的?
- 如何疾速判断一个数是奇数还是偶数,除开对 2 取其余呢。
- Spring 申明式事务原理?哪些场景事务会生效?
- 你们是微服务架构吗?如果你来设计一个相似淘宝的零碎,你怎么划分微服务?
- 你们是怎么分库分表的?分布式 ID 如何生成?
- 所有异样的独特先人是?运行时异样有哪几个?
1. 聊聊你印象最粗浅的我的项目,或者做了什么优化。
大家平时做的我的项目,如果很多知识点跟面试八股文相干的话,就能够绝对条理清晰地写到简历去。
- 比方缓存数据库相干的,查问为空,你设置了一个 - 1 到缓存,代表数据库没记录。下次判断 -1,就不查库了,以解决缓存穿透的问题。
- 又比方你设置缓存过期工夫比拟扩散,解决缓存击穿问题,都能够条理清晰写到简历去,这样面试官很可能会问你相干的问题,这时候就对答如流啦。
还有平时你做的我的项目,有一些比拟好的设计,都能够说一下哈,比方你是如何保证数据一致性的,怎么优化接口性能的。
- 如果是讲 优化接口 这一块的话,其实就是 缓存、分批、并发调用、异步 等那几个要害知识点。
- 如果是代码优化细节,你能够挑个简略的来讲,比方 简单的 if 逻辑条件,能够调整程序,让程序更高效,这样会让面试官眼前一亮哦。
2. 你我的项目提到分布式锁,你们是怎么应用分布式锁的?
个别你讲述你做的我的项目时,面试官会依据你我的项目波及的一些面试点,而后抽他感兴趣的一两个来问。所以大家对哪些知识点相熟,讲述我的项目时,就说你用该知识点,解决了什么问题。
3. 常见分布式事务解决方案
分布式事务:就是的分布式的参与者、反对事务的服务器、资源服务器以及事务管理器别离位于不同的分布式系统的不同节点之上。简略来说,分布式事务指的就是分布式系统中的事务,它的存在就是为了保障不同数据库节点的数据一致性。
聊到分布式事务,大家记得这两个实践哈:CAP 实践 和 BASE 实践
分布式事务的几种解决方案:
- 2PC(二阶段提交)计划、3PC
- TCC(Try、Confirm、Cancel)
- 本地音讯表
- 最大致力告诉
- seata
2PC(二阶段提交)计划
2PC,即两阶段提交,它将分布式事务的提交拆分为 2 个阶段:prepare 和 commit/rollback,即筹备阶段和提交执行阶段。在 prepare 筹备阶段须要期待所有参加子事务的反馈,因而可能造成数据库资源锁定工夫过长,不适宜并发高以及子事务生命周长较长的业务场景。并且协调者宕机的话,所有的参与者都收不到提交或回滚指令。
3PC
两阶段提交别离是:CanCommit,PreCommit 和 doCommit,这里不再详述。3PC 利用超时机制解决了 2PC 同步阻塞问题,防止资源被永恒锁定,进一步增强了整个事务过程的可靠性。然而 3PC 同样无奈应答相似的宕机问题,只不过呈现很多数据源中数据不统一问题的概率更小。
TCC
TCC 采纳了弥补机制,其核心思想是:针对每个操作,都要注册一个与其对应的确认和弥补(撤销)操作。它分为三个阶段:Try-Confirm-Cancel
- try 阶段:尝试去执行,实现所有业务的一致性查看,预留必须的业务资源。
- Confirm 阶段:该阶段对业务进行确认提交,不做任何查看,因为 try 阶段曾经查看过了,默认 Confirm 阶段是不会出错的。
- Cancel 阶段:若业务执行失败,则进入该阶段,它会开释 try 阶段占用的所有业务资源,并回滚 Confirm 阶段执行的所有操作。
TCC 计划让利用能够自定义数据库操作的粒度,升高了锁抵触,能够晋升性能。然而利用侵入性强,try、confirm、cancel 三个阶段都须要业务逻辑实现。
本地音讯表
ebay 最后提出本地音讯表这个计划,来解决分布式事务问题。业界目前应用这种计划是比拟多的,它的核心思想就是将分布式事务拆分老本地事务进行解决。能够看一下根本的实现流程图:
最大致力告诉
最大致力告诉计划的指标,就是发动告诉方通过肯定的机制,最大致力将业务处理结果告诉到接管方。
seata
Saga 模式是 Seata 提供的长期事务解决方案。核心思想是将长事务拆分为多个本地短事务,由 Saga 事务协调器协调,如果失常完结那就失常实现,如果某个步骤失败,则依据相同程序一次调用弥补操作。
Saga 的并发度高,然而一致性弱,对于转账,可能产生用户已扣款,最初转账又失败的状况。
4. 你们的接口幂等是如何保障的?
如果你调用上游接口超时了,是不是思考重试?如果重试,上游接口就须要反对幂等啦。
实现幂等个别有这 8 种计划:
- select+insert+ 主键 / 惟一的索引抵触
- 间接 insert + 主键 / 惟一的索引抵触
- 状态秘密等
- 抽取防重表
- token 令牌
- 乐观锁(如 select for update,很少用)
- 乐观说
- 分布式锁
大家平时是用哪个计划解决幂等的,最初联合工作理论讲讲哈。
5. 你们的 mySQL 架构是怎么的?
大家能够联合本人公司的 MySQL 架构聊聊。
数据的库高可用计划
- 双机主备
- 一主一从
- 一主多从
- MariaDB 同步多主机
- 数据库中间件
5.1 双机主备
- 长处:一个机器故障了能够主动切换,操作比较简单。
- 毛病:只有一个库在工作,读写压力大,未能实现读写拆散,并发也有肯定限度
5.2 一主一从
- 长处:从库反对读,分担了主库的压力,晋升了并发度。一个机器故障了能够主动切换,操作比较简单。
- 毛病:一台从库,并发反对还是不够,并且一共两台机器,还是存在同时故障的机率,不够高可用。
5.3 一主多从
- 长处:多个从库反对读,分担了主库的压力,显著晋升了读的并发度。
- 毛病:只有一台主机写,因而写的并发度不高
5.4 MariaDB 同步多主机集群
- 有代理层实现负载平衡,多个数据库能够同时进行读写操作;各个数据库之间能够通过 Galera Replication 办法进行数据同步,每个库实践上数据是完全一致的。
- 长处:读写的并发度都显著晋升,能够任意节点读写,能够主动剔除故障节点,具备较高的可靠性。
- 毛病:数据量不反对特地大。要防止大事务卡死,如果集群节点一个变慢,其余节点也会跟着变慢。
5.5 数据库中间件
- mycat 分片存储,每个分片配置一主多从的集群。
- 长处:解决高并发高数据量的高可用计划
- 毛病:保护老本比拟大。
6. 常见的索引构造有?哈希表构造属于哪种场景?
哈希表、有序数组和搜寻树。
- 哈希表这种构造实用于只有等值查问的场景
- 有序数组适宜范畴查问,用二分法疾速失去,工夫复杂度为 O(log(N))。查问还好,如果是插入,就得移动前面所有的记录,老本太高。因而它个别只实用动态存储引擎,比方保留 2018 年某个城市的所有人口信息。
- B+ 树适宜范畴查问,咱们个别建的索引构造都是 B + 树。
7. 给你 ab,ac,abc 字段,你是如何加索引的?
这次要考查联结索引的最左前缀准则知识点。
- 这个最左前缀能够是联结索引的最左 N 个字段。比方组合索引(a,b,c)能够相当于建了(a),(a,b),(a,b,c)三个索引,大大提高了索引复用能力。
- 最左前缀也能够是字符串索引的最左 M 个字符。
因而给你 ab,ac,abc 字段,你能够间接加 abc 联结索引和 ac 联结索引即可。
8. 数据库隔离级别是否理解?你们的数据库默认隔离级别是?为什么选它?
四大数据库隔离级别,别离是读未提交,读已提交,可反复读,串行化(Serializable)。
- 读未提交:事务即便未提交,却能够被别的事务读取到的,这级别的事务隔离有脏读、反复读、幻读的问题。
- 读已提交:以后事务只能读取到其余事务提交的数据,这种事务的隔离级别解决了脏读问题,但还是会存在不可反复读、幻读问题;
- 可反复读 :限度了读取数据的时候,不能够进行批改,所以解决了 不可反复读 的问题,然而读取范畴数据的时候,是能够插入数据,所以还会存在幻读问题。
- 串行化:事务最高的隔离级别,在该级别下,所有事务都是进行串行化程序执行的。能够防止脏读、不可反复读与幻读所有并发问题。然而这种事务隔离级别下,事务执行很耗性能。
MySQL 抉择 Repeatable Read(可反复读)作为默认隔离级别,咱们的数据库隔离级别选的是读已提交。
8.1 为什么 MySQL 的默认隔离离别是 RR?
binlog 的格局也有三种:statement,row,mixed。设置为 statement 格局,binlog 记录的是 SQL 的原文。又因为 MySQL 在主从复制的过程是通过 binlog 进行数据同步,如果设置为读已提交(RC)隔离级别,当呈现事务乱序的时候,就会导致备库在 SQL 回放之后,后果和主库内容不统一。
比方一个表 t,表中有两条记录:
CREATE TABLE t (a int(11) DEFAULT NULL,
b int(11) DEFAULT NULL,
PRIMARY KEY a (a),
KEY b(b)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
insert into t1 values(10,666),(20,233);
两个事务并发写操作,如下:
在读已提交(RC)隔离级别下,两个事务执行完后,数据库的两条记录就变成了(30,666)、(20,666)。这两个事务执行完后,binlog 也就有两条记录,因为事务 binlog 用的是 statement 格局,事务 2 先提交,因而 update t set b=666 where b=233 优先记录,而 update t set a=30 where b=666 记录在前面。
当 bin log 同步到从库后,执行 update t set b=666 where b=233 和 update t set a=30 where b=666 记录,数据库的记录就变成(30,666)、(30,666),这时候主从数据不统一啦。
因而 MySQL 的 默认隔离离别 抉择了 RR 而不是 RC。RR 隔离级别下,更新数据的时候不仅对更新的行加行级锁,还会加间隙锁(gap lock)。事务 2 要执行时,因为事务 1 减少了间隙锁,就会导致事务 2 执行被卡住,只有等事务 1 提交或者回滚后能力继续执行。
并且,MySQL 还禁止在应用 statement 格局的 binlog 的状况下,应用 READ COMMITTED 作为事务隔离级别。
咱们的数据库隔离级别最初选的是读已提交(RC)。
那为什么 MySQL 官网默认隔离级别是 RR,而有些大厂抉择了 RC 作为默认的隔离级别呢?
- 晋升并发
RC 在加锁的过程中,不须要增加 Gap Lock 和 Next-Key Lock 的,只对要批改的记录增加行级锁就行了。因而 RC 的反对的并发度比 RR 高得多,
- 缩小死锁
正是因为 RR 隔离级别减少了 Gap Lock 和 Next-Key Lock 锁,因而它绝对于 RC,更容易产生死锁。
9. RR 隔离级别实现原理,它是如何解决不可反复读的?
9.1 什么是不可反复读
先回顾下什么是 不可反复读。假如当初有两个事务 A 和 B:
- 事务 A 先查问 Jay 的余额,查到后果是 100
- 这时候事务 B 对 Jay 的账户余额进行扣减,扣去 10 后,提交事务
- 事务 A 再去查问 Jay 的账户余额发现变成了 90
事务 A 被事务 B 烦扰到了!在事务 A 范畴内,两个雷同的查问,读取同一条记录,却返回了不同的数据,这就是不可反复读。
9.2 undo log 版本链 + Read View 可见性规定
RR 隔离级别实现原理,就是 MVCC 多版本并发管制,而 MVCC 是是通过 Read View+ Undo Log 实现的,Undo Log 保留了历史快照,Read View 可见性规定帮忙判断以后版本的数据是否可见。
Undo Log 版本链长这样:
Read view 的几个重要属性
- m_ids: 以后零碎中那些沉闷 (未提交) 的读写事务 ID, 它数据结构为一个 List。
- min_limit_id: 示意在生成 Read View 时,以后零碎中沉闷的读写事务中最小的事务 id,即 m_ids 中的最小值。
- max_limit_id: 示意生成 Read View 时,零碎中应该调配给下一个事务的 id 值。
- creator_trx_id: 创立以后 Read View 的事务 ID
Read view 可见性规定如下:
- 如果数据事务 IDtrx_id < min_limit_id,表明生成该版本的事务在生成 Read View 前,曾经提交(因为事务 ID 是递增的),所以该版本能够被以后事务拜访。
- 如果 trx_id>= max_limit_id,表明生成该版本的事务在生成 Read View 后才生成,所以该版本不能够被以后事务拜访。
- 如果 min_limit_id =<trx_id< max_limit_id, 须要分 3 种状况探讨
3.1 如果 m_ids 蕴含 trx_id, 则代表 Read View 生成时刻,这个事务还未提交,然而如果数据的 trx_id 等于 creator_trx_id 的话,表明数据是本人生成的,因而是可见的。
3.2 如果 m_ids 蕴含 trx_id,并且 trx_id 不等于 creator_trx_id,则 Read View 生成时,事务未提交,并且不是本人生产的,所以以后事务也是看不见的;
3.3 如果 m_ids 不蕴含 trx_id,则阐明你这个事务在 Read View 生成之前就曾经提交了,批改的后果,以后事务是能看见的。
9.3 RR 如何解决不可反复读
查问一条记录,基于 MVCC,是怎么的流程
- 获取事务本人的版本号,即事务 ID
- 获取 Read View
- 查问失去的数据,而后 Read View 中的事务版本号进行比拟。
- 如果不合乎 Read View 的可见性规定,即就须要 Undo log 中历史快照;
- 最初返回合乎规定的数据
假如存在事务 A 和 B,SQL 执行流程如下
在可反复读(RR)隔离级别下,一个事务里只会获取一次 Read View,都是正本共用的,从而保障每次查问的数据都是一样的。
假如以后有一张 core_user 表,插入一条初始化数据, 如下:
基于 MVCC,咱们来看看执行流程
- A 开启事务,首先失去一个事务 ID 为 100
- B 开启事务,失去事务 ID 为 101
- 事务 A 生成一个 Read View,read view 对应的值如下
变量值 m_ids100,101max_limit_id102min_limit_id100creator_trx_id100
而后回到版本链:开始从版本链中筛选可见的记录:
由图能够看出,最新版本的列 name 的内容是孙权,该版本的 trx_id 值为 100。开始执行 read view 可见性规定 校验:
min_limit_id(100)=<trx_id(100)<102;
creator_trx_id = trx_id =100;
由此可得,trx_id=100 的这个记录,以后事务是可见的。所以查到是 name 为孙权 的记录。
- 事务 B 进行批改操作,把名字改为曹操。把原数据拷贝到 undo log, 而后对数据进行批改,标记事务 ID 和上一个数据版本在 undo log 的地址。
- 事务 B 提交事务
- 事务 A 再次执行查问操作,因为是 RR(可反复读)隔离级别,因而 会复用老的 Read View 正本,Read View 对应的值如下
变量值 m_ids100,101max_limit_id102min_limit_id100creator_trx_id100
而后再次回到版本链:从版本链中筛选可见的记录:
从图可得,最新版本的列 name 的内容是曹操,该版本的 trx_id 值为 101。开始执行 read view 可见性规定校验:
min_limit_id(100)=<trx_id(101)<max_limit_id(102);
因为 m_ids{100,101}蕴含 trx_id(101),并且 creator_trx_id (100) 不等于 trx_id(101)
所以,trx_id=101 这个记录,对于以后事务是不可见的。这时候呢,版本链 roll_pointer 跳到下一个版本,trx_id=100 这个记录,再次校验是否可见:
min_limit_id(100)=<trx_id(100)< max_limit_id(102);
因为 m_ids{100,101}蕴含 trx_id(100),并且 creator_trx_id (100) 等于 trx_id(100)
所以,trx_id=100 这个记录,对于以后事务是可见的,所以两次查问后果,都是 name= 孙权的那个记录。即在可反复读(RR)隔离级别下,复用老的 Read View 正本,解决了不可反复读的问题。
10. 你们我的项目应用了 RocketMQ 对吧?那你晓得如何保障音讯不失落吗?
一个音讯从生产者产生,到被消费者生产,次要通过这 3 个过程:
- 生产者产生音讯
- 音讯发送到存储端,保留下来
- 音讯推送到消费者,消费者生产完,ack 应答。
因而如何保障 MQ 不失落音讯,能够从这三个阶段论述:
- 生产者保障不丢音讯
- 存储端不丢音讯
- 消费者不丢音讯
10.1 生产者保障不丢音讯
生产端如何保障不丢音讯呢?确保生产的音讯能顺利达到存储端。
如果是 RocketMQ 消息中间件的话,Producer 生产者提供了三种发送音讯的形式,别离是:
- 同步发送
- 异步发送
- 单向发送
生产者要想发消息时保障音讯不失落,能够:
- 采纳同步形式发送,send 音讯办法返回胜利状态,即音讯失常达到了存储端 Broker。
- 如果 send 音讯异样或者返回非胜利状态,能够发动重试。
- 能够应用事务音讯,RocketMQ 的事务音讯机制就是为了保障零失落来设计的
10.2 存储端不丢音讯
如何保障存储端的音讯不失落呢?确保音讯长久化到磁盘,那就是刷盘机制嘛。
刷盘机制分 同步刷盘和异步刷盘:
- 同步刷盘:生产者音讯发过来时,只有长久化到磁盘,RocketMQ 的存储端 Broker 才返回一个胜利的 ACK 响应。它保障音讯不失落,然而影响了性能。
- 异步刷盘:只有音讯写入 PageCache 缓存,就返回一个胜利的 ACK 响应。这样进步了 MQ 的性能,然而如果这时候机器断电了,就会失落音讯。
除了同步刷盘机制,还有一个维度须要思考。Broker 个别是集群部署的,有主节点和从节点。音讯到 Broker 存储端,只有主节点和从节点都写入胜利,才反馈胜利的 ack 给生产者。这就是 同步复制 ,它保障了音讯不失落,然而升高了零碎的吞吐量。与之对应即是 异步复制,只有音讯写入主节点胜利,就返回胜利的 ack,它速度快,然而会有性能问题。
10.3 生产阶段不丢音讯
消费者 执行完业务逻辑,再反馈会 Broker 说生产胜利,这样才能够保障生产阶段不丢音讯。
11. 事务音讯是否理解?场景题:比方下单清空购物车,你是如何设计的?
事务音讯次要用来解决音讯生产者和音讯消费者的 数据一致性 问题。咱们先来回顾一下:一条一般的音讯队列音讯,从产生到被生产,经验的流程:
- 生产者产生音讯,发送到 MQ 服务器
- MQ 收到音讯后,将音讯长久化到存储系统。
- MQ 服务器返回 ACk 到生产者。
- MQ 服务器把音讯 push 给消费者
- 消费者生产完音讯,响应 ACK
- MQ 服务器收到 ACK,认为音讯生产胜利,即在存储中删除音讯。
音讯队列的事务音讯流程是怎么的呢?
- 生产者产生音讯,发送一条半事务音讯到 MQ 服务器
- MQ 收到音讯后,将音讯长久化到存储系统,这条音讯的状态是待发送状态。
- MQ 服务器返回 ACK 确认到生产者,此时 MQ 不会触发音讯推送事件
- 生产者执行本地事务
- 如果本地事务执行胜利,即 commit 执行后果到 MQ 服务器;如果执行失败,发送 rollback。
- 如果是失常的 commit,MQ 服务器更新音讯状态为可发送;如果是 rollback,即删除音讯。
- 如果音讯状态更新为可发送,则 MQ 服务器会 push 音讯给消费者。消费者生产完就回 ACK。
- 如果 MQ 服务器长时间没有收到生产者的 commit 或者 rollback,它会反查生产者,而后依据查问到的后果执行最终状态。
咱们举个下 订单清空购物车 的例子吧。订单零碎创立完订单后,而后发消息给上游零碎购物车零碎,清空购物车。
- 生产者(订单零碎)产生音讯,发送一条半事务音讯到 MQ 服务器
- MQ 收到音讯后,将音讯长久化到存储系统,这条音讯的状态是待发送状态。
- MQ 服务器返回 ACK 确认到生产者,此时 MQ 不会触发音讯推送事件
- 生产者执行本地事务(订单创立胜利,提交事务音讯)
- 如果本地事务执行胜利,即 commit 执行后果到 MQ 服务器;如果执行失败,发送 rollback。
- 如果是 commit 失常提交,MQ 服务器更新音讯状态为 可发送 ;如果是 rollback,即 删除音讯。
- 如果音讯状态更新为可发送,则 MQ 服务器会 push 音讯给消费者(购物车零碎)。消费者生产完(即拿到订单音讯,清空购物车胜利)就应答 ACK。
- 如果 MQ 服务器长时间没有收到生产者的 commit 或者 rollback,它会反查生产者,而后依据查问到的后果(回滚操作或者从新发送音讯)执行最终状态。
有些搭档可能有纳闷,如果消费者生产失败怎么办呢?那数据是不是不统一啦?所以就须要消费者生产胜利,执行业务逻辑胜利,再反馈 ack 嘛。如果消费者生产失败,那就主动重试嘛,接口反对幂等即可。
12. 如何疾速判断一个数是奇数还是偶数,除开对 2 取余呢。
判断一个数是奇数还是偶数,咱们最容易想到的就是对 2 取余。
if(x % 2)
// 奇数
else
// 偶数
还有一种办法,就是与 1 相与(&1),具体实现如下:
if(x & 1)
// 奇数
else
// 偶数
13. Spring 申明式事务原理?哪些场景事务会生效?
13.1 申明式事务原理
spring 申明式事务,即 @Transactional, 它能够帮忙咱们把事务开启、提交或者回滚的操作,通过 Aop 的形式进行治理。
在 spring 的 bean 的初始化过程中,就须要对实例化的 bean 进行代理,并且生成代理对象。生成代理对象的代理逻辑中,进行办法调用时,须要先获取切面逻辑,@Transactional 注解的切面逻辑相似于 @Around,在 spring 中是实现一种相似代理逻辑。
13.2 spring 申明式事务哪些场景会生效
- 办法的拜访权限必须是 public,其余 private 等权限,事务生效
- 办法被定义成了 final 的,这样会导致事务生效。
- 在同一个类中的办法间接外部调用,会导致事务生效。
- 一个办法如果没交给 spring 治理,就不会生成 spring 事务。
- 多线程调用,两个办法不在同一个线程中,获取到的数据库连贯不一样的。
- 表的存储引擎不反对事务
- 如果本人 try…catch 误吞了异样,事务生效。
- 谬误的流传
14. 你们是微服务架构嘛?如果你来设计一个相似淘宝的零碎,你怎么划分微服务?
能够按业务畛域、性能、重要水平进行划分。
- 能够按业务畛域,把用户、社区、商品信息、音讯等模块等划分。
- 繁多性能职责,按性能拆分,比方订单、领取、物流、权限。
- 按重要水平划分,辨别外围和非核心性能,比方领取、订单就是外围性能。
15. 你们是怎么分库分表的?分布式 ID 如何生成?
如果是咱们公司的话,应用了程度分库的形式,就是一个用户注册时,就划分了属于哪个数据库,而后具体的表构造是一样的。
业界还有垂直分库,就是依照不同的零碎中的不同业务进行拆分,比方拆分成用户库、订单库、积分库、商品库,把它们部署在不同的数据库服务器。
分表的话也有程度分表和垂直分表,垂直分表就是将一些不罕用的、数据较大或者长度较长的列拆分到另外一张表,程度分表就是能够依照某种规定(如 hash 取模、range),把数据切分到多张表去。一张订单表,按工夫 range 拆分如下:
range 划分利于数据迁徙,然而存在数据热点问题。hash 取模划分,不会存在显著的热点问题,然而不利于扩容。能够 range+hash 取模联合应用。
分布式 ID 能够应用雪花算法生成
雪花算法是一种生成分布式全局惟一 ID 的算法,生成的 ID 称为 Snowflake IDs。这种算法由 Twitter 创立,并用于推文的 ID。
一个 Snowflake ID 有 64 位。
- 第 1 位:Java 中 long 的最高位是符号位代表正负,负数是 0,正数是 1,个别生成 ID 都为负数,所以默认为 0。
- 接下来前 41 位是工夫戳,示意了自选定的期间以来的毫秒数。
- 接下来的 10 位代表计算机 ID,避免抵触。
- 其余 12 位代表每台机器上生成 ID 的序列号,这容许在同一毫秒内创立多个 Snowflake ID。
16. 所有异样的独特的先人是?运行时异样有哪几个?
Java 异样的顶层父类是 Throwable,它生了两个儿子,大儿子叫 Error, 二儿子叫 Exception。
- Error:是程序⽆法解决的谬误,个别示意零碎谬误,例如虚拟机相干的谬误 OutOfMemoryError
- Exception:程序自身能够解决的异样。它能够分为 RuntimeException(运行时异样)和 CheckedException(可查看的异样)。
什么是 RuntimeException(运行时异样)?
运行时异样是不查看异样,程序中能够抉择捕捉解决,也能够不解决。这些异样个别是由程序逻辑谬误引起的,程序应该从逻辑角度尽可能防止这类异样的产生。
常见的RuntimeException 异样:
- NullPointerException:空指针异样
- ArithmeticException:出现异常的运算条件时,抛出此异样
- IndexOutOfBoundsException:数组索引越界异样
- ClassNotFoundException:找不到类异样
- IllegalArgumentException(非法参数异样)
什么是CheckedException(可查看的异样)?
从程序语法角度讲是必须进行解决的异样,如果不解决,程序就不能编译通过。如 IOException、SQLException 等。
常见的 Checked Exception 异样:
- IOException:(操作输出流和输入流时可能呈现的异样)
- SQLException