Skip to content

Commit 9f18fe8

Browse files
committed
mq使用场景
1 parent 18f10c7 commit 9f18fe8

File tree

5 files changed

+153
-5
lines changed

5 files changed

+153
-5
lines changed

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,14 @@
8989

9090
- [Java8新特性总结](docs/java/java8-all.md)
9191
- [Java19新特性](docs/advance/excellent-article/19-java19.md)
92-
- [泛型中的 T、E、K、V,还记得嘛?](docs/advance/excellent-article/24-generic.md)
92+
- [Java Stream常见用法汇总](docs/advance/excellent-article/26-java-stream.md)
93+
- [泛型中的T、E、K、V,是什么含义?](docs/advance/excellent-article/24-generic.md)
9394

9495
**JVM重要知识点**
9596

9697
- [美团面试:熟悉哪些JVM调优参数?](docs/advance/excellent-article/9-jvm-optimize-param.md)
9798
- [一次简单的JVM调优,拿去写到简历里](docs/advance/excellent-article/5-jvm-optimize.md)
98-
- [阿里排错神器——Arthas](docs/advance/excellent-article/23-arthas-intro.md)
99+
- [阿里排错神器--Arthas](docs/advance/excellent-article/23-arthas-intro.md)
99100

100101
# 数据库
101102

@@ -111,6 +112,7 @@
111112
- [order by是怎么工作的?](docs/advance/excellent-article/13-order-by-work.md)
112113
- [8种最坑SQL语法](docs/advance/excellent-article/7-sql-optimize.md)
113114
- [为什么说数据库连接很消耗资源](docs/advance/excellent-article/18-db-connect-resource.md)
115+
- [SELECT COUNT(*) 会造成全表扫描?](docs/advance/excellent-article/25-select-count-slow-query.md)
114116

115117
## Redis
116118

@@ -221,6 +223,10 @@
221223
2. [RabbitMQ面试题总结](docs/message-queue/rabbitmq.md) (推荐 :+1:)
222224
3. [Kafka面试题总结](docs/message-queue/kafka.md) (推荐 :+1:)
223225

226+
**重要知识点:**
227+
228+
- [消息队列常见的使用场景](docs/advance/excellent-article/27-mq-usage.md)
229+
224230
# 海量数据场景题
225231

226232
1. [统计不同电话号码的个数](https://topjavaer.cn/mass-data/1-count-phone-num.html)
@@ -239,10 +245,12 @@
239245
- [短链系统设计](docs/advance/system-design/3-short-url.md)
240246
- [超卖问题](docs/advance/system-design/4-oversold.md)
241247
- [秒杀系统设计](docs/advance/system-design/5-second-kill.md)
248+
- [秒杀系统设计的5个要点](docs/advance/system-design/12-second-kill-5-pointmd)
242249
- [微信红包系统如何设计?](docs/advance/system-design/6-wechat-redpacket-design.md)
243250
- [如何把一个文件较快的发送到100w个服务器?](docs/advance/system-design/7-file-send.md)
244251
- [如何用 Redis 统计用户访问量?](docs/advance/system-design/10-pdd-visit-statistics)
245252
- [实时订阅推送设计](docs/advance/system-design/11-realtime-subscribe-push.md)
253+
- [权限系统设计方案](docs/advance/system-design/13-permission-system.md)
246254

247255
# 安全
248256

docs/advance/excellent-article/24-generic.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,15 +251,21 @@ public Class<T> clazzT;
251251

252252
所以当不知道定声明什么类型的 Class 的时候可以定义一 个Class<?>。
253253

254-
![图片](https://mmbiz.qpic.cn/mmbiz_jpg/JdLkEI9sZffWPDTNara23zX7cQiaVrP6plpf3S7CqZbryddwWFQN3gzKYlAZtRAnn0ro78WBiciaHVgKicD0kpSCPQ/640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1&wx_co=1)
254+
```java
255+
public class Test3 {
256+
public Class<?> clazz;
257+
public Class<T> clazzT;
258+
}
259+
```
255260

256261
那如果也想 `public Class<T> clazzT;`这样的话,就必须让当前的类也指定 T ,
257262

258-
```
263+
```java
259264
public class Test3<T> {
260265
public Class<?> clazz;
261266
// 不会报错
262267
public Class<T> clazzT;
268+
}
263269
```
264270

265271
## 小结

docs/advance/excellent-article/25-select-count-slow-query.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# SELECT COUNT(*) 会造成全表扫描?回去等通知吧
2+
13
## 前言
24

35
SELECT COUNT(*)会不会导致全表扫描引起慢查询呢?
@@ -16,7 +18,7 @@ EXPLAIN SELECT COUNT(*) FROM SomeTable
1618

1719
结果如下
1820

19-
![](C:\Users\Tyson\Desktop\img\0103\select count\select-count1.png)
21+
![](http://img.topjavaer.cn/img/select-count1.png)
2022

2123
如图所示: 发现确实此条语句在此例中用到的并不是主键索引,而是辅助索引,实际上在此例中我试验了,不管是 COUNT(1),还是 COUNT(*),MySQL 都会用**成本最小**的辅助索引查询方式来计数,也就是使用 COUNT(*) 由于 MySQL 的优化已经保证了它的查询性能是最好的!随带提一句,COUNT(*)是 SQL92 定义的标准统计行数的语法,并且效率高,所以请直接使用COUNT(*)查询表的行数!
2224

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
## 消息队列常见的使用场景
2+
3+
消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题
4+
5+
实现高性能,高可用,可伸缩和最终一致性架构。
6+
7+
使用较多的消息队列有 RocketMQ,RabbitMQ,Kafka,ZeroMQ,MetaMQ
8+
9+
以下介绍消息队列在实际应用中常用的使用场景。
10+
11+
异步处理,应用解耦,流量削锋、日志处理和消息通讯五个场景。
12+
13+
#### 场景 1:异步处理
14+
15+
场景说明:用户注册后,需要发注册邮件和注册短信。传统的做法有两种 1.串行的方式;2.并行方式
16+
17+
(1)串行方式:将注册信息写入数据库成功后,发送注册邮件,再发送注册短信。以上三个任务全部完成后,返回给客户端
18+
19+
![](http://img.topjavaer.cn/img/mq使用场景1.png)
20+
21+
(2)并行方式:将注册信息写入数据库成功后,发送注册邮件的同时,发送注册短信。以上三个任务完成后,返回给客户端。与串行的差别是,并行的方式可以提高处理的时间
22+
23+
![](http://img.topjavaer.cn/img/mq使用场景2.png)
24+
25+
假设三个业务节点每个使用 50 毫秒钟,不考虑网络等其他开销,则串行方式的时间是 150 毫秒,并行的时间可能是 100 毫秒。
26+
27+
因为 CPU 在单位时间内处理的请求数是一定的,假设 CPU1 秒内吞吐量是 100 次。则串行方式 1 秒内 CPU 可处理的请求量是 7 次(1000/150)。并行方式处理的请求量是 10 次(1000/100)
28+
29+
> 小结:如以上案例描述,传统的方式系统的性能(并发量,吞吐量,响应时间)会有瓶颈。如何解决这个问题呢?
30+
31+
引入消息队列,将不是必须的业务逻辑,异步处理。改造后的架构如下:
32+
33+
![](http://img.topjavaer.cn/img/mq使用场景3.png)
34+
35+
按照以上约定,用户的响应时间相当于是注册信息写入数据库的时间,也就是 50 毫秒。注册邮件,发送短信写入消息队列后,直接返回,因此写入消息队列的速度很快,基本可以忽略,因此用户的响应时间可能是 50 毫秒。因此架构改变后,系统的吞吐量提高到每秒 20 QPS。比串行提高了 3 倍,比并行提高了两倍
36+
37+
#### 场景 2:应用解耦
38+
39+
场景说明:用户下单后,订单系统需要通知库存系统。传统的做法是,订单系统调用库存系统的接口。如下图
40+
41+
![](http://img.topjavaer.cn/img/mq使用场景4.png)
42+
43+
传统模式的缺点:
44+
45+
- 假如库存系统无法访问,则订单减库存将失败,从而导致订单失败
46+
- 订单系统与库存系统耦合
47+
48+
> 如何解决以上问题呢?引入应用消息队列后的方案,如下图:
49+
50+
![](http://img.topjavaer.cn/img/mq使用场景5.png)
51+
52+
- 订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功
53+
- 库存系统:订阅下单的消息,采用拉/推的方式,获取下单信息,库存系统根据下单信息,进行库存操作
54+
- 假如:在下单时库存系统不能正常使用。也不影响正常下单,因为下单后,订单系统写入消息队列就不再关心其他的后续操作了。实现订单系统与库存系统的应用解耦
55+
56+
#### 场景 3:流量削锋
57+
58+
流量削锋也是消息队列中的常用场景,一般在秒杀或团抢活动中使用广泛
59+
60+
应用场景:秒杀活动,一般会因为流量过大,导致流量暴增,应用挂掉。为解决这个问题,一般需要在应用前端加入消息队列。
61+
62+
- 可以控制活动的人数
63+
- 可以缓解短时间内高流量压垮应用
64+
65+
![](http://img.topjavaer.cn/img/mq使用场景6.png)
66+
67+
- 用户的请求,服务器接收后,首先写入消息队列。假如消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面
68+
- 秒杀业务根据消息队列中的请求信息,再做后续处理
69+
70+
#### 场景 4:日志处理
71+
72+
日志处理是指将消息队列用在日志处理中,比如 Kafka 的应用,解决大量日志传输的问题。架构简化如下
73+
74+
![](http://img.topjavaer.cn/img/mq使用场景7.png)
75+
76+
- 日志采集客户端,负责日志数据采集,定时写入 Kafka 队列
77+
- Kafka 消息队列,负责日志数据的接收,存储和转发
78+
- 日志处理应用:订阅并消费 kafka 队列中的日志数据
79+
80+
以下是新浪 kafka 日志处理应用案例
81+
82+
![](http://img.topjavaer.cn/img/mq使用场景8.png)
83+
84+
(1)、Kafka:接收用户日志的消息队列
85+
86+
(2)、Logstash:做日志解析,统一成 JSON 输出给 Elasticsearch
87+
88+
(3)、Elasticsearch:实时日志分析服务的核心技术,一个 schemaless,实时的数据存储服务,通过 index 组织数据,兼具强大的搜索和统计功能
89+
90+
(4)、Kibana:基于 Elasticsearch 的数据可视化组件,超强的数据可视化能力是众多公司选择 ELK stack 的重要原因
91+
92+
#### 场景 5:消息通讯
93+
94+
消息通讯是指,消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯。比如实现点对点消息队列,或者聊天室等
95+
96+
点对点通讯:
97+
98+
![](http://img.topjavaer.cn/img/mq使用场景9.png)
99+
100+
客户端 A 和客户端 B 使用同一队列,进行消息通讯。
101+
102+
聊天室通讯:
103+
104+
![](http://img.topjavaer.cn/img/mq使用场景10.png)
105+
106+
客户端 A,客户端 B,客户端 N 订阅同一主题,进行消息发布和接收。实现类似聊天室效果。
107+
108+
以上实际是消息队列的两种消息模式,点对点或发布订阅模式。模型为示意图,供参考。
109+
110+
*本文转载自:https://www.cnblogs.com/ruiati/p/6649868.html*

docs/java/java-basic.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1551,6 +1551,28 @@ server {
15511551

15521552
8、**避免在循环中查询数据库**。循环查询数据库,非常耗时,最好能在一次查询中获取所有需要的数据。
15531553

1554+
## 为什么在阿里巴巴Java开发手册中强制要求使用包装类型定义属性呢?
15541555

1556+
嗯,以布尔字段为例,当我们没有设置对象的字段的值的时候,Boolean类型的变量会设置默认值为`null`,而boolean类型的变量会设置默认值为`false`
1557+
1558+
也就是说,包装类型的默认值都是null,而基本数据类型的默认值是一个固定值,如boolean是false,byte、short、int、long是0,float是0.0f等。
1559+
1560+
举一个例子,比如有一个扣费系统,扣费时需要从外部的定价系统中读取一个费率的值,我们预期该接口的返回值中会包含一个浮点型的费率字段。当我们取到这个值得时候就使用公式:金额*费率=费用 进行计算,计算结果进行划扣。
1561+
1562+
如果由于计费系统异常,他可能会返回个默认值,如果这个字段是Double类型的话,该默认值为null,如果该字段是double类型的话,该默认值为0.0。
1563+
1564+
如果扣费系统对于该费率返回值没做特殊处理的话,拿到null值进行计算会直接报错,阻断程序。拿到0.0可能就直接进行计算,得出接口为0后进行扣费了。这种异常情况就无法被感知。
1565+
1566+
**那我可以对0.0做特殊判断,如果是0就阻断报错,这样是否可以呢?**
1567+
1568+
不对,这时候就会产生一个问题,如果允许费率是0的场景又怎么处理呢?
1569+
1570+
使用基本数据类型只会让方案越来越复杂,坑越来越多。
1571+
1572+
这种使用包装类型定义变量的方式,通过异常来阻断程序,进而可以被识别到这种线上问题。如果使用基本数据类型的话,系统可能不会报错,进而认为无异常。
1573+
1574+
因此,建议在POJO和RPC的返回值中使用包装类型。
1575+
1576+
> 参考链接:https://mp.weixin.qq.com/s/O_jCxZWtTTkFZ9FlaZgOCg
15551577
15561578
![](http://img.topjavaer.cn/img/20220612101342.png)

0 commit comments

Comments
 (0)