java面试题(商汤科技)

商汤
1.简历写什么问什么,注意所⽤技术产品的同类产品⽣态及对⽐。
2.kafka数据分区和消费者的关系,kafka的数据offset读取流程,kafka内部如何保证顺序,结合外部组件如何保证消费者的顺序
1、kafka数据分区和消费者的关系:1个partition只能被同组的⼀个consumer消费,同组的consumer则起到均衡效果
2、kafka的数据offset读取流程
1.连接ZK集群,从ZK中拿到对应topic的partition信息和partition的Leader的相关信息
2.连接到对应Leader对应的broker
3.consumer将⾃⼰保存的offset发送给Leader
4.Leader根据offset等信息定位到segment(索引⽂件和⽇志⽂件)
5.根据索引⽂件中的内容,定位到⽇志⽂件中该偏移量对应的开始位置读取相应⻓度的数据并返回给consumer
3、kafka内部如何保证顺序:
kafka只能保证partition内是有序的,但是partition间的有序是没办法的。爱奇艺的搜索架构,是从业务上把需要有序的打到同⼀
个partition。
4、
3.cms垃圾回收机制
1、概念:CMS全称 Concurrent Mark Sweep,是⼀款并发的、使⽤标记-清除算法的垃圾回收器,
2、使⽤场景:GC过程短暂停,适合对时延要求较⾼的服务,⽤户线程不允许⻓时间的停顿。
3、缺点:
1、服务⻓时间运⾏,造成严重的内存碎⽚化。
2、算法实现⽐较复杂(如果也算缺点的话)。
4、实现机制:根据GC的触发机制分为:
1、周期性Old GC(被动):2s执⾏⼀次;
2、主动Old GC:触发条件:
i. YGC过程发⽣Promotion Failed,进⽽对⽼年代进⾏回收
ii. ⽐如执⾏了System.gc(),前提是没有参数ExplicitGCInvokesConcurrent
iii. 其它情况…
4.springcloud各个组件功能,内部细节,与dubbo区别,dubbo架构,dubbo负载策略
1、springcloud各个组件功能:
a. Ribbon,客户端负载均衡,特性有区域亲和、重试机制。
b. Hystrix,客户端容错保护,特性有服务降级、服务熔断、请求缓存、请求合并、依赖隔离。
c. Feign,声明式服务调⽤,本质上就是Ribbon+Hystrix
d. Stream,消息驱动,有Sink、Source、Processor三种通道,特性有订阅发布、消费组、消息分区。
e. Bus,消息总线,配合Config仓库修改的⼀种Stream实现,
f. Sleuth,分布式服务追踪,需要搞清楚TraceID和SpanID以及抽样,如何与ELK整合。
g. Eureka,服务注册中⼼,特性有失效剔除、服务保护。
h. Dashboard,Hystrix仪表盘,监控集群模式和单点模式,其中集群模式需要收集器Turbine配合。
i. Zuul,API服务⽹关,功能有路由分发和过滤。
j. Config,分布式配置中⼼,⽀持本地仓库、SVN、Git、Jar包内配置等模式,
2、dubbo负载策略:
5.mapreduce原理
1、简介:mapreduce源⾃google的⼀篇⽂章,将海量数据处理的过程拆分为map和reduce。mapreduce 成为了最早的分布式计算框
架,这样即使不懂的分布式计算框架的内部运⾏机制的⽤户,也可以利⽤分布式的计算框架实现分布式的计算,并在hadoop上⾯运⾏。
2、设计思想:
hadoop ⽂件系统 ,提供了⼀个分布式的⽂件系统,但是hadoop⽂件系统读写的操作都涉及到⼤量的⽹络的操作,并不能很好
的完成实时性⽐较强的任务。
但是hadoop可以给上⾯的应⽤提供⼀个很好的⽀持。⽐如hadoop⽂件系统上⾯可以运⾏mapreduce。mapreduce是⼀个计算的
框架,mapreduce是⼀个分布式的计算框架,这样mapreduce利⽤分布式的⽂件系统,将不同的机器上完成不同的计算,然后就计算结果
返回。这样很好的利⽤了分布式的⽂件系统。
数据分布式的存储,然后计算的时候,分布式的计算,然后将结果返回。这样的好处就是不会涉及到⼤量的⽹络传输数据。
3、优点:mapreduce的计算框架的优点是,极强的扩展能⼒,可以在数千台机器上并发的执⾏。其次,有很好的容错性,另外,就
是向上的接⼝简洁。⽤户只需要写map和reduce函数,即可完成⼤规模数据的并⾏处理。
4、缺点:mapreduce并不适合对实时性要求⽐较⾼的场景,⽐如交互式查询或者是流式计算。另外,也不适合迭代类的计算(⽐如
机器学习类的应⽤)。
1、mapreduce的启动时间⽐较长,对于批处理的任务,这个问题并不算⼤。但是对于实时性⽐较⾼的任务,其启动时间长的缺点就很
不合适了。
2、mapreduce⼀次执⾏的过程⾥⾯,往往涉及到多出磁盘读写,以及⽹络的传输。对于迭代的任务,这样很好的开销需要很多次,明
显降低了效率。
3、⽽Storm和Spark,⼀个是流式计算的框架,⼀个是机器学习的框架。他们更适合解决这类型的任务。
6.nio,bio,sellector/epoll,aio,netty⾃带编解码器,netty优势,java内存模型
Netty⾼性能:
1、NIO异步⾮阻塞通信
2、“零拷⻉”
3、内存池ByteBuf
4、Netty提供了多种内存管理策略,通过在启动辅助类中配置相关参数,可以实现差异化的定制。
5、⾼效的Reactor线程模型:Reactor单线程(多线程、主从)模型,指的是所有的IO操作都在同⼀个NIO线程上⾯完成
6、为了尽可能提升性能,Netty采⽤了串⾏⽆锁化设计,在IO线程内部进⾏串⾏操作,避免多线程竞争导致的性能下降。表⾯上看,串⾏
化设计似乎CPU利⽤率不⾼,并发程度不够。但是,通过调整NIO线程池的线程参数,可以同时启动多个串⾏化的线程并⾏运⾏,这种局部⽆锁化的串
⾏线程设计相⽐⼀个队列-多个⼯作线程模型性能更优。
7、⾼效的并发编程:Netty的⾼效并发编程主要体现在如下⼏点:

  1. volatile的⼤量、正确使⽤;
  2. CAS和原⼦类的⼴泛使⽤;
  3. 线程安全容器的使⽤;
  4. 通过读写锁提升并发性能。
    8、⾼效的序列化框架:
    9、灵活的TCP参数配置能⼒:合理设置TCP参数在某些场景下对于性能的提升可以起到显著的效果,例如SO_RCVBUF和SO_SNDBUF。如果
    设置不当,对性能的影响是⾮常⼤的。
    7.akka模型
    1、概念:Akka是⼀个构建在JVM上,基于Actor模型的的并发框架,为构建伸缩性强,有弹性的响应式并发应⽤提⾼更好的平台。
    2、Actor模型:Akka的核⼼就是Actor,所以不得不说Actor,Actor模型我通俗的举个例⼦,假定现实中的两个⼈,他们只知道对⽅
    的地址,他们想要交流,给对⽅传递信息,但是⼜没有⼿机,电话,⽹络之类的其他途径,所以他们之间只能⽤信件传递消息,很像
    现实中的的邮政系统,你要寄⼀封信,只需根据地址把信投寄到相应的信箱中,具体它是如何帮你处理送达的,你就不需要了解了,
    你也有可能收到收信⼈的回复,这相当于消息反馈。上述例⼦中的信件就相当于Actor中的消息,Actor与Actor之间只能通过消息通
    信。
    8.java arraylist,linkedlist区分及实现原理,hashmap和concurrenthashmap区分及实现原理,concurrenthashmap 1.7和1.8区分,
    实现细节,linkedhashmap排序原理,应⽤如何保证数据幂等
    1、java arraylist,linkedlist区分及实现原理:
  1. ArrayList是实现了基于动态数组的数据结构,⽽LinkedList是基于链表的数据结构;
  2. 对于随机访问get和set,ArrayList要优于LinkedList,因为LinkedList要移动指针;
  3. 对于添加和删除操作add和remove,⼀般⼤家都会说LinkedList要⽐ArrayList快,因为ArrayList要移动数据。
    2、concurrenthashmap 1.7和1.8区分:
    去除 Segment + HashEntry + Unsafe的实现,
    改为 Synchronized + CAS + Node + Unsafe的实现
    其实 Node 和 HashEntry 的内容⼀样,但是HashEntry是⼀个内部类。
    ⽤ Synchronized + CAS 代替 Segment ,这样锁的粒度更⼩了,并且不是每次都要加锁了,CAS尝试失败了在加锁。
    put()⽅法中 初始化数组⼤⼩时,1.8不⽤加锁,因为⽤了个 sizeCtl变量,将这个变量置为-1,就表明table正在初始化。
    3、linkedhashmap排序原理:
    1 public LinkedHashMap() {
    2 // 调⽤HashMap的构造⽅法,其实就是初始化Entry[] table
    3 super();
    4 // 这⾥是指是否基于访问排序,默认为false
    5 accessOrder = false;
    6 }
    1、LinkedHashMap存储数据是有序的,⽽且分为两种:插⼊顺序和访问顺序。默认为插⼊顺序。
    2、LinkedHashMap有⾃⼰的静态内部类Entry,它继承了HashMap.Entry,定义如下:
    1 /**
    2 * LinkedHashMap entry.
    3 /
    4 private static class Entry<K,V> extends HashMap.Entry<K,V> {
    5 // These fields comprise the doubly linked list used for iteration.
    6 Entry<K,V> before, after;
    7
    8 Entry(int hash, K key, V value, HashMap.Entry<K,V> next) {
    9 super(hash, key, value, next);
    10 }
    11 }
    3、所以LinkedHashMap构造函数,主要就是调⽤HashMap构造函数初始化了⼀个Entry[] table,然后调⽤⾃身的init初始化了⼀
    个只有头结点的双向链表。
    9.web.xml listener,filter,servlet加载顺序。如何不再web,xml中配置来加载filter
    1、web.xml listener,filter,servlet加载顺序:context-param -> listener -> filter -> servlet
    2、
    10.⽆穷数就top K问题,提供多个⽅案
    1、最简单且最容易想到的算法是对数组进⾏排序(快速排序),然后取最⼤或最⼩的K个元素。总的时间复杂度为
    O(N
    logN)+O(K)=O(N*logN)。该算法存在以下问题:
  4. 快速排序的平均复杂度为O(N*logN),但最坏时间复杂度为O(n2),不能始终保证较好的复杂度
  5. 只需要前k⼤或k⼩的数,,实际对其余不需要的数也进⾏了排序,浪费了⼤量排序时间
    总结:通常不会采取该⽅案。
    2、虽然我们不会采⽤快速排序的算法来实现TOP-K问题,但我们可以利⽤快速排序的思想,在数组中随机找⼀个元素key,将数组分
    成两部分Sa和Sb,其中Sa的元素>=key,Sb的元素<key,然后分析两种情况:
  6. 若Sa中元素的个数⼤于或等于k,则在Sa中查找最⼤的k个数
  7. 若Sa中元素的个数⼩于k,其个数为len,则在Sb中查找k-len个数字
    如此递归下去,不断把问题分解为更⼩的问题,直到求出结果。
    3、寻找N个数中的第K⼤的数,可以将问题转化寻找N个数中第K⼤的问题。对于⼀个给定的数p, 可以在O(N)的时间复杂度内找出
    所有不⼩于P的数。
    根据分析,可以使⽤⼆分查找的算法思想来寻找N个数中第K⼤的数。假设N个数中最⼤的数为Vmax,最⼩的数为Vmin, 那么N个数
    中第K⼤的数⼀定在区间[Vmin,Vmax]之间。然后在这个区间使⽤⼆分查找算法。
    总结:该算法实际应⽤效果不佳,尤其是不同的数据类型需要确定max - min > delta,因此时间复杂度跟数据分布有关。 整个算法的
    时间复杂度为O(N * log(Vmax-Vmin)/delta),在数据分布平均的情况下,时间复杂度为O(N * logN)。
    4、上⾯⼏种解法都会对数据访问多次,那么就有⼀个问题,当数组中元素个数⾮常⼤时,如:100亿,这时候数据不能全部加载到
    内存,就要求我们尽可能少的遍历所有数据。针对这种情况,下⾯我们介绍⼀种针对海量数据的解决⽅案。
    在学习堆排序的过程中,我们知道了堆这种数据结构。为了查找Top k⼤的数,我们可以使⽤⼤根堆来存储最⼤的K个元素。⼤根堆的
    堆顶元素就是最⼤K个数中最⼩的⼀个。每次考虑下⼀个数x时,如果x⽐堆顶元素⼩,则不需要改变原来的堆。如果想x⽐堆顶元素⼤,那
    么⽤x替换堆顶元素, 同时,在替换之后,x可能破坏最⼩堆的结构,需要调整堆来维持堆的性质。
    总结:该算法只需要扫描所有的数据⼀次,且不会占⽤太多内存空间(只需要容纳K个元素的空间),尤其适合处理海量数据的场
    景。算法的时间复杂度为O(N * logk),这实际上相当于执⾏了部分堆排序。
    5、TOP-K问题是⼀个经典的问题,这个问题是存在线性算法的,只不过算法的使⽤范围有⼀定的限制。如果所有N个数都是正整
    数,且他们的取值范围并不⼤,可以考虑申请空间,记录每个整数出现的次数,然后再从⼤到⼩取最⼤的K个。实际就是利⽤计数排序的
    思想。 假设所有整数都在(0,maxN)区间,利⽤⼀个数组count[maxN]来记录每个整数出现的次数。count[i]表示整数i在N个数中出现
    的次数。只需要扫描⼀遍就可以得到count数组,然后寻找第K⼤的元素。
    这是⼀个典型的以空间换取时间的做法。当数组中取值范围⽐较⼤时,是及其浪费空间的。如[3,1…9999],为了求出最⼤的K个元
    素,需要额外申请⼀个⻓度为10000的数组。
    极端情况下,如果 N 个整数各不相同,我们甚⾄只需要⼀个 bit 来存储这个整数是否存在,这样可节省很⼤的内存空间。
    11.a,b,c三张表,做关联查询,如何优化,可做外键,只在c表加a表外键即可。
  8. 对于要求全⾯的结果时,我们需要使⽤连接操作(LEFT JOIN / RIGHT JOIN / FULL JOIN);
  9. 不要以为使⽤MySQL的⼀些连接操作对查询有多么⼤的改善,核⼼是索引;
  10. 对被驱动表的join字段添加索引;
    12.CourrentHashMap JDK1.7和JDK1.8有什么区别?
  11. Java 7为实现并⾏访问,引⼊了Segment这⼀结构,实现了分段锁,理论上最⼤并发度与Segment个数相等。
  12. Java 8为进⼀步提⾼并发性,摒弃了分段锁的⽅案,⽽是直接使⽤⼀个⼤的数组。同时为了提⾼哈希碰撞下的寻址性能,Java 8在
    链表⻓度超过⼀定阈值(8)时将链表(寻址时间复杂度为O(N))转换为红⿊树(寻址时间复杂度为O(long(N)))。其数据结构如下
    图所示
    13.线程a,b,c,d运⾏任务,怎么保证当a,b,c线程执⾏完再执⾏d线程?
    1、CountDownLatch类
    ⼀个同步辅助类,常⽤于某个条件发⽣后才能执⾏后续进程。给定计数初始化CountDownLatch,调⽤countDown()⽅法,在计
    数到达零之前,await⽅法⼀直受阻塞。
    重要⽅法为countdown()与await();
    2、join⽅法
    将线程B加⼊到线程A的尾部,当A执⾏完后B才执⾏。
    1 public static void main(String[] args) throws Exception {
    2 Th t = new Th(“t1”);
    3 Th t2 = new Th(“t2”);
    4 t.start();
    5 t.join();
    6 t2.start();
    7 }
    8
    3、notify、wait⽅法,Java中的唤醒与等待⽅法,关键为synchronized代码块,参数线程间应相同,也常⽤Object作为参数。
    14.分布式系统中如何保证数据的⼀致性?
    15.拆分微服务应该注意哪些地⽅,如何拆分?
    1、业务⽅⾯拆分:所有技术⽅⾯的考虑,包括架构设计和解耦拆分都要考虑业务的需要。在服务拆分时,先从业务⻆度确定拆分的
    ⽅案。拆分的边界要充分考虑业务的独⽴性和专业性,⽐如搜索类服务、⽀付类服务、购物⻋类服务,按服务的业务功能合理地划出拆分
    边界。
    2、减少维护成本:拆分前的维护成本 - 拆分后的维护成本 ≧ 0
    3、服务独⽴:确保拆分后的服务由相对独⽴的团队负责维护,尽量不要出现在不同服务之间的交叉调⽤。
    4、系统扩展:拆分的⼀个重要理由也是最有价值的结果是提⾼了系统的扩展性。⽤户对不同的服务有不同的并发和性能⽅⾯的要
    求,因此服务具有不同的扩展性。把具有不同扩展性要求的服务拆分出来分别进⾏部署,可以降低成本,提⾼效率。
    16.SpringCloud全家桶包含哪些组件?
  13. Ribbon,客户端负载均衡,特性有区域亲和、重试机制。
  14. Hystrix,客户端容错保护,特性有服务降级、服务熔断、请求缓存、请求合并、依赖隔离。
  15. Feign,声明式服务调⽤,本质上就是Ribbon+Hystrix
  16. Stream,消息驱动,有Sink、Source、Processor三种通道,特性有订阅发布、消费组、消息分区。
  17. Bus,消息总线,配合Config仓库修改的⼀种Stream实现,
  18. Sleuth,分布式服务追踪,需要搞清楚TraceID和SpanID以及抽样,如何与ELK整合。
  19. Eureka,服务注册中⼼,特性有失效剔除、服务保护。
  20. Dashboard,Hystrix仪表盘,监控集群模式和单点模式,其中集群模式需要收集器Turbine配合。
  21. Zuul,API服务⽹关,功能有路由分发和过滤。
  22. Config,分布式配置中⼼,⽀持本地仓库、SVN、Git、Jar包内配置等模式,
    17.有没了解Docker,Docker和虚拟机有什么区别?
    1、虚拟机:我们传统的虚拟机需要模拟整台机器包括硬件,每台虚拟机都需要有⾃⼰的操作系统,虚拟机⼀旦被开启,预分配给他
    的资源将全部被占⽤。,每⼀个虚拟机包括应⽤,必要的⼆进制和库,以及⼀个完整的⽤户操作系统。
    2、Docker:容器技术是和我们的宿主机共享硬件资源及操作系统可以实现资源的动态分配。
    容器包含应⽤和其所有的依赖包,但是与其他容器共享内核。容器在宿主机操作系统中,在⽤户空间以分离的进程运⾏。
    3、对⽐:
  23. docker启动快速属于秒级别。虚拟机通常需要⼏分钟去启动。
  24. docker需要的资源更少,docker在操作系统级别进⾏虚拟化,docker容器和内核交互,⼏乎没有性能损耗,性能优于通过
    Hypervisor层与内核层的虚拟化。;
  25. docker更轻量,docker的架构可以共⽤⼀个内核与共享应⽤程序库,所占内存极⼩。同样的硬件环境,Docker运⾏的镜像数
    远多于虚拟机数量。对系统的利⽤率⾮常⾼
  26. 与虚拟机相⽐,docker隔离性更弱,docker属于进程之间的隔离,虚拟机可实现系统级别隔离;
  27. 安全性: docker的安全性也更弱。Docker的租户root和宿主机root等同,⼀旦容器内的⽤户从普通⽤户权限提升为root权
    限,它就直接具备了宿主机的root权限,进⽽可进⾏⽆限制的操作。虚拟机租户root权限和宿主机的root虚拟机权限是分离的,并且虚拟机
    利⽤如Intel的VT-d和VT-x的ring-1硬件隔离技术,这种隔离技术可以防⽌虚拟机突破和彼此交互,⽽容器⾄今还没有任何形式的硬件隔
    离,这使得容器容易受到攻击。
  28. 可管理性:docker的集中化管理⼯具还不算成熟。各种虚拟化技术都有成熟的管理⼯具,例如VMware vCenter提供完备的虚
    拟机管理能⼒。
  29. ⾼可⽤和可恢复性:docker对业务的⾼可⽤⽀持是通过快速重新部署实现的。虚拟化具备负载均衡,⾼可⽤,容错,迁移和数
    据保护等经过⽣产实践检验的成熟保障机制,VMware可承诺虚拟机99.999%⾼可⽤,保证业务连续性。
  30. 快速创建、删除:虚拟化创建是分钟级别的,Docker容器创建是秒级别的,Docker的快速迭代性,决定了⽆论是开发、测试、
    部署都可以节约⼤量时间。
  31. 交付、部署:虚拟机可以通过镜像实现环境交付的⼀致性,但镜像分发⽆法体系化;Docker在Dockerfile中记录了容器构建过
    程,可在集群中实现快速分发和快速部署;
    18.同⼀个宿主机中多个Docker容器之间如何通信?多个宿主机中Docker容器之间如何通信?
    1、这⾥同主机不同容器之间通信主要使⽤Docker桥接(Bridge)模式。
    2、不同主机的容器之间的通信可以借助于 pipework 这个⼯具。
    19.⾼并发系统如何做性能优化?如何防⽌库存超卖?
    1、⾼并发系统性能优化:
    优化程序,优化服务配置,优化系统配置
    1.尽量使⽤缓存,包括⽤户缓存,信息缓存等,多花点内存来做缓存,可以⼤量减少与数据库的交互,提⾼性能。
    2.⽤jprofiler等⼯具找出性能瓶颈,减少额外的开销。
    3.优化数据库查询语句,减少直接使⽤hibernate等⼯具的直接⽣成语句(仅耗时较⻓的查询做优化)。
    4.优化数据库结构,多做索引,提⾼查询效率。
    5.统计的功能尽量做缓存,或按每天⼀统计或定时统计相关报表,避免需要时进⾏统计的功能。
    6.能使⽤静态⻚⾯的地⽅尽量使⽤,减少容器的解析(尽量将动态内容⽣成静态html来显示)。
    7.解决以上问题后,使⽤服务器集群来解决单台的瓶颈问题。
    2、防⽌库存超卖:
    1、悲观锁:在更新库存期间加锁,不允许其它线程修改;
    1、数据库锁:select xxx for update;
    2、分布式锁;
    2、乐观锁:使⽤带版本号的更新。每个线程都可以并发修改,但在并发时,只有⼀个线程会修改成功,其它会返回失败。
    1、redis watch:监视键值对,作⽤时如果事务提交exec时发现监视的监视对发⽣变化,事务将被取消。
    3、消息队列:通过 FIFO 队列,使修改库存的操作串⾏化。
    4、总结:总的来说,不能把压⼒放在数据库上,所以使⽤ “select xxx for update” 的⽅式在⾼并发的场景下是不可⾏的。FIFO
    同步队列的⽅式,可以结合库存限制队列⻓,但是在库存较多的场景下,⼜不太适⽤。所以相对来说,我会倾向于选择:乐观锁 / 缓存锁
    / 分布式锁的⽅式。
    20.如何保证服务幂等性?
    1、概念:接⼝的幂等性实际上就是接⼝可重复调⽤,在调⽤⽅多次调⽤的情况下,接⼝最终得到的结果是⼀致的。有些接⼝可以天
    然的实现幂等性,⽐如查询接⼝,对于查询来说,你查询⼀次和两次,对于系统来说,没有任何影响,查出的结果也是⼀样。
    2、GET幂等:值得注意,幂等性指的是作⽤于结果⽽⾮资源本身。怎么理解呢?例如,这个HTTP GET⽅法可能会每次得到不同的返
    回内容,但并不影响资源。
    3、POST⾮幂等:因为它会对资源本身产⽣影响,每次调⽤都会有新的资源产⽣,因此不满⾜幂等性。
    4、如何保证幂等性:
    1、全局唯⼀id:如果使⽤全局唯⼀ID,就是根据业务的操作和内容⽣成⼀个全局ID,在执⾏操作前先根据这个全局唯⼀ID是否存
    在,来判断这个操作是否已经执⾏。如果不存在则把全局ID,存储到存储系统中,⽐如数据库、redis等。如果存在则表示该⽅法已经
    执⾏。
    从⼯程的⻆度来说,使⽤全局ID做幂等可以作为⼀个业务的基础的微服务存在,在很多的微服务中都会⽤到这样的服务,在
    每个微服务中都完成这样的功能,会存在⼯作量重复。另外打造⼀个⾼可靠的幂等服务还需要考虑很多问题,⽐如⼀台机器虽然把全
    局ID先写⼊了存储,但是在写⼊之后挂了,这就需要引⼊全局ID的超时机制。
    使⽤全局唯⼀ID是⼀个通⽤⽅案,可以⽀持插⼊、更新、删除业务操作。但是这个⽅案看起来很美但是实现起来⽐较麻烦,
    下⾯的⽅案适⽤于特定的场景,但是实现起来⽐较简单。
    2、去重表:这种⽅法适⽤于在业务中有唯⼀标的插⼊场景中,⽐如在以上的⽀付场景中,如果⼀个订单只会⽀付⼀次,所以订
    单ID可以作为唯⼀标识。这时,我们就可以建⼀张去重表,并且把唯⼀标识作为唯⼀索引,在我们实现时,把创建⽀付单据和写⼊去
    去重表,放在⼀个事务中,如果重复创建,数据库会抛出唯⼀约束异常,操作就会回滚。
    3、插⼊或更新:这种⽅法插⼊并且有唯⼀索引的情况,⽐如我们要关联商品品类,其中商品的ID和品类的ID可以构成唯⼀索
    引,并且在数据表中也增加了唯⼀索引。这时就可以使⽤InsertOrUpdate操作。在mysql数据库中如下:
    1 insert into goods_category (goods_id,category_id,create_time,update_time)
    2 values(#{goodsId},#{categoryId},now(),now())
    3 on DUPLICATE KEY UPDATE
    4 update_time=now()
    4、多版本控制:这种⽅法适合在更新的场景中,⽐如我们要更新商品的名字,这时我们就可以在更新的接⼝中增加⼀个版本
    号,来做幂等
    1 boolean updateGoodsName(int id,String newName,int version);
    在实现时可以如下
    1 update goods set name=#{newName},version=#{version} where id=#{id} and version<${version}
    5、状态机控制:这种⽅法适合在有状态机流转的情况下,⽐如就会订单的创建和付款,订单的付款肯定是在之前,这时我们可
    以通过在设计状态字段时,使⽤int类型,并且通过值类型的⼤⼩来做幂等,⽐如订单的创建为0,付款成功为100。付款失败为99
    在做状态机更新时,我们就这可以这样控制
    1 update order set status=#{status} where id=#{id} and status<#{status}
    商汤–0301
  32. springcloud有哪些核⼼组件,以及springcloud服务调⽤的详细⼯作流程?
    i.
    springcloud由以下⼏个核⼼组件构成:
    Eureka:各个服务启动时,Eureka Client都会将服务注册到Eureka Server,并且Eureka Client还可以反过来从Eureka Server拉
    取注册表,从⽽知道其他服务在哪⾥
    Ribbon:服务间发起请求的时候,基于Ribbon做负载均衡,从⼀个服务的多台机器中选择⼀台
    Feign:基于Feign的动态代理机制,根据注解和选择的机器,拼接请求URL地址,发起请求
    Hystrix:发起请求是通过Hystrix的线程池来⾛的,不同的服务⾛不同的线程池,实现了不同服务调⽤的隔离,避免了服务雪崩
    的问题
    Zuul:如果前端、移动端要调⽤后端系统,统⼀从Zuul⽹关进⼊,由Zuul⽹关转发请求给对应的服务
  33. 熔断的原理,以及如何恢复?
    熔断器模式定义了熔断器开关相互转换的逻辑:
    服务的健康状况 = 请求失败数 / 请求总数.
    熔断器开关由关闭到打开的状态转换是通过当前服务健康状况和设定阈值⽐较决定的.
  34. 当熔断器开关关闭时, 请求被允许通过熔断器. 如果当前健康状况⾼于设定阈值, 开关继续保持关闭. 如果当前健康状况低于设定
    阈值, 开关则切换为打开状态.
  35. 当熔断器开关打开时, 请求被禁⽌通过.
  36. 当熔断器开关处于打开状态, 经过⼀段时间后, 熔断器会⾃动进⼊半开状态, 这时熔断器只允许⼀个请求通过. 当该请求调⽤成功
    时, 熔断器恢复到关闭状态. 若该请求失败, 熔断器继续保持打开状态, 接下来的请求被禁⽌通过.
    熔断器的开关能保证服务调⽤者在调⽤异常服务时, 快速返回结果, 避免⼤量的同步等待. 并且熔断器能在⼀段时间后继续侦测请求执
    ⾏结果, 提供恢复服务调⽤的可能.
  37. 假如A服务可以调⽤B服务,A服务也可以调⽤C服务,如果B服务挂了,⼤量的A-B请求过来,Hystrix如何防⽌服务雪崩(Hystrix
    的隔离流程)?
    在⼀个⾼度服务化的系统中,我们实现的⼀个业务逻辑通常会依赖多个服务,⽐如:
    商品详情展示服务会依赖商品服务, 价格服务, 商品评论服务. 如图所示:
    调⽤三个依赖服务会共享商品详情服务的线程池. 如果其中的商品评论服务不可⽤, 就会出现线程池⾥所有线程都因等待响应⽽被
    阻塞, 从⽽造成服务雪崩. 如图所示:
    Hystrix通过将每个依赖服务分配独⽴的线程池进⾏资源隔离, 从⽽避免服务雪崩.
    如下图所示, 当商品评论服务不可⽤时, 即使商品服务独⽴分配的20个线程全部处于同步等待状态,也不会影响其他依赖服务的调⽤.
  38. mysql有哪些搜索引擎,以及他们之间的区别?
    a. InnoDB:
  39. ⽀持事务处理
  40. ⽀持外键
  41. ⽀持⾏锁
  42. 不⽀持FULLTEXT类型的索引(在Mysql5.6已引⼊)
  43. 不保存表的具体⾏数,扫描表来计算有多少⾏
  44. 对于AUTO_INCREMENT类型的字段,必须包含只有该字段的索引
  45. DELETE 表时,是⼀⾏⼀⾏的删除
  46. InnoDB 把数据和索引存放在表空间⾥⾯
  47. 跨平台可直接拷⻉使⽤
  48. 表格很难被压缩
    b. MyISAM:
  49. 不⽀持事务,回滚将造成不完全回滚,不具有原⼦性
  50. 不⽀持外键
  51. ⽀持全⽂搜索
  52. 保存表的具体⾏数,不带where时,直接返回保存的⾏数
  53. DELETE 表时,先drop表,然后重建表
  54. MyISAM 表被存放在三个⽂件 。frm ⽂件存放表格定义。 数据⽂件是MYD (MYData) 。 索引⽂件是MYI (MYIndex)引伸
  55. 跨平台很难直接拷⻉
  56. AUTO_INCREMENT类型字段可以和其他字段⼀起建⽴联合索引
  57. 表格可以被压缩
    c. 选择:因为MyISAM相对简单所以在效率上要优于InnoDB.如果系统读多,写少。对原⼦性要求低。那么MyISAM最好的选择。
    且MyISAM恢复速度快。可直接⽤备份覆盖恢复。如果系统读少,写多的时候,尤其是并发写⼊⾼的时候。InnoDB就是⾸选了。
    两种类型都有⾃⼰优缺点,选择那个完全要看⾃⼰的实际类弄。
  58. 请介绍⼀下mysql索引B+tree。
  59. B-tree:
    B-tree 利⽤了磁盘块的特性进⾏构建的树。每个磁盘块⼀个节点,每个节点包含了很关键字。把树的节点关键字增多后树的
    层级⽐原来的⼆叉树少了,减少数据查找的次数和复杂度。
    B-tree巧妙利⽤了磁盘预读原理,将⼀个节点的⼤⼩设为等于⼀个⻚(每⻚为4K),这样每个节点只需要⼀次I/O就可以完
    全载⼊。
    B-tree 的数据可以存在任何节点中。
  60. B+tree:
    B+tree 是 B-tree 的变种,B+tree 数据只存储在叶⼦节点中。这样在B树的基础上每个节点存储的关键字数更多,树的层级
    更少所以查询数据更快,所有指关键字指针都存在叶⼦节点,所以每次查找的次数都相同所以查询速度更稳定;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值