|
1 | 1 | * [Java基础](#java基础) |
2 | | - * [1.说下面向对象四大特性](#1说下面向对象四大特性) |
3 | | - * [2.抽象类和接口(Java7)的区别](#2抽象类和接口java7的区别) |
4 | | - * [3.Java 8的接口新增了哪些特性?](#3java-8的接口新增了哪些特性) |
5 | | - * [4.重写和重载的区别](#4重写和重载的区别) |
6 | | - * [5.ArrayList和LinkedList有什么区别?](#5arraylist和linkedlist有什么区别) |
| 2 | + * [1.说下面向对象四大特性](#1说下面向对象四大特性) |
| 3 | + * [2.抽象类和接口(Java7)的区别](#2抽象类和接口java7的区别) |
| 4 | + * [3.Java 8的接口新增了哪些特性?](#3java-8的接口新增了哪些特性) |
| 5 | + * [4.重写和重载的区别](#4重写和重载的区别) |
| 6 | + * [5.ArrayList和LinkedList有什么区别?](#5arraylist和linkedlist有什么区别) |
7 | 7 | * [6.HashMap是怎么实现的?](#6hashmap是怎么实现的) |
8 | 8 | * [7.HashMap在Java7和Java8中的实现有什么不同?](#7hashmap在java7和java8中的实现有什么不同) |
9 | 9 | * [8.HashMap有时候会死循环,你知道是什么原因吗?](#8hashmap有时候会死循环你知道是什么原因吗) |
@@ -640,264 +640,4 @@ Redis6.0之前,IO线程和执行线程都是单线程的。 |
640 | 640 | 缓存失效指的是大量的缓存在同一时间失效,到时DB的瞬间压力飙升。造成这种现象的原因是,key的过期时间都设置成一样了。解决方案是,key的过期时间引入随机因素,比如5分钟+随机秒这种方式。 |
641 | 641 |
|
642 | 642 | 2. 缓存穿透 |
643 | | -缓存穿透是指查询一条数据库和缓存都没有的一条数据,就会一直查询数据库,对数据库的访问压力就会增大,缓存穿透的解决方案,有以下2种: |
644 | | -缓存空对象:代码维护较简单,但是效果不好。 |
645 | | -布隆过滤器:代码维护复杂,效果很好。 |
646 | | - |
647 | | -3. 缓存雪崩 |
648 | | -缓存雪崩 是指在某一个时间段,缓存集中过期失效。此刻无数的请求直接绕开缓存,直接请求数据库。 |
649 | | -造成缓存雪崩的原因,有以下2种: |
650 | | -reids宕机。 |
651 | | -大部分数据失效。 |
652 | | - |
653 | | -对于缓存雪崩的解决方案有以下2种: |
654 | | -搭建高可用的集群,防止单机的redis宕机。 |
655 | | -设置不同的过期时间,防止同意之间内大量的key失效。 |
656 | | - |
657 | | -4. 缓存并发 |
658 | | -有时候如果网站并发访问高,一个缓存如果失效,可能出现多个进程同时查询DB,同时设置缓存的情况,如果并发确实很大,这也可能造成DB压力过大,还有缓存频繁更新的问题。 |
659 | | -一般处理方案是在查DB的时候进行加锁,如果KEY不存在,就加锁,然后查DB入缓存,然后解锁;其他进程如果发现有锁就等待,然后等解锁后再查缓存或者进入DB查询。 |
660 | | - |
661 | | -#### Redis中的热key怎么处理? |
662 | | - |
663 | | -1、对热key进行分散处理。比如:在key上加上不同的前后缀,缓存多个key,使得各个key分散到不同的节点上。 |
664 | | -2、采用多级缓存。 |
665 | | - |
666 | | -#### Redis中的大key怎么处理? |
667 | | - |
668 | | -大key指的是value特别大的key。比如很长的字符串,或者很大的set等等。 |
669 | | -大key会造成2个问题:1、数据倾斜,比如某些节点内存占用过高。2、当删除大key或者大key自动过期的时候,会造成QPS突降,因为Redis是单线程的缘故。 |
670 | | -处理方案:可以将一个大key进行分片处理,比如:将一个大set分成多个小的set。 |
671 | | - |
672 | | -#### 使用Redis统计网站的UV,应该怎么做? |
673 | | - |
674 | | -UV与PV不同,UV需要去重。一般有2种方案: |
675 | | -1、用BitMap。存的是用户的uid,计算UV的时候,做下bitcount就行了。 |
676 | | -2、用布隆过滤器。将每次访问的用户uid都放到布隆过滤器中。优点是省内存,缺点是无法得到精确的UV。但是对于不需要精确知道具体UV,只需要大概的数量级的场景,是个不错的选择。 |
677 | | - |
678 | | -#### Redis事务机制了解过吗? |
679 | | - |
680 | | -Redis事务的概念: |
681 | | -Redis 事务的本质是一组命令的集合。事务支持一次执行多个命令,一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。 |
682 | | -Redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令。 |
683 | | - |
684 | | -Redis事务没有隔离级别的概念: |
685 | | -批量操作在发送 EXEC 命令前被放入队列缓存,并不会被实际执行,也就不存在事务内的查询要看到事务里的更新,事务外查询不能看到。 |
686 | | -Redis不保证原子性: |
687 | | -Redis中,单条命令是原子性执行的,但事务不保证原子性,且没有回滚。事务中任意命令执行失败,其余的命令仍会被执行。 |
688 | | - |
689 | | -Redis事务的三个阶段: |
690 | | -开始事务 |
691 | | -命令入队 |
692 | | -执行事务 |
693 | | - |
694 | | -Redis事务相关命令: |
695 | | -watch key1 key2 ... : 监视一或多个key,如果在事务执行之前,被监视的key被其他命令改动,则事务被打断 ( 类似乐观锁 ) |
696 | | -multi : 标记一个事务块的开始( queued ) |
697 | | -exec : 执行所有事务块的命令 ( 一旦执行exec后,之前加的监控锁都会被取消掉 ) |
698 | | -discard : 取消事务,放弃事务块中的所有命令 |
699 | | -unwatch : 取消watch对所有key的监控 |
700 | | - |
701 | | -#### Redis key的淘汰策略有哪些? |
702 | | - |
703 | | -8种:noeviction,volatile-lru,volatile-lfu,volatile-ttl,volatile-random,allkey-lru,allkeys-lfu,allkeys-random |
704 | | - |
705 | | -#### Redis在什么情况下会触发key的回收? |
706 | | - |
707 | | -2种情况:1、定时(抽样)清理;2、执行命令时,判断内存是否超过maxmemory。 |
708 | | - |
709 | | -#### Redis的持久化了解过吗? |
710 | | - |
711 | | -Redis持久化有RDB和AOF这2种方式。 |
712 | | -RDB:将数据库快照以二进制的方式保存到磁盘中。 |
713 | | -AOF:以协议文本方式,将所有对数据库进行过写入的命令和参数记录到AOF文件,从而记录数据库状态。 |
714 | | - |
715 | | -#### Redis在集群种查找key的时候,是怎么定位到具体节点的? |
716 | | - |
717 | | -使用crc16算法对key进行hash |
718 | | -将hash值对16384取模,得到具体的槽位 |
719 | | -根据节点和槽位的映射信息(与集群建立连接后,客户端可以取得槽位映射信息),找到具体的节点地址 |
720 | | -去具体的节点找key |
721 | | -如果key不在这个节点上,则redis集群会返回moved指令,加上新的节点地址给客户端,同时,客户端会刷新本地的节点槽位映射关系 |
722 | | -如果槽位正在迁移中,那么redis集群会返回asking指令给客户端,这是临时纠正,客户端不会刷新本地的节点槽位映射关系 |
723 | | - |
724 | | -#### Redis集群各个节点之间是怎么保持数据一致性的? |
725 | | - |
726 | | -主要考察点是Redis的Gossip协议。 |
727 | | -详见:https://mp.weixin.qq.com/s/dW0I29Sw86lU0qHpxyhdmw |
728 | | - |
729 | | -#### 用Redis做延时队列,具体应该怎么实现? |
730 | | - |
731 | | -可以使用Zset实现。member是任务描述,score是执行时间,然后用定时器定时去扫描,一旦有执行时间小于或等于当前时间的任务,就立即执行。 |
732 | | - |
733 | | -#### Redis String的内部编码有哪些? |
734 | | - |
735 | | -int、embstr、raw |
736 | | -10000以下的整数会使用缓存里的int常量。 |
737 | | -长度小于等于44字节:embstr编码 |
738 | | -长度大于44字节:raw编码 |
739 | | - |
740 | | -## Spring |
741 | | - |
742 | | -#### Spring是怎么解决循环依赖的? |
743 | | - |
744 | | -整个IOC容器解决循环依赖,用到的几个重要成员: |
745 | | -singletonObjects:一级缓存,存放完全初始化好的Bean的集合,从这个集合中取出来的Bean可以立马返回 |
746 | | -earlySingletonObjects:二级缓存,存放创建好但没有初始化属性的Bean的集合,它用来解决循环依赖 |
747 | | -singletonFactories:三级缓存,存放单实例Bean工厂的集合 |
748 | | -singletonsCurrentlyInCreation:存放正在被创建的Bean的集合 |
749 | | - |
750 | | -IOC容器解决循环依赖的思路: |
751 | | -1. 初始化Bean之前,将这个BeanName放入三级缓存 |
752 | | -2. 创建Bean将准备创建的Bean放入 singletonsCurrentlyInCreation (正在创建的Bean) |
753 | | -3. createNewInstance 方法执行完后执行 addSingletonFactory,将这个实例化但没有属性赋值的Bean放入二级缓存,并从三级缓存中移除 |
754 | | -4. 属性赋值&自动注入时,引发关联创建 |
755 | | -5. 关联创建时,检查“正在被创建的Bean”中是否有即将注入的Bean。如果有,检查二级缓存中是否有当前创建好但没有赋值初始化的Bean。如果没有,检查三级缓存中是否有正在创建中的Bean。至此一般会有,将这个Bean放入二级缓存,并从三级缓存中移除 |
756 | | -6. 之后Bean被成功注入,最后执行 addSingleton,将这个完全创建好的Bean放入一级缓存,从二级缓存和三级缓存移除,并记录已经创建了的单实例Bean |
757 | | - |
758 | | -#### Spring Boot手动装配有哪几种方式? |
759 | | - |
760 | | -1. 使用模式注解 @Component 等(Spring2.5+) |
761 | | -2. 使用配置类 @Configuration 与 @Bean (Spring3.0+) |
762 | | -3. 使用模块装配 @EnableXXX 与 @Import (Spring3.1+) |
763 | | - |
764 | | -其中使用 @Component 及衍生注解很常见,咱开发中常用的套路,不再赘述。 |
765 | | -但模式注解只能在自己编写的代码中标注,无法装配jar包中的组件。为此可以使用 @Configuration 与 @Bean,手动装配组件(如上一篇的 @Configuration 示例)。但这种方式一旦注册过多,会导致编码成本高,维护不灵活等问题。 |
766 | | -SpringFramework 提供了模块装配功能,通过给配置类标注 @EnableXXX 注解,再在注解上标注 @Import 注解,即可完成组件装配的效果。 |
767 | | - |
768 | | -#### Spring Boot自动配置原理 |
769 | | - |
770 | | -详见:https://blog.csdn.net/Dongguabai/article/details/80865599 |
771 | | - |
772 | | -## Netty |
773 | | - |
774 | | -#### 你了解过哪些IO模型? |
775 | | - |
776 | | -详见:https://www.cnblogs.com/sharing-java/p/10791802.html |
777 | | - |
778 | | -#### 什么是Reactor模型?Reactor的3种版本都知道吗? |
779 | | - |
780 | | -Reactor模式究竟是个什么东西呢?这要从事件驱动的开发方式说起。我们知道,对于应用服务器,一个主要规律就是,CPU的处理速度是要远远快于IO速度的,如果CPU为了IO操作(例如从Socket读取一段数据)而阻塞显然是不划算的。好一点的方法是分为多进程或者线程去进行处理,但是这样会带来一些进程切换的开销,试想一个进程一个数据读了500ms,期间进程切换到它3次,但是CPU却什么都不能干,就这么切换走了,是不是也不划算? |
781 | | -这时先驱们找到了事件驱动,或者叫回调的方式,来完成这件事情。这种方式就是,应用业务向一个中间人注册一个回调(event handler),当IO就绪后,就这个中间人产生一个事件,并通知此handler进行处理。这种回调的方式,也体现了“好莱坞原则”(Hollywood principle)-“Don't call us, we'll call you”,在我们熟悉的IoC中也有用到。看来软件开发真是互通的! |
782 | | -好了,我们现在来看Reactor模式。在前面事件驱动的例子里有个问题:我们如何知道IO就绪这个事件,谁来充当这个中间人?Reactor模式的答案是:由一个不断等待和循环的单独进程(线程)来做这件事,它接受所有handler的注册,并负责先操作系统查询IO是否就绪,在就绪后就调用指定handler进行处理,这个角色的名字就叫做Reactor。 |
783 | | - |
784 | | -Reactor的3种版本:单线程模式、多线程模式、主从多线程模式 |
785 | | - |
786 | | -#### 了解过粘包拆包吗?为什么会出现粘包拆包?怎么处理粘包拆包? |
787 | | - |
788 | | -粘包的主要原因:发送方写入数据<套接字缓冲区大小;接收方读取套接字缓冲区数据不够及时。 |
789 | | - |
790 | | -拆包的主要原因:发送方写入数据>套接字缓冲区大小;发送方发送的数据大于协议的MTU(最大传输单元),不得已必须拆包。 |
791 | | - |
792 | | -如何处理:1、消息长度固定;2、消息之间用分隔符分隔;3、在消息头保留一个字段,用于描述消息的长度。 |
793 | | - |
794 | | -#### UDP协议会有粘包拆包的问题吗?为什么? |
795 | | - |
796 | | -UDP不会有这个问题。 |
797 | | -因为TCP是“数据流”协议,UDP是“数据报”协议。 |
798 | | -UDP协议的数据包之间是没有联系,而且有明确边界的。 |
799 | | - |
800 | | -## 微服务 |
801 | | - |
802 | | -#### 微服务有哪些优缺点? |
803 | | - |
804 | | -优点: |
805 | | -独立的可扩展性,每个微服务都可以独立进行横向或纵向扩展,根据业务实际增长情况来进行快速扩展; |
806 | | -独立的可升级性,每个微服务都可以独立进行服务升级、更新,不用依赖于其它服务,结合持续集成工具可以进行持续发布,开发人员就可以独立快速完成服务升级发布流程; |
807 | | -易维护性,每个微服务的代码均只专注于完成该单个业务范畴的事情,因此微服务项目代码数量将减少至IDE可以快速加载的大小,这样可以提高了代码的可读性,进而可以提高研发人员的生产效率; |
808 | | -语言无关性,研发人员可以选用自己最为熟悉的语言和框架来完成他们的微服务项目(当然,一般根据每个公司的实际技术栈需要来了),这样在面对新技术或新框架的选用时,微服务能够更好地进行快速响应; |
809 | | -故障和资源的隔离性,在系统中出现不好的资源操作行为时,例如内存泄露、数据库连接未关闭等情况,将仅仅只会影响单个微服务; |
810 | | -优化跨团队沟通,如果要完全实践微服务架构设计风格,研发团队势必会按照新的原则来进行划分,由之前的按照技能、职能划分的方式变为按照业务(单个微服务)来进行划分,如此这般团队里将有各个方向技能的研发人员,沟通效率上来说要优于之前按照技能进行划分的组织架构; |
811 | | -原生基于“云”的系统架构设计,基于微服务架构设计风格,我们能构建出来原生对于“云”具备超高友好度的系统,与常用容器工具如Docker能够很方便地结合,构建持续发布系统与IaaS、PaaS平台对接,使其能够方便的部署于各类“云”上,如公用云、私有云以及混合云。 |
812 | | - |
813 | | -缺点: |
814 | | -增加了系统复杂性; |
815 | | -运维难度增加; |
816 | | -本地调用变成RPC调用,接口耗时增加; |
817 | | -可能会引入分布式事务。 |
818 | | - |
819 | | -#### 作为注册中心,Zookeeper和Eureka有什么区别? |
820 | | - |
821 | | -详见:https://mp.weixin.qq.com/s/B6F9Ea1GnDIou41Po3NMAQ |
822 | | - |
823 | | -#### Service Mesh了解过吗? |
824 | | - |
825 | | -详见:https://www.jianshu.com/p/27a742e349f7 |
826 | | - |
827 | | -## Zookeeper |
828 | | - |
829 | | -#### Zookeeper有哪些节点类型? |
830 | | - |
831 | | -4种:持久节点、持久有序节点、临时节点、临时有序节点。 |
832 | | - |
833 | | -#### 了解过Zookeeper的ZAB协议吗? |
834 | | - |
835 | | -详见:https://blog.csdn.net/liuchang19950703/article/details/111406622 |
836 | | - |
837 | | -#### Zookeeper怎么实现分布式锁? |
838 | | - |
839 | | -详见:https://blog.csdn.net/crazymakercircle/article/details/85956246 |
840 | | - |
841 | | -#### Zookeeper是怎么保证数据一致性的? |
842 | | - |
843 | | -详见:https://blog.csdn.net/liuchang19950703/article/details/111406622 |
844 | | - |
845 | | -#### Zookeeper Leader选举过程是怎样的? |
846 | | - |
847 | | -详见:https://blog.csdn.net/liuchang19950703/article/details/111406622 |
848 | | - |
849 | | -#### Zookeeper怎么实现服务注册? |
850 | | - |
851 | | -详见:https://segmentfault.com/a/1190000019670015 |
852 | | - |
853 | | -## 消息队列 |
854 | | - |
855 | | -#### 消息队列有哪些应用场景? |
856 | | - |
857 | | -异步处理、流量控制、服务解耦、消息广播 |
858 | | - |
859 | | -#### 消息队列的弊端有哪些? |
860 | | - |
861 | | -数据延迟;增加系统复杂度;可能产生数据不一致的问题。 |
862 | | - |
863 | | -#### 使用消息队列,怎么确保消息不丢失? |
864 | | - |
865 | | -在生产阶段,你需要捕获消息发送的错误,并重发消息。 |
866 | | -在存储阶段,你可以通过配置刷盘和复制相关的参数,让消息写入到多个副本的磁盘上,来确保消息不会因为某个 Broker 宕机或者磁盘损坏而丢失。 |
867 | | -在消费阶段,你需要在处理完全部消费业务逻辑之后,再发送消费确认。 |
868 | | - |
869 | | -#### 使用消息队列,如果处理重复消息? |
870 | | - |
871 | | -1)利用数据库的唯一约束实现幂等 |
872 | | -2)为更新的数据设置前置条件(CAS) |
873 | | -3)记录并检查操作(在发送消息时,给每条消息指定一个全局唯一的 ID,消费时,先根据这个 ID 检查这条消息是否有被消费过,如果没有消费过,才更新数据,然后将消费状态置为已消费。) |
874 | | - |
875 | | -#### Kafka的消息是有序的吗?如果保证Kafka消息的顺序性? |
876 | | - |
877 | | -Kafka只能保证局部有序,即只能保证一个分区里的消息有序。而其具体实现是通过生产者为每个分区的消息维护一个发送队列,我们需要将保证顺序的消息都发送到同一个分区中。并且由于Kafka会同时发送多个消息,所以还需指定max.in.flight.requests.per.connection为1,保证前一个消息发送成功,后一个消息才开始发送。 |
878 | | - |
879 | | -## 计算机网络 |
880 | | - |
881 | | -#### 说下TCP三次握手的过程 |
882 | | - |
883 | | -详见:https://baijiahao.baidu.com/s?id=1654225744653405133 |
884 | | - |
885 | | -#### TCP为什么需要3次握手 |
886 | | - |
887 | | -主要原因是为了防止旧的重复连接引起连接混乱问题。 |
888 | | -比如在网络状况比较复杂或者网络状况比较差的情况下,发送方可能会连续发送多次建立连接的请求。如果 TCP 握手的次数只有两次,那么接收方只能选择接受请求或者拒绝接受请求,但它并不清楚这次的请求是正常的请求,还是由于网络环境问题而导致的过期请求,如果是过期请求的话就会造成错误的连接。 |
889 | | -所以如果 TCP 是三次握手的话,那么客户端在接收到服务器端 SEQ+1 的消息之后,就可以判断当前的连接是否为历史连接,如果判断为历史连接的话就会发送终止报文(RST)给服务器端终止连接;如果判断当前连接不是历史连接的话就会发送指令给服务器端来建立连接。 |
890 | | - |
891 | | -#### TCP为什么需要4次挥手 |
892 | | - |
893 | | -TCP协议是一种面向连接的、可靠的、基于字节流的运输层通信协议。TCP是全双工模式,这就意味着,当主机1发出FIN报文段时,只是表示主机1已经没有数据要发送了,主机1告诉主机2,它的数据已经全部发送完毕了;但是,这个时候主机1还是可以接受来自主机2的数据;当主机2返回ACK报文段时,表示它已经知道主机1没有数据发送了,但是主机2还是可以发送数据到主机1的;当主机2也发送了FIN报文段时,这个时候就表示主机2也没有数据要发送了,就会告诉主机1,我也没有数据要发送了,之后彼此就会愉快的中断这次TCP连接。 |
894 | | - |
895 | | -#### TCP time_wait状态是主动断开方才有,还是被动断开方才有?还是两边都有? |
896 | | - |
897 | | -主动断开方才有 |
898 | | - |
899 | | -#### TCP的keepalive机制了解过吗? |
900 | | - |
901 | | -详见:https://blog.csdn.net/chrisnotfound/article/details/80111559https://blog.csdn.net/chrisnotfound/article/details/80111559 |
902 | | - |
903 | | -#### HTTP的keepalive和TCP的keepalive, |
| 643 | +缓存穿透 |
0 commit comments