File tree 6 files changed +30
-14
lines changed
6 files changed +30
-14
lines changed Original file line number Diff line number Diff line change 14
14
### [ 消息队列] ( /docs/high-concurrency/mq-interview.md )
15
15
- [ 为什么使用消息队列?消息队列有什么优点和缺点?Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么优点和缺点?] ( /docs/high-concurrency/why-mq.md )
16
16
- [ 如何保证消息队列的高可用?] ( /docs/high-concurrency/how-to-ensure-high-availability-of-message-queues.md )
17
- - [ 如何保证消息不被重复消费?(如何保证消息消费时的幂等性 )] ( /docs/high-concurrency/how-to-ensure-that-messages-are-not-repeatedly-consumed.md )
17
+ - [ 如何保证消息不被重复消费?(如何保证消息消费的幂等性 )] ( /docs/high-concurrency/how-to-ensure-that-messages-are-not-repeatedly-consumed.md )
18
18
- [ 如何保证消息的可靠性传输?(如何处理消息丢失的问题)] ( /docs/high-concurrency/how-to-ensure-the-reliable-transmission-of-messages.md )
19
19
- [ 如何保证消息的顺序性?] ( /docs/high-concurrency/how-to-ensure-the-order-of-messages.md )
20
20
- [ 如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万消息持续积压几小时,说说怎么解决?] ( /docs/high-concurrency/mq-time-delay-and-expired-failure.md )
87
87
- [ 基于本地缓存的 fallback 降级机制] ( /docs/high-availability/hystrix-fallback.md )
88
88
- [ 深入 Hystrix 断路器执行原理] ( /docs/high-availability/hystrix-circuit-breaker.md )
89
89
- [ 深入 Hystrix 线程池隔离与接口限流] ( /docs/high-availability/hystrix-thread-pool-current-limiting.md )
90
+ - [ 基于 timeout 机制为服务接口调用超时提供安全保护] ( /docs/high-availability/hystrix-timeout.md )
90
91
91
92
### 高可用系统
92
93
- 如何设计一个高可用系统?
Original file line number Diff line number Diff line change @@ -88,14 +88,13 @@ public class HelloServiceImpl implements HelloService {
88
88
89
89
我们调用接口失败的时候,可以通过 ` mock ` 统一返回 null。
90
90
91
- mock 的值也可以修改为 true,然后再跟接口同一个路径下实现一个 Mock 类,命名规则是 ` 接口名称+Mock ` 后缀。然后在 Mock 类里实现自己的降级逻辑。
91
+ mock 的值也可以修改为 true,然后再跟接口同一个路径下实现一个 Mock 类,命名规则是 “ 接口名称+` Mock ` ” 后缀。然后在 Mock 类里实现自己的降级逻辑。
92
92
``` java
93
93
public class HelloServiceMock implements HelloService {
94
94
95
95
public void sayHello () {
96
96
// 降级逻辑
97
97
}
98
-
99
98
}
100
99
101
100
```
@@ -109,9 +108,9 @@ public class HelloServiceMock implements HelloService {
109
108
110
109
举个栗子。
111
110
112
- 某个服务的接口,要耗费 5s,你这边不能干等着,你这边配置了 timeout之后,我等待2s ,还没返回,我直接就撤了,不能干等你。
111
+ 某个服务的接口,要耗费 5s,你这边不能干等着,你这边配置了 timeout 之后,我等待 2s ,还没返回,我直接就撤了,不能干等你。
113
112
114
113
可以结合你们公司具体的场景来说说你是怎么设置这些参数的:
115
114
116
- - ` timeout ` :一般设置为 ` 200ms ` ,我们认为不能超过 ` 200ms ` 还没返回。
115
+ - ` timeout ` :一般设置为 ` 200ms ` ,我们认为不能超过 ` 200ms ` 还没返回。
117
116
- ` retries ` :设置 retries,一般是在读请求的时候,比如你要查询个数据,你可以设置个 retries,如果第一次没读到,报错,重试指定的次数,尝试再次读取。
Original file line number Diff line number Diff line change 5
5
6
6
![ e-commerce-website-detail-page-architecture-1] ( /images/e-commerce-website-detail-page-architecture-1.png )
7
7
8
- - 好处:用户每次浏览一个页面,不需要进行任何的跟数据库的交互逻辑,也不需要执行任何的代码,直接返回一个 html 页面就可以了,速度和性能非常高。
9
- - 坏处:仅仅适用于一些小型的网站,比如页面的规模在几十到几万不等。对于一些大型的电商网站,亿级数量的页面,你说你每次页面模板修改了,都需要将这么多页面全量静态化,靠谱吗?
8
+ 下面是页面模板的简单 Demo 。
9
+
10
+ ``` html
11
+ <html >
12
+ <body >
13
+ 商品名称:#{productName}<br >
14
+ 商品价格:#{productPrice}<br >
15
+ 商品描述:#{productDesc}
16
+ </body >
17
+ </html >
18
+ ```
19
+
20
+ 这样做,** 好处** 在于,用户每次浏览一个页面,不需要进行任何的跟数据库的交互逻辑,也不需要执行任何的代码,直接返回一个 html 页面就可以了,速度和性能非常高。
21
+
22
+ 对于小网站,页面很少,很实用,非常简单,Java 中可以使用 velocity、freemarker、thymeleaf 等等,然后做个 cms 页面内容管理系统,模板变更的时候,点击按钮或者系统自动化重新进行全量渲染。
23
+
24
+ ** 坏处** 在于,仅仅适用于一些小型的网站,比如页面的规模在几十到几万不等。对于一些大型的电商网站,亿级数量的页面,你说你每次页面模板修改了,都需要将这么多页面全量静态化,靠谱吗?每次渲染花个好几天时间,那你整个网站就废掉了。
10
25
11
26
### 大型电商网站的商品详情页系统架构
12
- 大型电商网站商品详情页的系统设计中,当商品信息发生变更时,会将变更消息压入消息队列中 。** 缓存服务** 从消息队列中消费此消息时,发现有信息发生变更,便通过调用接口 ,获取变更后的数据。将整合好的数据推送至 redis 中。Nginx 获取到最新的缓存数据,并且缓存到 Nginx 自己本地中 。
27
+ 大型电商网站商品详情页的系统设计中,当商品数据发生变更时,会将变更消息压入 MQ 消息队列中 。** 缓存服务** 从消息队列中消费这条消息时,感知到有数据发生变更,便通过调用数据服务接口 ,获取变更后的数据,然后将整合好的数据推送至 redis 中。Nginx 本地缓存的数据是有一定的时间期限的,比如说 10 分钟,当数据过期之后,它就会从 redis 获取到最新的缓存数据,并且缓存到自己本地 。
13
28
14
29
用户浏览网页时,动态将 Nginx 本地数据渲染到本地 html 模板并返回给用户。
15
30
16
31
![ e-commerce-website-detail-page-architecture-2] ( /images/e-commerce-website-detail-page-architecture-2.png )
17
32
18
33
19
- 虽然没有直接返回 html 页面那么快,但是因为数据在本地缓存,所以也很快,其实耗费的也就是动态渲染一个 html 页面的性能。如果 html 模板发生了变更,不需要将所有的页面重新静态化,直接将数据渲染进最新的 html 页面模板后响应即可。
34
+ 虽然没有直接返回 html 页面那么快,但是因为数据在本地缓存,所以也很快,其实耗费的也就是动态渲染一个 html 页面的性能。如果 html 模板发生了变更,不需要将所有的页面重新静态化,也不需要发送请求,没有网络请求的开销, 直接将数据渲染进最新的 html 页面模板后响应即可。
20
35
21
36
在这种架构下,我们需要** 保证系统的高可用性** 。
22
37
Original file line number Diff line number Diff line change
1
+ ## 基于 timeout 机制为服务接口调用超时提供安全保护
Original file line number Diff line number Diff line change 1
1
## 面试题
2
- 如何保证消息不被重复消费?或者说,如何保证消息消费时的幂等性 ?
2
+ 如何保证消息不被重复消费?或者说,如何保证消息消费的幂等性 ?
3
3
4
4
## 面试官心理分析
5
5
其实这是很常见的一个问题,这俩问题基本可以连起来问。既然是消费消息,那肯定要考虑会不会重复消费?能不能避免重复消费?或者重复消费了也别造成系统异常可以吗?这个是 MQ 领域的基本问题,其实本质上还是问你** 使用消息队列如何保证幂等性** ,这个是你架构里要考虑的一个问题。
Original file line number Diff line number Diff line change 24
24
25
25
** 面试官** :那你说说用消息队列都有什么优点和缺点?
26
26
27
- (面试官此时心里想的是,你的 ` MQ ` 在项目里为啥要用?你没考虑过 ,那我稍微简单点儿,我问问你消息队列你之前有没有考虑过如果用的话,优点和缺点分别是啥?)
27
+ (面试官此时心里想的是,你的 ` MQ ` 在项目里为啥要用,你没怎么考虑过 ,那我稍微简单点儿,我问问你消息队列你之前有没有考虑过如果用的话,优点和缺点分别是啥?)
28
28
29
29
** 候选人** :这个。。。(确实平时没怎么考虑过这个问题啊。。。胡言乱语了)
30
30
36
36
37
37
** 候选人** :我们就用过 ` ActiveMQ ` ,所以别的没用过。。。区别,也不太清楚。。。
38
38
39
- (面试官此时却是觉得你这哥儿们平时就是瞎用 ,根本就没什么思考,觉得不行)
39
+ (面试官此时更是觉得你这哥儿们平时就是瞎用 ,根本就没什么思考,觉得不行)
40
40
41
41
** 面试官** :那你们是如何保证消息队列的高可用啊?
42
42
52
52
53
53
** 面试官** :那如何保证消息的顺序性?
54
54
55
- ** 候选人** :顺序性?什么意思?我为什么要保证消息的顺序性?
55
+ ** 候选人** :顺序性?什么意思?我为什么要保证消息的顺序性?它不是本来就有顺序吗?
56
56
57
57
** 面试官** :如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万消息持续积压几小时,说说怎么解决?
58
58
64
64
65
65
---
66
66
67
- 这是面试官的一种面试风格,就是面试官的问题不是发散的 ,而是从一个小点慢慢铺开。比如说面试官可能会跟你聊聊高并发话题,就这个话题里面跟你聊聊缓存、` MQ ` 等等东西,** 由浅入深,一步步深挖** 。
67
+ 这其实是面试官的一种面试风格,就是说面试官的问题不是发散的 ,而是从一个小点慢慢铺开。比如说面试官可能会跟你聊聊高并发话题,就这个话题里面跟你聊聊缓存、` MQ ` 等等东西,** 由浅入深,一步步深挖** 。
68
68
69
69
其实上面是一个非常典型的关于消息队列的技术考察过程,好的面试官一定是从你做过的某一个点切入,然后层层展开深入考察,一个接一个问,直到把这个技术点刨根问底,问到最底层。
You can’t perform that action at this time.
0 commit comments