互联网架构
项目功能模块
- 商品详情(SKU、SPU)—>购物车(登录/不登录)业务分析?
- 全文检索 – es 的功能实现?
- SSO单点登录 – redis的业务实现?
- 全局异常处理的实现?
- 订单模块 – rabbitmq的业务分析?
- 单元测试(springboot)的业务实现?
面试题
-
redis和memcache有什么区别?
区别:
1.memcache 可缓存图片和视频。 redis 支持除 k/v 更多的数据结构;
2.redis 可以使用虚拟内存, rdb可持久化和aof 灾难恢复, redis通过主从支持数据备份;
3.redis 可以做消息队列。
原因: memcache 多线程模型引入了缓存一致性和锁,加锁带来了性能损耗。 -
redis主从复制如何实现的?
-
redis的集群模式如何实现?
-
redis的key如何寻址?
以上三个综合
主从复制实现:主节点将自己内存中的数据做一份快照,将快照发给从节点,从节点将数据恢复到内存中。之后再每次增加新数据的时候,主节点以类似于 mysql 的二进制日志方式将语句发送给从节点,从节点拿到主节点发送过来的语句进行重放。- 分片方式:
- 客户端分片
- 基于代理的分片
- Twemproxy
- codis
- 路由查询分片
Redis-cluster(本身提供了自动将数据分散到 Redis Cluster 不同节点的能力,整个数据集合的某个数据子集存储在哪个节点对于用户来说是透明的)
redis-cluster 分片原理:
Cluster 中有一个 16384 长度的槽(虚拟槽),编号分别为 0-16383。每个 Master 节点都会负责一部分的槽,当有某个 key 被映射到某个 Master 负责的槽,那么这个 Master 负责为这个 key 提供服务,至于哪个Master 节点负责哪个槽,可以由用户指定,也可以在初始化的时候自动生成,只有 Master 才拥有槽的所有权。 Master 节点维护着一个 16384/8 字节的位序列, Master 节点用 bit 来标识对于某个槽自己是否拥有。比如对于编号为 1 的槽, Master 只要判断序列的第二位(索引从 0 开始)是不是为 1 即可。这种结构很容易添加或者删除节点。比如如果我想新添加个节点 D, 我需要从节点 A、 B、C 中得部分槽到 D 上 - 分片方式:
-
使用redis如何设计分布式锁(实现思路)?
redis:
1)线程 A setnx(上锁的对象,超时时的时间戳 t1),如果返回 true,获得锁。
2)线程 B 用 get 获取 t1,与当前时间戳比较,判断是是否超时,没超时 false,若超时执行第 3 步;
3)计算新的超时时间 t2,使用 getset 命令返回 t3(该值可能其他线程已经修改过),如果 t1==t3,获得锁,如果 t1!=t3 说明锁被其他线程获取了。
4)获取锁后,处理完业务逻辑,再去判断锁是否超时,如果没超时删除锁,如果已超时,不用处理(防止删除其他线程的锁)。
zk:
1>客户端对某个方法加锁时,在 zk 上的与该方法对应的指定节点的目录下,生成一个唯一 的瞬时有序节点 node1;
2>客户端获取该路径下所有已经创建的子节点,如果发现自己创建的 node1 的序号是最小的,就认为这个客户端获得了锁。
3>如果发现 node1 是最小的,则监听比自己创建节点序号小的最大的节点,进入等待。
4>获取锁后,处理完逻辑,删除自己创建的 node1 即可。
区别:zk 性能差一些,开销大,实现简单。 -
Redis 当中有哪些数据结构?
String:字符串
Hash:面向对象的结构
List:双向链表
Set:集合
ZSet:有序集合 -
RabbitMQ中的broker是指什么?cluster又是指什么?
broker 是指一个或多个 erlang node 的逻辑分组,且 node 上运行着 RabbitMQ 应用程序。
cluster 是在 broker 的基础之上,增加了 node 之间共享元数据的约束。 -
什么是元数据?RabbitMQ中元数据分为哪些类型?包括哪些内容?
在非 cluster 模式下,元数据主要分为 Queue 元数据( queue 名字和属性等)、Exchange 元数据( exchange 名字、类型和属性等)、Binding 元数据(存放路由关系的查找表)、 Vhost 元数据( vhost 范围内针对前三者的名字空间约束和安全属性设置)。在 cluster 模式下,还包括cluster 中 node 位置信息和 node 关系信息。元数据按照 erlangnode 的类型确定是仅保存于 RAM 中,还是同时保存在 RAM 和 disk 上。元数据在 cluster 中是全 node 分布的 -
RabbitMQ 概念里的 channel、 exchange 和 queue 这些东东是逻辑概念,还是对应着进程实体?这些东东分别起什么作用?
queue 具有自己的 erlang 进程; exchange 内部实现为保存 binding 关系的查找表;
channel 是实际进行路由工作的实体,即负责按照 routing_key 将message 投递给 queue 。
由 AMQP 协议描述可知, channel 是真实 TCP 连接之上的虚拟连接,所有 AMQP 命令都是通过 channel 发送的,且每一个 channel 有唯一的 ID。一个 channel 只能被单独一个操作系统线程使用,故投递到特定 channel 上的 message 是有顺序的。但一个操作系统线程上允许使用多个 channel 。 channel 号为 0 的 channel 用于处理所有对于当前connection 全局有效的帧,而 1-65535 号 channel 用于处理和特定 channel 相关的帧。 -
SpringCloud中Hystrix 断路器是什么?什么是服务熔断? 什么是服务降级?
Hystrix 是一个用于处理分布式系统的延迟和容错的开源库,分布式系统里,许多依赖不可避免的会调用失败,比如超时、异常等,Hystrix 能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
“断路器”本身是一种开关装置,当某个服务单元发生故障以后,通过断路器的故障监控(类似熔断保险丝),向调用方放回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的当代或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间的、不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩
服务熔断: 一般是某个服务故障或异常引起,类似保险丝,当某个异常条件被触发,直接熔断整个服务,而不是一直等到服务超时。发生在服务端
服务降级: 通过切面的方式,在客户端实现服务熔断的效果。一般是从整体负荷考虑。当某个服务熔断后,服务器不可以被调用,此时客户端可以自己准备一个本地的 Fallback回调,返回一个缺省值。这样做,虽然服务水平下降,但好歹可以使用,比直接挂掉要好。 -
SpringCloud中的Netflix Feign是什么?它的优点是什么?
Feign 是受到 Retrofit,JAXRS-2.0 和 WebSocket 启发的 java 客户端联编程序。Feign的第一个目标是将约束分母的复杂性统一到 http apis,而不考虑其稳定性。在 employee consumer 的例子中, 我们使用employee-producer 使用 REST 模板公开的 REST 服务。
但是我们必须编写大量代码才能执行以下步骤
使用功能区进行负载平衡。
获取服务实例,然后获取基本 URL。
利用 REST 模板来使用服务。 前面的代码如下 :
@Controller
public class ConsumerControllerClient {
@Autowired
private LoadBalancerClient loadBalancer;
public void getEmployee() throws RestClientException, IOException {
ServiceInstance serviceInstance=loadBalancer.choose('employee-producer');
System.out.println(serviceInstance.getUri());
String baseUrl=serviceInstance.getUri().toString();
baseUrl=baseUrl+'/employee';
RestTemplate restTemplate = new RestTemplate();
ResponseEntity response=null;
try{
response=restTemplate.exchange(baseUrl,
HttpMethod.GET, getHeaders(),String.class);
}catch (Exception ex){
System.out.println(ex);
}System.out.println(response.getBody());
}
之前的代码,有像 NullPointer 这样的例外的机会,并不是最优的。我们将看到如何使用 Netflix
Feign 使呼叫变得更加轻松和清洁。如果 Netflix Ribbon 依赖关系也在类路径中,那么 Feign 默认也会负责负载平衡。
- SpringBoot是什么?它有哪些优点?
1) SpringBoot 是伴随着 Spring4.0 诞生的;
从字面理解,Boot 是引导的意思,因此 SpringBoot 帮助开发者快速搭建 Spring 框架;
SpringBoot 帮助开发者快速启动一个 Web 容器;
SpringBoot 继承了原有 Spring 框架的优秀基因;
SpringBoot 简化了使用 Spring 的过程。
2) 快速构建项目。
对主流开发框架的无配置集成。
项目可独立运行,无须外部依赖 Servlet 容器。
提供运行时的应用监控。
极大地提高了开发、部署效率。
与云计算的天然集成 - SpringBoot自动配置的原理是什么?
1)SpringBoot 启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration
2)@EnableAutoConfiguration 作用:将 类路径下 META-INF/spring.factories 里面配置的所有 EnableAutoConfiguration 的值加入到了容器中;利用EnableAutoConfigurationImportSelector 给容器中导入一些组件可以查看 selectImports()方法的内容;
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
获取候选的配置 SpringFactoriesLoader.loadFactoryNames()
扫描所有 jar 包类路径下 META-INF/spring.factories
把扫描到的这些文件的内容包装成 properties 对象
从 properties 中获取到 EnableAutoConfiguration.class 类(类名)对应的值,然后把他们添加在容器中每一个这样的 xxxAutoConfiguration 类都是容器中的一个组件,都加入到容器中;用他们来做自动配置;
3)每一个自动配置类进行自动配置功能; - Elasticsearch是如何实现Master选举?
Elasticsearch 的选主是 ZenDiscovery 模块负责的,主要包含 Ping(节点之间通过这个 RPC来发现彼此)和 Unicast(单播模块包含一个主机列表以控制哪些节点需要 ping 通)这两部分;对所有可以成为 master 的节点(node.master: true)根据 nodeId 字典排序,每次选举每个节点都把自己所知道节点排一次序,然后选出第一个(第 0 位)节点,暂且认为它是master 节点。如果对某个节点的投票数达到一定的值(可以成为 master 节点数 n/2+1)并且该节点自己也选举自己,那这个节点就是 master。否则重新选举一直到满足上述条件。
补充: master 节点的职责主要包括集群、节点和索引的管理,不负责文档级别的管理;data 节点可以关闭 http 功能。 - 项目中Elasticsearch的具体应用是如何应用的?
转载自此原文链接 - Nginx怎么实现高可用?
通过 keepalived 来实现同一个虚拟 IP 映射到两台 Nginx 代理服务器,如果主服务器挂掉或者主服务器的keepalived挂掉又或者主服务器的Nginx挂掉(Nginx挂掉后会杀死keepalived的进程,在脚本中有控制)那从服务器的 keepalived 会检测到并会接管原先 MASTER 的网络功能,这种方式来实现 Nginx 的高可用性(如上文中的 keepalived 简要介绍)