├── .idea
├── checkstyle-idea.xml
├── compiler.xml
├── description.html
├── encodings.xml
├── inspectionProfiles
│ └── Project_Default.xml
├── misc.xml
├── modules.xml
├── vcs.xml
└── workspace.xml
├── Java-Interview-Advanced.iml
├── README.md
├── docs
├── distributed-system
│ ├── 21-day-course-instructions.md
│ ├── BAT-interview-fire.md
│ ├── Dubbo-SpringCloud-experience.md
│ ├── README.md
│ ├── code
│ │ ├── code.zip
│ │ ├── code2.zip
│ │ ├── code3.zip
│ │ ├── code4.zip
│ │ └── rpc-demo.zip
│ ├── core-architecture-principle .md
│ ├── deal-line.md
│ ├── distributed-design.md
│ ├── distributed-framework-selection.md
│ ├── distributed-lock-redis-vs-zookeeper.md
│ ├── distributed-lock-taobao-and-jingdong.md
│ ├── distributed-lock.md
│ ├── distributed-session.md
│ ├── distributed-system-idempotency.md
│ ├── distributed-system-interview.md
│ ├── distributed-system-request-sequence.md
│ ├── distributed-transaction-tcc.md
│ ├── distributed-transaction.md
│ ├── dubbo-augmentability.md
│ ├── dubbo-framework-principle.md
│ ├── dubbo-independent-framework.md
│ ├── dubbo-load-balancing.md
│ ├── dubbo-operating-principle.md
│ ├── dubbo-rock-bottom.md
│ ├── dubbo-rpc-design.md
│ ├── dubbo-serialization-protocol.md
│ ├── dubbo-service-management.md
│ ├── dubbo-spi.md
│ ├── dubbo-vs-springCloud.md
│ ├── dynamic-route.md
│ ├── eventual-consistency.md
│ ├── floor-distribute-lock.md
│ ├── gateway-high-concurrency.md
│ ├── gateway-model-selection.md
│ ├── gateway-technical.md
│ ├── gray-environment.md
│ ├── highly-concurrent-distribute-lock.md
│ ├── highly-concurrent-majorization-distributed-lock.md
│ ├── hitch-redis-distribute-lock.md
│ ├── homework.md
│ ├── images
│ │ ├── SpringCloud-core-architecture.png
│ │ ├── async-replication-data-lose-case.png
│ │ ├── consistent-hashing-algorithm.png
│ │ ├── distributed-lock.png
│ │ ├── distributed-system-request-sequence.png
│ │ ├── distributed-transaction-TCC.png
│ │ ├── distributed-transaction-XA.png
│ │ ├── distributed-transaction-local-message-table.png
│ │ ├── distributed-transaction-reliable-message.png
│ │ ├── dubbo-framework-principle.png
│ │ ├── dubbo-keep-connection.png
│ │ ├── dubbo-not-keep-connection.png
│ │ ├── dubbo-operating-principle.png
│ │ ├── dubbo-rock-bottom.png
│ │ ├── dubbo-service-invoke-road.png
│ │ ├── dubbo-spi.png
│ │ ├── e-commerce-website-detail-page-architecture-1.png
│ │ ├── e-commerce-website-detail-page-architecture-2.png
│ │ ├── eureka-register.png
│ │ ├── favicon-16x16.png
│ │ ├── favicon-32x32.png
│ │ ├── gateway-high-concurrency.png
│ │ ├── hash-slot.png
│ │ ├── hash.png
│ │ ├── icon.png
│ │ ├── redis-distribute-lock.png
│ │ ├── registration-center-optimize.png
│ │ ├── rocketmq-transaction.png
│ │ ├── serialize-deserialize.png
│ │ ├── service-invoke-road.png
│ │ ├── simple-distributed-system-oa.png
│ │ ├── springCloud-study-theory.png
│ │ ├── zookeeper-active-standby.png
│ │ ├── zookeeper-centralized-storage.png
│ │ ├── zookeeper-distribute-lock-optimize.png
│ │ ├── zookeeper-distribute-lock.png
│ │ ├── zookeeper-distributed-coordination.png
│ │ ├── zookeeper-distributed-lock-demo.png
│ │ ├── zookeeper-distributed-lock.png
│ │ ├── zookeeper-meta-data-manage.png
│ │ └── zookeeper-register.png
│ ├── interface-idempotence.md
│ ├── java-internet-interview-outlook.md
│ ├── java-interview-season-1-summary.md
│ ├── redis-distribute-lock.md
│ ├── register-high-availability.md
│ ├── register-production-optimize.md
│ ├── registration-center- guide.md
│ ├── registration-center-optimize.md
│ ├── request-retry.md
│ ├── rocketmq-eventual-consistency.md
│ ├── rocketmq-transaction.md
│ ├── rpc-design.md
│ ├── service-register-discovery.md
│ ├── service-register-gateway-router.md
│ ├── service-request-time-out.md
│ ├── springCloud-and-rpc-framework.md
│ ├── springCloud-study-theory.md
│ ├── system-dilatation.md
│ ├── system-framework.md
│ ├── system-qps.md
│ ├── tcc-framework-principle.md
│ ├── tcc-high-concurrence.md
│ ├── tcc-landing-scheme.md
│ ├── why-dubbo.md
│ ├── work-distributed-transaction.md
│ ├── work-eventual-consistency.md
│ ├── work-interface-idempotence.md
│ ├── work-redis-distribute-lock.md
│ ├── work-register.md
│ ├── work-system-dilatation.md
│ ├── work-tcc-landing-scheme.md
│ ├── zookeeper-application-scenarios.md
│ ├── zookeeper-distribute-lock-optimize.md
│ ├── zookeeper-distribute-lock-scheme.md
│ ├── zookeeper-distribute-lock-split-brain.md
│ └── zookeeper-distribute-lock.md
├── high-availability
│ ├── README.md
│ ├── e-commerce-website-detail-page-architecture.md
│ ├── hystrix-circuit-breaker.md
│ ├── hystrix-execution-isolation.md
│ ├── hystrix-fallback.md
│ ├── hystrix-introduction.md
│ ├── hystrix-process.md
│ ├── hystrix-request-cache.md
│ ├── hystrix-semphore-isolation.md
│ ├── hystrix-thread-pool-current-limiting.md
│ ├── hystrix-thread-pool-isolation.md
│ ├── hystrix-timeout.md
│ └── images
│ │ ├── 220px-Internet_dog.jpg
│ │ ├── async-replication-data-lose-case.png
│ │ ├── bulkhead-partition.jpg
│ │ ├── consistent-hashing-algorithm.png
│ │ ├── distributed-system-request-sequence.png
│ │ ├── distributed-transaction-TCC.png
│ │ ├── distributed-transaction-XA.png
│ │ ├── distributed-transaction-local-message-table.png
│ │ ├── distributed-transaction-reliable-message.png
│ │ ├── dubbo-operating-principle.png
│ │ ├── dubbo-service-invoke-road.png
│ │ ├── dubbo-spi.png
│ │ ├── e-commerce-website-detail-page-architecture-1.png
│ │ ├── e-commerce-website-detail-page-architecture-2.png
│ │ ├── favicon-16x16.png
│ │ ├── favicon-32x32.png
│ │ ├── hash-slot.png
│ │ ├── hash.png
│ │ ├── hystrix-process.png
│ │ ├── hystrix-request-cache.png
│ │ ├── hystrix-semphore-thread-pool.png
│ │ ├── hystrix-semphore.png
│ │ ├── hystrix-thread-pool-isolation.png
│ │ ├── hystrix-thread-pool-queue.png
│ │ ├── icon.png
│ │ ├── service-invoke-road.png
│ │ ├── simple-distributed-system-oa.png
│ │ ├── zookeeper-active-standby.png
│ │ ├── zookeeper-centralized-storage.png
│ │ ├── zookeeper-distributed-coordination.png
│ │ ├── zookeeper-distributed-lock-demo.png
│ │ ├── zookeeper-distributed-lock.png
│ │ └── zookeeper-meta-data-manage.png
└── high-concurrency
│ ├── README.md
│ ├── database-shard-dynamic-expand.md
│ ├── database-shard-global-id-generate.md
│ ├── database-shard-method.md
│ ├── database-shard.md
│ ├── es-architecture.md
│ ├── es-introduction.md
│ ├── es-optimizing-query-performance.md
│ ├── es-production-cluster.md
│ ├── es-write-query-search.md
│ ├── high-concurrency-design.md
│ ├── how-to-ensure-high-availability-of-message-queues.md
│ ├── how-to-ensure-high-concurrency-and-high-availability-of-redis.md
│ ├── how-to-ensure-that-messages-are-not-repeatedly-consumed.md
│ ├── how-to-ensure-the-order-of-messages.md
│ ├── how-to-ensure-the-reliable-transmission-of-messages.md
│ ├── images
│ ├── async-replication-data-lose-case.png
│ ├── consistent-hashing-algorithm.png
│ ├── database-id-sequence-step.png
│ ├── database-shard-method-1.png
│ ├── database-shard-method-2.png
│ ├── database-split-horizon.png
│ ├── database-split-vertically.png
│ ├── distributed-system-request-sequence.png
│ ├── distributed-transaction-TCC.png
│ ├── distributed-transaction-XA.png
│ ├── distributed-transaction-local-message-table.png
│ ├── distributed-transaction-reliable-message.png
│ ├── dubbo-operating-principle.png
│ ├── dubbo-service-invoke-road.png
│ ├── dubbo-spi.png
│ ├── e-commerce-website-detail-page-architecture-1.png
│ ├── e-commerce-website-detail-page-architecture-2.png
│ ├── es-cluster-0.png
│ ├── es-cluster.png
│ ├── es-index-type-mapping-document-field.png
│ ├── es-search-process.png
│ ├── es-write-detail.png
│ ├── es-write.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── hash-slot.png
│ ├── hash.png
│ ├── high-concurrency-system-design.png
│ ├── icon.png
│ ├── kafka-after.png
│ ├── kafka-before.png
│ ├── kafka-order-01.png
│ ├── kafka-order-02.png
│ ├── mq-1.png
│ ├── mq-10.png
│ ├── mq-11.png
│ ├── mq-2.png
│ ├── mq-3.png
│ ├── mq-4.png
│ ├── mq-5.png
│ ├── mq-6.png
│ ├── mq-7.png
│ ├── mq-8.png
│ ├── mysql-master-slave.png
│ ├── rabbitmq-message-lose-solution.png
│ ├── rabbitmq-message-lose.png
│ ├── rabbitmq-order-01.png
│ ├── rabbitmq-order-02.png
│ ├── redis-caching-avalanche-solution.png
│ ├── redis-caching-avalanche.png
│ ├── redis-caching-penetration.png
│ ├── redis-cluster-split-brain.png
│ ├── redis-gossip.png
│ ├── redis-junior-inconsistent.png
│ ├── redis-master-slave-replication-detail.png
│ ├── redis-master-slave-replication.png
│ ├── redis-master-slave.png
│ ├── redis-redlock.png
│ ├── redis-single-thread-model.png
│ ├── service-invoke-road.png
│ ├── simple-distributed-system-oa.png
│ ├── zookeeper-active-standby.png
│ ├── zookeeper-centralized-storage.png
│ ├── zookeeper-distributed-coordination.png
│ ├── zookeeper-distributed-lock-demo.png
│ ├── zookeeper-distributed-lock.png
│ └── zookeeper-meta-data-manage.png
│ ├── mq-design.md
│ ├── mq-interview.md
│ ├── mq-time-delay-and-expired-failure.md
│ ├── mysql-read-write-separation.md
│ ├── redis-caching-avalanche-and-caching-penetration.md
│ ├── redis-cas.md
│ ├── redis-cluster.md
│ ├── redis-consistence.md
│ ├── redis-data-types.md
│ ├── redis-expiration-policies-and-lru.md
│ ├── redis-master-slave.md
│ ├── redis-persistence.md
│ ├── redis-production-environment.md
│ ├── redis-sentinel.md
│ ├── redis-single-thread-model.md
│ ├── why-cache.md
│ └── why-mq.md
└── images
├── PreferFunctionalStaffOrganization.png
├── async-replication-data-lose-case.png
├── basic-pipeline.png
├── bulkhead-partition.jpg
├── consistent-hashing-algorithm.png
├── conways-law.png
├── database-id-sequence-step.png
├── database-shard-method-1.png
├── database-shard-method-2.png
├── database-split-horizon.png
├── database-split-vertically.png
├── decentralised-data.png
├── distributed-system-request-sequence.png
├── distributed-transaction-TCC.png
├── distributed-transaction-XA.png
├── distributed-transaction-local-message-table.png
├── distributed-transaction-reliable-message.png
├── dubbo-keep-connection.png
├── dubbo-not-keep-connection.png
├── dubbo-operating-principle.png
├── dubbo-service-invoke-road.png
├── dubbo-spi.png
├── e-commerce-website-detail-page-architecture-1.png
├── e-commerce-website-detail-page-architecture-2.png
├── es-cluster-0.png
├── es-cluster.png
├── es-index-type-mapping-document-field.png
├── es-search-process.png
├── es-write-detail.png
├── es-write.png
├── favicon-16x16.png
├── favicon-32x32.png
├── get-up-and-study.png
├── hash-slot.png
├── hash.png
├── high-concurrency-system-design.png
├── hystrix-process.png
├── hystrix-request-cache.png
├── hystrix-semphore-thread-pool.png
├── hystrix-semphore.png
├── hystrix-thread-pool-isolation.png
├── hystrix-thread-pool-queue.png
├── icon.png
├── kafka-after.png
├── kafka-before.png
├── kafka-order-01.png
├── kafka-order-02.png
├── kafka-order-1.png
├── kafka-order-2.png
├── limaojishuwo.jpeg
├── micro-deployment.png
├── mq-1.png
├── mq-10.png
├── mq-11.png
├── mq-2.png
├── mq-3.png
├── mq-4.png
├── mq-5.png
├── mq-6.png
├── mq-7.png
├── mq-8.png
├── mysql-master-slave.png
├── rabbitmq-message-lose-solution.png
├── rabbitmq-message-lose.png
├── rabbitmq-order-01.png
├── rabbitmq-order-02.png
├── rabbitmq-order-1.png
├── rabbitmq-order-2.png
├── redis-caching-avalanche-solution.png
├── redis-caching-avalanche.png
├── redis-caching-penetration.png
├── redis-cluster-split-brain.png
├── redis-gossip.png
├── redis-junior-inconsistent.png
├── redis-master-slave-replication-detail.png
├── redis-master-slave-replication.png
├── redis-master-slave.png
├── redis-redlock.png
├── redis-single-thread-model.png
├── serialize-deserialize.png
├── service-invoke-road.png
├── simple-distributed-system-oa.png
├── sketch.png
├── where-is-my-offer.png
├── zookeeper-active-standby.png
├── zookeeper-centralized-storage.png
├── zookeeper-distributed-coordination.png
├── zookeeper-distributed-lock-demo.png
├── zookeeper-distributed-lock.png
└── zookeeper-meta-data-manage.png
/.idea/checkstyle-idea.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
15 |
16 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/.idea/description.html:
--------------------------------------------------------------------------------
1 | Simple Java application that includes a class with main()
method
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Java-Interview-Advanced.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/docs/distributed-system/21-day-course-instructions.md:
--------------------------------------------------------------------------------
1 |
2 | 技术广度的积累,问题不太大,面试突击第一季好好看完,把对应的一些技术都自己去找一些资料简单学习一下
3 |
4 | 项目经验、生产经验、技术深度、系统设计
5 |
6 | 6季,**分布式**、**微服务**、**海量数据**、**高性能**、**高并发**、**高可用**
7 |
8 | ## 第1季:分布式
9 |
10 | 每一季,都是把对应的技术主题中的相关的技术在项目里落地的细节,生产经验,架构经验,技术深度,系统设计,给大家结合很多的案例来进行讲解
11 |
12 | 每一季是持续21天,三周,每周的周一~周五会更新课程,15天,每天是更新4讲内容,每天的内容量大概在1小时左右,最后总课程时长大概在1000分钟左右
13 | 知己知彼
14 | 一线互联网公司面试分析
15 |
16 | 01、互联网大厂面试要求:技术广度、技术深度、系统设计以及项目经验
17 |
18 | 02、Java工程师面试突击第一季总结:你离一次成功的面试还差多少?
19 |
20 | 03、《21天互联网Java进阶面试训练营》的课程说明
21 |
22 | 04、作业:系统分析一下,自己距离大厂offer差在哪里?
23 |
24 | ### Dubbo vs Spring Cloud
25 | 两大核心分布式服务框架初探
26 |
27 | 05、感受一下BAT面试官对分布式技术的十几个面试连环炮!
28 |
29 | 06、你们公司用的Dubbo?那你再额外说说Spring Cloud的核心架构原理?
30 |
31 | 07、基于Dubbo和Spring Cloud分别搭建一个电商系统来快速体验一下!
32 |
33 | 08、作业:你们的系统使用了哪种服务框架?为什么要这样技术选型?
34 |
35 |
36 |
37 | ### 深入底层Dubbo与Spring Cloud的架构原理剖析
38 |
39 | 09、看过Dubbo源码吗?说说Dubbo的底层架构原理?
40 |
41 | 10、咱们来聊点深入的,说说Dubbo底层的网络通信机制原理!
42 |
43 | 11、Dubbo框架从架构设计角度,是怎么保证极高的可扩展性的?
44 |
45 | 12、作业:自己独立画出Dubbo的底层架构原理图
46 |
47 | 13、如果让你设计一个RPC框架,网络通信、代理机制、负载均衡等该如何设计?
48 |
49 | 14、平时除了使用外,有研究过Spring Cloud的底层架构原理么?
50 |
51 | 15、从底层实现原理的角度,对比一下Dubbo和Spring Cloud的优劣!
52 |
53 | 16、作业:自己独立画出Spring Cloud的架构原理图,RPC框架架构设计图!
54 |
55 |
56 | ### 服务注册中心与服务网关的生产实践
57 |
58 | 17、面试官:你们的服务注册中心进行过选型调研吗?对比一下各种服务注册中心!
59 |
60 | 18、画图阐述一下你们的服务注册中心部署架构,生产环境下怎么保证高可用?
61 |
62 | 19、你们系统遇到过服务发现过慢的问题吗?怎么优化和解决的?
63 |
64 | 20、作业:说一下自己公司的服务注册中心怎么技术选型的?生产环境中应该怎么优化?
65 | 21、你们对网关的技术选型是怎么考虑的?能对比一下各种网关技术的优劣吗?
66 |
67 | 22、说说生产环境下,你们是怎么实现网关对服务的动态路由的?
68 |
69 | 23、如果网关需要抗每秒10万的高并发访问,你应该怎么对网关进行生产优化?
70 |
71 | 24、作业:你们公司的网关是怎么技术选型的,假设有高并发场景怎么优化?
72 |
73 | 25、如果需要部署上万服务实例,现有的服务注册中心能否抗住?如何优化?
74 |
75 | 26、你们是如何基于网关实现灰度发布的?说说你们的灰度发布方案?
76 |
77 | 27、说说你们一个服务从开发到上线,服务注册、网关路由、服务调用的流程!
78 |
79 | 28、作业:看看你们公司的服务注册中心能否支撑上万服务实例的大规模场景?
80 |
81 |
82 | ### 分布式系统的生产实践
83 |
84 | 29、画一下你们系统的整体架构图,说说各个服务在生产环境怎么部署的?
85 |
86 | 30、你们系统每天有多大访问量?每个服务高峰QPS多少?压测过服务最大QPS吗?
87 |
88 | 31、如果系统访问量比现在增加10倍,你们考虑过系统的扩容方案吗?
89 |
90 | 32、作业:独立画出自己系统的生产部署架构图,梳理系统和服务的QPS以及扩容方案
91 |
92 | 33、你们生产环境的服务是怎么配置超时和重试参数的?为什么要这样配置?
93 |
94 | 34、如果出现服务请求重试,会不会出现类似重复下单的问题?
95 |
96 | 35、对于核心接口的防重幂等性,你们是怎么设计的?怎么防止重复下单问题?
97 |
98 | 36、作业:看看自己系统的核心接口有没有设计幂等性方案?如果没有,应该怎么设计?
99 |
100 |
101 | ### 分布式事务在项目中的落地实践与生产经验
102 |
103 | 37、画一下你们电商系统的核心交易链路图,说说分布式架构下存在什么问题?
104 |
105 | 38、针对电商核心交易链路,你们是怎么设计分布式事务技术方案的?
106 |
107 | 39、对于TCC事务、最终一致性事务的技术选型,你们是怎么做的?如何调研的?
108 |
109 | 40、作业:你们公司的核心链路是否有事务问题?分布式事务方案怎么调研选型?
110 |
111 | 41、在搭建好的电商系统里,落地开发对交易链路的TCC分布式事务方案
112 |
113 | 42、你能说说一个TCC分布式事务框架的核心架构原理吗?
114 |
115 | 43、现有的TCC事务方案的性能瓶颈在哪里?能支撑高并发交易场景吗?如何优化?
116 |
117 | 44、作业:如果对自己的系统核心链路落地TCC事务,应该如何落地实现?
118 |
119 | 45、在搭建好的电商系统里,如何基于RocketMQ最终一致性事务进行落地开发?
120 |
121 | 46、你了解RocketMQ对分布式事务支持的底层实现原理吗?
122 |
123 | 47、基于RocketMQ实现的最终一致性事务,如何抗住高并发交易场景?
124 |
125 | 48、作业:如果对自己的系统落地最终一致性事务,如何落地实现?
126 |
127 |
128 | ### 分布式锁在项目中的落地实践与生产经验
129 |
130 | 49、你们是用哪个开源框架实现的Redis分布式锁?能说说其核心原理么?
131 |
132 | 50、如果Redis是集群部署的,那么分布式锁的实现原理是什么?
133 |
134 | 51、在Redis集群出现故障的时候,会导致分布式锁失效吗?
135 |
136 | 52、作业:自己梳理出来Redis分布式锁的生产问题解决方案
137 |
138 | 53、如果要实现ZooKeeper分布式锁,一般用哪个开源框架?核心原理是什么?
139 |
140 | 54、对于ZooKeeper的羊群效应,分布式锁实现应该如何优化?
141 |
142 | 55、如果遇到ZooKeeper脑裂问题,分布式锁应该如何保证健壮性?
143 |
144 | 56、作业:自己梳理出来ZooKeeper分布式锁的生产问题解决方案
145 |
146 | 57、在搭建好的电商系统中,落地开发分布式锁保证库存数据准确的方案
147 |
148 | 58、你们的分布式锁做过高并发优化吗?能抗下每秒上万并发吗?
149 |
150 | 59、淘宝和京东的库存是怎么实现的?能不能不用分布式锁实现高并发库存更新?
151 |
152 | 60、作业:自己系统的分布式锁在高并发场景下应该如何优化?
153 |
154 |
155 | 我们的课程每天都会有一个作业,引导大家把学习到的项目经验、技术方案和生产优化落地到自己负责的项目中去,让大家出去面试的时候,可以把各种技术结合自己的项目来回答面试官的各种深度拷问
156 |
157 | 大家不要小看这个,根据我多年的面试经验来看,拥有这个技能的人凤毛麟角,这种人出去绝对是各大公司争抢的对象。
158 |
159 | **所以希望大家好好完成每天的作业,我布置的大量作业,就是为了帮你锻造出这种能力**
160 |
161 | **学习课程以及完成作业的过程中,大家一定会有很多的问题,可以到专栏的评论区去提问**
162 |
163 | **每天我都会和之前带出来的一批阿里、蚂蚁金服、滴滴的优秀同学给大家进行答疑,并且我们还有专门的付费用户的微信群,大家可以在微信群里跟我们一起进行技术交流**
164 |
165 | **如果你能坚持下来,学满6季,还可以获取私人定制的面试一条龙VIP服务**
166 |
167 | **如果是连续6季面试训练营都购买的同学,还可以获取面试一条龙VIP服务**
168 |
169 | **具体信息大家看“狸猫技术窝”公众号的知识店铺内的训练营详情即可**
170 |
171 | **具体可参见训练营目录下的《训练营专属服务》文档。简单来说,这个私人定制的面试VIP服务,会为你的跳槽面试全程保驾护航**
--------------------------------------------------------------------------------
/docs/distributed-system/BAT-interview-fire.md:
--------------------------------------------------------------------------------
1 | 针对面试突击第一季关于分布式这块的内容,相对应的做一个回顾和总结
2 |
3 | 面试突击第一季总共四五十讲,每个技术专题大概也是有十来讲
4 |
5 | #### (1)为什么要把系统拆分成分布式的?为啥要用dubbo?
6 | #### (2)dubbo的工作原理是啥?注册中心挂了可以继续通信吗?
7 | #### (3)dubbo都支持哪些通信协议以及序列化协议?
8 | #### (4)dubbo支持哪些负载均衡、高可用以及动态代理的策略?
9 | #### (5)SPI是啥思想?dubbo的SPI机制是怎么玩儿的?
10 | #### (6)基于dubbo如何做服务治理、服务降级以及重试?
11 |
12 | 这些问题在面试突击第一季里,我们都讲解过了,都是非常高简单的一些问题,作为一个合格的工程师,如果你是用了分布式系统架构,也就是把大的系统拆分为了多个子系统,或者是 多个服务
13 |
14 | 你肯定会用到一种服务框架,Dubbo、Spring Cloud、gRPC、Thrift
15 |
16 | 你必须 对这些服务框架的核心的架构原理,有一个认识和了解,服务注册和发现,通信和序列化,负载均衡,扩展机制,请求重试,请求超时
17 |
18 | #### (7)分布式系统中接口的幂等性该如何保证?比如不能重复扣款?
19 | #### (8)分布式系统中的接口调用如何保证顺序性?
20 |
21 | 接口幂等性,分布式系统,如果不保证,是否会发生类似重复下单,重复扣款之类的问题
22 |
23 | #### (9)如何设计一个类似dubbo的rpc框架?架构上该如何考虑?
24 |
25 | 自己看过一些dubbo、spring cloud的源码,对一款服务框架底层的实现原理,有一定的了解和认识,此时如果说他希望能够深入的考察你一下,看看你的水平,这个时候就有可能会问你这个问题
26 |
27 | #### (10)说说zookeeper一般都有哪些使用场景?
28 | #### (11)分布式锁是啥?对比下redis和zk两种分布式锁的优劣?
29 |
30 | 拆分成了分布式系统,就说明有很多子系统在同时的运作,如果说两个子系统都需要对某个数据资源进行一系列复杂的操作,在复杂操作期间,不能让数据被其他任何人来改变。分布式锁,技术实现原理
31 |
32 | #### (13)说说你们的分布式session方案是啥?怎么做的?
33 |
34 | 前后端分离之后,一般是前端那边来care session之类的问题,对于后端来说,玩儿分布式session玩儿的很少了
35 |
36 | #### (14)了解分布式事务方案吗?你们都咋做的?有啥坑?
37 |
38 |
39 | **我们的课程每天都会有一个作业,引导大家把学习到的项目经验、技术方案和生产优化落地到自己负责的项目中去,让大家出去面试的时候,可以把各种技术结合自己的项目来回答面试官的各种深度拷问**
40 |
41 | **大家不要小看这个,根据我多年的面试经验来看,拥有这个技能的人凤毛麟角,这种人出去绝对是各大公司争抢的对象。**
42 |
43 | **所以希望大家好好完成每天的作业,我布置的大量作业,就是为了帮你锻造出这种能力**
44 |
45 | **学习课程以及完成作业的过程中,大家一定会有很多的问题,可以到专栏的评论区去提问**
46 |
47 | **每天我都会和之前带出来的一批阿里、蚂蚁金服、滴滴的优秀同学给大家进行答疑,并且我们还有专门的付费用户的微信群,大家可以在微信群里跟我们一起进行技术交流**
48 |
49 | **如果你能坚持下来,学满6季,还可以获取私人定制的面试一条龙VIP服务**
50 |
51 | **如果是连续6季面试训练营都购买的同学,还可以获取面试一条龙VIP服务**
52 |
53 | **具体信息大家看“狸猫技术窝”公众号的知识店铺内的训练营详情即可**
54 |
55 | **具体可参见训练营目录下的《训练营专属服务》文档。简单来说,这个私人定制的面试VIP服务,会为你的跳槽面试全程保驾护航**
56 |
57 | **“狸猫技术窝”**,找到我们的训练营的详情页面
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/docs/distributed-system/Dubbo-SpringCloud-experience.md:
--------------------------------------------------------------------------------
1 | Spring Cloud来搭建了一套
2 |
3 | http://localhost:9000/order/order/create?productId=1&userId=1&count=3&totalPrice=300
4 |
5 | 刚开始几次请求会出现请求超时的问题,这个问题大家别纠结,后续要给大家讲spring cloud生产系统的优化
6 |
7 | 小小的小作业,参考一下dubbo的官方文档,搭建一个电商系统的dubbo版本的案例出来,我后面会搭建好的
8 |
9 | [代码下载点击这里哦!](https://github.com/shishan100/Java-Interview-Advanced/raw/master/docs/distributed-system/code/code.zip)
10 |
--------------------------------------------------------------------------------
/docs/distributed-system/README.md:
--------------------------------------------------------------------------------
1 | # 分布式系统
--------------------------------------------------------------------------------
/docs/distributed-system/code/code.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/code/code.zip
--------------------------------------------------------------------------------
/docs/distributed-system/code/code2.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/code/code2.zip
--------------------------------------------------------------------------------
/docs/distributed-system/code/code3.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/code/code3.zip
--------------------------------------------------------------------------------
/docs/distributed-system/code/code4.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/code/code4.zip
--------------------------------------------------------------------------------
/docs/distributed-system/code/rpc-demo.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/code/rpc-demo.zip
--------------------------------------------------------------------------------
/docs/distributed-system/core-architecture-principle .md:
--------------------------------------------------------------------------------
1 | 如果聊分布式这块的技术,围绕**Dubbo来拷问**的,但是呢,现在其实非常流行的是**Spring Cloud,Dubbo和Spring Cloud以及阿里系的一些技术**,现在正在融合,**Spring Cloud Alibaba,只不过现在用的公司暂时还没那么多而已**
2 |
3 | 作为合格的工程师,行业里主流的**分布式服务技术栈**,**Dubbo**和**Spring Cloud**两种,有的公司他是用**Dubbo**的,不用**Spring Cloud**的,有的公司是用**Spring Cloud**的,不用**Dubbo**的,他们是代表了两种主流技术栈
4 |
5 | Java工程师,Dubbo和Spring Cloud起码是基本原理,都有一定的了解
6 |
7 | **大白话 + 现场画图**
8 |
9 | 上网看一些博客资料,或者是买一些Spring Cloud的书,可能没考虑过一个事儿,第一篇必须是用非常通俗的语言,把一个系统如果用Spring Cloud来做分布式架构的话,那么他需要用到Spring Cloud哪些组件,为什么
10 |
11 | 跟着书或者博客,直接上手开始搭建demo,开始做起来了
12 |
13 | **分别用Dubbo和Spring Cloud做两个最基本的Demo工程**,用电商背景来搭建几个服务
14 |
15 | 比如说,现在我们有一个电商系统
16 |
17 | 用户现在需要下单购买一些东西这样子,订单系统、库存系统、仓储系统、积分系统
18 |
19 | 不太可能说用单块的架构,电商系统你想支撑多少用户量?10万注册用户,日活1000用户来你这里来购买?
20 |
21 | 百万级用户,十万级日活,单块系统就不太合适了,背后有几十个人的团队在协作开发,此时单块系统是绝对不合适的
22 |
23 | 梳理和明确一个概念:电商系统,拆分为了多个子系统,一次下订单的请求需要多个子系统协作完成,每个子系统都完成一部分的功能,多个子系统分别完成自己负责的事情,最终这个请求就处理完毕
24 |
25 | 我们不会让每个视频太长,按照我们大纲来讲,说是60讲,粗略的大纲,其实最终会拆分成可能上百讲,Spring Cloud架构原理,我们就要分为上下两讲来说
26 | 
27 |
28 | ### Spring Cloud
29 |
30 | #### Eureka:服务注册中心
31 | #### Feign:服务调用
32 | #### Ribbon:负载均衡
33 | #### Zuul/Spring Cloud Gatway:网关
34 |
35 | 这么多的系统,电商系统包含了20个子系统,每个子系统有20个核心接口,一共电商系统有400个接口,这么多的接口,直接对外暴露,前后端分离的架构,难道你让前端的同学必须记住你的20个系统的部署的机器,他们去做负载均衡,记住400个接口
36 |
37 |
38 | 微服务那块,**网关**
39 |
40 | **灰度发布**、**统一熔断**、**统一降级**、**统一缓存**、**统一限流**、**统一授权认证**
41 |
42 |
43 |
44 | **Hystrix**、**链路追踪**、**stream**、很多组件,Hystrix这块东西,其实是会放在高可用的环节去说的,并不是说一个普通系统刚开始就必须得用的,没有用好的话,反而会出问题,**Hystrix线路熔断的框架**,必须得设计对应的一整套的限流方案、熔断方案、资源隔离、降级机制,配合降级机制来做
45 |
--------------------------------------------------------------------------------
/docs/distributed-system/deal-line.md:
--------------------------------------------------------------------------------
1 |
2 | 分布式系统核心的问题,服务框架、注册中心、网关系统、部署架构、超时重试、幂等防重,生产相关的问题,都搞定了,还是针对面试这块,人家到时候问你很多的生产问题,你必须回答的很好,你可以自己主动聊,说我们在生产环境里做了哪些优化
3 |
4 | 分布式事务,分布式锁
5 |
6 | 核心交易链路,核心数据链路,核心计算链路,核心业务链路,都建议要上分布式事务,保证核心链路的数据一致性
7 |
8 | 面试突击第一季,如果你没看过,务必去看一下,分布式事务这块,几种技术方案,我当时都讲解过了,离落地还有一段距离
9 |
10 | 分布式锁,在分布式系统中用的是非常多的,单块系统,不需要分布式事务,一个系统对应一个数据库,事务都是本地数据库的事务就可以了;锁,很多地方多线程并发修改一些共享资源,在单块系统内部用synchronized锁就可以搞定了
11 |
12 |
13 |
14 | 分布式系统,事务 -> 分布式事务,锁 -> 分布式锁
15 |
16 |
17 |
18 |
19 | 订单服务 -> 创建订单
20 | -> 库存服务 -> 扣减库存
21 | -> 积分服务 -> 增加积分
22 | -> 仓储服务 -> 通知发货
23 |
24 |
25 |
26 | 微服务架构里,哪怕你就部署了一个MySQL在一台高配物理机上,但是在这个MySQL实例中会创建不同的database,db_order,db_inventory,db_credit,db_wms,订单服务涉及到5张表,db_order中就会有5张表
27 |
28 |
29 |
30 | 已经在自己本地插入了一条订单数据了,调用库存服务扣减库存,在db_inventory里执行sql扣减库存,此时库存服务执行失败了,但是对于订单服务,他可能是没有感知到,他的订单还是创建成功了,调用积分服务和仓储服务,积分增加了,还打算对商品进行发货
31 |
32 |
33 | 订单服务 -> 创建了订单,库存服务 -> 扣减了库存,积分服务 -> 增加积分失败,一旦回滚了之后,就会导致创建的订单被取消了,没了,create语句,放在本地事务里,一旦发现失败了,此时就会回滚,就会导致
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/docs/distributed-system/distributed-framework-selection.md:
--------------------------------------------------------------------------------
1 | **Spring Cloud**入门和使用级别的资料,建议大家自行百度,面试训练营,不是说针对每个技术详细给大家讲解的一个课程,我们会针对每个技术推出重磅的项目实战课程
2 |
3 | **自己公司如果是分布式的架构,你们当前选用的是Spring Cloud?Dubbo?自己研发的服务框架?对比一下各种服务框架的优点和缺点,技术选型,为什么?**
4 |
--------------------------------------------------------------------------------
/docs/distributed-system/distributed-lock-taobao-and-jingdong.md:
--------------------------------------------------------------------------------
1 |
2 | 大公司一般有分布式kv存储,tair,redis,mongodb,高并发,每秒几万几十万都没问题,甚至每秒百万
3 |
4 | 实时库存数据放kv存储里去,先查库存再扣减库存,你在操作库存的时候,直接扣减,如果你发现扣减之后是负数的话,此时就认为库存超卖了,回滚刚才的扣减,返回提示给用户。对kv做的库存修改写MQ,异步同步落数据库,相当于异步双写,用分布式kv抗高并发,做好一致性方案
5 |
6 |
7 |
--------------------------------------------------------------------------------
/docs/distributed-system/distributed-lock.md:
--------------------------------------------------------------------------------
1 |
2 | 下订单的环节,支付之前,创建一个订单
3 |
4 | 
5 | 创建一个订单,订单里会指定对哪些商品要购买多少件,此时就需要走一个流程,校验一下库存
6 |
7 | 查库存,确认库存充足,锁定库存
8 |
9 | 这个过程必须用分布式锁,锁掉这个商品的库存,对一个商品的购买同一时间只能有一个人操作
10 |
11 | redis和zookeeper实现分布式锁的原理,在之前面试突击第一季都讲过了,大家没看过的可以去看一下
12 |
--------------------------------------------------------------------------------
/docs/distributed-system/distributed-system-idempotency.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | 分布式服务接口的幂等性如何设计(比如不能重复扣款)?
3 |
4 | ## 面试官心理分析
5 | 从这个问题开始,面试官就已经进入了**实际的生产问题**的面试了。
6 |
7 | 一个分布式系统中的某个接口,该如何保证幂等性?这个事儿其实是你做分布式系统的时候必须要考虑的一个生产环境的技术问题。啥意思呢?
8 |
9 | 你看,假如你有个服务提供一些接口供外部调用,这个服务部署在了 5 台机器上,接着有个接口就是**付款接口**。然后人家用户在前端上操作的时候,不知道为啥,总之就是一个订单**不小心发起了两次支付请求**,然后这俩请求分散在了这个服务部署的不同的机器上,好了,结果一个订单扣款扣两次。
10 |
11 | 或者是订单系统调用支付系统进行支付,结果不小心因为**网络超时**了,然后订单系统走了前面我们看到的那个重试机制,咔嚓给你重试了一把,好,支付系统收到一个支付请求两次,而且因为负载均衡算法落在了不同的机器上,尴尬了。。。
12 |
13 | 所以你肯定得知道这事儿,否则你做出来的分布式系统恐怕容易埋坑。
14 |
15 | ## 面试题剖析
16 | 这个不是技术问题,这个没有通用的一个方法,这个应该**结合业务**来保证幂等性。
17 |
18 | 所谓**幂等性**,就是说一个接口,多次发起同一个请求,你这个接口得保证结果是准确的,比如不能多扣款、不能多插入一条数据、不能将统计值多加了 1。这就是幂等性。
19 |
20 | 其实保证幂等性主要是三点:
21 | - 对于每个请求必须有一个唯一的标识,举个栗子:订单支付请求,肯定得包含订单 id,一个订单 id 最多支付一次,对吧。
22 | - 每次处理完请求之后,必须有一个记录标识这个请求处理过了。常见的方案是在 mysql 中记录个状态啥的,比如支付之前记录一条这个订单的支付流水。
23 | - 每次接收请求需要进行判断,判断之前是否处理过。比如说,如果有一个订单已经支付了,就已经有了一条支付流水,那么如果重复发送这个请求,则此时先插入支付流水,orderId 已经存在了,唯一键约束生效,报错插入不进去的。然后你就不用再扣款了。
24 |
25 | 实际运作过程中,你要结合自己的业务来,比如说利用 redis,用 orderId 作为唯一键。只有成功插入这个支付流水,才可以执行实际的支付扣款。
26 |
27 | 要求是支付一个订单,必须插入一条支付流水,order_id 建一个唯一键 `unique key`。你在支付一个订单之前,先插入一条支付流水,order_id 就已经进去了。你就可以写一个标识到 redis 里面去,`set order_id payed`,下一次重复请求过来了,先查 redis 的 order_id 对应的 value,如果是 `payed` 就说明已经支付过了,你就别重复支付了。
--------------------------------------------------------------------------------
/docs/distributed-system/distributed-system-interview.md:
--------------------------------------------------------------------------------
1 | ## 分布式系统面试连环炮
2 | 有一些同学,之前呢主要是做传统行业,或者外包项目,一直是在那种小的公司,技术一直都搞的比较简单。他们有共同的一个问题,就是都没怎么搞过分布式系统,现在互联网公司,一般都是做分布式的系统,大家都不是做底层的分布式系统、分布式存储系统 hadoop hdfs、分布式计算系统 hadoop mapreduce / spark、分布式流式计算系统 storm。
3 |
4 | 分布式业务系统,就是把原来用 Java 开发的一个大块系统,给拆分成**多个子系统**,多个子系统之间互相调用,形成一个大系统的整体。假设原来你做了一个 OA 系统,里面包含了权限模块、员工模块、请假模块、财务模块,一个工程,里面包含了一堆模块,模块与模块之间会互相去调用,1 台机器部署。现在如果你把这个系统给拆开,权限系统、员工系统、请假系统、财务系统 4 个系统,4 个工程,分别在 4 台机器上部署。一个请求过来,完成这个请求,这个员工系统,调用权限系统,调用请假系统,调用财务系统,4 个系统分别完成了一部分的事情,最后 4 个系统都干完了以后,才认为是这个请求已经完成了。
5 |
6 | 
7 |
8 | > 近几年开始兴起和流行 Spring Cloud,刚流行,还没开始普及,目前普及的是 dubbo,因此这里也主要讲 dubbo。
9 |
10 | 面试官可能会问你以下问题。
11 | ### 为什么要进行系统拆分?
12 | - 为什么要进行系统拆分?如何进行系统拆分?拆分后不用dubbo可以吗?dubbo和thrift有什么区别呢?
13 | ### 分布式服务框架
14 | - 说一下的 dubbo 的工作原理?注册中心挂了可以继续通信吗?
15 | - dubbo 支持哪些序列化协议?说一下 hessian 的数据结构?PB 知道吗?为什么 PB 的效率是最高的?
16 | - dubbo 负载均衡策略和高可用策略都有哪些?动态代理策略呢?
17 | - dubbo 的 spi 思想是什么?
18 | - 如何基于 dubbo 进行服务治理、服务降级、失败重试以及超时重试?
19 | - 分布式服务接口的幂等性如何设计(比如不能重复扣款)?
20 | - 分布式服务接口请求的顺序性如何保证?
21 | - 如何自己设计一个类似 dubbo 的 rpc 框架?
22 |
23 | ### 分布式锁
24 | - 使用 redis 如何设计分布式锁?使用 zk 来设计分布式锁可以吗?这两种分布式锁的实现方式哪种效率比较高?
25 |
26 | ### 分布式事务
27 | - 分布式事务了解吗?你们如何解决分布式事务问题的?TCC 如果出现网络连不通怎么办?XA 的一致性如何保证?
28 |
29 | ### 分布式会话
30 | - 集群部署时的分布式 session 如何实现?
31 |
--------------------------------------------------------------------------------
/docs/distributed-system/distributed-system-request-sequence.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | 分布式服务接口请求的顺序性如何保证?
3 |
4 | ## 面试官心理分析
5 | 其实分布式系统接口的调用顺序,也是个问题,一般来说是不用保证顺序的。但是**有时候**可能确实是需要**严格的顺序**保证。给大家举个例子,你服务 A 调用服务 B,先插入再删除。好,结果俩请求过去了,落在不同机器上,可能插入请求因为某些原因执行慢了一些,导致删除请求先执行了,此时因为没数据所以啥效果也没有;结果这个时候插入请求过来了,好,数据插入进去了,那就尴尬了。
6 |
7 | 本来应该是 “先插入 -> 再删除”,这条数据应该没了,结果现在 “先删除 -> 再插入”,数据还存在,最后你死都想不明白是怎么回事。
8 |
9 | 所以这都是分布式系统一些很常见的问题。
10 |
11 | ## 面试题剖析
12 | 首先,一般来说,个人建议是,你们从业务逻辑上设计的这个系统最好是不需要这种顺序性的保证,因为一旦引入顺序性保障,比如使用**分布式锁**,会**导致系统复杂度上升**,而且会带来**效率低下**,热点数据压力过大等问题。
13 |
14 | 下面我给个我们用过的方案吧,简单来说,首先你得用 dubbo 的一致性 hash 负载均衡策略,将比如某一个订单 id 对应的请求都给分发到某个机器上去,接着就是在那个机器上,因为可能还是多线程并发执行的,你可能得立即将某个订单 id 对应的请求扔一个**内存队列**里去,强制排队,这样来确保他们的顺序性。
15 |
16 | 
17 |
18 | 但是这样引发的后续问题就很多,比如说要是某个订单对应的请求特别多,造成某台机器成**热点**怎么办?解决这些问题又要开启后续一连串的复杂技术方案......曾经这类问题弄的我们头疼不已,所以,还是建议什么呢?
19 |
20 | 最好是比如说刚才那种,一个订单的插入和删除操作,能不能合并成一个操作,就是一个删除,或者是其它什么,避免这种问题的产生。
--------------------------------------------------------------------------------
/docs/distributed-system/distributed-transaction-tcc.md:
--------------------------------------------------------------------------------
1 |
2 | 类似TCC事务的,开源框架,ByteTCC,Himly,个人技术高手自己写的,star也不少,也有一些中小型公司生产环境用了类似的分布式事务框架,知名度和普及型不高;很多公司,对类似的分布式事务,是自己写一些类似的框架
3 |
4 |
5 |
6 | 阿里开源了分布式事务框架,fescar,技术体系上有很多地方都是有自己的东西,seata,阿里开源的分布式事务框架,类似TCC事务,seata来做,这个框架是经历过阿里生产环境大量的考验的一个框架
7 |
8 | 支持dubbo、spring cloud两种服务框架,都是可以的
9 |
10 |
11 |
12 |
13 | 可靠消息最终一致性方案,面试突击第一季里都说过,ActiveMQ封装一个可靠消息服务,基于RabbitMQ封装,自己开发一个可靠消息服务,收到一个消息之后,会尝试投递到MQ上去,投递失败,重试投递
14 |
15 | 人家消费成功了以后必须回调他一个接口,通知他消息处理成功,如果一段时间后发现消息还是没有处理成功,此时会再次投递消息到MQ上去,在本地数据库里存放一些消息,基于ActiveMQ / RabbitMQ来实现消息的异步投递和消费
16 |
17 |
18 |
19 | RocketMQ,作为MQ中间件,提供了分布式事务支持,他把可靠消息服务需要实现的功能逻辑都做好了
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/docs/distributed-system/distributed-transaction.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | 分布式事务了解吗?你们是如何解决分布式事务问题的?
3 |
4 | ## 面试官心理分析
5 | 只要聊到你做了分布式系统,必问分布式事务,你对分布式事务一无所知的话,确实会很坑,你起码得知道有哪些方案,一般怎么来做,每个方案的优缺点是什么。
6 |
7 | 现在面试,分布式系统成了标配,而分布式系统带来的**分布式事务**也成了标配了。因为你做系统肯定要用事务吧,如果是分布式系统,肯定要用分布式事务吧。先不说你搞过没有,起码你得明白有哪几种方案,每种方案可能有啥坑?比如 TCC 方案的网络问题、XA 方案的一致性问题。
8 |
9 | ## 面试题剖析
10 | 分布式事务的实现主要有以下 5 种方案:
11 |
12 | - XA 方案
13 | - TCC 方案
14 | - 本地消息表
15 | - 可靠消息最终一致性方案
16 | - 最大努力通知方案
17 |
18 | ### 两阶段提交方案/XA方案
19 | 所谓的 XA 方案,即:两阶段提交,有一个**事务管理器**的概念,负责协调多个数据库(资源管理器)的事务,事务管理器先问问各个数据库你准备好了吗?如果每个数据库都回复 ok,那么就正式提交事务,在各个数据库上执行操作;如果任何其中一个数据库回答不 ok,那么就回滚事务。
20 |
21 | 这种分布式事务方案,比较适合单块应用里,跨多个库的分布式事务,而且因为严重依赖于数据库层面来搞定复杂的事务,效率很低,绝对不适合高并发的场景。如果要玩儿,那么基于 `Spring + JTA` 就可以搞定,自己随便搜个 demo 看看就知道了。
22 |
23 | 这个方案,我们很少用,一般来说**某个系统内部如果出现跨多个库**的这么一个操作,是**不合规**的。我可以给大家介绍一下, 现在微服务,一个大的系统分成几十个甚至几百个服务。一般来说,我们的规定和规范,是要求**每个服务只能操作自己对应的一个数据库**。
24 |
25 | 如果你要操作别的服务对应的库,不允许直连别的服务的库,违反微服务架构的规范,你随便交叉胡乱访问,几百个服务的话,全体乱套,这样的一套服务是没法管理的,没法治理的,可能会出现数据被别人改错,自己的库被别人写挂等情况。
26 |
27 | 如果你要操作别人的服务的库,你必须是通过**调用别的服务的接口**来实现,绝对不允许交叉访问别人的数据库。
28 |
29 | 
30 |
31 | ### TCC 方案
32 | TCC 的全称是:`Try`、`Confirm`、`Cancel`。
33 |
34 | - Try 阶段:这个阶段说的是对各个服务的资源做检测以及对资源进行**锁定或者预留**。
35 | - Confirm 阶段:这个阶段说的是在各个服务中**执行实际的操作**。
36 | - Cancel 阶段:如果任何一个服务的业务方法执行出错,那么这里就需要**进行补偿**,就是执行已经执行成功的业务逻辑的回滚操作。(把那些执行成功的回滚)
37 |
38 | 这种方案说实话几乎很少人使用,我们用的也比较少,但是也有使用的场景。因为这个**事务回滚**实际上是**严重依赖于你自己写代码来回滚和补偿**了,会造成补偿代码巨大,非常之恶心。
39 |
40 | 比如说我们,一般来说跟**钱**相关的,跟钱打交道的,**支付**、**交易**相关的场景,我们会用 TCC,严格保证分布式事务要么全部成功,要么全部自动回滚,严格保证资金的正确性,保证在资金上不会出现问题。
41 |
42 | 而且最好是你的各个业务执行的时间都比较短。
43 |
44 | 但是说实话,一般尽量别这么搞,自己手写回滚逻辑,或者是补偿逻辑,实在太恶心了,那个业务代码是很难维护的。
45 |
46 | 
47 |
48 | ### 本地消息表
49 | 本地消息表其实是国外的 ebay 搞出来的这么一套思想。
50 |
51 | 这个大概意思是这样的:
52 |
53 | 1. A 系统在自己本地一个事务里操作同时,插入一条数据到消息表;
54 | 2. 接着 A 系统将这个消息发送到 MQ 中去;
55 | 3. B 系统接收到消息之后,在一个事务里,往自己本地消息表里插入一条数据,同时执行其他的业务操作,如果这个消息已经被处理过了,那么此时这个事务会回滚,这样**保证不会重复处理消息**;
56 | 4. B 系统执行成功之后,就会更新自己本地消息表的状态以及 A 系统消息表的状态;
57 | 5. 如果 B 系统处理失败了,那么就不会更新消息表状态,那么此时 A 系统会定时扫描自己的消息表,如果有未处理的消息,会再次发送到 MQ 中去,让 B 再次处理;
58 | 6. 这个方案保证了最终一致性,哪怕 B 事务失败了,但是 A 会不断重发消息,直到 B 那边成功为止。
59 |
60 | 这个方案说实话最大的问题就在于**严重依赖于数据库的消息表来管理事务**啥的,如果是高并发场景咋办呢?咋扩展呢?所以一般确实很少用。
61 |
62 | 
63 |
64 | ### 可靠消息最终一致性方案
65 | 这个的意思,就是干脆不要用本地的消息表了,直接基于 MQ 来实现事务。比如阿里的 RocketMQ 就支持消息事务。
66 |
67 | 大概的意思就是:
68 |
69 | 1. A 系统先发送一个 prepared 消息到 mq,如果这个 prepared 消息发送失败那么就直接取消操作别执行了;
70 | 2. 如果这个消息发送成功过了,那么接着执行本地事务,如果成功就告诉 mq 发送确认消息,如果失败就告诉 mq 回滚消息;
71 | 3. 如果发送了确认消息,那么此时 B 系统会接收到确认消息,然后执行本地的事务;
72 | 4. mq 会自动**定时轮询**所有 prepared 消息回调你的接口,问你,这个消息是不是本地事务处理失败了,所有没发送确认的消息,是继续重试还是回滚?一般来说这里你就可以查下数据库看之前本地事务是否执行,如果回滚了,那么这里也回滚吧。这个就是避免可能本地事务执行成功了,而确认消息却发送失败了。
73 | 5. 这个方案里,要是系统 B 的事务失败了咋办?重试咯,自动不断重试直到成功,如果实在是不行,要么就是针对重要的资金类业务进行回滚,比如 B 系统本地回滚后,想办法通知系统 A 也回滚;或者是发送报警由人工来手工回滚和补偿。
74 | 6. 这个还是比较合适的,目前国内互联网公司大都是这么玩儿的,要不你举用 RocketMQ 支持的,要不你就自己基于类似 ActiveMQ?RabbitMQ?自己封装一套类似的逻辑出来,总之思路就是这样子的。
75 |
76 | 
77 |
78 | ### 最大努力通知方案
79 | 这个方案的大致意思就是:
80 |
81 | 1. 系统 A 本地事务执行完之后,发送个消息到 MQ;
82 | 2. 这里会有个专门消费 MQ 的**最大努力通知服务**,这个服务会消费 MQ 然后写入数据库中记录下来,或者是放入个内存队列也可以,接着调用系统 B 的接口;
83 | 3. 要是系统 B 执行成功就 ok 了;要是系统 B 执行失败了,那么最大努力通知服务就定时尝试重新调用系统 B,反复 N 次,最后还是不行就放弃。
84 |
85 | ### 你们公司是如何处理分布式事务的?
86 | 如果你真的被问到,可以这么说,我们某某特别严格的场景,用的是 TCC 来保证强一致性;然后其他的一些场景基于阿里的 RocketMQ 来实现分布式事务。
87 |
88 | 你找一个严格资金要求绝对不能错的场景,你可以说你是用的 TCC 方案;如果是一般的分布式事务场景,订单插入之后要调用库存服务更新库存,库存数据没有资金那么的敏感,可以用可靠消息最终一致性方案。
89 |
90 | 友情提示一下,RocketMQ 3.2.6 之前的版本,是可以按照上面的思路来的,但是之后接口做了一些改变,我这里不再赘述了。
91 |
92 | 当然如果你愿意,你可以参考可靠消息最终一致性方案来自己实现一套分布式事务,比如基于 RocketMQ 来玩儿。
--------------------------------------------------------------------------------
/docs/distributed-system/dubbo-augmentability.md:
--------------------------------------------------------------------------------
1 | 两点,第一点,是核心的组件全部接口化,组件和组件之间的调用,必须全部是依托于接口,去动态找配置的实现类,如果没有配置就用他自己默认的
2 |
3 | 第二点,提供一种自己实现的组件的配置的方式,比如说你要是自己实现了某个组件,配置一下,人家到时候运行的时候直接找你配置的那个组件即可,作为实现类,不用自己默认的组件了
4 |
5 |
6 |
7 |
8 | **我们的课程每天都会有一个作业,引导大家把学习到的项目经验、技术方案和生产优化落地到自己负责的项目中去,让大家出去面试的时候,可以把各种技术结合自己的项目来回答面试官的各种深度拷问**
9 |
10 | **大家不要小看这个,根据我多年的面试经验来看,拥有这个技能的人凤毛麟角,这种人出去绝对是各大公司争抢的对象。**
11 |
12 | **所以希望大家好好完成每天的作业,我布置的大量作业,就是为了帮你锻造出这种能力**
13 |
14 | **学习课程以及完成作业的过程中,大家一定会有很多的问题,可以到专栏的评论区去提问**
15 |
16 | **每天我都会和之前带出来的一批阿里、蚂蚁金服、滴滴的优秀同学给大家进行答疑,并且我们还有专门的付费用户的微信群,大家可以在微信群里跟我们一起进行技术交流**
17 |
18 | **如果你能坚持下来,学满6季,还可以获取私人定制的面试一条龙VIP服务**
19 |
20 | **如果是连续6季面试训练营都购买的同学,还可以获取面试一条龙VIP服务**
21 |
22 | **具体信息大家看“狸猫技术窝”公众号的知识店铺内的训练营详情即可**
23 |
24 | **具体可参见训练营目录下的《训练营专属服务》文档。简单来说,这个私人定制的面试VIP服务,会为你的跳槽面试全程保驾护航**
25 |
26 |
--------------------------------------------------------------------------------
/docs/distributed-system/dubbo-framework-principle.md:
--------------------------------------------------------------------------------
1 | 聊**分布式**这块,**Dubbo相关的原理**,**Spring Cloud相关的原理**,有的面试官可能会这样问,你有没有看过**Dubbo或者Spring Cloud的源码呢**?**技术广度**、**技术深度**、**项目经验**、**系统设计**、**基本功**
2 |
3 | 平时看你简历主要是用一些技术来开发一些系统,就会问问你了,对于一些你平时常用的技术,有没有关注过底层的原理,或者是看过源码,你要是说,90%的人,一般都会在这个时候支支吾吾的说
4 |
5 | 源码看过一点点,但是没怎么看过
6 |
7 | 在我们面试训练营里,能给你来分析源码吗?不太现实的,任何一个开源项目,**源码**少则几万行,多则几十万行,**Hadoop、Spark**,**面试训练营**,几讲的时间来讲透任何一个**开源项目**的**源码**,不现实
8 |
9 | 看源码技巧是有,但是,需要**技术功底**
10 |
11 | 就是说提炼一些**Dubbo、Spring Cloud**相关的一些底层的运行的原理,给大家来用大白话+现场画图的方式,说清楚,你就可以结合我们视频讲解的内容,去现场画图给面试官画一画一些技术底层的运行的一些原理
12 |
13 |
14 | 我们的课程每天都会有一个作业,引导大家把学习到的项目经验、技术方案和生产优化落地到自己负责的项目中去,让大家出去面试的时候,可以把各种技术结合自己的项目来回答面试官的各种深度拷问
15 |
16 | 大家不要小看这个,根据我多年的面试经验来看,拥有这个技能的人凤毛麟角,这种人出去绝对是各大公司争抢的对象。
17 |
18 | 所以希望大家好好完成每天的作业,我布置的大量作业,就是为了帮你锻造出这种能力
19 |
20 | 学习课程以及完成作业的过程中,大家一定会有很多的问题,可以到专栏的评论区去提问
21 |
22 | 每天我都会和之前带出来的一批阿里、蚂蚁金服、滴滴的优秀同学给大家进行答疑,并且我们还有专门的付费用户的微信群,大家可以在微信群里跟我们一起进行技术交流
23 |
24 | 如果你能坚持下来,学满6季,还可以获取私人定制的面试一条龙VIP服务
25 |
26 | 如果是连续6季面试训练营都购买的同学,还可以获取面试一条龙VIP服务
27 |
28 | 具体信息大家看“狸猫技术窝”公众号的知识店铺内的训练营详情即可,
29 |
30 | 具体可参见训练营目录下的《训练营专属服务》文档。简单来说,这个私人定制的面试VIP服务,会为你的跳槽面试全程保驾护航
31 |
32 |
33 |
34 |
35 | 分布式系统
36 |
37 | 拆分为了多个子系统之后,各个系统之间如何通过Spring Cloud服务框架来进行调用,Dubbo框架来进行调用
38 |
39 | 
40 | 提供接口
41 |
42 | 服务注册中心:
43 |
44 | ###消费者
45 |
46 | #### 动态代理:Proxy
47 | #### 负载均衡:Cluster,负载均衡,故障转移
48 | #### 注册中心:Registry
49 | #### 通信协议:Protocol,filter机制,http、rmi、dubbo等协议
50 |
51 | #### http、rmi、dubbo
52 |
53 | 比如说,我现在其实想要调用的是,DemoService里的sayHello接口
54 |
55 | 你的请求用什么样的方式来组织发送过去呢?以一个什么样的格式来发送你的请求?
56 |
57 | http,/demoService/sayHello?name=leo
58 | rmi,另外一种样子
59 | dubbo,另外一种样子,interface=demoService|method=sayHello|params=name:leo
60 |
61 | 信息交换:Exchange,Request和Response
62 |
63 | 对于你的协议的格式组织好的请求数据,需要进行一个封装,Request
64 |
65 | ##### 网络通信:Transport,netty、mina
66 | ##### 序列化:封装好的请求如何序列化成二进制数组,通过netty/mina发送出去
67 |
68 | 提供者
69 |
70 | #### 网络通信:Transport,基于netty/mina实现的Server
71 | #### 信息交换:Exchange,Response
72 | #### 通信协议:Protocol,filter机制
73 | #### 动态代理:Proxy
74 |
--------------------------------------------------------------------------------
/docs/distributed-system/dubbo-independent-framework.md:
--------------------------------------------------------------------------------
1 |
2 | 对**Dubbo**稍微做了一点进一步深入的讲解,但是远远是达不到精通源码的程度,只能说是相对于面试突击第一季要深入了一些,**Dubbo**一次服务请求调用,牵扯到了哪些组件,**负载均衡组件**、**注册中心**、**协议层**、**转换层**、**网络层(netty开发)**、**动态代理**,服务提供者也是类似的
3 |
4 | 网络通信的一些东西,是如何通过**NIO**的方式,**多线程**的方式,让一个服务提供者被多个服务消费者去并发的调用和请求
5 |
6 | 从整体架构原理的角度,说了一下如何进行扩展的
7 |
8 | 能说比普通的人稍微好一些,**技术深度**,那必须得是学其他的课程深入的理解他里面的源码,才能在面试的时候说,我精通一个技术的源码
9 |
10 | **Dubbo底层架构原理的图**,自己手画出来,画的足够的熟练,如果有一些什么问题的话,可以提问
11 |
--------------------------------------------------------------------------------
/docs/distributed-system/dubbo-load-balancing.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | dubbo 负载均衡策略和集群容错策略都有哪些?动态代理策略呢?
3 |
4 | ## 面试官心理分析
5 | 继续深问吧,这些都是用 dubbo 必须知道的一些东西,你得知道基本原理,知道序列化是什么协议,还得知道具体用 dubbo 的时候,如何负载均衡,如何高可用,如何动态代理。
6 |
7 | 说白了,就是看你对 dubbo 熟悉不熟悉:
8 | - dubbo 工作原理:服务注册、注册中心、消费者、代理通信、负载均衡;
9 | - 网络通信、序列化:dubbo 协议、长连接、NIO、hessian 序列化协议;
10 | - 负载均衡策略、集群容错策略、动态代理策略:dubbo 跑起来的时候一些功能是如何运转的?怎么做负载均衡?怎么做集群容错?怎么生成动态代理?
11 | - dubbo SPI 机制:你了解不了解 dubbo 的 SPI 机制?如何基于 SPI 机制对 dubbo 进行扩展?
12 |
13 | ## 面试题剖析
14 | ### dubbo 负载均衡策略
15 | #### random loadbalance
16 | 默认情况下,dubbo 是 random load balance ,即**随机**调用实现负载均衡,可以对 provider 不同实例**设置不同的权重**,会按照权重来负载均衡,权重越大分配流量越高,一般就用这个默认的就可以了。
17 |
18 | #### roundrobin loadbalance
19 | 这个的话默认就是均匀地将流量打到各个机器上去,但是如果各个机器的性能不一样,容易导致性能差的机器负载过高。所以此时需要调整权重,让性能差的机器承载权重小一些,流量少一些。
20 |
21 | 举个栗子。
22 |
23 | 跟运维同学申请机器,有的时候,我们运气好,正好公司资源比较充足,刚刚有一批热气腾腾、刚刚做好的虚拟机新鲜出炉,配置都比较高:8 核 + 16G 机器,申请到 2 台。过了一段时间,我们感觉 2 台机器有点不太够,我就去找运维同学说,“哥儿们,你能不能再给我一台机器”,但是这时只剩下一台 4 核 + 8G 的机器。我要还是得要。
24 |
25 | 这个时候,可以给两台 8 核 16G 的机器设置权重 4,给剩余 1 台 4 核 8G 的机器设置权重 2。
26 |
27 | #### leastactive loadbalance
28 | 这个就是自动感知一下,如果某个机器性能越差,那么接收的请求越少,越不活跃,此时就会给**不活跃的性能差的机器更少的请求**。
29 |
30 | #### consistanthash loadbalance
31 | 一致性 Hash 算法,相同参数的请求一定分发到一个 provider 上去,provider 挂掉的时候,会基于虚拟节点均匀分配剩余的流量,抖动不会太大。**如果你需要的不是随机负载均衡**,是要一类请求都到一个节点,那就走这个一致性 Hash 策略。
32 |
33 | ### dubbo 集群容错策略
34 | #### failover cluster 模式
35 | 失败自动切换,自动重试其他机器,**默认**就是这个,常见于读操作。(失败重试其它机器)
36 |
37 | 可以通过以下几种方式配置重试次数:
38 |
39 | ```xml
40 |
41 | ```
42 |
43 | 或者
44 |
45 | ```xml
46 |
47 | ```
48 |
49 | 或者
50 |
51 | ```xml
52 |
53 |
54 |
55 | ```
56 |
57 | #### failfast cluster 模式
58 | 一次调用失败就立即失败,常见于非幂等性的写操作,比如新增一条记录(调用失败就立即失败)
59 |
60 | #### failsafe cluster 模式
61 | 出现异常时忽略掉,常用于不重要的接口调用,比如记录日志。
62 |
63 | 配置示例如下:
64 |
65 | ```xml
66 |
67 | ```
68 |
69 | 或者
70 |
71 | ```xml
72 |
73 | ```
74 |
75 | #### failback cluster 模式
76 | 失败了后台自动记录请求,然后定时重发,比较适合于写消息队列这种。
77 |
78 | #### forking cluster 模式
79 | **并行调用**多个 provider,只要一个成功就立即返回。常用于实时性要求比较高的读操作,但是会浪费更多的服务资源,可通过 `forks="2"` 来设置最大并行数。
80 |
81 | #### broadcacst cluster
82 | 逐个调用所有的 provider。任何一个 provider 出错则报错(从`2.1.0` 版本开始支持)。通常用于通知所有提供者更新缓存或日志等本地资源信息。
83 |
84 | ### dubbo动态代理策略
85 | 默认使用 javassist 动态字节码生成,创建代理类。但是可以通过 spi 扩展机制配置自己的动态代理策略。
--------------------------------------------------------------------------------
/docs/distributed-system/dubbo-operating-principle.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | 说一下的 dubbo 的工作原理?注册中心挂了可以继续通信吗?说说一次 rpc 请求的流程?
3 |
4 | ## 面试官心理分析
5 | MQ、ES、Redis、Dubbo,上来先问你一些**思考性的问题**、**原理**,比如 kafka 高可用架构原理、es 分布式架构原理、redis 线程模型原理、Dubbo 工作原理;之后就是生产环境里可能会碰到的一些问题,因为每种技术引入之后生产环境都可能会碰到一些问题;再来点综合的,就是系统设计,比如让你设计一个 MQ、设计一个搜索引擎、设计一个缓存、设计一个 rpc 框架等等。
6 |
7 | 那既然开始聊分布式系统了,自然重点先聊聊 dubbo 了,毕竟 dubbo 是目前事实上大部分公司的分布式系统的 rpc 框架标准,基于 dubbo 也可以构建一整套的微服务架构。但是需要自己大量开发。
8 |
9 | 当然去年开始 spring cloud 非常火,现在大量的公司开始转向 spring cloud 了,spring cloud 人家毕竟是微服务架构的全家桶式的这么一个东西。但是因为很多公司还在用 dubbo,所以 dubbo 肯定会是目前面试的重点,何况人家 dubbo 现在重启开源社区维护了,捐献给了 apache,未来应该也还是有一定市场和地位的。
10 |
11 | 既然聊 dubbo,那肯定是先从 dubbo 原理开始聊了,你先说说 dubbo 支撑 rpc 分布式调用的架构啥的,然后说说一次 rpc 请求 dubbo 是怎么给你完成的,对吧。
12 |
13 | ## 面试题剖析
14 | ### dubbo 工作原理
15 | - 第一层:service 层,接口层,给服务提供者和消费者来实现的
16 | - 第二层:config 层,配置层,主要是对 dubbo 进行各种配置的
17 | - 第三层:proxy 层,服务代理层,无论是 consumer 还是 provider,dubbo 都会给你生成代理,代理之间进行网络通信
18 | - 第四层:registry 层,服务注册层,负责服务的注册与发现
19 | - 第五层:cluster 层,集群层,封装多个服务提供者的路由以及负载均衡,将多个实例组合成一个服务
20 | - 第六层:monitor 层,监控层,对 rpc 接口的调用次数和调用时间进行监控
21 | - 第七层:protocal 层,远程调用层,封装 rpc 调用
22 | - 第八层:exchange 层,信息交换层,封装请求响应模式,同步转异步
23 | - 第九层:transport 层,网络传输层,抽象 mina 和 netty 为统一接口
24 | - 第十层:serialize 层,数据序列化层
25 |
26 | ### 工作流程
27 | - 第一步:provider 向注册中心去注册
28 | - 第二步:consumer 从注册中心订阅服务,注册中心会通知 consumer 注册好的服务
29 | - 第三步:consumer 调用 provider
30 | - 第四步:consumer 和 provider 都异步通知监控中心
31 |
32 | 
33 |
34 | ### 注册中心挂了可以继续通信吗?
35 | 可以,因为刚开始初始化的时候,消费者会将提供者的地址等信息**拉取到本地缓存**,所以注册中心挂了可以继续通信。
--------------------------------------------------------------------------------
/docs/distributed-system/dubbo-rock-bottom.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 | 如果问到Dubbo底层原理,肯定除了上一讲的底层架构,你能说出来之外,还很可能会追问几个问题,网络通信这块原理的话
4 |
5 | netty来举例,NIO来实现的,一台机器同时抗高并发的请求
6 |
7 |
8 |
9 | **所以希望大家好好完成每天的作业,我布置的大量作业,就是为了帮你锻造出这种能力**
10 |
11 | **学习课程以及完成作业的过程中,大家一定会有很多的问题,可以到专栏的评论区去提问**
12 |
13 | **每天我都会和之前带出来的一批阿里、蚂蚁金服、滴滴的优秀同学给大家进行答疑,并且我们还有专门的付费用户的微信群,大家可以在微信群里跟我们一起进行技术交流**
14 |
15 | **如果你能坚持下来,学满6季,还可以获取私人定制的面试一条龙VIP服务**
16 |
17 | **如果是连续6季面试训练营都购买的同学,还可以获取面试一条龙VIP服务**
18 |
19 | **具体信息大家看“狸猫技术窝”公众号的知识店铺内的训练营详情即可**
20 |
21 | **具体可参见训练营目录下的《训练营专属服务》文档。简单来说,这个私人定制的面试VIP服务,会为你的跳槽面试全程保驾护航**
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/docs/distributed-system/dubbo-rpc-design.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | 如何自己设计一个类似 Dubbo 的 RPC 框架?
3 |
4 | ## 面试官心理分析
5 | 说实话,就这问题,其实就跟问你如何自己设计一个 MQ 一样的道理,就考两个:
6 | - 你有没有对某个 rpc 框架原理有非常深入的理解。
7 | - 你能不能从整体上来思考一下,如何设计一个 rpc 框架,考考你的系统设计能力。
8 |
9 | ## 面试题剖析
10 | 其实问到你这问题,你起码不能认怂,因为是知识的扫盲,那我不可能给你深入讲解什么 kafka 源码剖析,dubbo 源码剖析,何况我就算讲了,你要真的消化理解和吸收,起码个把月以后了。
11 |
12 | 所以我给大家一个建议,遇到这类问题,起码从你了解的类似框架的原理入手,自己说说参照 dubbo 的原理,你来设计一下,举个例子,dubbo 不是有那么多分层么?而且每个分层是干啥的,你大概是不是知道?那就按照这个思路大致说一下吧,起码你不能懵逼,要比那些上来就懵,啥也说不出来的人要好一些。
13 |
14 | 举个栗子,我给大家说个最简单的回答思路:
15 | - 上来你的服务就得去注册中心注册吧,你是不是得有个注册中心,保留各个服务的信息,可以用 zookeeper 来做,对吧。
16 | - 然后你的消费者需要去注册中心拿对应的服务信息吧,对吧,而且每个服务可能会存在于多台机器上。
17 | - 接着你就该发起一次请求了,咋发起?当然是基于动态代理了,你面向接口获取到一个动态代理,这个动态代理就是接口在本地的一个代理,然后这个代理会找到服务对应的机器地址。
18 | - 然后找哪个机器发送请求?那肯定得有个负载均衡算法了,比如最简单的可以随机轮询是不是。
19 | - 接着找到一台机器,就可以跟它发送请求了,第一个问题咋发送?你可以说用 netty 了,nio 方式;第二个问题发送啥格式数据?你可以说用 hessian 序列化协议了,或者是别的,对吧。然后请求过去了。
20 | - 服务器那边一样的,需要针对你自己的服务生成一个动态代理,监听某个网络端口了,然后代理你本地的服务代码。接收到请求的时候,就调用对应的服务代码,对吧。
21 |
22 | 这就是一个最最基本的 rpc 框架的思路,先不说你有多牛逼的技术功底,哪怕这个最简单的思路你先给出来行不行?
--------------------------------------------------------------------------------
/docs/distributed-system/dubbo-serialization-protocol.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | dubbo 支持哪些通信协议?支持哪些序列化协议?说一下 Hessian 的数据结构?PB 知道吗?为什么 PB 的效率是最高的?
3 |
4 | ## 面试官心理分析
5 | 上一个问题,说说 dubbo 的基本工作原理,那是你必须知道的,至少要知道 dubbo 分成哪些层,然后平时怎么发起 rpc 请求的,注册、发现、调用,这些是基本的。
6 |
7 | 接着就可以针对底层进行深入的问问了,比如第一步就可以先问问序列化协议这块,就是平时 RPC 的时候怎么走的?
8 |
9 | ## 面试题剖析
10 | **序列化**,就是把数据结构或者是一些对象,转换为二进制串的过程,而**反序列化**是将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程。
11 |
12 | 
13 |
14 | ### dubbo 支持不同的通信协议
15 | - dubbo 协议
16 |
17 | **默认**就是走 dubbo 协议,单一长连接,进行的是 NIO 异步通信,基于 hessian 作为序列化协议。使用的场景是:传输数据量小(每次请求在 100kb 以内),但是并发量很高。
18 |
19 | 为了要支持高并发场景,一般是服务提供者就几台机器,但是服务消费者有上百台,可能每天调用量达到上亿次!此时用长连接是最合适的,就是跟每个服务消费者维持一个长连接就可以,可能总共就 100 个连接。然后后面直接基于长连接 NIO 异步通信,可以支撑高并发请求。
20 |
21 | 长连接,通俗点说,就是建立连接过后可以持续发送请求,无须再建立连接。
22 |
23 | 
24 |
25 | 而短连接,每次要发送请求之前,需要先重新建立一次连接。
26 |
27 | 
28 |
29 | - rmi 协议
30 |
31 | 走 Java 二进制序列化,多个短连接,适合消费者和提供者数量差不多的情况,适用于文件的传输,一般较少用。
32 |
33 | - hessian 协议
34 |
35 | 走 hessian 序列化协议,多个短连接,适用于提供者数量比消费者数量还多的情况,适用于文件的传输,一般较少用。
36 |
37 | - http 协议
38 |
39 | 走 json 序列化。
40 |
41 | - webservice
42 |
43 | 走 SOAP 文本序列化。
44 |
45 | ### dubbo 支持的序列化协议
46 | dubbo 支持 hession、Java 二进制序列化、json、SOAP 文本序列化多种序列化协议。但是 hessian 是其默认的序列化协议。
47 |
48 | ### 说一下 Hessian 的数据结构
49 | Hessian 的对象序列化机制有 8 种原始类型:
50 |
51 | - 原始二进制数据
52 | - boolean
53 | - 64-bit date(64 位毫秒值的日期)
54 | - 64-bit double
55 | - 32-bit int
56 | - 64-bit long
57 | - null
58 | - UTF-8 编码的 string
59 |
60 | 另外还包括 3 种递归类型:
61 |
62 | - list for lists and arrays
63 | - map for maps and dictionaries
64 | - object for objects
65 |
66 | 还有一种特殊的类型:
67 |
68 | - ref:用来表示对共享对象的引用。
69 |
70 | ### 为什么 PB 的效率是最高的?
71 | 可能有一些同学比较习惯于 `JSON` or `XML` 数据存储格式,对于 `Protocol Buffer` 还比较陌生。`Protocol Buffer` 其实是 Google 出品的一种轻量并且高效的结构化数据存储格式,性能比 `JSON`、`XML` 要高很多。
72 |
73 | 其实 PB 之所以性能如此好,主要得益于两个:**第一**,它使用 proto 编译器,自动进行序列化和反序列化,速度非常快,应该比 `XML` 和 `JSON` 快上了 `20~100` 倍;**第二**,它的数据压缩效果好,就是说它序列化后的数据量体积小。因为体积小,传输起来带宽和速度上会有优化。
--------------------------------------------------------------------------------
/docs/distributed-system/dubbo-service-management.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | 如何基于 dubbo 进行服务治理、服务降级、失败重试以及超时重试?
3 |
4 | ## 面试官心理分析
5 | 服务治理,这个问题如果问你,其实就是看看你有没有**服务治理**的思想,因为这个是做过复杂微服务的人肯定会遇到的一个问题。
6 |
7 | **服务降级**,这个是涉及到复杂分布式系统中必备的一个话题,因为分布式系统互相来回调用,任何一个系统故障了,你不降级,直接就全盘崩溃?那就太坑爹了吧。
8 |
9 | **失败重试**,分布式系统中网络请求如此频繁,要是因为网络问题不小心失败了一次,是不是要重试?
10 |
11 | **超时重试**,跟上面一样,如果不小心网络慢一点,超时了,如何重试?
12 |
13 | ## 面试题剖析
14 | ### 服务治理
15 | #### 1. 调用链路自动生成
16 | 一个大型的分布式系统,或者说是用现在流行的微服务架构来说吧,**分布式系统由大量的服务组成**。那么这些服务之间互相是如何调用的?调用链路是啥?说实话,几乎到后面没人搞的清楚了,因为服务实在太多了,可能几百个甚至几千个服务。
17 |
18 | 那就需要基于 dubbo 做的分布式系统中,对各个服务之间的调用自动记录下来,然后自动将**各个服务之间的依赖关系和调用链路生成出来**,做成一张图,显示出来,大家才可以看到对吧。
19 |
20 | 
21 |
22 | #### 2. 服务访问压力以及时长统计
23 | 需要自动统计**各个接口和服务之间的调用次数以及访问延时**,而且要分成两个级别。
24 |
25 | - 一个级别是接口粒度,就是每个服务的每个接口每天被调用多少次,TP50/TP90/TP99,三个档次的请求延时分别是多少;
26 | - 第二个级别是从源头入口开始,一个完整的请求链路经过几十个服务之后,完成一次请求,每天全链路走多少次,全链路请求延时的 TP50/TP90/TP99,分别是多少。
27 |
28 | 这些东西都搞定了之后,后面才可以来看当前系统的压力主要在哪里,如何来扩容和优化啊。
29 |
30 | #### 3. 其它
31 | - 服务分层(避免循环依赖)
32 | - 调用链路失败监控和报警
33 | - 服务鉴权
34 | - 每个服务的可用性的监控(接口调用成功率?几个 9?99.99%,99.9%,99%)
35 |
36 | ### 服务降级
37 | 比如说服务 A 调用服务 B,结果服务 B 挂掉了,服务 A 重试几次调用服务 B,还是不行,那么直接降级,走一个备用的逻辑,给用户返回响应。
38 |
39 | 举个栗子,我们有接口 `HelloService`。`HelloServiceImpl` 有该接口的具体实现。
40 |
41 | ```java
42 | public interface HelloService {
43 | void sayHello();
44 | }
45 |
46 | public class HelloServiceImpl implements HelloService {
47 | public void sayHello() {
48 | System.out.println("hello world......");
49 | }
50 | }
51 | ```
52 |
53 | ```xml
54 |
55 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | ```
83 |
84 | 我们调用接口失败的时候,可以通过 `mock` 统一返回 null。
85 |
86 | mock 的值也可以修改为 true,然后再跟接口同一个路径下实现一个 Mock 类,命名规则是 “接口名称+`Mock`” 后缀。然后在 Mock 类里实现自己的降级逻辑。
87 |
88 | ```java
89 | public class HelloServiceMock implements HelloService {
90 | public void sayHello() {
91 | // 降级逻辑
92 | }
93 | }
94 | ```
95 |
96 | ### 失败重试和超时重试
97 | 所谓失败重试,就是 consumer 调用 provider 要是失败了,比如抛异常了,此时应该是可以重试的,或者调用超时了也可以重试。配置如下:
98 |
99 | ```xml
100 |
101 | ```
102 |
103 | 举个栗子。
104 |
105 | 某个服务的接口,要耗费 5s,你这边不能干等着,你这边配置了 timeout 之后,我等待 2s,还没返回,我直接就撤了,不能干等你。
106 |
107 | 可以结合你们公司具体的场景来说说你是怎么设置这些参数的:
108 |
109 | - `timeout`:一般设置为 `200ms`,我们认为不能超过 `200ms` 还没返回。
110 | - `retries`:设置 retries,一般是在读请求的时候,比如你要查询个数据,你可以设置个 retries,如果第一次没读到,报错,重试指定的次数,尝试再次读取。
--------------------------------------------------------------------------------
/docs/distributed-system/dubbo-spi.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | dubbo 的 spi 思想是什么?
3 |
4 | ## 面试官心理分析
5 | 继续深入问呗,前面一些基础性的东西问完了,确定你应该都 ok,了解 dubbo 的一些基本东西,那么问个稍微难一点点的问题,就是 spi,先问问你 spi 是啥?然后问问你 dubbo 的 spi 是怎么实现的?
6 |
7 | 其实就是看看你对 dubbo 的掌握如何。
8 |
9 | ## 面试题剖析
10 | ### spi 是啥?
11 | spi,简单来说,就是 `service provider interface`,说白了是什么意思呢,比如你有个接口,现在这个接口有 3 个实现类,那么在系统运行的时候对这个接口到底选择哪个实现类呢?这就需要 spi 了,需要**根据指定的配置**或者是**默认的配置**,去**找到对应的实现类**加载进来,然后用这个实现类的实例对象。
12 |
13 | 举个栗子。
14 |
15 | 你有一个接口 A。A1/A2/A3 分别是接口A的不同实现。你通过配置 `接口 A = 实现 A2`,那么在系统实际运行的时候,会加载你的配置,用实现 A2 实例化一个对象来提供服务。
16 |
17 | spi 机制一般用在哪儿?**插件扩展的场景**,比如说你开发了一个给别人使用的开源框架,如果你想让别人自己写个插件,插到你的开源框架里面,从而扩展某个功能,这个时候 spi 思想就用上了。
18 |
19 | ### Java spi 思想的体现
20 | spi 经典的思想体现,大家平时都在用,比如说 jdbc。
21 |
22 | Java 定义了一套 jdbc 的接口,但是 Java 并没有提供 jdbc 的实现类。
23 |
24 | 但是实际上项目跑的时候,要使用 jdbc 接口的哪些实现类呢?一般来说,我们要**根据自己使用的数据库**,比如 mysql,你就将 `mysql-jdbc-connector.jar` 引入进来;oracle,你就将 `oracle-jdbc-connector.jar` 引入进来。
25 |
26 | 在系统跑的时候,碰到你使用 jdbc 的接口,他会在底层使用你引入的那个 jar 中提供的实现类。
27 |
28 | ### dubbo 的 spi 思想
29 | dubbo 也用了 spi 思想,不过没有用 jdk 的 spi 机制,是自己实现的一套 spi 机制。
30 | ```java
31 | Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
32 | ```
33 |
34 | Protocol 接口,在系统运行的时候,,dubbo 会判断一下应该选用这个 Protocol 接口的哪个实现类来实例化对象来使用。
35 |
36 | 它会去找一个你配置的 Protocol,将你配置的 Protocol 实现类,加载到 jvm 中来,然后实例化对象,就用你的那个 Protocol 实现类就可以了。
37 |
38 |
39 | 上面那行代码就是 dubbo 里大量使用的,就是对很多组件,都是保留一个接口和多个实现,然后在系统运行的时候动态根据配置去找到对应的实现类。如果你没配置,那就走默认的实现好了,没问题。
40 | ```java
41 | @SPI("dubbo")
42 | public interface Protocol {
43 |
44 | int getDefaultPort();
45 |
46 | @Adaptive
47 | Exporter export(Invoker invoker) throws RpcException;
48 |
49 | @Adaptive
50 | Invoker refer(Class type, URL url) throws RpcException;
51 |
52 | void destroy();
53 |
54 | }
55 | ```
56 |
57 | 在 dubbo 自己的 jar 里,在`/META_INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol`文件中:
58 | ```xml
59 | dubbo=com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol
60 | http=com.alibaba.dubbo.rpc.protocol.http.HttpProtocol
61 | hessian=com.alibaba.dubbo.rpc.protocol.hessian.HessianProtocol
62 | ```
63 |
64 | 所以说,这就看到了 dubbo 的 spi 机制默认是怎么玩儿的了,其实就是 Protocol 接口,`@SPI("dubbo")` 说的是,通过 SPI 机制来提供实现类,实现类是通过 dubbo 作为默认 key 去配置文件里找到的,配置文件名称与接口全限定名一样的,通过 dubbo 作为 key 可以找到默认的实现类就是 `com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol`。
65 |
66 |
67 | 如果想要动态替换掉默认的实现类,需要使用 `@Adaptive` 接口,Protocol 接口中,有两个方法加了 `@Adaptive` 注解,就是说那俩接口会被代理实现。
68 |
69 | 啥意思呢?
70 |
71 | 比如这个 Protocol 接口搞了俩 `@Adaptive` 注解标注了方法,在运行的时候会针对 Protocol 生成代理类,这个代理类的那俩方法里面会有代理代码,代理代码会在运行的时候动态根据 url 中的 protocol 来获取那个 key,默认是 dubbo,你也可以自己指定,你如果指定了别的 key,那么就会获取别的实现类的实例了。
72 |
73 | ### 如何自己扩展 dubbo 中的组件
74 | 下面来说说怎么来自己扩展 dubbo 中的组件。
75 |
76 | 自己写个工程,要是那种可以打成 jar 包的,里面的 `src/main/resources` 目录下,搞一个 `META-INF/services`,里面放个文件叫:`com.alibaba.dubbo.rpc.Protocol`,文件里搞一个`my=com.bingo.MyProtocol`。自己把 jar 弄到 nexus 私服里去。
77 |
78 | 然后自己搞一个 `dubbo provider` 工程,在这个工程里面依赖你自己搞的那个 jar,然后在 spring 配置文件里给个配置:
79 |
80 | ```xml
81 |
82 | ```
83 | provider 启动的时候,就会加载到我们 jar 包里的`my=com.bingo.MyProtocol` 这行配置里,接着会根据你的配置使用你定义好的 MyProtocol 了,这个就是简单说明一下,你通过上述方式,可以替换掉大量的 dubbo 内部的组件,就是扔个你自己的 jar 包,然后配置一下即可。
84 |
85 | 
86 |
87 | dubbo 里面提供了大量的类似上面的扩展点,就是说,你如果要扩展一个东西,只要自己写个 jar,让你的 consumer 或者是 provider 工程,依赖你的那个 jar,在你的 jar 里指定目录下配置好接口名称对应的文件,里面通过 `key=实现类`。
88 |
89 | 然后对于对应的组件,类似 `` 用你的那个 key 对应的实现类来实现某个接口,你可以自己去扩展 dubbo 的各种功能,提供你自己的实现。
--------------------------------------------------------------------------------
/docs/distributed-system/dubbo-vs-springCloud.md:
--------------------------------------------------------------------------------
1 | 底层架构原理是类似的
2 |
3 | **Dubbo,RPC的性能比HTTP的性能更好,并发能力更强,经过深度优化的RPC服务框架,性能和并发能力是更好一些**
4 |
5 | 很多中小型公司而言,其实稍微好一点的性能,**Dubbo一次请求10ms,Spring Cloud耗费20ms**,对很多中小型公司而言,性能、并发,并不是最主要的因素
6 |
7 | **Spring Cloud这套架构原理,走HTTP接口和HTTP请求,就足够满足性能和并发的需要了,没必要使用高度优化的RPC服务框架**
8 |
9 |
10 |
11 | Dubbo之前的一个定位,就是一个单纯的服务框架而已,不提供任何其他的功能,配合的网关还得选择其他的一些技术
12 |
13 | **Spring Cloud**,中小型公司用的特别多,老系统从**Dubbo迁移到Spring Cloud**,新系统都是用**Spring Cloud来进行开发,全家桶,主打的是微服务架构里,组件齐全,功能齐全。网关直接提供了,分布式配置中心,授权认证,服务调用链路追踪,Hystrix可以做服务的资源隔离、熔断降级、服务请求QPS监控、契约测试、消息中间件封装、ZK封装**
14 |
15 |
16 | 剩是剩在功能齐全,中小型公司开箱即用,直接满足系统的开发需求
17 |
18 |
19 | **Spring Cloud**原来支持的一些技术慢慢的未来会演变为,跟阿里技术体系进行融合,**Spring Cloud Alibaba**,阿里技术会融入**Spring Cloud**里面去
20 |
21 |
22 |
23 |
24 | **我们的课程每天都会有一个作业,引导大家把学习到的项目经验、技术方案和生产优化落地到自己负责的项目中去,让大家出去面试的时候,可以把各种技术结合自己的项目来回答面试官的各种深度拷问**
25 |
26 | **大家不要小看这个,根据我多年的面试经验来看,拥有这个技能的人凤毛麟角,这种人出去绝对是各大公司争抢的对象。**
27 |
28 | **我们的课程每天都会有一个作业,引导大家把学习到的项目经验、技术方案和生产优化落地到自己负责的项目中去,让大家出去面试的时候,可以把各种技术结合自己的项目来回答面试官的各种深度拷问**
29 |
30 | **大家不要小看这个,根据我多年的面试经验来看,拥有这个技能的人凤毛麟角,这种人出去绝对是各大公司争抢的对象。**
31 |
32 | **所以希望大家好好完成每天的作业,我布置的大量作业,就是为了帮你锻造出这种能力**
33 |
34 | **学习课程以及完成作业的过程中,大家一定会有很多的问题,可以到专栏的评论区去提问**
35 |
36 | **每天我都会和之前带出来的一批阿里、蚂蚁金服、滴滴的优秀同学给大家进行答疑,并且我们还有专门的付费用户的微信群,大家可以在微信群里跟我们一起进行技术交流**
37 |
38 | **如果你能坚持下来,学满6季,还可以获取私人定制的面试一条龙VIP服务**
39 |
40 | **如果是连续6季面试训练营都购买的同学,还可以获取面试一条龙VIP服务**
41 |
42 | **具体信息大家看“狸猫技术窝”公众号的知识店铺内的训练营详情即可**
43 |
44 | **具体可参见训练营目录下的《训练营专属服务》文档。简单来说,这个私人定制的面试VIP服务,会为你的跳槽面试全程保驾护航**
45 |
46 | **“狸猫技术窝”**,找到我们的训练营的详情页面
47 |
--------------------------------------------------------------------------------
/docs/distributed-system/dynamic-route.md:
--------------------------------------------------------------------------------
1 | ```
2 | CREATE TABLE `gateway_api_route` (
3 | `id` varchar(50) NOT NULL,
4 | `path` varchar(255) NOT NULL,
5 | `service_id` varchar(50) DEFAULT NULL,
6 | `url` varchar(255) DEFAULT NULL,
7 | `retryable` tinyint(1) DEFAULT NULL,
8 | `enabled` tinyint(1) NOT NULL,
9 | `strip_prefix` int(11) DEFAULT NULL,
10 | `api_name` varchar(255) DEFAULT NULL,
11 | PRIMARY KEY (`id`)
12 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8
13 |
14 | INSERT INTO gateway_api_route (id, path, service_id, retryable, strip_prefix, url, enabled) VALUES ('order-service', '/order/**', 'order-service',0,1, NULL, 1);
15 |
16 | ```
17 |
18 | 你可以自己用简单的spring mvc+前端页面封装一个可视化的网关管理工作台,如果新开发了一个服务之后,就可以在这个界面上配置一下,说某个服务对应某个url路径,修改,增删改查
19 |
20 | http://localhost:9000/order/order/create?productId=1&userId=1&count=2&totalPrice=50
21 |
22 | 生产级,企业级的功能,网关的动态路由
23 |
--------------------------------------------------------------------------------
/docs/distributed-system/eventual-consistency.md:
--------------------------------------------------------------------------------
1 |
2 | 其实也很简单,自己写一个可靠消息服务即可,接收人家发送的half message,然后返回响应给人家,如果Producer没收到响应,则重发。然后Producer执行本地事务,接着发送commit/rollback给可靠消息服务。
3 |
4 | 可靠消息服务启动一个后台线程定时扫描本地数据库表中所有half message,超过一定时间没commit/rollback就回调Producer接口,确认本地事务是否成功,获取commit/rollback
5 |
6 | 如果消息被rollback就废弃掉,如果消息被commit就发送这个消息给下游服务,或者是发送给RabbitMQ/Kafka/ActiveMQ,都可以,然后下游服务消费了,必须回调可靠消息服务接口进行ack
7 |
8 | 如果一段时间都没收到ack,则重发消息给下游服务
9 |
--------------------------------------------------------------------------------
/docs/distributed-system/floor-distribute-lock.md:
--------------------------------------------------------------------------------
1 |
2 | 《亿级流量电商详情页系统实战》,部署redis和zookeeper,redisson做分布式锁,curator做分布式锁,试一试
3 |
--------------------------------------------------------------------------------
/docs/distributed-system/gateway-high-concurrency.md:
--------------------------------------------------------------------------------
1 |
2 | 第一个是高并发,第二个是如何优化
3 |
4 | 
5 | **Zuul**网关部署的是什么配置的机器,**部署32核64G,对网关路由转发的请求**,**每秒抗个小几万请求是不成问题的,几台Zuul网关机器**
6 |
7 | **每秒是1万请求,8核16G的机器部署Zuul网关,5台机器就够了**
8 |
9 | ### 生产级的网关,应该具备我刚才说的几个特点和功能:
10 |
11 | #### (1)动态路由:新开发某个服务,动态把请求路径和服务的映射关系热加载到网关里去;服务增减机器,网关自动热感知
12 | #### (2)灰度发布:基于现成的开源插件来做
13 | #### (3)授权认证
14 | #### (4)限流熔断
15 | #### (5)性能监控:每个API接口的耗时、成功率、QPS
16 | #### (6)系统日志
17 | #### (7)数据缓存
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/docs/distributed-system/gateway-model-selection.md:
--------------------------------------------------------------------------------
1 |
2 | ### 网关的核心功能
3 |
4 | #### (1)动态路由:新开发某个服务,动态把请求路径和服务的映射关系热加载到网关里去;服务增减机器,网关自动热感知
5 | #### (2)灰度发布
6 | #### (3)授权认证
7 | #### (4)性能监控:每个API接口的耗时、成功率、QPS
8 | #### (5)系统日志
9 | #### (6)数据缓存
10 | #### (7)限流熔断
11 |
12 |
13 | ### 几种技术选型
14 |
15 | #### Kong、Zuul、Nginx+Lua(OpenResty)、自研网关
16 |
17 | **Kong:Nginx里面的一个基于lua写的模块,实现了网关的功能**
18 | **Zuul:Spring Cloud来玩儿微服务技术架构,Zuul**
19 |
20 | **Nginx+Lua(OpenResty):课程目录里面,有一个文档,课程免费学习,亿级流量系统架构的课程,详细讲解了Nginx+Lua的开发**,基于lua自己写类似Kong的网关
21 | **自研网关:自己来写类似Zuul的网关,基于Servlet、Netty来做网关,实现上述所有的功能**
22 |
23 |
24 | 大厂:BAT、京东、美团、滴滴之类的,自研网关,都是基于Netty等技术自研网关;Nginx + Lua(Tengine)来做,封装网关的功能
25 |
26 | 中小型公司:Spring Cloud技术栈主要是用Zuul,Gateway;如果是Dubbo等技术栈,有的采用Kong等网关,也可以直接不用网关,很多公司压根儿就没用网关,直接Nginx反向代理+负载均衡;
27 |
28 | Zuul:基于Java开发,核心网关功能都比较简单,但是比如灰度发布、限流、动态路由之类的,很多都要自己做二次开发
29 |
30 | Kong:依托于Nginx实现,OpenResty,lua实现的模块,现成的一些插件,可以直接使用
31 |
32 |
33 |
34 | Zuul(Servlet、Java):高并发能力不强,部署到一些机器上去,还要基于Tomcat来部署,Spring Boot用Tomcat把网关系统跑起来;Java语言开发,可以直接把控源码,可以做二次开发封装各种需要的功能
35 |
36 | Nginx(Kong、Nginx+Lua):Nginx抗高并发的能力很强,少数几台机器部署一下,就可以抗很高的并发,精通Nginx源码,很难,c语言,很难说从Nginx内核层面去做一些二次开发和源码定制
37 |
38 |
39 | Java技术栈为主的大厂,很多其实用Java、Servlet、Netty来开发高并发、高性能的网关系统,自己可以把控一切
40 |
41 |
--------------------------------------------------------------------------------
/docs/distributed-system/gateway-technical.md:
--------------------------------------------------------------------------------
1 |
2 | 服务框架的原理和技术选型,你们公司到底是怎么选,为什么?
3 |
4 | 服务注册中心,思考,你们公司到底是怎么选的,生产环境有没有做一些优化,如果没有,哪些地方是有优化空间的?
5 |
6 | 网关系统,思考,你们公司是怎么选型的,为什么?生产环境是否对类似动态路由的功能做过优化,如果没有是否有优化空间?
7 |
--------------------------------------------------------------------------------
/docs/distributed-system/gray-environment.md:
--------------------------------------------------------------------------------
1 |
2 | #### 准备一个数据库和一个表(也可以用Apollo配置中心、Redis、ZooKeeper,其实都可以),放一个灰度发布启用表
3 |
4 | ```
5 | id service_id path enable_gray_release
6 |
7 | CREATE TABLE `gray_release_config` (
8 | `id` int(11) NOT NULL AUTO_INCREMENT,
9 | `service_id` varchar(255) DEFAULT NULL,
10 | `path` varchar(255) DEFAULT NULL,
11 | `enable_gray_release` int(11) DEFAULT NULL,
12 | PRIMARY KEY (`id`)
13 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8
14 |
15 |
16 |
17 | 在zuul里面加入下面的filter,可以在zuul的filter里定制ribbon的负载均衡策略
18 |
19 |
20 | io.jmnarloch
21 | ribbon-discovery-filter-spring-cloud-starter
22 | 2.1.0
23 |
24 |
25 | 写一个zuul的filter,对每个请求,zuul都会调用这个filter
26 |
27 | @Configuration
28 | public class GrayReleaseFilter extends ZuulFilter {
29 |
30 | @Autowired
31 | private JdbcTemplate jdbcTemplate;
32 |
33 | @Override
34 | public int filterOrder() {
35 | return PRE_DECORATION_FILTER_ORDER - 1;
36 | }
37 |
38 | @Override
39 | public String filterType() {
40 | return PRE_TYPE;
41 | }
42 |
43 | @Override
44 | public boolean shouldFilter() {
45 |
46 | }
47 |
48 | @Override
49 | public Object run() {
50 | RequestContext ctx = RequestContext.getCurrentContext();
51 | HttpServletRequest request = ctx.getRequest();
52 |
53 | Random random = new Random();
54 | int seed = random.getInt() * 100;
55 |
56 | if (seed = 50) {
57 | // put the serviceId in `RequestContext`
58 | RibbonFilterContextHolder.getCurrentContext()
59 | .add("version", "new");
60 | } else {
61 | RibbonFilterContextHolder.getCurrentContext()
62 | .add("version", "old");
63 | }
64 |
65 | return null;
66 | }
67 | }
68 | ```
69 |
70 | eureka:
71 | instance:
72 | metadata-map:
73 | version: new
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/docs/distributed-system/highly-concurrent-distribute-lock.md:
--------------------------------------------------------------------------------
1 |
2 | 分段加锁
3 |
4 | 有好多同学出去面试,聊到分布式锁这块,都被人考察分布式锁能不能抗高并发的问题了
5 |
6 | 对某个商品下单,对一个分布式锁每秒突然有上万请求过来,都要进行加锁,此时怎么办呢?可能就会导致你
7 |
8 |
9 |
10 | 比如你的苹果库存有10000个,此时你在数据库中创建10个库存字段
11 |
12 | 一个表里有10个库存字段,stock_01,stock_02,每个库存字段里放1000个库存
13 |
14 | 此时这个库存的分布式锁,对应10个key,product_1_stock_01,product_1_stock_02
15 |
16 | 请求过来之后,你从10个key随机选择一个key,去加锁就可以了,每秒过来1万个请求,此时他们会对10个库存分段key加锁,每个key就1000个请求,每台服务器就1000个请求而已
17 |
18 |
19 | 万一说某个库存分段仅仅剩余10个库存了,此时我下订单要买20个苹果,合并扣减库存,你对product_1_stock_5,加锁了,此时查询对应的数据库中的库存,此时库存是10个,不够买20个苹果
20 |
21 | 你可以尝试去锁product_1_stock_1,再查询他的库存可能有30个
22 |
23 | 此时你就可以下订单,锁定库存的时候,就对product_1_stock_5锁定10个库存,对product_1_stock1锁定10个库存,锁定了20个库存
24 |
25 |
26 | 分段加锁 + 合并扣减
27 |
--------------------------------------------------------------------------------
/docs/distributed-system/highly-concurrent-majorization-distributed-lock.md:
--------------------------------------------------------------------------------
1 |
2 | 想想自己的分布式锁用在业务系统中,有没有高并发问题,如果有,如何用分段加锁思路来解决,或者用kv存储来存放实时库存抗并发,直接在kv里扣减,避免用分布式锁
3 |
--------------------------------------------------------------------------------
/docs/distributed-system/hitch-redis-distribute-lock.md:
--------------------------------------------------------------------------------
1 |
2 | 瞬时故障问题
3 |
4 | 彻底解决这个问题,很难,除非你修改一些redis和redisson框架的源码,源码级的二次开发,加锁,必须是master和slave同时写成功,才算是加锁成功
5 |
--------------------------------------------------------------------------------
/docs/distributed-system/homework.md:
--------------------------------------------------------------------------------
1 |
2 | 结合自身的情况来分析一下
3 |
4 | 结合面试突击第一季的课程,在“狸猫技术窝”公众号的知识店铺里去,在里面会有一个免费的课程,就是面试突击第一季,大家去里面找就可以了
5 |
6 | 可以把免费的面试突击第一季和我们现在付费的后续面试训练营系统同时同步一起看
7 |
8 | 技术广度的一些,各种技术
9 |
10 | ### (1)自己在技术广度上做的如何?你现在主流技术栈哪些技术都有一定的了解,包括核心原理和常见技术方案
11 |
12 | ### (2)自己在项目经验和生产经验上做的如何?你会的这些技术,自己在项目里到底用过多少?用的有多复杂?用的时候考虑了哪些项目细节和生产细节?
13 |
14 | ### (3)技术深度,你现在对哪些技术是除了核心原理以及基础知识之外,对一些技术的底层的概念和原理有一定的了解
15 |
16 | ### (4)系统设计,你目前自己独立负责过设计的系统和架构有多复杂?如果让你来独立设计秒杀系统、红包系统、12306系统,或者是一些其他大型的架构,你会如何来设计呢?
17 |
18 | 能力差距在哪里,肯定会有很多的疑问,第一周是预售周,是除了这4讲试看以外,其他的是不更新的,从第一周预售周结束之后会开始每日更新课程,可以把面试突击第一季复习巩固一下,没看过的人正好借着这一周把面试突击第一季先去看一下
19 |
20 | 而且可以对自己的能力模型做一个详细的梳理,看看自己现在能力有多强,差距在哪里
21 |
22 |
--------------------------------------------------------------------------------
/docs/distributed-system/images/SpringCloud-core-architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/SpringCloud-core-architecture.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/async-replication-data-lose-case.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/async-replication-data-lose-case.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/consistent-hashing-algorithm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/consistent-hashing-algorithm.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/distributed-lock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/distributed-lock.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/distributed-system-request-sequence.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/distributed-system-request-sequence.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/distributed-transaction-TCC.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/distributed-transaction-TCC.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/distributed-transaction-XA.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/distributed-transaction-XA.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/distributed-transaction-local-message-table.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/distributed-transaction-local-message-table.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/distributed-transaction-reliable-message.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/distributed-transaction-reliable-message.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/dubbo-framework-principle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/dubbo-framework-principle.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/dubbo-keep-connection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/dubbo-keep-connection.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/dubbo-not-keep-connection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/dubbo-not-keep-connection.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/dubbo-operating-principle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/dubbo-operating-principle.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/dubbo-rock-bottom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/dubbo-rock-bottom.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/dubbo-service-invoke-road.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/dubbo-service-invoke-road.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/dubbo-spi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/dubbo-spi.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/e-commerce-website-detail-page-architecture-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/e-commerce-website-detail-page-architecture-1.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/e-commerce-website-detail-page-architecture-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/e-commerce-website-detail-page-architecture-2.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/eureka-register.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/eureka-register.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/favicon-16x16.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/favicon-32x32.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/gateway-high-concurrency.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/gateway-high-concurrency.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/hash-slot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/hash-slot.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/hash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/hash.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/icon.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/redis-distribute-lock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/redis-distribute-lock.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/registration-center-optimize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/registration-center-optimize.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/rocketmq-transaction.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/rocketmq-transaction.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/serialize-deserialize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/serialize-deserialize.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/service-invoke-road.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/service-invoke-road.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/simple-distributed-system-oa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/simple-distributed-system-oa.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/springCloud-study-theory.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/springCloud-study-theory.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/zookeeper-active-standby.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/zookeeper-active-standby.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/zookeeper-centralized-storage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/zookeeper-centralized-storage.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/zookeeper-distribute-lock-optimize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/zookeeper-distribute-lock-optimize.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/zookeeper-distribute-lock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/zookeeper-distribute-lock.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/zookeeper-distributed-coordination.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/zookeeper-distributed-coordination.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/zookeeper-distributed-lock-demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/zookeeper-distributed-lock-demo.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/zookeeper-distributed-lock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/zookeeper-distributed-lock.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/zookeeper-meta-data-manage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/zookeeper-meta-data-manage.png
--------------------------------------------------------------------------------
/docs/distributed-system/images/zookeeper-register.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/images/zookeeper-register.png
--------------------------------------------------------------------------------
/docs/distributed-system/interface-idempotence.md:
--------------------------------------------------------------------------------
1 |
2 | 接口幂等性实现起来非常的简单,不打算带着大家手写代码
3 |
4 | (1)数据库唯一索引
5 | (2)基于Redis实现一套幂等性防重框架
6 |
7 |
8 |
9 | 对于插入类的操作,一般都是建议大家要在数据库表中设计一些唯一索引
10 |
11 |
12 | 你如果有一个订单被支付了,此时就要通知wms创建一个对应发货单,也是数据库里的一个表,仓库里的人会看到这个发货单,此时他就会根据发货单的信息从仓库里进行拣货,打包,封装,交给物流公司
13 |
14 |
15 |
16 | 发货单
17 |
18 | id order_id 订单金额 发货地址 xxxx
19 |
20 | 对order_id就可以建立一个唯一索引,你插入发货单的时候,同一个order_id最多只能对应一个发货单,不可能说同样的一个order_id对应了多个发货单
21 |
22 |
23 | 订单服务 -> wms服务,出现了重试,导致第二次请求再次让人家创建这个订单的发货单,create语句,order_id触发了唯一索引约束
24 |
25 |
26 |
27 |
28 |
29 | 扣减库存、累加积分,更新,很难通过数据库唯一索引来保证
30 |
31 |
32 | 基于Redis实现一套接口的防重框架
33 |
34 | 你得做一个类似spring mvc里的拦截器这样的东西,在这个拦截器里,他会拦截所有的请求,对所有的请求都会提取请求对应的参数,GET请求、POST请求、PUT请求,有些参数是跟在URL地址里的,?xx=xx&xx=xx
35 |
36 | POST、PUT,可能是请求体里的,可能是一个JSON格式
37 |
38 | 把参数拼接在一起,作为key去redis中判断一下,是否存在这个key,之前附加这些参数的请求是否发起过,如果没有的话,此时就可以把这些参数+接口名称,作为一个key,存储到redis中去
39 |
40 | 然后呢,把请求放行,去执行这个请求
41 |
42 | 如果说人家重试再次发起一个这个请求,此时就可以判断出来,参数组成的key在redis中已经存在了,此时就不让执行这个请求了,认为是重复调用了
43 |
44 |
45 |
46 |
47 |
48 | 考虑很多问题,幂等不幂等,通用框架,需要一个公司所有的接口都按照指定的参数来传递,还有很多业务语义的问题
49 |
50 | 第一次发起一个请求,直接把请求key放入redis,但是他执行的过程中失败了,而且还阻塞了一段时间,此时人家再次重试发起第二次请求,这个时候按照上述的框架逻辑,就会把请求拦截下来了
51 |
52 |
53 | 到底是不是要对所有接口都开启这么一个东西呢?
54 |
55 |
56 | 每个接口如果执行成功了之后,我可以设置一个每个接口调用的时候执行成功之后,做一个后拦截器,如果成功了,就把请求对应的参数拼接为key放入redis中
57 |
58 | 有没有可能是第一次请求发送过来,在执行过程中,时间长了,比如需要1.3秒才执行完毕;此时人家发现超过1s了,直接重试,第二次请求过来了,也在正常的执行
59 |
60 | 第一次请求1.3秒之后执行成功了,第二次请求也执行成功了
61 |
62 | 只要一个服务希望对自己的接口开启幂等性防重功能,就把你开发好的拦截器对应的jar包,通过maven引入一个依赖就可以了
63 |
64 |
65 |
66 | 中大型互联网公司里也没做一个统一的防重幂等框架,其实一般都是各个服务对自己核心的接口,如果要保证幂等性的话,每个服务根据自己的业务逻辑来实现,而且仅仅是对少数核心接口做幂等性保障
67 |
68 |
69 | 核心接口,库存服务,扣减库存接口
70 |
71 | 定制化的去针对接口开发幂等性的机制,比如说一旦库存扣减成功之后,就立马要写一条数据到redis里去,order_id_11356_stock_deduct,写入redis中,如果写入成功,就说明之前这个订单的库存扣减,没人执行过
72 |
73 | 但是如果此时有一些重试的请求过来了,调用了你的库存扣减接口,他同时也进行了库存的扣减,但是他用同样的一个key,order_id_11356_stock_deduct,写入redis中,此时会发现已经有人写过key,key已经存在了
74 |
75 | 此时你就应该直接对刚才的库存扣减逻辑做一个反向的回滚逻辑,update product_stock set stock = stock - 100,update product_stock set stock = stock + 100,反向逻辑,回滚掉,自己避免说重复扣减库存
76 |
77 |
78 |
79 |
80 |
81 |
82 | 核心接口,幂等性都是自己保证的,人家可能会重试调用你的接口,对于create类的操作,用唯一索引来保证;对update类的操作,建议在核心接口里基于自己的业务逻辑,配合上redis,来保证幂等性
83 |
84 |
85 |
--------------------------------------------------------------------------------
/docs/distributed-system/java-internet-interview-outlook.md:
--------------------------------------------------------------------------------
1 |
2 | 快速扫盲,MQ、ES、Dubbo、分布式事务、分布式锁、缓存架构、高并发、高可用,各种常考的技术问题,都拎出来,重点的讲解一下
3 |
4 | 21天互联网Java工程师面试训练营(分布式篇),互联网Java工程师面试突击训练(第二季)
5 |
6 | 对第一季的分布式面试题,进一步加深了,分布式这块再抗一堆连环炮都没问题
7 |
8 | 接着对后面几季的内容,会考虑一下形式,可能会考虑把五季合并为一季,作为面试突击第三季,形式上会综合考虑是继续用视频,还是用文章形式更便于大家日常学习
9 |
10 | 微服务、海量数据、高性能、高并发、高可用,五季
11 |
12 | 互联网Java工程师面试突击训练营(第三季)
13 |
14 | 视频,路上,在公司里不方便看视频,等到回家,晚上来一局王者荣耀
15 |
16 | 文章,上下班路上,在公司里,支持在PC端可以看文章,自己写写代码,做点实验
17 |
18 | 狸猫技术窝,知识店铺,有一个文章专栏,救火队队长,《从0开始带你成为JVM实战高手》,一步一图,大白话,通俗易懂,1个多月,将近2000人买了专栏,普遍好评,非常的好,看的浅显易懂,实战型强,就知道生产环境jvm如何优化
19 |
20 |
21 |
22 | 后台观察一下购买面试训练营第二季的同学学习的进度,没时间看视频,赶进度一个过程中,学习中,第三季,那一定是观察大部分同学都得把第二季学的差不多,重磅推出第三季,加量不加价
23 |
24 |
25 | 付费微信群,里面有很多我这两年带出来的大厂的同学,滴滴、阿里、百度、美团、美菜、每日优鲜、vipkid,热火朝天聊技术问题
26 |
27 | 学习+作业+思考+复习+提问+答疑
28 |
--------------------------------------------------------------------------------
/docs/distributed-system/java-interview-season-1-summary.md:
--------------------------------------------------------------------------------
1 |
2 | ### 系统性的分析了一下大厂对一个工程师的要:
3 | **数据结构和算法**,**软素质**,**工程素养**,**履历背景**,**学历**,**带团队管理**,真正在招人的时候,会考虑很多的方面,**技术广度**、**技术深度**、**项目经验**、**系统设计**,技术上的要求
4 |
5 | 发布过:《互联网Java工程师面试突击(第一季)》
6 |
7 | Spring MVC、Spring、Lucene、Activiti,单块系统,做的项目很多都是那种OA系统,财务系统,CRM系统,工厂管理系统,类似这样的一些东西
8 |
9 | 跟上国内主流的技术栈
10 |
11 | MQ,消息丢失,消息重复,高可用部署,原理;缓存,数据库和缓存双写怎么保证一致性;分布式锁,实现原理;分布式事务的常见方案;Dubbo、Spring Cloud
12 |
13 | 定位,面试突击第一季的定位,就是把常见互联网技术栈里的技术和主流技术方案给大家分析一下,做一个扫盲,避免说出去面试一问三不知
14 |
15 | 数据库原理和优化,JVM原理和优化,并发的原理和优化
16 |
17 | 已经帮助了数以千计的同学了,不完全统计,从去年到今年,看过面试突击第一季的同学,估算人数在5000人以上,帮助大量的同学快速扫盲,积累了很多互联网主流技术栈,出去面试,很多人给我们发感谢信
18 |
19 | 我们也收到了很多同学的反馈,老师,但是还是有很多的问题,项目经验、生产经验、技术深度:
20 |
21 | **(1)项目经验:分库分表深挖我的项目细节,死磕到底架势,我直接挂掉了**
22 |
23 | **(2)生产经验:Spring Cloud Zuul网关在生产环境如何进行优化,分布式锁会不会导致并发能力降低,如何优化,分布式事务会不会导致交易TPS降低,如何优化,服务注册中心如果发现过慢如何解决,访问量有多大怎么部署的,需要多少台机器**
24 |
25 | **(3)技术深度:Kafka基本原理、RocketMQ基本原理,一问到深度点的东西,比如Kafka底层的分布式架构,副本同步机制,推还是拉,生产者底层的网络通信机制**
26 |
27 | **(4)系统设计:面试官现场出系统设计的问题,让我结合某个业务场景现场设计一个什么什么方案或者架构,让我给思路**
28 |
29 |
30 | 我们的课程每天都会有一个作业,引导大家把学习到的项目经验、技术方案和生产优化落地到自己负责的项目中去,让大家出去面试的时候,可以把各种技术结合自己的项目来回答面试官的各种深度拷问
31 |
32 | 大家不要小看这个,根据我多年的面试经验来看,拥有这个技能的人凤毛麟角,这种人出去绝对是各大公司争抢的对象。
33 |
34 | 所以希望大家好好完成每天的作业,我布置的大量作业,就是为了帮你锻造出这种能力
35 |
36 | 学习课程以及完成作业的过程中,大家一定会有很多的问题,可以到专栏的评论区去提问
37 |
38 | 每天我都会和之前带出来的一批阿里、蚂蚁金服、滴滴的优秀同学给大家进行答疑,并且我们还有专门的付费用户的微信群,大家可以在微信群里跟我们一起进行技术交流
39 |
40 | 如果你能坚持下来,学满6季,还可以获取私人定制的面试一条龙VIP服务
41 |
42 | 如果是连续6季面试训练营都购买的同学,还可以获取面试一条龙VIP服务
43 |
44 | 具体信息大家看“狸猫技术窝”公众号的知识店铺内的训练营详情即可,
45 |
46 | 具体可参见训练营目录下的《训练营专属服务》文档。简单来说,这个私人定制的面试VIP服务,会为你的跳槽面试全程保驾护航
47 |
--------------------------------------------------------------------------------
/docs/distributed-system/redis-distribute-lock.md:
--------------------------------------------------------------------------------
1 |
2 | 面试突击第二季
3 | 
4 | Redis分布式锁,很少自己撸,Redisson框架,他基于Redis实现了一系列的开箱即用的高级功能,比如说分布式锁
5 |
6 | 引入maven依赖,他示例代码就几行
7 |
8 | 比如说,苹果这个商品的id是1
9 |
10 | redisson.lock(“product_1_stock”)
11 |
12 | key的业务语义,就是针对product_id = 1的商品的库存,也就就是苹果的库存,进行加锁
13 |
14 | 如果要学习redis技术的,跟我之前录制的《亿级流量商品详情页系统》去学习,在训练营的课程目录里有一个文档,有我之前的课程的地址
15 |
16 |
17 | product_1_stock: {
18 | “xxxx”: 1
19 | }
20 |
21 | 生存时间:30s
22 |
23 | watchdog,redisson框架后台执行一段逻辑,每隔10s去检查一下这个锁是否还被当前客户端持有,如果是的话,重新刷新一下key的生存时间为30s
24 |
25 | 其他客户端尝试加锁,这个时候发现“product_1_stock”这个key已经存在了,里面显示被别的客户端加锁了,此时他就会陷入一个无限循环,阻塞住自己,不能干任何事情,必须在这里等待
26 |
27 |
28 | 第一个客户端加锁成功了,此时有两种情况,第一种情况,这个客户端操作完毕之后,主动释放锁;第二种情况,如果这个客户端宕机了,那么这个客户端的redisson框架之前启动的后台watchdog线程,就没了
29 |
30 | 此时最多30s,key-value就消失了,自动释放了宕机客户端之前持有的锁
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/docs/distributed-system/register-high-availability.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/distributed-system/register-high-availability.md
--------------------------------------------------------------------------------
/docs/distributed-system/register-production-optimize.md:
--------------------------------------------------------------------------------
1 |
2 | #### 分布式系统架构的
3 |
4 | **服务注册中心,eureka、zk、consul,原理画图画清楚**
5 |
6 | **数据一致性,CP、AP**
7 |
8 | 服务注册、故障 和发现的时效性是多长时间
9 |
10 | 注册中心最大能支撑多少服务实例
11 |
12 | 如何部署的,几台机器,每台机器的配置如何,会用比较高配置的机器来做,8核16G,16核32G的高配置机器来搞,基本上可以做到每台机器每秒钟的请求支撑几千绝对没问题
13 |
14 | 可用性如何来保证
15 |
16 | **有没有做过一些优化,服务注册、故障以及发现的时效性,是否可以优化一下,用eureka的话,可以尝试一下,配合我们讲解的那些参数,优化一下时效性,服务上线、故障到发现是几秒钟的时效性**
17 |
18 | **zk,一旦服务挂掉,zk感知到以及通知其他服务的时效性,服务注册到zk之后通知到其他服务的时效性,leader挂掉之后可用性是否会出现短暂的问题,为了去换取一致性**
19 |
20 |
21 | **所以希望大家好好完成每天的作业,我布置的大量作业,就是为了帮你锻造出这种能力**
22 |
23 | **学习课程以及完成作业的过程中,大家一定会有很多的问题,可以到专栏的评论区去提问**
24 |
25 | **每天我都会和之前带出来的一批阿里、蚂蚁金服、滴滴的优秀同学给大家进行答疑,并且我们还有专门的付费用户的微信群,大家可以在微信群里跟我们一起进行技术交流**
26 |
27 | **如果你能坚持下来,学满6季,还可以获取私人定制的面试一条龙VIP服务**
28 |
29 | **如果是连续6季面试训练营都购买的同学,还可以获取面试一条龙VIP服务**
30 |
31 | **具体信息大家看“狸猫技术窝”公众号的知识店铺内的训练营详情即可**
32 |
33 | **具体可参见训练营目录下的《训练营专属服务》文档。简单来说,这个私人定制的面试VIP服务,会为你的跳槽面试全程保驾护航**
34 |
35 |
--------------------------------------------------------------------------------
/docs/distributed-system/registration-center- guide.md:
--------------------------------------------------------------------------------
1 |
2 | 非常常见的一个技术面试题,但凡只要是聊到分布式这块,一定会问问你,**Dubbo,Spring Cloud,服务注册中心**,你们当时是怎么选型和调研的,你们最终是选择了哪块技术呢?你选择这块技术的原因和理由是什么呢?
3 |
4 | **Eureka、ZooKeeper**
5 |
6 | **Dubbo**作为服务框架的,一般注册中心会选择zk
7 |
8 | **Spring Cloud**作为服务框架的,**一般服务注册中心会选择Eureka**
9 |
10 | **Consul、Nacos,**普及型还没那么广泛,我会在面试训练营课程里增加对应的内容,给大家去进行补充
11 |
12 | #### (1)服务注册发现的原理
13 |
14 | 集群模式
15 | 
16 |
17 | **Eureka,peer-to-pee**r,部署一个集群,**但是集群里每个机器的地位是对等的,各个服务可以向任何一个Eureka实例服务注册和服务发现,集群里任何一个Euerka实例接收到写请求之后,会自动同步给其他所有的Eureka实例**
18 | 
19 |
20 | **ZooKeeper,服务注册和发现的原理,Leader + Follower两种角色,只有Leader可以负责写也就是服务注册,他可以把数据同步给Follower,读的时候leader/follower都可以读**
21 |
22 | #### (2)一致性保障:CP or AP
23 |
24 | **CAP,C是一致性,A是可用性,P是分区容错性**
25 |
26 | **CP,AP**
27 |
28 | **ZooKeeper是有一个leader节点会接收数据, 然后同步写其他节点,一旦leader挂了,要重新选举leader,这个过程里为了保证C,就牺牲了A,不可用一段时间,但是一个leader选举好了,那么就可以继续写数据了,保证一致性**
29 |
30 | Eureka是peer模式,可能还没同步数据过去,结果自己就死了,此时还是可以继续从别的机器上拉取注册表,但是看到的就不是最新的数据了,但是保证了可用性,强一致,最终一致性
31 |
32 | (3)服务注册发现的时效性
33 |
34 | zk,时效性更好,注册或者是挂了,一般秒级就能感知到
35 |
36 | eureka,默认配置非常糟糕,服务发现感知要到几十秒,甚至分钟级别,上线一个新的服务实例,到其他人可以发现他,极端情况下,可能要1分钟的时间,ribbon去获取每个服务上缓存的eureka的注册表进行负载均衡
37 |
38 | 服务故障,隔60秒才去检查心跳,发现这个服务上一次心跳是在60秒之前,隔60秒去检查心跳,超过90秒没有心跳,才会认为他死了,2分钟都过去
39 |
40 | 30秒,才会更新缓存,30秒,其他服务才会来拉取最新的注册表
41 |
42 | 三分钟都过去了,如果你的服务实例挂掉了,此时别人感知到,可能要两三分钟的时间,一两分钟的时间,很漫长
43 |
44 | #### (4)容量
45 |
46 | zk,不适合大规模的服务实例,因为服务上下线的时候,需要瞬间推送数据通知到所有的其他服务实例,所以一旦服务规模太大,到了几千个服务实例的时候,会导致网络带宽被大量占用
47 |
48 | eureka,也很难支撑大规模的服务实例,因为每个eureka实例都要接受所有的请求,实例多了压力太大,扛不住,也很难到几千服务实例
49 |
50 | 之前dubbo技术体系都是用zk当注册中心,spring cloud技术体系都是用eureka当注册中心这两种是运用最广泛的,但是现在很多中小型公司以spring cloud居多,所以后面基于eureka说一下服务注册中心的生产优化
51 |
52 | (5)多机房、多数据中心、健康检查
53 |
54 |
55 |
--------------------------------------------------------------------------------
/docs/distributed-system/registration-center-optimize.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 | #### eureka:peer-to-peer,每台机器都是高并发请求,有瓶颈
4 | #### zookeeper:服务上下线,全量通知其他服务,网络带宽被打满,有瓶颈
5 |
6 | #### 分布式服务注册中心,分片存储服务注册表,横向扩容,每台机器均摊高并发请求,各个服务主动拉取,避免反向通知网卡被打满
7 |
--------------------------------------------------------------------------------
/docs/distributed-system/request-retry.md:
--------------------------------------------------------------------------------
1 |
2 | 订单服务 -> 创建订单
3 |
4 | -> 库存服务 -> 扣减库存
5 | -> wms服务 -> 通知发货
6 | -> 积分服务 -> 增加积分
7 |
8 | 订单服务调用库存服务的时候,因为网络抖动,请求超时了,超过了秒钟,此时订单服务会重试,再次调用一下库存服务,发送一模一样的请求过去
9 |
10 |
11 |
12 | 比如说,订单服务第一次请求库存服务,库存服务其实是把扣减库存的业务逻辑执行成功了,只不过网络问题,导致响应迟迟没有返回给订单服务,可能在1.2s之后返回了响应给订单服务
13 |
14 | 订单服务就认为请求超时了,他就再次发送了一个一模一样的请求给库存服务,库存服务可能会再次对库存进行扣减
15 |
16 |
17 |
--------------------------------------------------------------------------------
/docs/distributed-system/rocketmq-eventual-consistency.md:
--------------------------------------------------------------------------------
1 |
2 | seata,作业,参考官网示例,自己玩儿,在自己本地部署一个单机版的RocketMQ,做实验,参考示例代码,实现一下发送消息,回调接口,一个是事务消息,一个是消费者ack
3 |
4 | 面试训练营,讲究必须留作业给你自己动手
5 |
6 | 如果要看详细的项目实战类课程,参考训练营的课程目录中有一个文档,里面有我之前的课程,《亿级流量电商详情页系统实战》,一步一步带着手敲代码,可以去看看
7 |
--------------------------------------------------------------------------------
/docs/distributed-system/rocketmq-transaction.md:
--------------------------------------------------------------------------------
1 |
2 | 类似TCC事务的落地的一些东西,技术选型,业务场景需要分布式事务,结合我个人亲身经历的一个创业公司APP的一个事故,给大家介绍了一下,对于系统核心链路,为什么必须要上分布式事务
3 |
4 | seata,github上,都会提供sample,跟dubbo,官方的同学是定义为double,spring cloud,seata都提供了sample,知道如何把分布式事务框架整合到框架里去了
5 |
6 |
7 | 
8 | 核心交易链路,分布式事务框架
9 |
10 |
11 |
12 | 有些服务之间的调用是走异步的,下成功了订单之后,你会通知一个wms服务去发货,这个过程可以是异步的,可以是走一个MQ的,发送一个消息到MQ里去,由wms服务去从MQ里消费消息
13 |
14 |
15 | MQ,消息中间件,面试突击第一季,刚开头我就讲过消息中间件的面试连环炮
16 |
17 |
18 |
19 | 可靠消息最终一致性方案,参考面试突击第一季
20 |
21 |
22 |
23 | 落地,RocketMQ来实现可靠消息最终一致性事务方案
24 |
25 |
26 | Producer向RocketMQ发送一个half message
27 |
28 | RocketMQ返回一个half message success的响应给Producer,这个时候就形成了一个half message了,此时这个message是不能被消费的
29 |
30 | 注意,这个步骤可能会因为网络等原因失败,可能你没收到RocketMQ返回的响应,那么就需要重试发送half message,直到一个half message成功建立为止
31 |
32 | 接着Producer本地执行数据库操作
33 |
34 | Producer根据本地数据库操作的结果发送commit/rollback给RocketMQ,如果本地数据库执行成功,那么就发送一个commit给RocketMQ,让他把消息变为可以被消费的;如果本地数据库执行失败,那么就发送一个rollback给RocketMQ,废弃之前的message
35 |
36 | 注意,这个步骤可能失败,就是Producer可能因为网络原因没成功发送commit/rollback给RocketMQ,此时RocketMQ自己过一段时间发现一直没收到message的commit/rollback,就回调你服务提供的一个接口
37 |
38 | 此时在这个接口里,你需要自己去检查之前执行的本地数据库操作是否成功了,然后返回commit/rollback给RocketMQ
39 |
40 | 只要message被commit了,此时下游的服务就可以消费到这个消息,此时还需要结合ack机制,下游消费必须是消费成功了返回ack给RocketMQ,才可以认为是成功了,否则一旦失败没有ack,则必须让RocketMQ重新投递message给其他consumer
41 |
--------------------------------------------------------------------------------
/docs/distributed-system/rpc-design.md:
--------------------------------------------------------------------------------
1 | 这个面试题还是挺常见的,在面试突击第一季里,基本上带了一下,当时但是没有细讲,是因为当时面试突击第一季里对服务框架的原理没有做一个相对深入一点点的分析,当时主要就是讲了一些最基本的概念
2 |
3 | 人家并不是要你手撸一个**RPC框架**,资料,现场手撸一个**RPC框架**,撸的特别的简单,人家也不是要你手撸,也不是说让你进来了以后就是让你来研发RPC框架的
4 |
5 | 系统设计的问题,就是让你站在系统设计的角度,来考虑一下,到底如果要设计一个RPC框架,你会如何来考虑
6 |
7 | 动态代理:比如消费者和提供者,其实都是需要一个实现某个接口的动态代理的,RPC框架的一切的逻辑细节,都是在这个动态代理中实现的,动态代理里面的代码逻辑就是你的RPC框架核心的逻辑
8 |
9 | JDK提供了API,去创建针对某个接口的动态代理
10 |
11 | 调用动态代理对象的方法之后,此时就应该先干一个事情,通过Cluster层的一些组件,服务注册中心,是用什么技术来进行实现呢?往简单了说,服务注册中心也可以是你自己手撸一个,也不难
12 |
13 | 自己手撸一个,服务去注册,其他服务去拉取注册表进行发现
14 |
15 | **ZooKeeper**,稍微自己上网百度搜索一下,**ZooKeeper**入门使用教程,基本概念和原理,还有基本的使用,了解一下
16 |
17 | **Cluster层**,从本地缓存的服务注册表里获取到要调用的服务的机器列表
18 |
19 | **负载均衡**,**面试突击第一季**里,我们分析过**Dubbo的负载均衡策略**,此时你就可以把那些策略说一说,我要设计多少种策略,从服务的机器列表中采用负载均衡算法从里面选择出来一台机器
20 |
21 | 选择好了机器,知道了对方的端口号,而且知道你的请求调用,调用哪个Interface的哪个方法,把这些信息交给协议层
22 |
23 | 把数据组织一下,**协议**,**序列化机制**,**底层用什么网络通信框架**,比如**netty,mina**现在用的比较少,序列化和反序列化有没有概念,**Java基础概念,一个复杂的请求数据序列化成二进制的字节数组**
24 |
25 | **反序列化就是从字节数组变成请求数据结构**
26 |
27 | 按照那个协议的规范对请求数据进行组织,不同的协议,组织出来的数据看起来是不一样的
28 |
29 | **netty基本的原理**
30 |
31 | 解析完毕了之后,就知道,应该调用自己本地哪个Interface的实现类的哪个方法
32 |
33 |
34 |
35 | **我们的课程每天都会有一个作业,引导大家把学习到的项目经验、技术方案和生产优化落地到自己负责的项目中去,让大家出去面试的时候,可以把各种技术结合自己的项目来回答面试官的各种深度拷问**
36 |
37 | **大家不要小看这个,根据我多年的面试经验来看,拥有这个技能的人凤毛麟角,这种人出去绝对是各大公司争抢的对象。**
38 |
39 | **我们的课程每天都会有一个作业,引导大家把学习到的项目经验、技术方案和生产优化落地到自己负责的项目中去,让大家出去面试的时候,可以把各种技术结合自己的项目来回答面试官的各种深度拷问**
40 |
41 | **大家不要小看这个,根据我多年的面试经验来看,拥有这个技能的人凤毛麟角,这种人出去绝对是各大公司争抢的对象。**
42 |
43 | **所以希望大家好好完成每天的作业,我布置的大量作业,就是为了帮你锻造出这种能力**
44 |
45 | **学习课程以及完成作业的过程中,大家一定会有很多的问题,可以到专栏的评论区去提问**
46 |
47 | **每天我都会和之前带出来的一批阿里、蚂蚁金服、滴滴的优秀同学给大家进行答疑,并且我们还有专门的付费用户的微信群,大家可以在微信群里跟我们一起进行技术交流**
48 |
49 | **如果你能坚持下来,学满6季,还可以获取私人定制的面试一条龙VIP服务**
50 |
51 | **如果是连续6季面试训练营都购买的同学,还可以获取面试一条龙VIP服务**
52 |
53 | **具体信息大家看“狸猫技术窝”公众号的知识店铺内的训练营详情即可**
54 |
55 | **具体可参见训练营目录下的《训练营专属服务》文档。简单来说,这个私人定制的面试VIP服务,会为你的跳槽面试全程保驾护航**
56 |
57 | **“狸猫技术窝”**,找到我们的训练营的详情页面
58 |
59 |
60 |
--------------------------------------------------------------------------------
/docs/distributed-system/service-register-discovery.md:
--------------------------------------------------------------------------------
1 |
2 | **zk,一般来说还好,服务注册和发现,都是很快的**
3 |
4 | **eureka,必须优化参数**
5 |
6 | **eureka.server.responseCacheUpdateIntervalMs = 3000**
7 | **eureka.client.registryFetchIntervalSeconds = 30000**
8 |
9 | **eureka.client.leaseRenewalIntervalInSeconds = 30**
10 | **eureka.server.evictionIntervalTimerInMs = 60000**
11 | **eureka.instance.leaseExpirationDurationInSeconds = 90**
12 |
13 | **服务发现的时效性变成秒级,几秒钟可以感知服务的上线和下线**
14 |
15 |
--------------------------------------------------------------------------------
/docs/distributed-system/service-register-gateway-router.md:
--------------------------------------------------------------------------------
1 |
2 | #### 生产环境,微服务生产实践
3 |
4 | 开发了一个新的服务,线上部署,配合网关动态路由的功能,在网关里配置一下路径和新服务的映射关系,此时请求过来直接就可以走到新的服务里去
5 |
6 | 对已有服务进行迭代和开发,新版本,灰度发布,新版本部署少数几台机器,通过一个界面,开启这个服务的灰度发布,**此时zuul filter启用,按照你的规则,把少量的流量打入到新版本部署的机器上去**
7 |
8 | 观察一下少量流量在新版本的机器上运行是否正常
9 |
10 | 版本改成current,全量机器部署,关闭灰度发布功能,网关就会把流量均匀分发给那个服务了
11 |
12 |
13 |
--------------------------------------------------------------------------------
/docs/distributed-system/service-request-time-out.md:
--------------------------------------------------------------------------------
1 |
2 | 分布式系统,拆分为很多个服务之后,他们互相之间要进行调用,平时服务内要优化的一些参数其实不多,服务与服务之间的调用,会不会出现调用的超时,每个服务超时的时间是多长,超时之后是否要进行重试,重试几次
3 |
4 | 高可用,hystrix进行资源隔离、熔断、降级,zuul网关层直接进行限流
5 |
6 |
7 | 网关 ->(卡住) 订单服务 ->(卡住) wms服务
8 |
9 | 网关收到的一个http响应,可能就是一个500,internal error
10 |
11 |
12 |
13 |
14 |
15 | Spring Cloud生产优化,系统第一次启动的时候,人家调用你经常会出现timeout
16 |
17 | 每个服务第一次被请求的时候,他会去初始化一个Ribbon的组件,初始化这些组件需要耗费一定的时间,所以很容易会导致。让每个服务启动的时候就直接初始化Ribbon相关的组件,避免第一次请求的时候初始化
18 |
19 | ```
20 | ribbon:
21 | eager-load:
22 | enabled: true
23 |
24 |
25 | zuul:
26 | ribbon:
27 | eager-load:
28 | enabled: true
29 |
30 | feign:
31 | hystrix:
32 | enabled: false
33 |
34 | ```
35 |
36 | 我们刚才启动了wms服务之后,其实订单服务和积分服务、wms服务、库存服务之间的请求都是没问题的,日志全部都打印出来了,不会说第一次请求因为ribbon加载过慢导致请求失败的问题
37 |
38 | 但是zuul网关层面去请求订单服务的时候,他还是可能会认为自己超时了,windows电脑上跑这样的一套系统,网络请求都是比较慢的,因为你有很多服务与服务之间的调用,order和另外3个服务一套交互下来,比如超过了1秒钟
39 |
40 | zuul而言感觉耗时太久了,还是会认为是超时的
41 |
42 | windows电脑走的都是家用网络,我家里的网络情况不是太好,网卡,网速慢,信号弱
43 |
44 |
45 |
46 |
47 | 线上的服务,每个服务部署上线的时候,一般来说都需要配置相关的超时时间还有重试次数
48 |
49 | 订单服务 -> 积分服务、库存服务、仓促服务
50 |
51 | 订单服务对于其他服务的调用,一般来说限制在多长时间就必须认为是超时了,如果超时之后如何进行重试
52 |
53 | 积分服务部署了两台机器,机器1和机器2
54 |
55 | 订单服务在一次请求积分服务的机器1的时候,超过1秒钟,超时了;此时需要进行重试,对积分服务当前的这台机器1重试几次?如果说机器1不行,是否可以重试一下积分服务的机器2?
56 |
57 |
58 | ```
59 | ribbon:
60 | ConnectTimeout: 3000
61 | ReadTimeout: 3000
62 | OkToRetryOnAllOperations: true
63 | MaxAutoRetries: 1
64 | MaxAutoRetriesNextServer: 1
65 |
66 | 中小型的系统,没必要直接开启hystrix,资源隔离、熔断、降级,如果你没有设计好一整套系统高可用的方案
67 |
68 | zuul请求一个订单服务,超过1秒就认为超时了,此时会先重试一下订单服务这台机器,如果还是不行就重试一下订单服务的其他机器
69 |
70 |
71 | org.springframework.retry
72 | spring-retry
73 |
74 |
75 | hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000
76 | ```
--------------------------------------------------------------------------------
/docs/distributed-system/springCloud-and-rpc-framework.md:
--------------------------------------------------------------------------------
1 |
2 | ### 1、作业1
3 |
4 | **把RPC框架如何设计,这个问题,你把整体思路去屡一下,对应的一些细节,很多可以参考之前面试突击第一季的,还有一些网络通信框架,netty,找一些资料,补充了解一些细节,包括动态代理**
5 |
6 | 序列化协议
7 |
8 | ### 2、作业2
9 |
10 | **不看资料,手画Spring Cloud底层原理,Eureka**
11 |
--------------------------------------------------------------------------------
/docs/distributed-system/springCloud-study-theory.md:
--------------------------------------------------------------------------------
1 | 问你**Dubbo底层架构原理**是一样的,不求你说能看过**Spring Cloud的源码**,单单就是说搞明白他的一些底层架构原理,也是不错的
2 |
3 | 
4 | **Eureka、Ribbon、Feign、Zuul**
5 |
6 | 就是优化并发冲突
7 |
8 | 如果你基于**Spring Cloud**对外发布一个接口,实际上就是支持**http协议**的,对外发布的就是一个最最普通的**Spring MVC的http接口**
9 |
10 | **feign**,他是对一个接口打了一个注解,他一定会针对这个注解标注的接口生成动态代理,然后你针对feign的动态代理去调用他的方法的时候,此时会在底层生成http协议格式的请求,/order/create?productId=1
11 |
12 | 底层的话,使用HTTP通信的框架组件,**HttpClient**,**先得使用Ribbon去从本地的Eureka注册表的缓存里获取出来对方机器的列表,然后进行负载均衡,选择一台机器出来,接着针对那台机器发送Http请求过去即可**
13 |
14 | 配置一下不同的请求路径和服务的对应关系,你的请求到了网关,他直接查找到匹配的服务,然后就直接把请求转发给那个服务的某台机器,**Ribbon从Eureka本地的缓存列表里获取一台机器,负载均衡,把请求直接用HTTP通信框架发送到指定机器上去**
15 |
16 |
17 |
18 | **我们的课程每天都会有一个作业,引导大家把学习到的项目经验、技术方案和生产优化落地到自己负责的项目中去,让大家出去面试的时候,可以把各种技术结合自己的项目来回答面试官的各种深度拷问**
19 |
20 | **大家不要小看这个,根据我多年的面试经验来看,拥有这个技能的人凤毛麟角,这种人出去绝对是各大公司争抢的对象。**
21 |
22 | **我们的课程每天都会有一个作业,引导大家把学习到的项目经验、技术方案和生产优化落地到自己负责的项目中去,让大家出去面试的时候,可以把各种技术结合自己的项目来回答面试官的各种深度拷问**
23 |
24 | **大家不要小看这个,根据我多年的面试经验来看,拥有这个技能的人凤毛麟角,这种人出去绝对是各大公司争抢的对象。**
25 |
26 | **所以希望大家好好完成每天的作业,我布置的大量作业,就是为了帮你锻造出这种能力**
27 |
28 | **学习课程以及完成作业的过程中,大家一定会有很多的问题,可以到专栏的评论区去提问**
29 |
30 | **每天我都会和之前带出来的一批阿里、蚂蚁金服、滴滴的优秀同学给大家进行答疑,并且我们还有专门的付费用户的微信群,大家可以在微信群里跟我们一起进行技术交流**
31 |
32 | **如果你能坚持下来,学满6季,还可以获取私人定制的面试一条龙VIP服务**
33 |
34 | **如果是连续6季面试训练营都购买的同学,还可以获取面试一条龙VIP服务**
35 |
36 | **具体信息大家看“狸猫技术窝”公众号的知识店铺内的训练营详情即可**
37 |
38 | **具体可参见训练营目录下的《训练营专属服务》文档。简单来说,这个私人定制的面试VIP服务,会为你的跳槽面试全程保驾护航**
39 |
40 | **“狸猫技术窝”**,找到我们的训练营的详情页面
41 |
42 |
--------------------------------------------------------------------------------
/docs/distributed-system/system-dilatation.md:
--------------------------------------------------------------------------------
1 |
2 | 如果访问量扩大10倍,如何扩容?
3 |
4 | 网关直接多部署10倍的机器即可,前面的Nginx做会负载均衡,把流量均匀分发给各个网关机器
5 |
6 | 服务扩容,都很简单的,多加机器,部署启动,自动注册到注册中心里去,此时其他服务会自动感知到你的服务多加了一些机器
7 |
8 | 服务实例变多了10倍,此时几十个服务实例,几百个服务实例,对eureka机器会造成每秒几百请求,没问题,eureka机器,8核16G的配置,单机抗上千请求,很轻松
9 |
10 | 数据库本来是每秒几百请求,10倍,每秒高峰期是三四千请求,横向扩容很麻烦,此时可以考虑给单个数据库部署的机器提高配置,32核128G高配物理机,每秒钟抗几千请求问题不大
11 |
12 |
13 |
--------------------------------------------------------------------------------
/docs/distributed-system/system-framework.md:
--------------------------------------------------------------------------------
1 |
2 | ### 服务框架、注册中心、网关系统
3 |
4 | 即使你没有用很多微服务架构里的东西,只要有上述三个东西,配合上写一些文档,接口文档,分布式系统架构,其实就出来了,很多中小型公司,一个小型技术团队,后端开发工程师总共就10多个人
5 |
6 | 关注分布式系统一些生茶实践的问题,应对你们公司的流量,各个服务、网关、注册中心,都是如何部署的,部署几台机器,每台机器的配置是什么,每天整体的流量有多少,高峰期的请求量有多少,你的整体系统是否抗住了
7 |
8 | 各个服务之间的超时、重试、幂等,是否搞定了
9 |
10 | 数据库配置和部署
11 |
12 |
13 | 很多同学,他们因为在自己公司里面开发的都是一些单块系统,微服务架构,但是公司没什么流量,他对机器的配置抗多少并发请求,其实没多大的概念,都不是什么技术问题,很多同学出去面试的时候
14 |
15 | 死扣生产细节问题,每秒3000并发请求,各个服务部署多少机器,机器的配置,数据库的机器和配置,网关的机器和配置,注册中心的机器和配置,什么样的机器配置能抗多大的流量和请求
16 |
17 |
18 |
19 | 中小型的系统,拆分为10~20个服务,微服务,庞大的互联网公司,都有几百个、几千个、几万个服务,服务规模,服务注册中心,妥妥的,2~3台机器就足够了,把服务的上线、故障以及发现优化到极致
20 |
21 | 服务上线,注册表多级缓存同步1秒,注册表拉取频率降低为1秒
22 | 服务心跳,1秒上报1次
23 | 故障发现,1秒钟检查一次1心跳,如果发现2秒内服务没上报心跳,认为故障了
24 |
25 | 服务注册中心都没任何压力,最多就是每秒钟几十次请求而已
26 |
27 | 服务注册中部署个2台机器,每台机器就是4核8G,高可用冗余,任何一台机器死掉,不会影响系统的运行
28 |
29 | 服务注册中心这样的一个处理逻辑,4核8G的机器,每秒钟轻松抗几百请求,上千请求也是可以的
30 |
31 | 通常来说,如果每秒钟的并发在1000以内的话,很少部署的,每个服务部署2台机器,每台机器4核8G,每台机器每秒抗个几百请求,一点问题都没有,别搞出来一个请求过来,查数据库SQL写的太烂了,一条SQL要跑3秒钟
32 |
33 | 大部分的系统,高峰期每秒几百请求,低峰期每秒几十请求,甚至几个请求
34 |
35 |
36 |
37 | 网关系统,4核8G的机器,一台机器抗每秒几百请求,部署3~4台机器,保证可以网关系统每台机器的压力比较小,进一步保证网关系统可靠性
38 |
39 |
40 |
41 | 数据库,MySQL,16核32G,物理机最佳,32核64G,最多抗个每秒钟几千请求问题不大,平时抗个每秒钟几十或者几百请求,三四千请求,但是只不过此时会导致MySQL机器的负载很高,CPU使用率很高,磁盘IO负载很高,网络负载很高
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/docs/distributed-system/system-qps.md:
--------------------------------------------------------------------------------
1 |
2 | 很常问,很多人回来跟我说,老师,我不知道我们系统每秒钟请求有多少,每天请求量有多大,我都没任何的概念,因为系统开发好直接部署,根本不管这些东西,有没有什么比较好的工具可以看到服务的访问量,qps
3 |
4 |
5 |
6 |
7 |
8 | 每个服务每天多少请求量,高峰期每秒钟多少请求量,你完全可以在代码里,稍微加一些metrics的代码,如果你看过很多的开源项目的话,开源的分布式系统,eureka、hadoop、spark、hbase、kafka,metrics机制
9 |
10 |
11 | 任何一个开源系统都需要对自己运行过程中各种请求量、每秒的请求量、成功次数、失败次数,在内存里直接做一些计数,他会给你开放一些端口号,比如http端口号,你只要请求他这个端口号,他就会把这些metrics统计返回给你
12 |
13 |
14 |
15 |
16 | 在你负责的核心服务里,核心接口,开发一个简单的metric统计机制,AtomicLong,原子性,并发下数据统计准确,不会错误,每个接口被调用的时候,一个是可以对每个接口每分钟都做一个Metric统计
17 |
18 | 对每个接口每天的请求使用一个AtomicLong做一个计数,统计出来每天的请求次数
19 |
20 | 计算一下每个接口从请求到执行完毕,需要耗费多长时间,算一下每个接口平均的请求延时,TP99,TP95,TP90,TP50,TP99,99%的请求耗费的时间在100ms以内,但是1%的请求可能耗费的时间在100ms以上
21 |
22 | **TP99 = 100ms**
23 | **TP95 = 50ms,95%的请求耗费的时间多在50ms以内,但是5%的请求耗费的时间在50ms以上**
24 |
25 | 平均响应延时
26 |
27 | 你可以计算出来这个接口平均响应延时,把每次调用的耗时跟历史总耗时加起来,除以当前的请求次数,不就是最新的接口响应平均延时
28 |
29 |
30 |
31 |
32 | 你完全可以通过log4j,logback,日志组件,把每分钟每个接口被访问的次数直接打印到日志文件里去,除以60,不就知道高峰期每秒钟系统被访问的次数了吗,每天每个接口访问的总次数打印到日志里去
33 |
34 |
35 |
36 | 压测工具,百度一下:java压测工具,开源的可以用的,模拟出来同时有多少用户发起多少请求,每秒发起1000请求能抗住吗?每秒钟发起2000请求能抗住吗?
37 |
38 | 假设你的系统每秒钟最多抗800请求,如果你的压测工具每秒发起了1000个请求,此时他会发现最多只有800个请求同时可以被处理,剩余200个请求需要进行排队被阻塞住了,告诉你,你的这个系统每秒钟最多抗800个请求
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/docs/distributed-system/tcc-framework-principle.md:
--------------------------------------------------------------------------------
1 |
2 | 面试突击第一季里仅仅是说了一下核心的一些思想
3 |
4 | 基于seata去跑分布式事务的,必须先独立去部署seata-server,TC
5 |
--------------------------------------------------------------------------------
/docs/distributed-system/tcc-high-concurrence.md:
--------------------------------------------------------------------------------
1 |
2 | TCC框架,bytetcc,seata
3 |
4 | seata-server
5 |
6 | bytetcc,大家就是基于mysql里面创建一些表,基于表中的数据进行状态的更新
7 |
8 |
9 | 核心链路中的各个服务都需要跟TC这个角色进行频繁的网络通信,频繁的网络通信其实就会带来性能的开销,本来一次请求不引入分布式事务只需要100ms,此时引入了分布式事务之后可能需要耗费200ms
10 |
11 |
12 |
13 | 网络请求可能还挺耗时的,上报一些分支事务的状态给TC,seata-server,选择基于哪种存储来放这些分布式事务日志或者状态的,file,磁盘文件,MySQL,数据库来存放对应的一些状态
14 |
15 |
16 |
17 |
18 | 高并发场景下,会不会有问题,seata-server,你也需要支持扩容,也需要部署多台机器,用一个数据库来存放分布式事务的日志和状态的话,假设并发量每秒上万,分库分表,对TC背后的数据库也会有同样的压力
19 |
20 | 这个时候对TC背后的db也得进行分库分表,抗更高的并发压力
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/docs/distributed-system/tcc-landing-scheme.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | 训练营的课程目录里,有我之前的一些课程,在网上大家都可以去看
4 |
5 | 亿级流量电商详情页系统
6 | elasticsearch从入门到精通
7 |
8 | 针对某个技术领域手把手的教学,课程内容量非常的大,代码都是一行一行的写
9 |
10 |
11 | https://github.com/seata/seata
12 |
13 |
14 | 自己安装一个git bash,百度一下如何安装即可,在win上可以执行linux类的命令
15 |
16 | 然后自己建一个目录
17 |
18 | git clone https://github.com/seata/seata-samples.git
19 |
20 | 也可以直接在github页面上下载:https://github.com/seata/seata-samples,建议这种方式,比较快一点,git clone速度太慢了
21 |
22 | 就可以把seata所有的示例代码拷贝下来,里面提供的例子就是跟我们说的电商的核心例子是类似的,然后导入到Eclipse中去,这个过程会eclipse会通过maven下载很多的依赖,需要耐心等待
23 |
24 | 使用脚本初始化数据库
25 |
26 | ```
27 | CREATE TABLE `account_tbl` (
28 | `id` int(11) NOT NULL AUTO_INCREMENT,
29 | `user_id` varchar(255) DEFAULT NULL,
30 | `money` int(11) DEFAULT '0',
31 | PRIMARY KEY (`id`)
32 | ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
33 |
34 | CREATE TABLE `storage_tbl` (
35 | `id` int(11) NOT NULL AUTO_INCREMENT,
36 | `commodity_code` varchar(255) DEFAULT NULL,
37 | `count` int(11) DEFAULT '0',
38 | PRIMARY KEY (`id`),
39 | UNIQUE KEY `commodity_code` (`commodity_code`)
40 | ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
41 |
42 | CREATE TABLE `order_tbl` (
43 | `id` int(11) NOT NULL AUTO_INCREMENT,
44 | `user_id` varchar(255) DEFAULT NULL,
45 | `commodity_code` varchar(255) DEFAULT NULL,
46 | `count` int(11) DEFAULT '0',
47 | `money` int(11) DEFAULT '0',
48 | PRIMARY KEY (`id`)
49 | ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
50 |
51 | CREATE TABLE `undo_log` (
52 | `id` bigint(20) NOT NULL AUTO_INCREMENT,
53 | `branch_id` bigint(20) NOT NULL,
54 | `xid` varchar(100) NOT NULL,
55 | `context` varchar(128) NOT NULL,
56 | `rollback_info` longblob NOT NULL,
57 | `log_status` int(11) NOT NULL,
58 | `log_created` datetime NOT NULL,
59 | `log_modified` datetime NOT NULL,
60 | `ext` varchar(100) DEFAULT NULL,
61 | PRIMARY KEY (`id`),
62 | UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
63 | ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
64 | ```
65 | 然后先要下载一个seata-server到本地,在这里下载:https://github.com/seata/seata/releases,然后启动起来,这是分布式事务管理中心,负责维护每一个分布式事务的状态,触发分布式事务的提交和回滚
66 |
67 | seata-server.bat -h 127.0.0.1 -p 8091 -m file
68 |
69 | 直接把Spring Cloud版本的例子运行起来,观察一下依赖、配置和代码,以后自己在系统里使用直接仿照即可,eureka、account、order、storage、business,依次运行起来,修改一些配置,比如说数据库连接配置
70 |
71 |
72 | 但是任何一个服务报错之后,seata这个分布式事务的框架会感知到,自动触发所有服务之前做的数据库操作全部进行回滚
73 |
74 |
75 | 纯正的tcc框架,很麻烦,需要你手动把各种接口实现出来3个接口,try,confirm,cancel,bytetcc,纯的tcc框架,star
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/docs/distributed-system/why-dubbo.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | 为什么要进行系统拆分?如何进行系统拆分?拆分后不用 dubbo 可以吗?
3 |
4 | ## 面试官心理分析
5 | 从这个问题开始就进行分布式系统环节了,现在出去面试分布式都成标配了,没有哪个公司不问问你分布式的事儿。你要是不会分布式的东西,简直这简历没法看,没人会让你去面试。
6 |
7 | 其实为啥会这样呢?这就是因为整个大行业技术发展的原因。
8 |
9 | 早些年,印象中在 2010 年初的时候,整个 IT 行业,很少有人谈分布式,更不用说微服务,虽然很多 BAT 等大型公司,因为系统的复杂性,很早就是分布式架构,大量的服务,只不过微服务大多基于自己搞的一套框架来实现而已。
10 |
11 | 但是确实,那个年代,大家很重视 ssh2,很多中小型公司几乎大部分都是玩儿 struts2、spring、hibernate,稍晚一些,才进入了 spring mvc、spring、mybatis 的组合。那个时候整个行业的技术水平就是那样,当年 oracle 很火,oracle 管理员很吃香,oracle 性能优化啥的都是 IT 男的大杀招啊。连大数据都没人提,当年 OCP、OCM 等认证培训机构,火的不行。
12 |
13 | 但是确实随着时代的发展,慢慢的,很多公司开始接受分布式系统架构了,这里面尤为对行业有至关重要影响的,是阿里的 dubbo,**某种程度上而言,阿里在这里推动了行业技术的前进**。
14 |
15 | 正是因为有阿里的 dubbo,很多中小型公司才可以基于 dubbo,来把系统拆分成很多的服务,每个人负责一个服务,大家的代码都没有冲突,服务可以自治,自己选用什么技术都可以,每次发布如果就改动一个服务那就上线一个服务好了,不用所有人一起联调,每次发布都是几十万行代码,甚至几百万行代码了。
16 |
17 | 直到今日,很高兴看到分布式系统都成行业面试标配了,任何一个普通的程序员都该掌握这个东西,其实这是行业的进步,也是所有 IT 码农的技术进步。所以既然分布式都成标配了,那么面试官当然会问了,因为很多公司现在都是分布式、微服务的架构,那面试官当然得考察考察你了。
18 |
19 | ## 面试题剖析
20 | ### 为什么要将系统进行拆分?
21 | 网上查查,答案极度零散和复杂,很琐碎,原因一大坨。但是我这里给大家直观的感受:
22 |
23 | 要是**不拆分**,一个大系统几十万行代码,20 个人维护一份代码,简直是悲剧啊。代码经常改着改着就冲突了,各种代码冲突和合并要处理,非常耗费时间;经常我改动了我的代码,你调用了我的,导致你的代码也得重新测试,麻烦的要死;然后每次发布都是几十万行代码的系统一起发布,大家得一起提心吊胆准备上线,几十万行代码的上线,可能每次上线都要做很多的检查,很多异常问题的处理,简直是又麻烦又痛苦;而且如果我现在打算把技术升级到最新的 spring 版本,还不行,因为这可能导致你的代码报错,我不敢随意乱改技术。
24 |
25 | 假设一个系统是 20 万行代码,其中 A 在里面改了 1000 行代码,但是此时发布的时候是这个 20 万行代码的大系统一块儿发布。就意味着 20 万上代码在线上就可能出现各种变化,20 个人,每个人都要紧张地等在电脑面前,上线之后,检查日志,看自己负责的那一块儿有没有什么问题。
26 |
27 | A 就检查了自己负责的 1 万行代码对应的功能,确保 ok 就闪人了;结果不巧的是,A 上线的时候不小心修改了线上机器的某个配置,导致另外 B 和 C 负责的 2 万行代码对应的一些功能,出错了。
28 |
29 | 几十个人负责维护一个几十万行代码的单块应用,每次上线,准备几个礼拜,上线 -> 部署 -> 检查自己负责的功能。
30 |
31 | **拆分了以后**,整个世界清爽了,几十万行代码的系统,拆分成 20 个服务,平均每个服务就 1~2 万行代码,每个服务部署到单独的机器上。20 个工程,20 个 git 代码仓库,20 个开发人员,每个人维护自己的那个服务就可以了,是自己独立的代码,跟别人没关系。再也没有代码冲突了,爽。每次就测试我自己的代码就可以了,爽。每次就发布我自己的一个小服务就可以了,爽。技术上想怎么升级就怎么升级,保持接口不变就可以了,真爽。
32 |
33 | 所以简单来说,一句话总结,如果是那种代码量多达几十万行的中大型项目,团队里有几十个人,那么如果不拆分系统,**开发效率极其低下**,问题很多。但是拆分系统之后,每个人就负责自己的一小部分就好了,可以随便玩儿随便弄。分布式系统拆分之后,可以大幅度提升复杂系统大型团队的开发效率。
34 |
35 | 但是同时,也要**提醒**的一点是,系统拆分成分布式系统之后,大量的分布式系统面临的问题也是接踵而来,所以后面的问题都是在**围绕分布式系统带来的复杂技术挑战**在说。
36 |
37 | ### 如何进行系统拆分?
38 | 这个问题说大可以很大,可以扯到领域驱动模型设计上去,说小了也很小,我不太想给大家太过于学术的说法,因为你也不可能背这个答案,过去了直接说吧。还是说的简单一点,大家自己到时候知道怎么回答就行了。
39 |
40 | 系统拆分为分布式系统,拆成多个服务,拆成微服务的架构,是需要拆很多轮的。并不是说上来一个架构师一次就给拆好了,而以后都不用拆。
41 |
42 | 第一轮;团队继续扩大,拆好的某个服务,刚开始是 1 个人维护 1 万行代码,后来业务系统越来越复杂,这个服务是 10 万行代码,5 个人;第二轮,1个服务 -> 5个服务,每个服务 2 万行代码,每人负责一个服务。
43 |
44 | 如果是多人维护一个服务,最理想的情况下,几十个人,1 个人负责 1 个或 2~3 个服务;某个服务工作量变大了,代码量越来越多,某个同学,负责一个服务,代码量变成了 10 万行了,他自己不堪重负,他现在一个人拆开,5 个服务,1 个人顶着,负责 5 个人,接着招人,2 个人,给那个同学带着,3 个人负责 5 个服务,其中 2 个人每个人负责 2 个服务,1 个人负责 1 个服务。
45 |
46 | 个人建议,一个服务的代码不要太多,1 万行左右,两三万撑死了吧。
47 |
48 | 大部分的系统,是要进行**多轮拆分**的,第一次拆分,可能就是将以前的多个模块该拆分开来了,比如说将电商系统拆分成订单系统、商品系统、采购系统、仓储系统、用户系统,等等吧。
49 |
50 | 但是后面可能每个系统又变得越来越复杂了,比如说采购系统里面又分成了供应商管理系统、采购单管理系统,订单系统又拆分成了购物车系统、价格系统、订单管理系统。
51 |
52 | 扯深了实在很深,所以这里先给大家举个例子,你自己感受一下,**核心意思就是根据情况,先拆分一轮,后面如果系统更复杂了,可以继续分拆**。你根据自己负责系统的例子,来考虑一下就好了。
53 |
54 | ### 拆分后不用 dubbo 可以吗?
55 | 当然可以了,大不了最次,就是各个系统之间,直接基于 spring mvc,就纯 http 接口互相通信呗,还能咋样。但是这个肯定是有问题的,因为 http 接口通信维护起来成本很高,你要考虑**超时重试**、**负载均衡**等等各种乱七八糟的问题,比如说你的订单系统调用商品系统,商品系统部署了 5 台机器,你怎么把请求均匀地甩给那 5 台机器?这不就是负载均衡?你要是都自己搞那是可以的,但是确实很痛苦。
56 |
57 | 所以 dubbo 说白了,是一种 rpc 框架,就是说本地就是进行接口调用,但是 dubbo 会代理这个调用请求,跟远程机器网络通信,给你处理掉负载均衡、服务实例上下线自动感知、超时重试等等乱七八糟的问题。那你就不用自己做了,用 dubbo 就可以了。
--------------------------------------------------------------------------------
/docs/distributed-system/work-distributed-transaction.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | 你自己的系统,核心链路,是否存在数据不一致的问题,如果要设计分布式事务方案,如何设计,对分布式事务的技术如何选型,好好做一下,然后提交到狸猫技术窝,知识店铺,训练营里有作业本
4 |
5 | 完成作业的时候有任何疑问,可以提出来,我们每天会进行答疑
6 |
7 | 微信群,训练营的课程目录里有一个文档
8 |
--------------------------------------------------------------------------------
/docs/distributed-system/work-eventual-consistency.md:
--------------------------------------------------------------------------------
1 |
2 | 思路全给到位了,想想自己系统里哪个业务场景可以用这个分布式事务,基于RocketMQ自己实现一遍,自己写可靠消息服务实现一遍
3 |
--------------------------------------------------------------------------------
/docs/distributed-system/work-interface-idempotence.md:
--------------------------------------------------------------------------------
1 |
2 | 分布式系统,考察生产实践细节,常问的面试问题
3 |
4 | 服务框架、注册中心、网关系统、部署架构、超时重试、幂等性
5 |
6 |
7 | 跟你自己的业务系统有关系了,你们的系统服务之间的调用,有没有超时和重试的配置,如果没有,如何优化配置,如果有,核心接口有没有幂等性机制,重复插入数据,重复跟新数据
8 |
9 | 如果有问题,结合你的业务,如何基于唯一索引、redis定制化防重机制
10 |
11 |
12 | 可以在评论区提问,我们会给大家答疑,狸猫技术窝,知识店铺,训练营页面里,有评论区,提问,答疑
13 |
14 | 好好的完成作业,在作业里设计自己的系统业务逻辑对应的一套幂等性机制,每天的作业,都是可以提交,你可以把作业提交到店铺里去,每天我们都会给你们提交的作业进行点评,对你们作业里的问题进行答疑
15 |
16 |
17 | 付费微信交流群,课程目录里有一个文档,入群步骤
18 |
--------------------------------------------------------------------------------
/docs/distributed-system/work-redis-distribute-lock.md:
--------------------------------------------------------------------------------
1 |
2 | 自己哪个业务可以用分布式锁?用什么框架?有什么生产问题?
3 |
--------------------------------------------------------------------------------
/docs/distributed-system/work-register.md:
--------------------------------------------------------------------------------
1 |
2 | #### Dubbo框架原理
3 | #### Spring Cloud框架原理
4 | #### 服务框架的技术选型
5 |
6 | #### 服务注册中心技术选型和核心原理
7 | #### 生产优化
8 | #### 架构优化
9 |
10 | #### 网关系统技术选型和核心原理
11 | #### 生产优化(灰度发布、动态路由)
12 |
13 | #### 生产级的分布式系统里,新服务开发如何做,老服务迭代如何做
14 |
--------------------------------------------------------------------------------
/docs/distributed-system/work-system-dilatation.md:
--------------------------------------------------------------------------------
1 |
2 | 部署,机器配置,大概能抗多少并发;流量、QPS、性能,metrics;压测,借助一些小工具;扩容方案,横向加机器,还是说纵向提升机器的配置
3 |
--------------------------------------------------------------------------------
/docs/distributed-system/work-tcc-landing-scheme.md:
--------------------------------------------------------------------------------
1 |
2 | 大家按照我提示的思路,参考人家的sample,尝试把seata分布式事务框架整合到spring cloud技术架构里去,把这个东西跑出来,如果遇到了问题之后,可以上seata github提issue,问人家怎么回事
3 |
--------------------------------------------------------------------------------
/docs/distributed-system/zookeeper-application-scenarios.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | zookeeper 都有哪些使用场景?
3 |
4 | ## 面试官心理分析
5 | 现在聊的 topic 是分布式系统,面试官跟你聊完了 dubbo 相关的一些问题之后,已经确认你对分布式服务框架/RPC框架基本都有一些认知了。那么他可能开始要跟你聊分布式相关的其它问题了。
6 |
7 | 分布式锁这个东西,很常用的,你做 Java 系统开发,分布式系统,可能会有一些场景会用到。最常用的分布式锁就是基于 zookeeper 来实现的。
8 |
9 | 其实说实话,问这个问题,一般就是看看你是否了解 zookeeper,因为 zookeeper 是分布式系统中很常见的一个基础系统。而且问的话常问的就是说 zookeeper 的使用场景是什么?看你知道不知道一些基本的使用场景。但是其实 zookeeper 挖深了自然是可以问的很深很深的。
10 |
11 | ## 面试题剖析
12 | 大致来说,zookeeper 的使用场景如下,我就举几个简单的,大家能说几个就好了:
13 |
14 | - 分布式协调
15 | - 分布式锁
16 | - 元数据/配置信息管理
17 | - HA高可用性
18 |
19 | ### 分布式协调
20 | 这个其实是 zookeeper 很经典的一个用法,简单来说,就好比,你 A 系统发送个请求到 mq,然后 B 系统消息消费之后处理了。那 A 系统如何知道 B 系统的处理结果?用 zookeeper 就可以实现分布式系统之间的协调工作。A 系统发送请求之后可以在 zookeeper 上**对某个节点的值注册个监听器**,一旦 B 系统处理完了就修改 zookeeper 那个节点的值,A 系统立马就可以收到通知,完美解决。
21 |
22 | 
23 |
24 | ### 分布式锁
25 | 举个栗子。对某一个数据连续发出两个修改操作,两台机器同时收到了请求,但是只能一台机器先执行完另外一个机器再执行。那么此时就可以使用 zookeeper 分布式锁,一个机器接收到了请求之后先获取 zookeeper 上的一把分布式锁,就是可以去创建一个 znode,接着执行操作;然后另外一个机器也**尝试去创建**那个 znode,结果发现自己创建不了,因为被别人创建了,那只能等着,等第一个机器执行完了自己再执行。
26 |
27 | 
28 |
29 | ### 元数据/配置信息管理
30 | zookeeper 可以用作很多系统的配置信息的管理,比如 kafka、storm 等等很多分布式系统都会选用 zookeeper 来做一些元数据、配置信息的管理,包括 dubbo 注册中心不也支持 zookeeper 么?
31 |
32 | 
33 |
34 | ### HA高可用性
35 | 这个应该是很常见的,比如 hadoop、hdfs、yarn 等很多大数据系统,都选择基于 zookeeper 来开发 HA 高可用机制,就是一个**重要进程一般会做主备**两个,主进程挂了立马通过 zookeeper 感知到切换到备用进程。
36 |
37 | 
--------------------------------------------------------------------------------
/docs/distributed-system/zookeeper-distribute-lock-optimize.md:
--------------------------------------------------------------------------------
1 |
2 | 
3 | 也可以,羊群效应
4 |
5 | 如果几十个客户端同时争抢一个锁,此时会导致任何一个客户端释放锁的时候,zk反向通知几十个客户端,几十个客户端又要发送请求到zk去尝试创建锁,所以大家会发现,几十个人要加锁,大家乱糟糟的,无序的
6 |
7 | 羊群效应
8 |
9 | 造成很多没必要的请求和网络开销,会加重网络的负载
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/docs/distributed-system/zookeeper-distribute-lock-scheme.md:
--------------------------------------------------------------------------------
1 |
2 | Redis和ZooKeeper,哪种分布式锁更好?
3 |
4 | 从分布式系统协调语义而言,是ZooKeeper做分布式锁更好一些,因为Redis本身其实是缓存,但是Redis能抗高并发,高并发场景下更好一些
5 |
6 | zookeeper本身不适合部署大规模集群,他本身适用的场景就是部署三五台机器,不是承载高并发请求的,仅仅是用作分布式系统的协调的
7 |
8 |
9 | Redis?ZooKeeper?
10 |
11 | 有redis集群,没有zookeeper集群,那你当然就选择redis了;如果你们公司两个都有,用哪种分布式锁都可以,高并发场景,redis
12 |
--------------------------------------------------------------------------------
/docs/distributed-system/zookeeper-distribute-lock-split-brain.md:
--------------------------------------------------------------------------------
1 |
2 | 分布式锁脑裂,重复加锁
3 |
4 | 分布式系统,主控节点有一个Master,此时因为网络故障,导致其他人以为这个Master不可用了,其他节点出现了别的Master,导致集群里有2个Master同时在运行
5 |
6 | curator框架源码,加一些协调机制
7 |
--------------------------------------------------------------------------------
/docs/distributed-system/zookeeper-distribute-lock.md:
--------------------------------------------------------------------------------
1 |
2 | 看图说话
3 | 
4 | 一般很少自己手撸,curator,基于zk实现了一整套的高级功能
5 |
6 | product_1_stock
7 |
8 | curator.lock(“product_1_stock”)
9 |
10 | /locks/product_1_stock
11 |
--------------------------------------------------------------------------------
/docs/high-availability/README.md:
--------------------------------------------------------------------------------
1 | # 高可用架构
--------------------------------------------------------------------------------
/docs/high-availability/e-commerce-website-detail-page-architecture.md:
--------------------------------------------------------------------------------
1 | ## 电商网站的商品详情页系统架构
2 |
3 | ### 小型电商网站的商品详情页系统架构
4 | 小型电商网站的页面展示采用页面全量静态化的思想。数据库中存放了所有的商品信息,页面静态化系统,将数据填充进静态模板中,形成静态化页面,推入 Nginx 服务器。用户浏览网站页面时,取用一个已经静态化好的 html 页面,直接返回回去,不涉及任何的业务逻辑处理。
5 |
6 | 
7 |
8 | 下面是页面模板的简单 Demo 。
9 |
10 | ```html
11 |
12 |
13 | 商品名称:#{productName}
14 | 商品价格:#{productPrice}
15 | 商品描述:#{productDesc}
16 |
17 |
18 | ```
19 |
20 | 这样做,**好处**在于,用户每次浏览一个页面,不需要进行任何的跟数据库的交互逻辑,也不需要执行任何的代码,直接返回一个 html 页面就可以了,速度和性能非常高。
21 |
22 | 对于小网站,页面很少,很实用,非常简单,Java 中可以使用 velocity、freemarker、thymeleaf 等等,然后做个 cms 页面内容管理系统,模板变更的时候,点击按钮或者系统自动化重新进行全量渲染。
23 |
24 | **坏处**在于,仅仅适用于一些小型的网站,比如页面的规模在几十到几万不等。对于一些大型的电商网站,亿级数量的页面,你说你每次页面模板修改了,都需要将这么多页面全量静态化,靠谱吗?每次渲染花个好几天时间,那你整个网站就废掉了。
25 |
26 | ### 大型电商网站的商品详情页系统架构
27 | 大型电商网站商品详情页的系统设计中,当商品数据发生变更时,会将变更消息压入 MQ 消息队列中。**缓存服务**从消息队列中消费这条消息时,感知到有数据发生变更,便通过调用数据服务接口,获取变更后的数据,然后将整合好的数据推送至 redis 中。Nginx 本地缓存的数据是有一定的时间期限的,比如说 10 分钟,当数据过期之后,它就会从 redis 获取到最新的缓存数据,并且缓存到自己本地。
28 |
29 | 用户浏览网页时,动态将 Nginx 本地数据渲染到本地 html 模板并返回给用户。
30 |
31 | 
32 |
33 |
34 | 虽然没有直接返回 html 页面那么快,但是因为数据在本地缓存,所以也很快,其实耗费的也就是动态渲染一个 html 页面的性能。如果 html 模板发生了变更,不需要将所有的页面重新静态化,也不需要发送请求,没有网络请求的开销,直接将数据渲染进最新的 html 页面模板后响应即可。
35 |
36 | 在这种架构下,我们需要**保证系统的高可用性**。
37 |
38 | 如果系统访问量很高,Nginx 本地缓存过期失效了,redis 中的缓存也被 LRU 算法给清理掉了,那么会有较高的访问量,从缓存服务调用商品服务。但如果此时商品服务的接口发生故障,调用出现了延时,缓存服务全部的线程都被这个调用商品服务接口给耗尽了,每个线程去调用商品服务接口的时候,都会卡住很长时间,后面大量的请求过来都会卡在那儿,此时缓存服务没有足够的线程去调用其它一些服务的接口,从而导致整个大量的商品详情页无法正常显示。
39 |
40 | 这其实就是一个商品接口服务故障导致缓存服务资源耗尽的现象。
--------------------------------------------------------------------------------
/docs/high-availability/hystrix-fallback.md:
--------------------------------------------------------------------------------
1 | ## 基于本地缓存的 fallback 降级机制
2 | Hystrix 出现以下四种情况,都会去调用 fallback 降级机制:
3 |
4 | - 断路器处于打开的状态。
5 | - 资源池已满(线程池+队列 / 信号量)。
6 | - Hystrix 调用各种接口,或者访问外部依赖,比如 MySQL、Redis、Zookeeper、Kafka 等等,出现了任何异常的情况。
7 | - 访问外部依赖的时候,访问时间过长,报了 TimeoutException 异常。
8 |
9 | ### 两种最经典的降级机制
10 |
11 | - 纯内存数据
12 | 在降级逻辑中,你可以在内存中维护一个 ehcache,作为一个纯内存的基于 LRU 自动清理的缓存,让数据放在缓存内。如果说外部依赖有异常,fallback 这里直接尝试从 ehcache 中获取数据。
13 |
14 | - 默认值
15 | fallback 降级逻辑中,也可以直接返回一个默认值。
16 |
17 | 在 `HystrixCommand`,降级逻辑的书写,是通过实现 getFallback() 接口;而在 `HystrixObservableCommand` 中,则是实现 resumeWithFallback() 方法。
18 |
19 |
20 | 现在,我们用一个简单的栗子,来演示 fallback 降级是怎么做的。
21 |
22 | 比如,有这么个**场景**。我们现在有个包含 brandId 的商品数据,假设正常的逻辑是这样:拿到一个商品数据,根据 brandId 去调用品牌服务的接口,获取品牌的最新名称 brandName。
23 |
24 | 假如说,品牌服务接口挂掉了,那么我们可以尝试从本地内存中,获取一份稍过期的数据,先凑合着用。
25 |
26 | ### 步骤一:本地缓存获取数据
27 | 本地获取品牌名称的代码大致如下。
28 |
29 | ```java
30 | /**
31 | * 品牌名称本地缓存
32 | *
33 | */
34 |
35 | public class BrandCache {
36 |
37 | private static Map brandMap = new HashMap<>();
38 |
39 | static {
40 | brandMap.put(1L, "Nike");
41 | }
42 |
43 | /**
44 | * brandId 获取 brandName
45 | *
46 | * @param brandId 品牌id
47 | * @return 品牌名
48 | */
49 | public static String getBrandName(Long brandId) {
50 | return brandMap.get(brandId);
51 | }
52 | ```
53 |
54 | ### 步骤二:实现 GetBrandNameCommand
55 | 在 GetBrandNameCommand 中,run() 方法的正常逻辑是去调用品牌服务的接口获取到品牌名称,如果调用失败,报错了,那么就会去调用 fallback 降级机制。
56 |
57 | 这里,我们直接**模拟接口调用报错**,给它抛出个异常。
58 |
59 | 而在 getFallback() 方法中,就是我们的**降级逻辑**,我们直接从本地的缓存中,**获取到品牌名称**的数据。
60 |
61 | ```java
62 | /**
63 | * 获取品牌名称的command
64 | *
65 | */
66 |
67 | public class GetBrandNameCommand extends HystrixCommand {
68 |
69 | private Long brandId;
70 |
71 | public GetBrandNameCommand(Long brandId) {
72 | super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("BrandService"))
73 | .andCommandKey(HystrixCommandKey.Factory.asKey("GetBrandNameCommand"))
74 | .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
75 | // 设置降级机制最大并发请求数
76 | .withFallbackIsolationSemaphoreMaxConcurrentRequests(15)));
77 | this.brandId = brandId;
78 | }
79 |
80 | @Override
81 | protected String run() throws Exception {
82 | // 这里正常的逻辑应该是去调用一个品牌服务的接口获取名称
83 | // 如果调用失败,报错了,那么就会去调用fallback降级机制
84 |
85 | // 这里我们直接模拟调用报错,抛出异常
86 | throw new Exception();
87 | }
88 |
89 | @Override
90 | protected String getFallback() {
91 | return BrandCache.getBrandName(brandId);
92 | }
93 | }
94 | ```
95 |
96 | `FallbackIsolationSemaphoreMaxConcurrentRequests` 用于设置 fallback 最大允许的并发请求量,默认值是 10,是通过 semaphore 信号量的机制去限流的。如果超出了这个最大值,那么直接 reject。
97 |
98 | ### 步骤三:CacheController 调用接口
99 | 在 CacheController 中,我们通过 productInfo 获取 brandId,然后创建 GetBrandNameCommand 并执行,去尝试获取 brandName。这里执行会报错,因为我们在 run() 方法中直接抛出异常,Hystrix 就会去调用 getFallback() 方法走降级逻辑。
100 |
101 | ```java
102 | @Controller
103 | public class CacheController {
104 |
105 | @RequestMapping("/getProductInfo")
106 | @ResponseBody
107 | public String getProductInfo(Long productId) {
108 | HystrixCommand getProductInfoCommand = new GetProductInfoCommand(productId);
109 |
110 | ProductInfo productInfo = getProductInfoCommand.execute();
111 | Long brandId = productInfo.getBrandId();
112 |
113 | HystrixCommand getBrandNameCommand = new GetBrandNameCommand(brandId);
114 |
115 | // 执行会抛异常报错,然后走降级
116 | String brandName = getBrandNameCommand.execute();
117 | productInfo.setBrandName(brandName);
118 |
119 | System.out.println(productInfo);
120 | return "success";
121 | }
122 | }
123 | ```
124 |
125 | 关于降级逻辑的演示,基本上就结束了。
--------------------------------------------------------------------------------
/docs/high-availability/hystrix-introduction.md:
--------------------------------------------------------------------------------
1 | ## 用 Hystrix 构建高可用服务架构
2 | 参考 [Hystrix Home](https://github.com/Netflix/Hystrix/wiki#what)。
3 |
4 | ### Hystrix 是什么?
5 | 在分布式系统中,每个服务都可能会调用很多其他服务,被调用的那些服务就是**依赖服务**,有的时候某些依赖服务出现故障也是很正常的。
6 |
7 | Hystrix 可以让我们在分布式系统中对服务间的调用进行控制,加入一些**调用延迟**或者**依赖故障**的**容错机制**。
8 |
9 | Hystrix 通过将依赖服务进行**资源隔离**,进而阻止某个依赖服务出现故障时在整个系统所有的依赖服务调用中进行蔓延;同时Hystrix 还提供故障时的 fallback 降级机制。
10 |
11 | 总而言之,Hystrix 通过这些方法帮助我们提升分布式系统的可用性和稳定性。
12 |
13 | ### Hystrix 的历史
14 | Hystrix 是高可用性保障的一个框架。Netflix(可以认为是国外的优酷或者爱奇艺之类的视频网站)的 API 团队从 2011 年开始做一些提升系统可用性和稳定性的工作,Hystrix 就是从那时候开始发展出来的。
15 |
16 | 在 2012 年的时候,Hystrix 就变得比较成熟和稳定了,Netflix 中,除了 API 团队以外,很多其他的团队都开始使用 Hystrix。
17 |
18 | 时至今日,Netflix 中每天都有数十亿次的服务间调用,通过 Hystrix 框架在进行,而 Hystrix 也帮助 Netflix 网站提升了整体的可用性和稳定性。
19 |
20 | [2018 年 11 月,Hystrix 在其 Github 主页宣布,不再开放新功能,推荐开发者使用其他仍然活跃的开源项目](https://github.com/Netflix/Hystrix/blob/master/README.md#hystrix-status)。维护模式的转变绝不意味着 Hystrix 不再有价值。相反,Hystrix 激发了很多伟大的想法和项目,我们高可用的这一块知识还是会针对 Hystrix 进行讲解。
21 |
22 | ### Hystrix 的设计原则
23 | - 对依赖服务调用时出现的调用延迟和调用失败进行**控制和容错保护**。
24 | - 在复杂的分布式系统中,阻止某一个依赖服务的故障在整个系统中蔓延。比如某一个服务故障了,导致其它服务也跟着故障。
25 | - 提供 `fail-fast`(快速失败)和快速恢复的支持。
26 | - 提供 fallback 优雅降级的支持。
27 | - 支持近实时的监控、报警以及运维操作。
28 |
29 |
30 | 举个栗子。
31 |
32 | 有这样一个分布式系统,服务 A 依赖于服务 B,服务 B 依赖于服务 C/D/E。在这样一个成熟的系统内,比如说最多可能只有 100 个线程资源。正常情况下,40 个线程并发调用服务 C,各 30 个线程并发调用 D/E。
33 |
34 | 调用服务 C,只需要 20ms,现在因为服务 C 故障了,比如延迟,或者挂了,此时线程会 hang 住 2s 左右。40 个线程全部被卡住,由于请求不断涌入,其它的线程也用来调用服务 C,同样也会被卡住。这样导致服务 B 的线程资源被耗尽,无法接收新的请求,甚至可能因为大量线程不断的运转,导致自己宕机。服务 A 也挂。
35 |
36 | 
37 |
38 | Hystrix 可以对其进行资源隔离,比如限制服务 B 只有 40 个线程调用服务 C。当此 40 个线程被 hang 住时,其它 60 个线程依然能正常调用工作。从而确保整个系统不会被拖垮。
39 |
40 |
41 | ### Hystrix 更加细节的设计原则
42 | - 阻止任何一个依赖服务耗尽所有的资源,比如 tomcat 中的所有线程资源。
43 | - 避免请求排队和积压,采用限流和 `fail fast` 来控制故障。
44 | - 提供 fallback 降级机制来应对故障。
45 | - 使用资源隔离技术,比如 `bulkhead`(舱壁隔离技术)、`swimlane`(泳道技术)、`circuit breaker`(断路技术)来限制任何一个依赖服务的故障的影响。
46 | - 通过近实时的统计/监控/报警功能,来提高故障发现的速度。
47 | - 通过近实时的属性和配置**热修改**功能,来提高故障处理和恢复的速度。
48 | - 保护依赖服务调用的所有故障情况,而不仅仅只是网络故障情况。
--------------------------------------------------------------------------------
/docs/high-availability/hystrix-semphore-isolation.md:
--------------------------------------------------------------------------------
1 | ## 基于 Hystrix 信号量机制实现资源隔离
2 | Hystrix 里面核心的一项功能,其实就是所谓的**资源隔离**,要解决的最最核心的问题,就是将多个依赖服务的调用分别隔离到各自的资源池内。避免说对某一个依赖服务的调用,因为依赖服务的接口调用的延迟或者失败,导致服务所有的线程资源全部耗费在这个服务的接口调用上。一旦说某个服务的线程资源全部耗尽的话,就可能导致服务崩溃,甚至说这种故障会不断蔓延。
3 |
4 | Hystrix 实现资源隔离,主要有两种技术:
5 |
6 | - 线程池
7 | - 信号量
8 |
9 | 默认情况下,Hystrix 使用线程池模式。
10 |
11 | 前面已经说过线程池技术了,这一小节就来说说信号量机制实现资源隔离,以及这两种技术的区别与具体应用场景。
12 |
13 | ### 信号量机制
14 | 信号量的资源隔离只是起到一个开关的作用,比如,服务 A 的信号量大小为 10,那么就是说它同时只允许有 10 个 tomcat 线程来访问服务 A,其它的请求都会被拒绝,从而达到资源隔离和限流保护的作用。
15 |
16 | 
17 |
18 | ### 线程池与信号量区别
19 | 线程池隔离技术,并不是说去控制类似 tomcat 这种 web 容器的线程。更加严格的意义上来说,Hystrix 的线程池隔离技术,控制的是 tomcat 线程的执行。Hystrix 线程池满后,会确保说,tomcat 的线程不会因为依赖服务的接口调用延迟或故障而被 hang 住,tomcat 其它的线程不会卡死,可以快速返回,然后支撑其它的事情。
20 |
21 | 线程池隔离技术,是用 Hystrix 自己的线程去执行调用;而信号量隔离技术,是直接让 tomcat 线程去调用依赖服务。信号量隔离,只是一道关卡,信号量有多少,就允许多少个 tomcat 线程通过它,然后去执行。
22 |
23 | 
24 |
25 | **适用场景**:
26 | - **线程池技术**,适合绝大多数场景,比如说我们对依赖服务的网络请求的调用和访问、需要对调用的 timeout 进行控制(捕捉 timeout 超时异常)。
27 | - **信号量技术**,适合说你的访问不是对外部依赖的访问,而是对内部的一些比较复杂的业务逻辑的访问,并且系统内部的代码,其实不涉及任何的网络请求,那么只要做信号量的普通限流就可以了,因为不需要去捕获 timeout 类似的问题。
28 |
29 | ### 信号量简单 Demo
30 | 业务背景里,比较适合信号量的是什么场景呢?
31 |
32 | 比如说,我们一般来说,缓存服务,可能会将一些量特别少、访问又特别频繁的数据,放在自己的纯内存中。
33 |
34 | 举个栗子。一般我们在获取到商品数据之后,都要去获取商品是属于哪个地理位置、省、市、卖家等,可能在自己的纯内存中,比如就一个 Map 去获取。对于这种直接访问本地内存的逻辑,比较适合用信号量做一下简单的隔离。
35 |
36 | 优点在于,不用自己管理线程池啦,不用 care timeout 超时啦,也不需要进行线程的上下文切换啦。信号量做隔离的话,性能相对来说会高一些。
37 |
38 | 假如这是本地缓存,我们可以通过 cityId,拿到 cityName。
39 | ```java
40 | public class LocationCache {
41 | private static Map cityMap = new HashMap<>();
42 |
43 | static {
44 | cityMap.put(1L, "北京");
45 | }
46 |
47 | /**
48 | * 通过cityId 获取 cityName
49 | *
50 | * @param cityId 城市id
51 | * @return 城市名
52 | */
53 | public static String getCityName(Long cityId) {
54 | return cityMap.get(cityId);
55 | }
56 | }
57 | ```
58 |
59 | 写一个 GetCityNameCommand,策略设置为**信号量**。run() 方法中获取本地缓存。我们目的就是对获取本地缓存的代码进行资源隔离。
60 | ```java
61 | public class GetCityNameCommand extends HystrixCommand {
62 |
63 | private Long cityId;
64 |
65 | public GetCityNameCommand(Long cityId) {
66 | // 设置信号量隔离策略
67 | super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("GetCityNameGroup"))
68 | .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
69 | .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE)));
70 |
71 | this.cityId = cityId;
72 | }
73 |
74 | @Override
75 | protected String run() {
76 | // 需要进行信号量隔离的代码
77 | return LocationCache.getCityName(cityId);
78 | }
79 | }
80 | ```
81 |
82 | 在接口层,通过创建 GetCityNameCommand,传入 cityId,执行 execute() 方法,那么获取本地 cityName 缓存的代码将会进行信号量的资源隔离。
83 | ```java
84 | @RequestMapping("/getProductInfo")
85 | @ResponseBody
86 | public String getProductInfo(Long productId) {
87 | HystrixCommand getProductInfoCommand = new GetProductInfoCommand(productId);
88 |
89 | // 通过command执行,获取最新商品数据
90 | ProductInfo productInfo = getProductInfoCommand.execute();
91 |
92 | Long cityId = productInfo.getCityId();
93 |
94 | GetCityNameCommand getCityNameCommand = new GetCityNameCommand(cityId);
95 | // 获取本地内存(cityName)的代码会被信号量进行资源隔离
96 | String cityName = getCityNameCommand.execute();
97 |
98 | productInfo.setCityName(cityName);
99 |
100 | System.out.println(productInfo);
101 | return "success";
102 | }
103 | ```
--------------------------------------------------------------------------------
/docs/high-availability/images/220px-Internet_dog.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/220px-Internet_dog.jpg
--------------------------------------------------------------------------------
/docs/high-availability/images/async-replication-data-lose-case.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/async-replication-data-lose-case.png
--------------------------------------------------------------------------------
/docs/high-availability/images/bulkhead-partition.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/bulkhead-partition.jpg
--------------------------------------------------------------------------------
/docs/high-availability/images/consistent-hashing-algorithm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/consistent-hashing-algorithm.png
--------------------------------------------------------------------------------
/docs/high-availability/images/distributed-system-request-sequence.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/distributed-system-request-sequence.png
--------------------------------------------------------------------------------
/docs/high-availability/images/distributed-transaction-TCC.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/distributed-transaction-TCC.png
--------------------------------------------------------------------------------
/docs/high-availability/images/distributed-transaction-XA.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/distributed-transaction-XA.png
--------------------------------------------------------------------------------
/docs/high-availability/images/distributed-transaction-local-message-table.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/distributed-transaction-local-message-table.png
--------------------------------------------------------------------------------
/docs/high-availability/images/distributed-transaction-reliable-message.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/distributed-transaction-reliable-message.png
--------------------------------------------------------------------------------
/docs/high-availability/images/dubbo-operating-principle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/dubbo-operating-principle.png
--------------------------------------------------------------------------------
/docs/high-availability/images/dubbo-service-invoke-road.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/dubbo-service-invoke-road.png
--------------------------------------------------------------------------------
/docs/high-availability/images/dubbo-spi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/dubbo-spi.png
--------------------------------------------------------------------------------
/docs/high-availability/images/e-commerce-website-detail-page-architecture-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/e-commerce-website-detail-page-architecture-1.png
--------------------------------------------------------------------------------
/docs/high-availability/images/e-commerce-website-detail-page-architecture-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/e-commerce-website-detail-page-architecture-2.png
--------------------------------------------------------------------------------
/docs/high-availability/images/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/favicon-16x16.png
--------------------------------------------------------------------------------
/docs/high-availability/images/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/favicon-32x32.png
--------------------------------------------------------------------------------
/docs/high-availability/images/hash-slot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/hash-slot.png
--------------------------------------------------------------------------------
/docs/high-availability/images/hash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/hash.png
--------------------------------------------------------------------------------
/docs/high-availability/images/hystrix-process.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/hystrix-process.png
--------------------------------------------------------------------------------
/docs/high-availability/images/hystrix-request-cache.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/hystrix-request-cache.png
--------------------------------------------------------------------------------
/docs/high-availability/images/hystrix-semphore-thread-pool.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/hystrix-semphore-thread-pool.png
--------------------------------------------------------------------------------
/docs/high-availability/images/hystrix-semphore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/hystrix-semphore.png
--------------------------------------------------------------------------------
/docs/high-availability/images/hystrix-thread-pool-isolation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/hystrix-thread-pool-isolation.png
--------------------------------------------------------------------------------
/docs/high-availability/images/hystrix-thread-pool-queue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/hystrix-thread-pool-queue.png
--------------------------------------------------------------------------------
/docs/high-availability/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/icon.png
--------------------------------------------------------------------------------
/docs/high-availability/images/service-invoke-road.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/service-invoke-road.png
--------------------------------------------------------------------------------
/docs/high-availability/images/simple-distributed-system-oa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/simple-distributed-system-oa.png
--------------------------------------------------------------------------------
/docs/high-availability/images/zookeeper-active-standby.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/zookeeper-active-standby.png
--------------------------------------------------------------------------------
/docs/high-availability/images/zookeeper-centralized-storage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/zookeeper-centralized-storage.png
--------------------------------------------------------------------------------
/docs/high-availability/images/zookeeper-distributed-coordination.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/zookeeper-distributed-coordination.png
--------------------------------------------------------------------------------
/docs/high-availability/images/zookeeper-distributed-lock-demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/zookeeper-distributed-lock-demo.png
--------------------------------------------------------------------------------
/docs/high-availability/images/zookeeper-distributed-lock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/zookeeper-distributed-lock.png
--------------------------------------------------------------------------------
/docs/high-availability/images/zookeeper-meta-data-manage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-availability/images/zookeeper-meta-data-manage.png
--------------------------------------------------------------------------------
/docs/high-concurrency/README.md:
--------------------------------------------------------------------------------
1 | # 高并发架构
--------------------------------------------------------------------------------
/docs/high-concurrency/database-shard-dynamic-expand.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | 如何设计可以动态扩容缩容的分库分表方案?
3 |
4 | ## 面试官心理分析
5 | 对于分库分表来说,主要是面对以下问题:
6 |
7 | - 选择一个数据库中间件,调研、学习、测试;
8 | - 设计你的分库分表的一个方案,你要分成多少个库,每个库分成多少个表,比如 3 个库,每个库 4 个表;
9 | - 基于选择好的数据库中间件,以及在测试环境建立好的分库分表的环境,然后测试一下能否正常进行分库分表的读写;
10 | - 完成单库单表到分库分表的**迁移**,双写方案;
11 | - 线上系统开始基于分库分表对外提供服务;
12 | - 扩容了,扩容成 6 个库,每个库需要 12 个表,你怎么来增加更多库和表呢?
13 |
14 | 这个是你必须面对的一个事儿,就是你已经弄好分库分表方案了,然后一堆库和表都建好了,基于分库分表中间件的代码开发啥的都好了,测试都 ok 了,数据能均匀分布到各个库和各个表里去,而且接着你还通过双写的方案咔嚓一下上了系统,已经直接基于分库分表方案在搞了。
15 |
16 | 那么现在问题来了,你现在这些库和表又支撑不住了,要继续扩容咋办?这个可能就是说你的每个库的容量又快满了,或者是你的表数据量又太大了,也可能是你每个库的写并发太高了,你得继续扩容。
17 |
18 | 这都是玩儿分库分表线上必须经历的事儿。
19 |
20 | ## 面试题剖析
21 | ### 停机扩容(不推荐)
22 | 这个方案就跟停机迁移一样,步骤几乎一致,唯一的一点就是那个导数的工具,是把现有库表的数据抽出来慢慢倒入到新的库和表里去。但是最好别这么玩儿,有点不太靠谱,因为既然**分库分表**就说明数据量实在是太大了,可能多达几亿条,甚至几十亿,你这么玩儿,可能会出问题。
23 |
24 | 从单库单表迁移到分库分表的时候,数据量并不是很大,单表最大也就两三千万。那么你写个工具,多弄几台机器并行跑,1小时数据就导完了。这没有问题。
25 |
26 | 如果 3 个库 + 12 个表,跑了一段时间了,数据量都 1~2 亿了。光是导 2 亿数据,都要导个几个小时,6 点,刚刚导完数据,还要搞后续的修改配置,重启系统,测试验证,10 点才可以搞完。所以不能这么搞。
27 |
28 | ### 优化后的方案
29 | 一开始上来就是 32 个库,每个库 32 个表,那么总共是 1024 张表。
30 |
31 | 我可以告诉各位同学,这个分法,第一,基本上国内的互联网肯定都是够用了,第二,无论是并发支撑还是数据量支撑都没问题。
32 |
33 | 每个库正常承载的写入并发量是 1000,那么 32 个库就可以承载 32 * 1000 = 32000 的写并发,如果每个库承载 1500 的写并发,32 * 1500 = 48000 的写并发,接近 5 万每秒的写入并发,前面再加一个MQ,削峰,每秒写入 MQ 8 万条数据,每秒消费 5 万条数据。
34 |
35 | 有些除非是国内排名非常靠前的这些公司,他们的最核心的系统的数据库,可能会出现几百台数据库的这么一个规模,128 个库,256 个库,512 个库。
36 |
37 | 1024 张表,假设每个表放 500 万数据,在 MySQL 里可以放 50 亿条数据。
38 |
39 | 每秒 5 万的写并发,总共 50 亿条数据,对于国内大部分的互联网公司来说,其实一般来说都够了。
40 |
41 | 谈分库分表的扩容,**第一次分库分表,就一次性给他分个够**,32 个库,1024 张表,可能对大部分的中小型互联网公司来说,已经可以支撑好几年了。
42 |
43 | 一个实践是利用 `32 * 32` 来分库分表,即分为 32 个库,每个库里一个表分为 32 张表。一共就是 1024 张表。根据某个 id 先根据 32 取模路由到库,再根据 32 取模路由到库里的表。
44 |
45 | | orderId | id % 32 (库) | id / 32 % 32 (表) |
46 | |---|---|---|
47 | | 259 | 3 | 8 |
48 | | 1189 | 5 | 5 |
49 | | 352 | 0 | 11 |
50 | | 4593 | 17 | 15 |
51 |
52 |
53 | 刚开始的时候,这个库可能就是逻辑库,建在一个数据库上的,就是一个 mysql 服务器可能建了 n 个库,比如 32 个库。后面如果要拆分,就是不断在库和 mysql 服务器之间做迁移就可以了。然后系统配合改一下配置即可。
54 |
55 | 比如说最多可以扩展到 32 个数据库服务器,每个数据库服务器是一个库。如果还是不够?最多可以扩展到 1024 个数据库服务器,每个数据库服务器上面一个库一个表。因为最多是 1024 个表。
56 |
57 | 这么搞,是不用自己写代码做数据迁移的,都交给 dba 来搞好了,但是 dba 确实是需要做一些库表迁移的工作,但是总比你自己写代码,然后抽数据导数据来的效率高得多吧。
58 |
59 | 哪怕是要减少库的数量,也很简单,其实说白了就是按倍数缩容就可以了,然后修改一下路由规则。
60 |
61 | 这里对步骤做一个总结:
62 |
63 | 1. 设定好几台数据库服务器,每台服务器上几个库,每个库多少个表,推荐是 32 库 * 32 表,对于大部分公司来说,可能几年都够了。
64 | 2. 路由的规则,orderId 模 32 = 库,orderId / 32 模 32 = 表
65 | 3. 扩容的时候,申请增加更多的数据库服务器,装好 mysql,呈倍数扩容,4 台服务器,扩到 8 台服务器,再到 16 台服务器。
66 | 4. 由 dba 负责将原先数据库服务器的库,迁移到新的数据库服务器上去,库迁移是有一些便捷的工具的。
67 | 5. 我们这边就是修改一下配置,调整迁移的库所在数据库服务器的地址。
68 | 6. 重新发布系统,上线,原先的路由规则变都不用变,直接可以基于 n 倍的数据库服务器的资源,继续进行线上系统的提供服务。
--------------------------------------------------------------------------------
/docs/high-concurrency/database-shard-method.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | 现在有一个未分库分表的系统,未来要分库分表,如何设计才可以让系统从未分库分表**动态切换**到分库分表上?
3 |
4 | ## 面试官心理分析
5 | 你看看,你现在已经明白为啥要分库分表了,你也知道常用的分库分表中间件了,你也设计好你们如何分库分表的方案了(水平拆分、垂直拆分、分表),那问题来了,你接下来该怎么把你那个单库单表的系统给迁移到分库分表上去?
6 |
7 | 所以这都是一环扣一环的,就是看你有没有全流程经历过这个过程。
8 |
9 | ## 面试题剖析
10 | 这个其实从 low 到高大上有好几种方案,我们都玩儿过,我都给你说一下。
11 |
12 | ### 停机迁移方案
13 | 我先给你说一个最 low 的方案,就是很简单,大家伙儿凌晨 12 点开始运维,网站或者 app 挂个公告,说 0 点到早上 6 点进行运维,无法访问。
14 |
15 | 接着到 0 点停机,系统停掉,没有流量写入了,此时老的单库单表数据库静止了。然后你之前得写好一个**导数的一次性工具**,此时直接跑起来,然后将单库单表的数据哗哗哗读出来,写到分库分表里面去。
16 |
17 | 导数完了之后,就 ok 了,修改系统的数据库连接配置啥的,包括可能代码和 SQL 也许有修改,那你就用最新的代码,然后直接启动连到新的分库分表上去。
18 |
19 | 验证一下,ok了,完美,大家伸个懒腰,看看看凌晨 4 点钟的北京夜景,打个滴滴回家吧。
20 |
21 | 但是这个方案比较 low,谁都能干,我们来看看高大上一点的方案。
22 |
23 | 
24 |
25 | ### 双写迁移方案
26 | 这个是我们常用的一种迁移方案,比较靠谱一些,不用停机,不用看北京凌晨 4 点的风景。
27 |
28 | 简单来说,就是在线上系统里面,之前所有写库的地方,增删改操作,**除了对老库增删改,都加上对新库的增删改**,这就是所谓的**双写**,同时写俩库,老库和新库。
29 |
30 | 然后**系统部署**之后,新库数据差太远,用之前说的导数工具,跑起来读老库数据写新库,写的时候要根据 gmt_modified 这类字段判断这条数据最后修改的时间,除非是读出来的数据在新库里没有,或者是比新库的数据新才会写。简单来说,就是不允许用老数据覆盖新数据。
31 |
32 | 导完一轮之后,有可能数据还是存在不一致,那么就程序自动做一轮校验,比对新老库每个表的每条数据,接着如果有不一样的,就针对那些不一样的,从老库读数据再次写。反复循环,直到两个库每个表的数据都完全一致为止。
33 |
34 | 接着当数据完全一致了,就 ok 了,基于仅仅使用分库分表的最新代码,重新部署一次,不就仅仅基于分库分表在操作了么,还没有几个小时的停机时间,很稳。所以现在基本玩儿数据迁移之类的,都是这么干的。
35 |
36 | 
--------------------------------------------------------------------------------
/docs/high-concurrency/es-architecture.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | es 的分布式架构原理能说一下么(es 是如何实现分布式的啊)?
3 |
4 | ## 面试官心理分析
5 | 在搜索这块,lucene 是最流行的搜索库。几年前业内一般都问,你了解 lucene 吗?你知道倒排索引的原理吗?现在早已经 out 了,因为现在很多项目都是直接用基于 lucene 的分布式搜索引擎—— ElasticSearch,简称为 es。
6 |
7 | 而现在分布式搜索基本已经成为大部分互联网行业的 Java 系统的标配,其中尤为流行的就是 es,前几年 es 没火的时候,大家一般用 solr。但是这两年基本大部分企业和项目都开始转向 es 了。
8 |
9 | 所以互联网面试,肯定会跟你聊聊分布式搜索引擎,也就一定会聊聊 es,如果你确实不知道,那你真的就 out 了。
10 |
11 | 如果面试官问你第一个问题,确实一般都会问你 es 的分布式架构设计能介绍一下么?就看看你对分布式搜索引擎架构的一个基本理解。
12 |
13 | ## 面试题剖析
14 | ElasticSearch 设计的理念就是分布式搜索引擎,底层其实还是基于 lucene 的。核心思想就是在多台机器上启动多个 es 进程实例,组成了一个 es 集群。
15 |
16 | es 中存储数据的**基本单位是索引**,比如说你现在要在 es 中存储一些订单数据,你就应该在 es 中创建一个索引 `order_idx`,所有的订单数据就都写到这个索引里面去,一个索引差不多就是相当于是 mysql 里的一张表。
17 |
18 | ```
19 | index -> type -> mapping -> document -> field。
20 | ```
21 |
22 | 这样吧,为了做个更直白的介绍,我在这里做个类比。但是切记,不要划等号,类比只是为了便于理解。
23 |
24 | index 相当于 mysql 里的一张表。而 type 没法跟 mysql 里去对比,一个 index 里可以有多个 type,每个 type 的字段都是差不多的,但是有一些略微的差别。假设有一个 index,是订单 index,里面专门是放订单数据的。就好比说你在 mysql 中建表,有些订单是实物商品的订单,比如一件衣服、一双鞋子;有些订单是虚拟商品的订单,比如游戏点卡,话费充值。就两种订单大部分字段是一样的,但是少部分字段可能有略微的一些差别。
25 |
26 | 所以就会在订单 index 里,建两个 type,一个是实物商品订单 type,一个是虚拟商品订单 type,这两个 type 大部分字段是一样的,少部分字段是不一样的。
27 |
28 | 很多情况下,一个 index 里可能就一个 type,但是确实如果说是一个 index 里有多个 type 的情况(**注意**,`mapping types` 这个概念在 ElasticSearch 7.X 已被完全移除,详细说明可以参考[官方文档](https://github.com/elastic/elasticsearch/blob/6.5/docs/reference/mapping/removal_of_types.asciidoc)),你可以认为 index 是一个类别的表,具体的每个 type 代表了 mysql 中的一个表。每个 type 有一个 mapping,如果你认为一个 type 是具体的一个表,index 就代表多个 type 同属于的一个类型,而 mapping 就是这个 type 的**表结构定义**,你在 mysql 中创建一个表,肯定是要定义表结构的,里面有哪些字段,每个字段是什么类型。实际上你往 index 里的一个 type 里面写的一条数据,叫做一条 document,一条 document 就代表了 mysql 中某个表里的一行,每个 document 有多个 field,每个 field 就代表了这个 document 中的一个字段的值。
29 |
30 | 
31 |
32 | 你搞一个索引,这个索引可以拆分成多个 `shard`,每个 shard 存储部分数据。拆分多个 shard 是有好处的,一是**支持横向扩展**,比如你数据量是 3T,3 个 shard,每个 shard 就 1T 的数据,若现在数据量增加到 4T,怎么扩展,很简单,重新建一个有 4 个 shard 的索引,将数据导进去;二是**提高性能**,数据分布在多个 shard,即多台服务器上,所有的操作,都会在多台机器上并行分布式执行,提高了吞吐量和性能。
33 |
34 | 接着就是这个 shard 的数据实际是有多个备份,就是说每个 shard 都有一个 `primary shard`,负责写入数据,但是还有几个 `replica shard`。`primary shard` 写入数据之后,会将数据同步到其他几个 `replica shard` 上去。
35 |
36 | 
37 |
38 | 通过这个 replica 的方案,每个 shard 的数据都有多个备份,如果某个机器宕机了,没关系啊,还有别的数据副本在别的机器上呢。高可用了吧。
39 |
40 | es 集群多个节点,会自动选举一个节点为 master 节点,这个 master 节点其实就是干一些管理的工作的,比如维护索引元数据、负责切换 primary shard 和 replica shard 身份等。要是 master 节点宕机了,那么会重新选举一个节点为 master 节点。
41 |
42 | 如果是非 master节点宕机了,那么会由 master 节点,让那个宕机节点上的 primary shard 的身份转移到其他机器上的 replica shard。接着你要是修复了那个宕机机器,重启了之后,master 节点会控制将缺失的 replica shard 分配过去,同步后续修改的数据之类的,让集群恢复正常。
43 |
44 | 说得更简单一点,就是说如果某个非 master 节点宕机了。那么此节点上的 primary shard 不就没了。那好,master 会让 primary shard 对应的 replica shard(在其他机器上)切换为 primary shard。如果宕机的机器修复了,修复后的节点也不再是 primary shard,而是 replica shard。
45 |
46 | 其实上述就是 ElasticSearch 作为分布式搜索引擎最基本的一个架构设计。
--------------------------------------------------------------------------------
/docs/high-concurrency/es-introduction.md:
--------------------------------------------------------------------------------
1 | ## lucene 和 es 的前世今生
2 | lucene 是最先进、功能最强大的搜索库。如果直接基于 lucene 开发,非常复杂,即便写一些简单的功能,也要写大量的 Java 代码,需要深入理解原理。
3 |
4 | elasticsearch 基于 lucene,隐藏了 lucene 的复杂性,提供了简单易用的 restful api / Java api 接口(另外还有其他语言的 api 接口)。
5 |
6 | - 分布式的文档存储引擎
7 | - 分布式的搜索引擎和分析引擎
8 | - 分布式,支持 PB 级数据
9 |
10 | ## es 的核心概念
11 | ### Near Realtime
12 | 近实时,有两层意思:
13 |
14 | - 从写入数据到数据可以被搜索到有一个小延迟(大概是 1s)
15 | - 基于 es 执行搜索和分析可以达到秒级
16 |
17 | ### Cluster 集群
18 | 集群包含多个节点,每个节点属于哪个集群都是通过一个配置来决定的,对于中小型应用来说,刚开始一个集群就一个节点很正常。
19 |
20 | ### Node 节点
21 | Node 是集群中的一个节点,节点也有一个名称,默认是随机分配的。默认节点会去加入一个名称为 `elasticsearch` 的集群。如果直接启动一堆节点,那么它们会自动组成一个 elasticsearch 集群,当然一个节点也可以组成 elasticsearch 集群。
22 |
23 | ### Document & field
24 | 文档是 es 中最小的数据单元,一个 document 可以是一条客户数据、一条商品分类数据、一条订单数据,通常用 json 数据结构来表示。每个 index 下的 type,都可以存储多条 document。一个 document 里面有多个 field,每个 field 就是一个数据字段。
25 |
26 | ```json
27 | {
28 | "product_id": "1",
29 | "product_name": "iPhone X",
30 | "product_desc": "苹果手机",
31 | "category_id": "2",
32 | "category_name": "电子产品"
33 | }
34 | ```
35 |
36 | ### Index
37 | 索引包含了一堆有相似结构的文档数据,比如商品索引。一个索引包含很多 document,一个索引就代表了一类相似或者相同的 ducument。
38 |
39 | ### Type
40 | 类型,每个索引里可以有一个或者多个 type,type 是 index 的一个逻辑分类,比如商品 index 下有多个 type:日化商品 type、电器商品 type、生鲜商品 type。每个 type 下的 document 的 field 可能不太一样。
41 |
42 | ### shard
43 | 单台机器无法存储大量数据,es 可以将一个索引中的数据切分为多个 shard,分布在多台服务器上存储。有了 shard 就可以横向扩展,存储更多数据,让搜索和分析等操作分布到多台服务器上去执行,提升吞吐量和性能。每个 shard 都是一个 lucene index。
44 |
45 | ### replica
46 | 任何一个服务器随时可能故障或宕机,此时 shard 可能就会丢失,因此可以为每个 shard 创建多个 replica 副本。replica 可以在 shard 故障时提供备用服务,保证数据不丢失,多个 replica 还可以提升搜索操作的吞吐量和性能。primary shard(建立索引时一次设置,不能修改,默认 5 个),replica shard(随时修改数量,默认 1 个),默认每个索引 10 个 shard,5 个 primary shard,5个 replica shard,最小的高可用配置,是 2 台服务器。
47 |
48 | 这么说吧,shard 分为 primary shard 和 replica shard。而 primary shard 一般简称为 shard,而 replica shard 一般简称为 replica。
49 |
50 | 
51 |
52 | ## es 核心概念 vs. db 核心概念
53 | | es | db |
54 | |---|---|
55 | | index | 数据库 |
56 | | type | 数据表 |
57 | | docuemnt | 一行数据 |
58 |
59 | 以上是一个简单的类比。
--------------------------------------------------------------------------------
/docs/high-concurrency/es-production-cluster.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | es 生产集群的部署架构是什么?每个索引的数据量大概有多少?每个索引大概有多少个分片?
3 |
4 | ## 面试官心理分析
5 | 这个问题,包括后面的 redis 什么的,谈到 es、redis、mysql 分库分表等等技术,面试必问!就是你生产环境咋部署的?说白了,这个问题没啥技术含量,就是看你有没有在真正的生产环境里干过这事儿!
6 |
7 | 有些同学可能是没在生产环境中干过的,没实际去拿线上机器部署过 es 集群,也没实际玩儿过,也没往 es 集群里面导入过几千万甚至是几亿的数据量,可能你就不太清楚这里面的一些生产项目中的细节。
8 |
9 | 如果你是自己就玩儿过 demo,没碰过真实的 es 集群,那你可能此时会懵。别懵,你一定要云淡风轻的回答出来这个问题,表示你确实干过这事儿。
10 |
11 | ## 面试题剖析
12 | 其实这个问题没啥,如果你确实干过 es,那你肯定了解你们生产 es 集群的实际情况,部署了几台机器?有多少个索引?每个索引有多大数据量?每个索引给了多少个分片?你肯定知道!
13 |
14 | 但是如果你确实没干过,也别虚,我给你说一个基本的版本,你到时候就简单说一下就好了。
15 |
16 | - es 生产集群我们部署了 5 台机器,每台机器是 6 核 64G 的,集群总内存是 320G。
17 | - 我们 es 集群的日增量数据大概是 2000 万条,每天日增量数据大概是 500MB,每月增量数据大概是 6 亿,15G。目前系统已经运行了几个月,现在 es 集群里数据总量大概是 100G 左右。
18 | - 目前线上有 5 个索引(这个结合你们自己业务来,看看自己有哪些数据可以放 es 的),每个索引的数据量大概是 20G,所以这个数据量之内,我们每个索引分配的是 8 个 shard,比默认的 5 个 shard 多了 3 个 shard。
19 |
20 | 大概就这么说一下就行了。
--------------------------------------------------------------------------------
/docs/high-concurrency/high-concurrency-design.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | 如何设计一个高并发系统?
3 |
4 | ## 面试官心理分析
5 | 说实话,如果面试官问你这个题目,那么你必须要使出全身吃奶劲了。为啥?因为你没看到现在很多公司招聘的 JD 里都是说啥,有高并发就经验者优先。
6 |
7 | 如果你确实有真才实学,在互联网公司里干过高并发系统,那你确实拿 offer 基本如探囊取物,没啥问题。面试官也绝对不会这样来问你,否则他就是蠢。
8 |
9 | 假设你在某知名电商公司干过高并发系统,用户上亿,一天流量几十亿,高峰期并发量上万,甚至是十万。那么人家一定会仔细盘问你的系统架构,你们系统啥架构?怎么部署的?部署了多少台机器?缓存咋用的?MQ 咋用的?数据库咋用的?就是深挖你到底是如何扛住高并发的。
10 |
11 | 因为真正干过高并发的人一定知道,脱离了业务的系统架构都是在纸上谈兵,真正在复杂业务场景而且还高并发的时候,那系统架构一定不是那么简单的,用个 redis,用 mq 就能搞定?当然不是,真实的系统架构搭配上业务之后,会比这种简单的所谓“高并发架构”要复杂很多倍。
12 |
13 | 如果有面试官问你个问题说,如何设计一个高并发系统?那么不好意思,**一定是因为你实际上没干过高并发系统**。面试官看你简历就没啥出彩的,感觉就不咋地,所以就会问问你,如何设计一个高并发系统?其实说白了本质就是看看你有没有自己研究过,有没有一定的知识积累。
14 |
15 | 最好的当然是招聘个真正干过高并发的哥儿们咯,但是这种哥儿们人数稀缺,不好招。所以可能次一点的就是招一个自己研究过的哥儿们,总比招一个啥也不会的哥儿们好吧!
16 |
17 | 所以这个时候你必须得做一把个人秀了,秀出你所有关于高并发的知识!
18 |
19 |
20 | ## 面试题剖析
21 | 其实所谓的高并发,如果你要理解这个问题呢,其实就得从高并发的根源出发,为啥会有高并发?为啥高并发就很牛逼?
22 |
23 | 我说的浅显一点,很简单,就是因为刚开始系统都是连接数据库的,但是要知道数据库支撑到每秒并发两三千的时候,基本就快完了。所以才有说,很多公司,刚开始干的时候,技术比较 low,结果业务发展太快,有的时候系统扛不住压力就挂了。
24 |
25 | 当然会挂了,凭什么不挂?你数据库如果瞬间承载每秒 5000/8000,甚至上万的并发,一定会宕机,因为比如 mysql 就压根儿扛不住这么高的并发量。
26 |
27 | 所以为啥高并发牛逼?就是因为现在用互联网的人越来越多,很多 app、网站、系统承载的都是高并发请求,可能高峰期每秒并发量几千,很正常的。如果是什么双十一之类的,每秒并发几万几十万都有可能。
28 |
29 | 那么如此之高的并发量,加上原本就如此之复杂的业务,咋玩儿?真正厉害的,一定是在复杂业务系统里玩儿过高并发架构的人,但是你没有,那么我给你说一下你该怎么回答这个问题:
30 |
31 | 可以分为以下 6 点:
32 |
33 | - 系统拆分
34 | - 缓存
35 | - MQ
36 | - 分库分表
37 | - 读写分离
38 | - ElasticSearch
39 |
40 | 
41 |
42 | ### 系统拆分
43 | 将一个系统拆分为多个子系统,用 dubbo 来搞。然后每个系统连一个数据库,这样本来就一个库,现在多个数据库,不也可以扛高并发么。
44 |
45 | ### 缓存
46 | 缓存,必须得用缓存。大部分的高并发场景,都是**读多写少**,那你完全可以在数据库和缓存里都写一份,然后读的时候大量走缓存不就得了。毕竟人家 redis 轻轻松松单机几万的并发。所以你可以考虑考虑你的项目里,那些承载主要请求的**读场景,怎么用缓存来抗高并发**。
47 |
48 | ### MQ
49 | MQ,必须得用 MQ。可能你还是会出现高并发写的场景,比如说一个业务操作里要频繁搞数据库几十次,增删改增删改,疯了。那高并发绝对搞挂你的系统,你要是用 redis 来承载写那肯定不行,人家是缓存,数据随时就被 LRU 了,数据格式还无比简单,没有事务支持。所以该用 mysql 还得用 mysql 啊。那你咋办?用 MQ 吧,大量的写请求灌入 MQ 里,排队慢慢玩儿,**后边系统消费后慢慢写**,控制在 mysql 承载范围之内。所以你得考虑考虑你的项目里,那些承载复杂写业务逻辑的场景里,如何用 MQ 来异步写,提升并发性。MQ 单机抗几万并发也是 ok 的,这个之前还特意说过。
50 |
51 | ### 分库分表
52 | 分库分表,可能到了最后数据库层面还是免不了抗高并发的要求,好吧,那么就将一个数据库拆分为多个库,多个库来扛更高的并发;然后将一个表**拆分为多个表**,每个表的数据量保持少一点,提高 sql 跑的性能。
53 |
54 | ### 读写分离
55 | 读写分离,这个就是说大部分时候数据库可能也是读多写少,没必要所有请求都集中在一个库上吧,可以搞个主从架构,**主库写**入,**从库读**取,搞一个读写分离。**读流量太多**的时候,还可以**加更多的从库**。
56 |
57 | ### ElasticSearch
58 | Elasticsearch,简称 es。es 是分布式的,可以随便扩容,分布式天然就可以支撑高并发,因为动不动就可以扩容加机器来扛更高的并发。那么一些比较简单的查询、统计类的操作,可以考虑用 es 来承载,还有一些全文搜索类的操作,也可以考虑用 es 来承载。
59 |
60 |
61 | 上面的 6 点,基本就是高并发系统肯定要干的一些事儿,大家可以仔细结合之前讲过的知识考虑一下,到时候你可以系统的把这块阐述一下,然后每个部分要注意哪些问题,之前都讲过了,你都可以阐述阐述,表明你对这块是有点积累的。
62 |
63 | 说句实话,毕竟你真正厉害的一点,不是在于弄明白一些技术,或者大概知道一个高并发系统应该长什么样?其实实际上在真正的复杂的业务系统里,做高并发要远远比上面提到的点要复杂几十倍到上百倍。你需要考虑:哪些需要分库分表,哪些不需要分库分表,单库单表跟分库分表如何 join,哪些数据要放到缓存里去,放哪些数据才可以扛住高并发的请求,你需要完成对一个复杂业务系统的分析之后,然后逐步逐步的加入高并发的系统架构的改造,这个过程是无比复杂的,一旦做过一次,并且做好了,你在这个市场上就会非常的吃香。
64 |
65 | 其实大部分公司,真正看重的,不是说你掌握高并发相关的一些基本的架构知识,架构中的一些技术,RocketMQ、Kafka、Redis、Elasticsearch,高并发这一块,你了解了,也只能是次一等的人才。对一个有几十万行代码的复杂的分布式系统,一步一步架构、设计以及实践过高并发架构的人,这个经验是难能可贵的。
--------------------------------------------------------------------------------
/docs/high-concurrency/how-to-ensure-high-availability-of-message-queues.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | 如何保证消息队列的高可用?
3 |
4 | ## 面试官心理分析
5 | 如果有人问到你 MQ 的知识,**高可用是必问的**。[上一讲](/docs/high-concurrency/why-mq.md)提到,MQ 会导致**系统可用性降低**。所以只要你用了 MQ,接下来问的一些要点肯定就是围绕着 MQ 的那些缺点怎么来解决了。
6 |
7 | 要是你傻乎乎的就干用了一个 MQ,各种问题从来没考虑过,那你就杯具了,面试官对你的感觉就是,只会简单使用一些技术,没任何思考,马上对你的印象就不太好了。这样的同学招进来要是做个 20k 薪资以内的普通小弟还凑合,要是做薪资 20k+ 的高工,那就惨了,让你设计个系统,里面肯定一堆坑,出了事故公司受损失,团队一起背锅。
8 |
9 | ## 面试题剖析
10 | 这个问题这么问是很好的,因为不能问你 Kafka 的高可用性怎么保证?ActiveMQ 的高可用性怎么保证?一个面试官要是这么问就显得很没水平,人家可能用的就是 RabbitMQ,没用过 Kafka,你上来问人家 Kafka 干什么?这不是摆明了刁难人么。
11 |
12 | 所以有水平的面试官,问的是 MQ 的高可用性怎么保证?这样就是你用过哪个 MQ,你就说说你对那个 MQ 的高可用性的理解。
13 |
14 | ### RabbitMQ 的高可用性
15 | RabbitMQ 是比较有代表性的,因为是**基于主从**(非分布式)做高可用性的,我们就以 RabbitMQ 为例子讲解第一种 MQ 的高可用性怎么实现。
16 |
17 | RabbitMQ 有三种模式:单机模式、普通集群模式、镜像集群模式。
18 |
19 | #### 单机模式
20 | 单机模式,就是 Demo 级别的,一般就是你本地启动了玩玩儿的😄,没人生产用单机模式。
21 |
22 | #### 普通集群模式(无高可用性)
23 | 普通集群模式,意思就是在多台机器上启动多个 RabbitMQ 实例,每个机器启动一个。你**创建的 queue,只会放在一个 RabbitMQ 实例上**,但是每个实例都同步 queue 的元数据(元数据可以认为是 queue 的一些配置信息,通过元数据,可以找到 queue 所在实例)。你消费的时候,实际上如果连接到了另外一个实例,那么那个实例会从 queue 所在实例上拉取数据过来。
24 |
25 | 
26 |
27 | 这种方式确实很麻烦,也不怎么好,**没做到所谓的分布式**,就是个普通集群。因为这导致你要么消费者每次随机连接一个实例然后拉取数据,要么固定连接那个 queue 所在实例消费数据,前者有**数据拉取的开销**,后者导致**单实例性能瓶颈**。
28 |
29 | 而且如果那个放 queue 的实例宕机了,会导致接下来其他实例就无法从那个实例拉取,如果你**开启了消息持久化**,让 RabbitMQ 落地存储消息的话,**消息不一定会丢**,得等这个实例恢复了,然后才可以继续从这个 queue 拉取数据。
30 |
31 | 所以这个事儿就比较尴尬了,这就**没有什么所谓的高可用性**,**这方案主要是提高吞吐量的**,就是说让集群中多个节点来服务某个 queue 的读写操作。
32 |
33 | #### 镜像集群模式(高可用性)
34 | 这种模式,才是所谓的 RabbitMQ 的高可用模式。跟普通集群模式不一样的是,在镜像集群模式下,你创建的 queue,无论元数据还是 queue 里的消息都会**存在于多个实例上**,就是说,每个 RabbitMQ 节点都有这个 queue 的一个**完整镜像**,包含 queue 的全部数据的意思。然后每次你写消息到 queue 的时候,都会自动把**消息同步**到多个实例的 queue 上。
35 |
36 | 
37 |
38 | 那么**如何开启这个镜像集群模式**呢?其实很简单,RabbitMQ 有很好的管理控制台,就是在后台新增一个策略,这个策略是**镜像集群模式的策略**,指定的时候是可以要求数据同步到所有节点的,也可以要求同步到指定数量的节点,再次创建 queue 的时候,应用这个策略,就会自动将数据同步到其他的节点上去了。
39 |
40 | 这样的话,好处在于,你任何一个机器宕机了,没事儿,其它机器(节点)还包含了这个 queue 的完整数据,别的 consumer 都可以到其它节点上去消费数据。坏处在于,第一,这个性能开销也太大了吧,消息需要同步到所有机器上,导致网络带宽压力和消耗很重!第二,这么玩儿,不是分布式的,就**没有扩展性可言**了,如果某个 queue 负载很重,你加机器,新增的机器也包含了这个 queue 的所有数据,并**没有办法线性扩展**你的 queue。你想,如果这个 queue 的数据量很大,大到这个机器上的容量无法容纳了,此时该怎么办呢?
41 |
42 | ### Kafka 的高可用性
43 | Kafka 一个最基本的架构认识:由多个 broker 组成,每个 broker 是一个节点;你创建一个 topic,这个 topic 可以划分为多个 partition,每个 partition 可以存在于不同的 broker 上,每个 partition 就放一部分数据。
44 |
45 | 这就是**天然的分布式消息队列**,就是说一个 topic 的数据,是**分散放在多个机器上的,每个机器就放一部分数据**。
46 |
47 | 实际上 RabbmitMQ 之类的,并不是分布式消息队列,它就是传统的消息队列,只不过提供了一些集群、HA(High Availability, 高可用性) 的机制而已,因为无论怎么玩儿,RabbitMQ 一个 queue 的数据都是放在一个节点里的,镜像集群下,也是每个节点都放这个 queue 的完整数据。
48 |
49 | Kafka 0.8 以前,是没有 HA 机制的,就是任何一个 broker 宕机了,那个 broker 上的 partition 就废了,没法写也没法读,没有什么高可用性可言。
50 |
51 | 比如说,我们假设创建了一个 topic,指定其 partition 数量是 3 个,分别在三台机器上。但是,如果第二台机器宕机了,会导致这个 topic 的 1/3 的数据就丢了,因此这个是做不到高可用的。
52 |
53 | 
54 |
55 | Kafka 0.8 以后,提供了 HA 机制,就是 replica(复制品) 副本机制。每个 partition 的数据都会同步到其它机器上,形成自己的多个 replica 副本。所有 replica 会选举一个 leader 出来,那么生产和消费都跟这个 leader 打交道,然后其他 replica 就是 follower。写的时候,leader 会负责把数据同步到所有 follower 上去,读的时候就直接读 leader 上的数据即可。只能读写 leader?很简单,**要是你可以随意读写每个 follower,那么就要 care 数据一致性的问题**,系统复杂度太高,很容易出问题。Kafka 会均匀地将一个 partition 的所有 replica 分布在不同的机器上,这样才可以提高容错性。
56 |
57 | 
58 |
59 | 这么搞,就有所谓的**高可用性**了,因为如果某个 broker 宕机了,没事儿,那个 broker上面的 partition 在其他机器上都有副本的。如果这个宕机的 broker 上面有某个 partition 的 leader,那么此时会从 follower 中**重新选举**一个新的 leader 出来,大家继续读写那个新的 leader 即可。这就有所谓的高可用性了。
60 |
61 | **写数据**的时候,生产者就写 leader,然后 leader 将数据落地写本地磁盘,接着其他 follower 自己主动从 leader 来 pull 数据。一旦所有 follower 同步好数据了,就会发送 ack 给 leader,leader 收到所有 follower 的 ack 之后,就会返回写成功的消息给生产者。(当然,这只是其中一种模式,还可以适当调整这个行为)
62 |
63 | **消费**的时候,只会从 leader 去读,但是只有当一个消息已经被所有 follower 都同步成功返回 ack 的时候,这个消息才会被消费者读到。
64 |
65 | 看到这里,相信你大致明白了 Kafka 是如何保证高可用机制的了,对吧?不至于一无所知,现场还能给面试官画画图。要是遇上面试官确实是 Kafka 高手,深挖了问,那你只能说不好意思,太深入的你没研究过。
--------------------------------------------------------------------------------
/docs/high-concurrency/how-to-ensure-high-concurrency-and-high-availability-of-redis.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | 如何保证 redis 的高并发和高可用?redis 的主从复制原理能介绍一下么?redis 的哨兵原理能介绍一下么?
3 |
4 | ## 面试官心理分析
5 | 其实问这个问题,主要是考考你,redis 单机能承载多高并发?如果单机扛不住如何扩容扛更多的并发?redis 会不会挂?既然 redis 会挂那怎么保证 redis 是高可用的?
6 |
7 | 其实针对的都是项目中你肯定要考虑的一些问题,如果你没考虑过,那确实你对生产系统中的问题思考太少。
8 |
9 | ## 面试题剖析
10 | 如果你用 redis 缓存技术的话,肯定要考虑如何用 redis 来加多台机器,保证 redis 是高并发的,还有就是如何让 redis 保证自己不是挂掉以后就直接死掉了,即 redis 高可用。
11 |
12 | 由于此节内容较多,因此,会分为两个小节进行讲解。
13 | - [redis 主从架构](/docs/high-concurrency/redis-master-slave.md)
14 | - [redis 基于哨兵实现高可用](/docs/high-concurrency/redis-sentinel.md)
15 |
16 | redis 实现**高并发**主要依靠**主从架构**,一主多从,一般来说,很多项目其实就足够了,单主用来写入数据,单机几万 QPS,多从用来查询数据,多个从实例可以提供每秒 10w 的 QPS。
17 |
18 | 如果想要在实现高并发的同时,容纳大量的数据,那么就需要 redis 集群,使用 redis 集群之后,可以提供每秒几十万的读写并发。
19 |
20 | redis 高可用,如果是做主从架构部署,那么加上哨兵就可以了,就可以实现,任何一个实例宕机,可以进行主备切换。
--------------------------------------------------------------------------------
/docs/high-concurrency/how-to-ensure-that-messages-are-not-repeatedly-consumed.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | 如何保证消息不被重复消费?或者说,如何保证消息消费的幂等性?
3 |
4 | ## 面试官心理分析
5 | 其实这是很常见的一个问题,这俩问题基本可以连起来问。既然是消费消息,那肯定要考虑会不会重复消费?能不能避免重复消费?或者重复消费了也别造成系统异常可以吗?这个是 MQ 领域的基本问题,其实本质上还是问你**使用消息队列如何保证幂等性**,这个是你架构里要考虑的一个问题。
6 |
7 | ## 面试题剖析
8 | 回答这个问题,首先你别听到重复消息这个事儿,就一无所知吧,你**先大概说一说可能会有哪些重复消费的问题**。
9 |
10 | 首先,比如 RabbitMQ、RocketMQ、Kafka,都有可能会出现消息重复消费的问题,正常。因为这问题通常不是 MQ 自己保证的,是由我们开发来保证的。挑一个 Kafka 来举个例子,说说怎么重复消费吧。
11 |
12 | Kafka 实际上有个 offset 的概念,就是每个消息写进去,都有一个 offset,代表消息的序号,然后 consumer 消费了数据之后,**每隔一段时间**(定时定期),会把自己消费过的消息的 offset 提交一下,表示“我已经消费过了,下次我要是重启啥的,你就让我继续从上次消费到的 offset 来继续消费吧”。
13 |
14 | 但是凡事总有意外,比如我们之前生产经常遇到的,就是你有时候重启系统,看你怎么重启了,如果碰到点着急的,直接 kill 进程了,再重启。这会导致 consumer 有些消息处理了,但是没来得及提交 offset,尴尬了。重启之后,少数消息会再次消费一次。
15 |
16 | 举个栗子。
17 |
18 | 有这么个场景。数据 1/2/3 依次进入 kafka,kafka 会给这三条数据每条分配一个 offset,代表这条数据的序号,我们就假设分配的 offset 依次是 152/153/154。消费者从 kafka 去消费的时候,也是按照这个顺序去消费。假如当消费者消费了 `offset=153` 的这条数据,刚准备去提交 offset 到 zookeeper,此时消费者进程被重启了。那么此时消费过的数据 1/2 的 offset 并没有提交,kafka 也就不知道你已经消费了 `offset=153` 这条数据。那么重启之后,消费者会找 kafka 说,嘿,哥儿们,你给我接着把上次我消费到的那个地方后面的数据继续给我传递过来。由于之前的 offset 没有提交成功,那么数据 1/2 会再次传过来,如果此时消费者没有去重的话,那么就会导致重复消费。
19 |
20 | 
21 |
22 | 如果消费者干的事儿是拿一条数据就往数据库里写一条,会导致说,你可能就把数据 1/2 在数据库里插入了 2 次,那么数据就错啦。
23 |
24 | 其实重复消费不可怕,可怕的是你没考虑到重复消费之后,**怎么保证幂等性**。
25 |
26 | 举个例子吧。假设你有个系统,消费一条消息就往数据库里插入一条数据,要是你一个消息重复两次,你不就插入了两条,这数据不就错了?但是你要是消费到第二次的时候,自己判断一下是否已经消费过了,若是就直接扔了,这样不就保留了一条数据,从而保证了数据的正确性。
27 |
28 | 一条数据重复出现两次,数据库里就只有一条数据,这就保证了系统的幂等性。
29 |
30 | 幂等性,通俗点说,就一个数据,或者一个请求,给你重复来多次,你得确保对应的数据是不会改变的,**不能出错**。
31 |
32 | 所以第二个问题来了,怎么保证消息队列消费的幂等性?
33 |
34 | 其实还是得结合业务来思考,我这里给几个思路:
35 |
36 | - 比如你拿个数据要写库,你先根据主键查一下,如果这数据都有了,你就别插入了,update 一下好吧。
37 | - 比如你是写 Redis,那没问题了,反正每次都是 set,天然幂等性。
38 | - 比如你不是上面两个场景,那做的稍微复杂一点,你需要让生产者发送每条数据的时候,里面加一个全局唯一的 id,类似订单 id 之类的东西,然后你这里消费到了之后,先根据这个 id 去比如 Redis 里查一下,之前消费过吗?如果没有消费过,你就处理,然后这个 id 写 Redis。如果消费过了,那你就别处理了,保证别重复处理相同的消息即可。
39 | - 比如基于数据库的唯一键来保证重复数据不会重复插入多条。因为有唯一键约束了,重复数据插入只会报错,不会导致数据库中出现脏数据。
40 |
41 | 
42 |
43 | 当然,如何保证 MQ 的消费是幂等性的,需要结合具体的业务来看。
--------------------------------------------------------------------------------
/docs/high-concurrency/how-to-ensure-the-order-of-messages.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | 如何保证消息的顺序性?
3 |
4 | ## 面试官心理分析
5 | 其实这个也是用 MQ 的时候必问的话题,第一看看你了不了解顺序这个事儿?第二看看你有没有办法保证消息是有顺序的?这是生产系统中常见的问题。
6 |
7 | ## 面试题剖析
8 | 我举个例子,我们以前做过一个 mysql `binlog` 同步的系统,压力还是非常大的,日同步数据要达到上亿,就是说数据从一个 mysql 库原封不动地同步到另一个 mysql 库里面去(mysql -> mysql)。常见的一点在于说比如大数据 team,就需要同步一个 mysql 库过来,对公司的业务系统的数据做各种复杂的操作。
9 |
10 | 你在 mysql 里增删改一条数据,对应出来了增删改 3 条 `binlog` 日志,接着这三条 `binlog` 发送到 MQ 里面,再消费出来依次执行,起码得保证人家是按照顺序来的吧?不然本来是:增加、修改、删除;你楞是换了顺序给执行成删除、修改、增加,不全错了么。
11 |
12 | 本来这个数据同步过来,应该最后这个数据被删除了;结果你搞错了这个顺序,最后这个数据保留下来了,数据同步就出错了。
13 |
14 | 先看看顺序会错乱的俩场景:
15 | - **RabbitMQ**:一个 queue,多个 consumer。比如,生产者向 RabbitMQ 里发送了三条数据,顺序依次是 data1/data2/data3,压入的是 RabbitMQ 的一个内存队列。有三个消费者分别从 MQ 中消费这三条数据中的一条,结果消费者2先执行完操作,把 data2 存入数据库,然后是 data1/data3。这不明显乱了。
16 |
17 | 
18 |
19 | - **Kafka**:比如说我们建了一个 topic,有三个 partition。生产者在写的时候,其实可以指定一个 key,比如说我们指定了某个订单 id 作为 key,那么这个订单相关的数据,一定会被分发到同一个 partition 中去,而且这个 partition 中的数据一定是有顺序的。
消费者从 partition 中取出来数据的时候,也一定是有顺序的。到这里,顺序还是 ok 的,没有错乱。接着,我们在消费者里可能会搞**多个线程来并发处理消息**。因为如果消费者是单线程消费处理,而处理比较耗时的话,比如处理一条消息耗时几十 ms,那么 1 秒钟只能处理几十条消息,这吞吐量太低了。而多个线程并发跑的话,顺序可能就乱掉了。
20 |
21 | 
22 |
23 | ### 解决方案
24 | #### RabbitMQ
25 | 拆分多个 queue,每个 queue 一个 consumer,就是多一些 queue 而已,确实是麻烦点;或者就一个 queue 但是对应一个 consumer,然后这个 consumer 内部用内存队列做排队,然后分发给底层不同的 worker 来处理。
26 | 
27 |
28 | #### Kafka
29 | - 一个 topic,一个 partition,一个 consumer,内部单线程消费,单线程吞吐量太低,一般不会用这个。
30 | - 写 N 个内存 queue,具有相同 key 的数据都到同一个内存 queue;然后对于 N 个线程,每个线程分别消费一个内存 queue 即可,这样就能保证顺序性。
31 |
32 | 
--------------------------------------------------------------------------------
/docs/high-concurrency/images/async-replication-data-lose-case.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/async-replication-data-lose-case.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/consistent-hashing-algorithm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/consistent-hashing-algorithm.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/database-id-sequence-step.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/database-id-sequence-step.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/database-shard-method-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/database-shard-method-1.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/database-shard-method-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/database-shard-method-2.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/database-split-horizon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/database-split-horizon.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/database-split-vertically.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/database-split-vertically.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/distributed-system-request-sequence.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/distributed-system-request-sequence.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/distributed-transaction-TCC.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/distributed-transaction-TCC.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/distributed-transaction-XA.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/distributed-transaction-XA.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/distributed-transaction-local-message-table.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/distributed-transaction-local-message-table.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/distributed-transaction-reliable-message.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/distributed-transaction-reliable-message.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/dubbo-operating-principle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/dubbo-operating-principle.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/dubbo-service-invoke-road.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/dubbo-service-invoke-road.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/dubbo-spi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/dubbo-spi.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/e-commerce-website-detail-page-architecture-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/e-commerce-website-detail-page-architecture-1.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/e-commerce-website-detail-page-architecture-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/e-commerce-website-detail-page-architecture-2.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/es-cluster-0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/es-cluster-0.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/es-cluster.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/es-cluster.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/es-index-type-mapping-document-field.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/es-index-type-mapping-document-field.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/es-search-process.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/es-search-process.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/es-write-detail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/es-write-detail.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/es-write.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/es-write.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/favicon-16x16.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/favicon-32x32.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/hash-slot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/hash-slot.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/hash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/hash.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/high-concurrency-system-design.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/high-concurrency-system-design.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/icon.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/kafka-after.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/kafka-after.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/kafka-before.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/kafka-before.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/kafka-order-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/kafka-order-01.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/kafka-order-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/kafka-order-02.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/mq-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/mq-1.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/mq-10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/mq-10.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/mq-11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/mq-11.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/mq-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/mq-2.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/mq-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/mq-3.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/mq-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/mq-4.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/mq-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/mq-5.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/mq-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/mq-6.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/mq-7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/mq-7.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/mq-8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/mq-8.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/mysql-master-slave.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/mysql-master-slave.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/rabbitmq-message-lose-solution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/rabbitmq-message-lose-solution.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/rabbitmq-message-lose.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/rabbitmq-message-lose.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/rabbitmq-order-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/rabbitmq-order-01.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/rabbitmq-order-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/rabbitmq-order-02.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/redis-caching-avalanche-solution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/redis-caching-avalanche-solution.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/redis-caching-avalanche.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/redis-caching-avalanche.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/redis-caching-penetration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/redis-caching-penetration.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/redis-cluster-split-brain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/redis-cluster-split-brain.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/redis-gossip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/redis-gossip.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/redis-junior-inconsistent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/redis-junior-inconsistent.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/redis-master-slave-replication-detail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/redis-master-slave-replication-detail.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/redis-master-slave-replication.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/redis-master-slave-replication.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/redis-master-slave.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/redis-master-slave.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/redis-redlock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/redis-redlock.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/redis-single-thread-model.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/redis-single-thread-model.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/service-invoke-road.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/service-invoke-road.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/simple-distributed-system-oa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/simple-distributed-system-oa.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/zookeeper-active-standby.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/zookeeper-active-standby.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/zookeeper-centralized-storage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/zookeeper-centralized-storage.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/zookeeper-distributed-coordination.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/zookeeper-distributed-coordination.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/zookeeper-distributed-lock-demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/zookeeper-distributed-lock-demo.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/zookeeper-distributed-lock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/zookeeper-distributed-lock.png
--------------------------------------------------------------------------------
/docs/high-concurrency/images/zookeeper-meta-data-manage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/docs/high-concurrency/images/zookeeper-meta-data-manage.png
--------------------------------------------------------------------------------
/docs/high-concurrency/mq-design.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | 如果让你写一个消息队列,该如何进行架构设计?说一下你的思路。
3 |
4 | ## 面试官心理分析
5 | 其实聊到这个问题,一般面试官要考察两块:
6 |
7 | - 你有没有对某一个消息队列做过较为深入的原理的了解,或者从整体了解把握住一个消息队列的架构原理。
8 | - 看看你的设计能力,给你一个常见的系统,就是消息队列系统,看看你能不能从全局把握一下整体架构设计,给出一些关键点出来。
9 |
10 | 说实话,问类似问题的时候,大部分人基本都会蒙,因为平时从来没有思考过类似的问题,大多数人就是平时埋头用,从来不去思考背后的一些东西。类似的问题,比如,如果让你来设计一个 Spring 框架你会怎么做?如果让你来设计一个 Dubbo 框架你会怎么做?如果让你来设计一个 MyBatis 框架你会怎么做?
11 |
12 |
13 | ## 面试题剖析
14 | 其实回答这类问题,说白了,不求你看过那技术的源码,起码你要大概知道那个技术的基本原理、核心组成部分、基本架构构成,然后参照一些开源的技术把一个系统设计出来的思路说一下就好。
15 |
16 | 比如说这个消息队列系统,我们从以下几个角度来考虑一下:
17 |
18 | - 首先这个 mq 得支持可伸缩性吧,就是需要的时候快速扩容,就可以增加吞吐量和容量,那怎么搞?设计个分布式的系统呗,参照一下 kafka 的设计理念,broker -> topic -> partition,每个 partition 放一个机器,就存一部分数据。如果现在资源不够了,简单啊,给 topic 增加 partition,然后做数据迁移,增加机器,不就可以存放更多数据,提供更高的吞吐量了?
19 |
20 | - 其次你得考虑一下这个 mq 的数据要不要落地磁盘吧?那肯定要了,落磁盘才能保证别进程挂了数据就丢了。那落磁盘的时候怎么落啊?顺序写,这样就没有磁盘随机读写的寻址开销,磁盘顺序读写的性能是很高的,这就是 kafka 的思路。
21 |
22 | - 其次你考虑一下你的 mq 的可用性啊?这个事儿,具体参考之前可用性那个环节讲解的 kafka 的高可用保障机制。多副本 -> leader & follower -> broker 挂了重新选举 leader 即可对外服务。
23 |
24 | - 能不能支持数据 0 丢失啊?可以的,参考我们之前说的那个 kafka 数据零丢失方案。
25 |
26 | mq 肯定是很复杂的,面试官问你这个问题,其实是个开放题,他就是看看你有没有从架构角度整体构思和设计的思维以及能力。确实这个问题可以刷掉一大批人,因为大部分人平时不思考这些东西。
--------------------------------------------------------------------------------
/docs/high-concurrency/mq-interview.md:
--------------------------------------------------------------------------------
1 | ## 消息队列面试场景
2 |
3 | **面试官**:你好。
4 |
5 | **候选人**:你好。
6 |
7 | (面试官在你的简历上面看到了,呦,有个亮点,你在项目里用过 `MQ`,比如说你用过 `ActiveMQ`)
8 |
9 | **面试官**:你在系统里用过消息队列吗?(面试官在随和的语气中展开了面试)
10 |
11 | **候选人**:用过的(此时感觉没啥)
12 |
13 | **面试官**:那你说一下你们在项目里是怎么用消息队列的?
14 |
15 | **候选人**:巴拉巴拉,“我们啥啥系统发送个啥啥消息到队列,别的系统来消费啥啥的。比如我们有个订单系统,订单系统每次下一个新的订单的时候,就会发送一条消息到 `ActiveMQ` 里面去,后台有个库存系统负责获取消息然后更新库存。”
16 |
17 | (部分同学在这里会进入一个误区,就是你仅仅就是知道以及回答你们是怎么用这个消息队列的,用这个消息队列来干了个什么事情?)
18 |
19 | **面试官**:那你们为什么使用消息队列啊?你的订单系统不发送消息到 `MQ`,直接订单系统调用库存系统一个接口,咔嚓一下,直接就调用成功,库存不也就更新了。
20 |
21 | **候选人**:额。。。(楞了一下,为什么?我没怎么仔细想过啊,老大让用就用了),硬着头皮胡言乱语了几句。
22 |
23 | (面试官此时听你楞了一下,然后听你胡言乱语了几句,开始心里觉得有点儿那什么了,怀疑你之前就压根儿没思考过这问题)
24 |
25 | **面试官**:那你说说用消息队列都有什么优点和缺点?
26 |
27 | (面试官此时心里想的是,你的 `MQ` 在项目里为啥要用,你没怎么考虑过,那我稍微简单点儿,我问问你消息队列你之前有没有考虑过如果用的话,优点和缺点分别是啥?)
28 |
29 | **候选人**:这个。。。(确实平时没怎么考虑过这个问题啊。。。胡言乱语了)
30 |
31 | (面试官此时心里已经更觉得你这哥儿们不行,平时都没什么思考)
32 |
33 | **面试官**:`Kafka`、`ActiveMQ`、`RabbitMQ`、`RocketMQ` 都有什么区别?
34 |
35 | (面试官问你这个问题,就是说,绕过比较虚的话题,直接看看你对各种 `MQ` 中间件是否了解,是否做过功课,是否做过调研)
36 |
37 | **候选人**:我们就用过 `ActiveMQ`,所以别的没用过。。。区别,也不太清楚。。。
38 |
39 | (面试官此时更是觉得你这哥儿们平时就是瞎用,根本就没什么思考,觉得不行)
40 |
41 | **面试官**:那你们是如何保证消息队列的高可用啊?
42 |
43 | **候选人**:这个。。。我平时就是简单走 API 调用一下,不太清楚消息队列怎么部署的。。。
44 |
45 | **面试官**:如何保证消息不被重复消费啊?如何保证消费的时候是幂等的啊?
46 |
47 | **候选人**:啥?(`MQ` 不就是写入&消费就可以了,哪来这么多问题)
48 |
49 | **面试官**:如何保证消息的可靠性传输啊?要是消息丢失了怎么办啊?
50 |
51 | **候选人**:我们没怎么丢过消息啊。。。
52 |
53 | **面试官**:那如何保证消息的顺序性?
54 |
55 | **候选人**:顺序性?什么意思?我为什么要保证消息的顺序性?它不是本来就有顺序吗?
56 |
57 | **面试官**:如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万消息持续积压几小时,说说怎么解决?
58 |
59 | **候选人**:不是,我这平时没遇到过这些问题啊,就是简单用用,知道 `MQ` 的一些功能。
60 |
61 | **面试官**:如果让你写一个消息队列,该如何进行架构设计啊?说一下你的思路。
62 |
63 | **候选人**:。。。。。我还是走吧。。。。
64 |
65 | ---
66 |
67 | 这其实是面试官的一种面试风格,就是说面试官的问题不是发散的,而是从一个小点慢慢铺开。比如说面试官可能会跟你聊聊高并发话题,就这个话题里面跟你聊聊缓存、`MQ` 等等东西,**由浅入深,一步步深挖**。
68 |
69 | 其实上面是一个非常典型的关于消息队列的技术考察过程,好的面试官一定是从你做过的某一个点切入,然后层层展开深入考察,一个接一个问,直到把这个技术点刨根问底,问到最底层。
--------------------------------------------------------------------------------
/docs/high-concurrency/mq-time-delay-and-expired-failure.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | 如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万消息持续积压几小时,说说怎么解决?
3 |
4 | ## 面试官心理分析
5 | 你看这问法,其实本质针对的场景,都是说,可能你的消费端出了问题,不消费了;或者消费的速度极其慢。接着就坑爹了,可能你的消息队列集群的磁盘都快写满了,都没人消费,这个时候怎么办?或者是这整个就积压了几个小时,你这个时候怎么办?或者是你积压的时间太长了,导致比如 RabbitMQ 设置了消息过期时间后就没了怎么办?
6 |
7 | 所以就这事儿,其实线上挺常见的,一般不出,一出就是大 case。一般常见于,举个例子,消费端每次消费之后要写 mysql,结果 mysql 挂了,消费端 hang 那儿了,不动了;或者是消费端出了个什么岔子,导致消费速度极其慢。
8 |
9 | ## 面试题剖析
10 | 关于这个事儿,我们一个一个来梳理吧,先假设一个场景,我们现在消费端出故障了,然后大量消息在 mq 里积压,现在出事故了,慌了。
11 |
12 | ### 大量消息在 mq 里积压了几个小时了还没解决
13 | 几千万条数据在 MQ 里积压了七八个小时,从下午 4 点多,积压到了晚上 11 点多。这个是我们真实遇到过的一个场景,确实是线上故障了,这个时候要不然就是修复 consumer 的问题,让它恢复消费速度,然后傻傻的等待几个小时消费完毕。这个肯定不能在面试的时候说吧。
14 |
15 | 一个消费者一秒是 1000 条,一秒 3 个消费者是 3000 条,一分钟就是 18 万条。所以如果你积压了几百万到上千万的数据,即使消费者恢复了,也需要大概 1 小时的时间才能恢复过来。
16 |
17 | 一般这个时候,只能临时紧急扩容了,具体操作步骤和思路如下:
18 | - 先修复 consumer 的问题,确保其恢复消费速度,然后将现有 consumer 都停掉。
19 | - 新建一个 topic,partition 是原来的 10 倍,临时建立好原先 10 倍的 queue 数量。
20 | - 然后写一个临时的分发数据的 consumer 程序,这个程序部署上去消费积压的数据,**消费之后不做耗时的处理**,直接均匀轮询写入临时建立好的 10 倍数量的 queue。
21 | - 接着临时征用 10 倍的机器来部署 consumer,每一批 consumer 消费一个临时 queue 的数据。这种做法相当于是临时将 queue 资源和 consumer 资源扩大 10 倍,以正常的 10 倍速度来消费数据。
22 | - 等快速消费完积压数据之后,**得恢复原先部署的架构**,**重新**用原先的 consumer 机器来消费消息。
23 |
24 | ### mq 中的消息过期失效了
25 | 假设你用的是 RabbitMQ,RabbtiMQ 是可以设置过期时间的,也就是 TTL。如果消息在 queue 中积压超过一定的时间就会被 RabbitMQ 给清理掉,这个数据就没了。那这就是第二个坑了。这就不是说数据会大量积压在 mq 里,而是**大量的数据会直接搞丢**。
26 |
27 | 这个情况下,就不是说要增加 consumer 消费积压的消息,因为实际上没啥积压,而是丢了大量的消息。我们可以采取一个方案,就是**批量重导**,这个我们之前线上也有类似的场景干过。就是大量积压的时候,我们当时就直接丢弃数据了,然后等过了高峰期以后,比如大家一起喝咖啡熬夜到晚上12点以后,用户都睡觉了。这个时候我们就开始写程序,将丢失的那批数据,写个临时程序,一点一点的查出来,然后重新灌入 mq 里面去,把白天丢的数据给他补回来。也只能是这样了。
28 |
29 | 假设 1 万个订单积压在 mq 里面,没有处理,其中 1000 个订单都丢了,你只能手动写程序把那 1000 个订单给查出来,手动发到 mq 里去再补一次。
30 |
31 | ### mq 都快写满了
32 | 如果消息积压在 mq 里,你很长时间都没有处理掉,此时导致 mq 都快写满了,咋办?这个还有别的办法吗?没有,谁让你第一个方案执行的太慢了,你临时写程序,接入数据来消费,**消费一个丢弃一个,都不要了**,快速消费掉所有的消息。然后走第二个方案,到了晚上再补数据吧。
33 |
--------------------------------------------------------------------------------
/docs/high-concurrency/mysql-read-write-separation.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | 你们有没有做 MySQL 读写分离?如何实现 MySQL 的读写分离?MySQL 主从复制原理的是啥?如何解决 MySQL 主从同步的延时问题?
3 |
4 | ## 面试官心理分析
5 | 高并发这个阶段,肯定是需要做读写分离的,啥意思?因为实际上大部分的互联网公司,一些网站,或者是 app,其实都是读多写少。所以针对这个情况,就是写一个主库,但是主库挂多个从库,然后从多个从库来读,那不就可以支撑更高的读并发压力了吗?
6 |
7 | ## 面试题剖析
8 | ### 如何实现 MySQL 的读写分离?
9 | 其实很简单,就是基于主从复制架构,简单来说,就搞一个主库,挂多个从库,然后我们就单单只是写主库,然后主库会自动把数据给同步到从库上去。
10 |
11 | ### MySQL 主从复制原理的是啥?
12 | 主库将变更写入 binlog 日志,然后从库连接到主库之后,从库有一个 IO 线程,将主库的 binlog 日志拷贝到自己本地,写入一个 relay 中继日志中。接着从库中有一个 SQL 线程会从中继日志读取 binlog,然后执行 binlog 日志中的内容,也就是在自己本地再次执行一遍 SQL,这样就可以保证自己跟主库的数据是一样的。
13 |
14 | 
15 |
16 | 这里有一个非常重要的一点,就是从库同步主库数据的过程是串行化的,也就是说主库上并行的操作,在从库上会串行执行。所以这就是一个非常重要的点了,由于从库从主库拷贝日志以及串行执行 SQL 的特点,在高并发场景下,从库的数据一定会比主库慢一些,是**有延时**的。所以经常出现,刚写入主库的数据可能是读不到的,要过几十毫秒,甚至几百毫秒才能读取到。
17 |
18 | 而且这里还有另外一个问题,就是如果主库突然宕机,然后恰好数据还没同步到从库,那么有些数据可能在从库上是没有的,有些数据可能就丢失了。
19 |
20 | 所以 MySQL 实际上在这一块有两个机制,一个是**半同步复制**,用来解决主库数据丢失问题;一个是**并行复制**,用来解决主从同步延时问题。
21 |
22 | 这个所谓**半同步复制**,也叫 `semi-sync` 复制,指的就是主库写入 binlog 日志之后,就会将**强制**此时立即将数据同步到从库,从库将日志写入自己本地的 relay log 之后,接着会返回一个 ack 给主库,主库接收到**至少一个从库**的 ack 之后才会认为写操作完成了。
23 |
24 | 所谓**并行复制**,指的是从库开启多个线程,并行读取 relay log 中不同库的日志,然后**并行重放不同库的日志**,这是库级别的并行。
25 |
26 | ### MySQL 主从同步延时问题(精华)
27 | 以前线上确实处理过因为主从同步延时问题而导致的线上的 bug,属于小型的生产事故。
28 |
29 | 是这个么场景。有个同学是这样写代码逻辑的。先插入一条数据,再把它查出来,然后更新这条数据。在生产环境高峰期,写并发达到了 2000/s,这个时候,主从复制延时大概是在小几十毫秒。线上会发现,每天总有那么一些数据,我们期望更新一些重要的数据状态,但在高峰期时候却没更新。用户跟客服反馈,而客服就会反馈给我们。
30 |
31 | 我们通过 MySQL 命令:
32 | ```sql
33 | show status
34 | ```
35 | 查看 `Seconds_Behind_Master`,可以看到从库复制主库的数据落后了几 ms。
36 |
37 | 一般来说,如果主从延迟较为严重,有以下解决方案:
38 | - 分库,将一个主库拆分为多个主库,每个主库的写并发就减少了几倍,此时主从延迟可以忽略不计。
39 | - 打开 MySQL 支持的并行复制,多个库并行复制。如果说某个库的写入并发就是特别高,单库写并发达到了 2000/s,并行复制还是没意义。
40 | - 重写代码,写代码的同学,要慎重,插入数据时立马查询可能查不到。
41 | - 如果确实是存在必须先插入,立马要求就查询到,然后立马就要反过来执行一些操作,对这个查询**设置直连主库**。**不推荐**这种方法,你要是这么搞,读写分离的意义就丧失了。
42 |
--------------------------------------------------------------------------------
/docs/high-concurrency/redis-caching-avalanche-and-caching-penetration.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | 了解什么是 redis 的雪崩、穿透和击穿?redis 崩溃之后会怎么样?系统该如何应对这种情况?如何处理 redis 的穿透?
3 |
4 | ## 面试官心理分析
5 | 其实这是问到缓存必问的,因为缓存雪崩和穿透,是缓存最大的两个问题,要么不出现,一旦出现就是致命性的问题,所以面试官一定会问你。
6 |
7 | ## 面试题剖析
8 | ### 缓存雪崩
9 | 对于系统 A,假设每天高峰期每秒 5000 个请求,本来缓存在高峰期可以扛住每秒 4000 个请求,但是缓存机器意外发生了全盘宕机。缓存挂了,此时 1 秒 5000 个请求全部落数据库,数据库必然扛不住,它会报一下警,然后就挂了。此时,如果没有采用什么特别的方案来处理这个故障,DBA 很着急,重启数据库,但是数据库立马又被新的流量给打死了。
10 |
11 | 这就是缓存雪崩。
12 |
13 | 
14 |
15 | 大约在 3 年前,国内比较知名的一个互联网公司,曾因为缓存事故,导致雪崩,后台系统全部崩溃,事故从当天下午持续到晚上凌晨 3~4 点,公司损失了几千万。
16 |
17 | 缓存雪崩的事前事中事后的解决方案如下。
18 | - 事前:redis 高可用,主从+哨兵,redis cluster,避免全盘崩溃。
19 | - 事中:本地 ehcache 缓存 + hystrix 限流&降级,避免 MySQL 被打死。
20 | - 事后:redis 持久化,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据。
21 |
22 | 
23 |
24 | 用户发送一个请求,系统 A 收到请求后,先查本地 ehcache 缓存,如果没查到再查 redis。如果 ehcache 和 redis 都没有,再查数据库,将数据库中的结果,写入 ehcache 和 redis 中。
25 |
26 | 限流组件,可以设置每秒的请求,有多少能通过组件,剩余的未通过的请求,怎么办?**走降级**!可以返回一些默认的值,或者友情提示,或者空白的值。
27 |
28 | 好处:
29 | - 数据库绝对不会死,限流组件确保了每秒只有多少个请求能通过。
30 | - 只要数据库不死,就是说,对用户来说,2/5 的请求都是可以被处理的。
31 | - 只要有 2/5 的请求可以被处理,就意味着你的系统没死,对用户来说,可能就是点击几次刷不出来页面,但是多点几次,就可以刷出来一次。
32 |
33 | ### 缓存穿透
34 | 对于系统A,假设一秒 5000 个请求,结果其中 4000 个请求是黑客发出的恶意攻击。
35 |
36 | 黑客发出的那 4000 个攻击,缓存中查不到,每次你去数据库里查,也查不到。
37 |
38 | 举个栗子。数据库 id 是从 1 开始的,结果黑客发过来的请求 id 全部都是负数。这样的话,缓存中不会有,请求每次都“**视缓存于无物**”,直接查询数据库。这种恶意攻击场景的缓存穿透就会直接把数据库给打死。
39 |
40 | 
41 |
42 | 解决方式很简单,每次系统 A 从数据库中只要没查到,就写一个空值到缓存里去,比如 `set -999 UNKNOWN`。然后设置一个过期时间,这样的话,下次有相同的 key 来访问的时候,在缓存失效之前,都可以直接从缓存中取数据。
43 |
44 | ### 缓存击穿
45 | 缓存击穿,就是说某个 key 非常热点,访问非常频繁,处于集中式高并发访问的情况,当这个 key 在失效的瞬间,大量的请求就击穿了缓存,直接请求数据库,就像是在一道屏障上凿开了一个洞。
46 |
47 | 解决方式也很简单,可以将热点数据设置为永远不过期;或者基于 redis or zookeeper 实现互斥锁,等待第一个请求构建完缓存之后,再释放锁,进而其它请求才能通过该 key 访问数据。
--------------------------------------------------------------------------------
/docs/high-concurrency/redis-cas.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | redis 的并发竞争问题是什么?如何解决这个问题?了解 redis 事务的 CAS 方案吗?
3 |
4 | ## 面试官心理分析
5 | 这个也是线上非常常见的一个问题,就是**多客户端同时并发写**一个 key,可能本来应该先到的数据后到了,导致数据版本错了;或者是多客户端同时获取一个 key,修改值之后再写回去,只要顺序错了,数据就错了。
6 |
7 | 而且 redis 自己就有天然解决这个问题的 CAS 类的乐观锁方案。
8 |
9 | ## 面试题剖析
10 | 某个时刻,多个系统实例都去更新某个 key。可以基于 zookeeper 实现分布式锁。每个系统通过 zookeeper 获取分布式锁,确保同一时间,只能有一个系统实例在操作某个 key,别人都不允许读和写。
11 |
12 | 
13 |
14 | 你要写入缓存的数据,都是从 mysql 里查出来的,都得写入 mysql 中,写入 mysql 中的时候必须保存一个时间戳,从 mysql 查出来的时候,时间戳也查出来。
15 |
16 | 每次要**写之前,先判断**一下当前这个 value 的时间戳是否比缓存里的 value 的时间戳要新。如果是的话,那么可以写,否则,就不能用旧的数据覆盖新的数据。
--------------------------------------------------------------------------------
/docs/high-concurrency/redis-data-types.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | redis 都有哪些数据类型?分别在哪些场景下使用比较合适?
3 |
4 | ## 面试官心理分析
5 | 除非是面试官感觉看你简历,是工作 3 年以内的比较初级的同学,可能对技术没有很深入的研究,面试官才会问这类问题。否则,在宝贵的面试时间里,面试官实在不想多问。
6 |
7 | 其实问这个问题,主要有两个原因:
8 | - 看看你到底有没有全面的了解 redis 有哪些功能,一般怎么来用,啥场景用什么,就怕你别就会最简单的 KV 操作;
9 | - 看看你在实际项目里都怎么玩儿过 redis。
10 |
11 | 要是你回答的不好,没说出几种数据类型,也没说什么场景,你完了,面试官对你印象肯定不好,觉得你平时就是做个简单的 set 和 get。
12 |
13 | ## 面试题剖析
14 | redis 主要有以下几种数据类型:
15 | - string
16 | - hash
17 | - list
18 | - set
19 | - sorted set
20 |
21 | ### string
22 | 这是最简单的类型,就是普通的 set 和 get,做简单的 KV 缓存。
23 | ```bash
24 | set college szu
25 | ```
26 |
27 | ### hash
28 | 这个是类似 map 的一种结构,这个一般就是可以将结构化的数据,比如一个对象(前提是**这个对象没嵌套其他的对象**)给缓存在 redis 里,然后每次读写缓存的时候,可以就操作 hash 里的**某个字段**。
29 |
30 | ```bash
31 | hset person name bingo
32 | hset person age 20
33 | hset person id 1
34 | hget person name
35 | ```
36 |
37 | ```json
38 | person = {
39 | "name": "bingo",
40 | "age": 20,
41 | "id": 1
42 | }
43 | ```
44 |
45 | ### list
46 | list 是有序列表,这个可以玩儿出很多花样。
47 |
48 | 比如可以通过 list 存储一些列表型的数据结构,类似粉丝列表、文章的评论列表之类的东西。
49 |
50 | 比如可以通过 lrange 命令,读取某个闭区间内的元素,可以基于 list 实现分页查询,这个是很棒的一个功能,基于 redis 实现简单的高性能分页,可以做类似微博那种下拉不断分页的东西,性能高,就一页一页走。
51 | ```bash
52 | # 0开始位置,-1结束位置,结束位置为-1时,表示列表的最后一个位置,即查看所有。
53 | lrange mylist 0 -1
54 | ```
55 |
56 | 比如可以搞个简单的消息队列,从 list 头怼进去,从 list 尾巴那里弄出来。
57 | ```bash
58 | lpush mylist 1
59 | lpush mylist 2
60 | lpush mylist 3 4 5
61 |
62 | # 1
63 | rpop mylist
64 | ```
65 |
66 | ### set
67 | set 是无序集合,自动去重。
68 |
69 | 直接基于 set 将系统里需要去重的数据扔进去,自动就给去重了,如果你需要对一些数据进行快速的全局去重,你当然也可以基于 jvm 内存里的 HashSet 进行去重,但是如果你的某个系统部署在多台机器上呢?得基于 redis 进行全局的 set 去重。
70 |
71 | 可以基于 set 玩儿交集、并集、差集的操作,比如交集吧,可以把两个人的粉丝列表整一个交集,看看俩人的共同好友是谁?对吧。
72 |
73 | 把两个大 V 的粉丝都放在两个 set 中,对两个 set 做交集。
74 | ```bash
75 | #-------操作一个set-------
76 | # 添加元素
77 | sadd mySet 1
78 |
79 | # 查看全部元素
80 | smembers mySet
81 |
82 | # 判断是否包含某个值
83 | sismember mySet 3
84 |
85 | # 删除某个/些元素
86 | srem mySet 1
87 | srem mySet 2 4
88 |
89 | # 查看元素个数
90 | scard mySet
91 |
92 | # 随机删除一个元素
93 | spop mySet
94 |
95 | #-------操作多个set-------
96 | # 将一个set的元素移动到另外一个set
97 | smove yourSet mySet 2
98 |
99 | # 求两set的交集
100 | sinter yourSet mySet
101 |
102 | # 求两set的并集
103 | sunion yourSet mySet
104 |
105 | # 求在yourSet中而不在mySet中的元素
106 | sdiff yourSet mySet
107 | ```
108 |
109 | ### sorted set
110 | sorted set 是排序的 set,去重但可以排序,写进去的时候给一个分数,自动根据分数排序。
111 | ```bash
112 | zadd board 85 zhangsan
113 | zadd board 72 lisi
114 | zadd board 96 wangwu
115 | zadd board 63 zhaoliu
116 |
117 | # 获取排名前三的用户(默认是升序,所以需要 rev 改为降序)
118 | zrevrange board 0 3
119 |
120 | # 获取某用户的排名
121 | zrank board zhaoliu
122 | ```
--------------------------------------------------------------------------------
/docs/high-concurrency/redis-expiration-policies-and-lru.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | redis 的过期策略都有哪些?内存淘汰机制都有哪些?手写一下 LRU 代码实现?
3 |
4 | ## 面试官心理分析
5 | 如果你连这个问题都不知道,上来就懵了,回答不出来,那线上你写代码的时候,想当然的认为写进 redis 的数据就一定会存在,后面导致系统各种 bug,谁来负责?
6 |
7 | 常见的有两个问题:
8 | - 往 redis 写入的数据怎么没了?
9 |
10 | 可能有同学会遇到,在生产环境的 redis 经常会丢掉一些数据,写进去了,过一会儿可能就没了。我的天,同学,你问这个问题就说明 redis 你就没用对啊。redis 是缓存,你给当存储了是吧?
11 |
12 | 啥叫缓存?用内存当缓存。内存是无限的吗,内存是很宝贵而且是有限的,磁盘是廉价而且是大量的。可能一台机器就几十个 G 的内存,但是可以有几个 T 的硬盘空间。redis 主要是基于内存来进行高性能、高并发的读写操作的。
13 |
14 | 那既然内存是有限的,比如 redis 就只能用 10G,你要是往里面写了 20G 的数据,会咋办?当然会干掉 10G 的数据,然后就保留 10G 的数据了。那干掉哪些数据?保留哪些数据?当然是干掉不常用的数据,保留常用的数据了。
15 |
16 | - 数据明明过期了,怎么还占用着内存?
17 |
18 | 这是由 redis 的过期策略来决定。
19 |
20 | ## 面试题剖析
21 | ### redis 过期策略
22 | redis 过期策略是:**定期删除+惰性删除**。
23 |
24 | 所谓**定期删除**,指的是 redis 默认是每隔 100ms 就随机抽取一些设置了过期时间的 key,检查其是否过期,如果过期就删除。
25 |
26 | 假设 redis 里放了 10w 个 key,都设置了过期时间,你每隔几百毫秒,就检查 10w 个 key,那 redis 基本上就死了,cpu 负载会很高的,消耗在你的检查过期 key 上了。注意,这里可不是每隔 100ms 就遍历所有的设置过期时间的 key,那样就是一场性能上的**灾难**。实际上 redis 是每隔 100ms **随机抽取**一些 key 来检查和删除的。
27 |
28 | 但是问题是,定期删除可能会导致很多过期 key 到了时间并没有被删除掉,那咋整呢?所以就是惰性删除了。这就是说,在你获取某个 key 的时候,redis 会检查一下 ,这个 key 如果设置了过期时间那么是否过期了?如果过期了此时就会删除,不会给你返回任何东西。
29 |
30 | > 获取 key 的时候,如果此时 key 已经过期,就删除,不会返回任何东西。
31 |
32 | 但是实际上这还是有问题的,如果定期删除漏掉了很多过期 key,然后你也没及时去查,也就没走惰性删除,此时会怎么样?如果大量过期 key 堆积在内存里,导致 redis 内存块耗尽了,咋整?
33 |
34 | 答案是:**走内存淘汰机制**。
35 |
36 | ### 内存淘汰机制
37 | redis 内存淘汰机制有以下几个:
38 | - noeviction: 当内存不足以容纳新写入数据时,新写入操作会报错,这个一般没人用吧,实在是太恶心了。
39 | - **allkeys-lru**:当内存不足以容纳新写入数据时,在**键空间**中,移除最近最少使用的 key(这个是**最常用**的)。
40 | - allkeys-random:当内存不足以容纳新写入数据时,在**键空间**中,随机移除某个 key,这个一般没人用吧,为啥要随机,肯定是把最近最少使用的 key 给干掉啊。
41 | - volatile-lru:当内存不足以容纳新写入数据时,在**设置了过期时间的键空间**中,移除最近最少使用的 key(这个一般不太合适)。
42 | - volatile-random:当内存不足以容纳新写入数据时,在**设置了过期时间的键空间**中,**随机移除**某个 key。
43 | - volatile-ttl:当内存不足以容纳新写入数据时,在**设置了过期时间的键空间**中,有**更早过期时间**的 key 优先移除。
44 |
45 | ### 手写一个 LRU 算法
46 | 你可以现场手写最原始的 LRU 算法,那个代码量太大了,似乎不太现实。
47 |
48 | 不求自己纯手工从底层开始打造出自己的 LRU,但是起码要知道如何利用已有的 JDK 数据结构实现一个 Java 版的 LRU。
49 |
50 | ```java
51 | class LRUCache extends LinkedHashMap {
52 | private final int CACHE_SIZE;
53 |
54 | /**
55 | * 传递进来最多能缓存多少数据
56 | *
57 | * @param cacheSize 缓存大小
58 | */
59 | public LRUCache(int cacheSize) {
60 | // true 表示让 linkedHashMap 按照访问顺序来进行排序,最近访问的放在头部,最老访问的放在尾部。
61 | super((int) Math.ceil(cacheSize / 0.75) + 1, 0.75f, true);
62 | CACHE_SIZE = cacheSize;
63 | }
64 |
65 | @Override
66 | protected boolean removeEldestEntry(Map.Entry eldest) {
67 | // 当 map中的数据量大于指定的缓存个数的时候,就自动删除最老的数据。
68 | return size() > CACHE_SIZE;
69 | }
70 | }
71 | ```
--------------------------------------------------------------------------------
/docs/high-concurrency/redis-persistence.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | redis 的持久化有哪几种方式?不同的持久化机制都有什么优缺点?持久化机制具体底层是如何实现的?
3 |
4 | ## 面试官心理分析
5 | redis 如果仅仅只是将数据缓存在内存里面,如果 redis 宕机了再重启,内存里的数据就全部都弄丢了啊。你必须得用 redis 的持久化机制,将数据写入内存的同时,异步的慢慢的将数据写入磁盘文件里,进行持久化。
6 |
7 | 如果 redis 宕机重启,自动从磁盘上加载之前持久化的一些数据就可以了,也许会丢失少许数据,但是至少不会将所有数据都弄丢。
8 |
9 | 这个其实一样,针对的都是 redis 的生产环境可能遇到的一些问题,就是 redis 要是挂了再重启,内存里的数据不就全丢了?能不能重启的时候把数据给恢复了?
10 |
11 | ## 面试题剖析
12 | 持久化主要是做灾难恢复、数据恢复,也可以归类到高可用的一个环节中去,比如你 redis 整个挂了,然后 redis 就不可用了,你要做的事情就是让 redis 变得可用,尽快变得可用。
13 |
14 | 重启 redis,尽快让它对外提供服务,如果没做数据备份,这时候 redis 启动了,也不可用啊,数据都没了。
15 |
16 | 很可能说,大量的请求过来,缓存全部无法命中,在 redis 里根本找不到数据,这个时候就死定了,出现**缓存雪崩**问题。所有请求没有在 redis 命中,就会去 mysql 数据库这种数据源头中去找,一下子 mysql 承接高并发,然后就挂了...
17 |
18 | 如果你把 redis 持久化做好,备份和恢复方案做到企业级的程度,那么即使你的 redis 故障了,也可以通过备份数据,快速恢复,一旦恢复立即对外提供服务。
19 |
20 | ### redis 持久化的两种方式
21 | - RDB:RDB 持久化机制,是对 redis 中的数据执行**周期性**的持久化。
22 | - AOF:AOF 机制对每条写入命令作为日志,以 `append-only` 的模式写入一个日志文件中,在 redis 重启的时候,可以通过**回放** AOF 日志中的写入指令来重新构建整个数据集。
23 |
24 | 通过 RDB 或 AOF,都可以将 redis 内存中的数据给持久化到磁盘上面来,然后可以将这些数据备份到别的地方去,比如说阿里云等云服务。
25 |
26 | 如果 redis 挂了,服务器上的内存和磁盘上的数据都丢了,可以从云服务上拷贝回来之前的数据,放到指定的目录中,然后重新启动 redis,redis 就会自动根据持久化数据文件中的数据,去恢复内存中的数据,继续对外提供服务。
27 |
28 | 如果同时使用 RDB 和 AOF 两种持久化机制,那么在 redis 重启的时候,会使用 **AOF** 来重新构建数据,因为 AOF 中的**数据更加完整**。
29 |
30 | #### RDB 优缺点
31 | - RDB 会生成多个数据文件,每个数据文件都代表了某一个时刻中 redis 的数据,这种多个数据文件的方式,**非常适合做冷备**,可以将这种完整的数据文件发送到一些远程的安全存储上去,比如说 Amazon 的 S3 云服务上去,在国内可以是阿里云的 ODPS 分布式存储上,以预定好的备份策略来定期备份 redis 中的数据。
32 | - RDB 对 redis 对外提供的读写服务,影响非常小,可以让 redis **保持高性能**,因为 redis 主进程只需要 fork 一个子进程,让子进程执行磁盘 IO 操作来进行 RDB 持久化即可。
33 | - 相对于 AOF 持久化机制来说,直接基于 RDB 数据文件来重启和恢复 redis 进程,更加快速。
34 |
35 | - 如果想要在 redis 故障时,尽可能少的丢失数据,那么 RDB 没有 AOF 好。一般来说,RDB 数据快照文件,都是每隔 5 分钟,或者更长时间生成一次,这个时候就得接受一旦 redis 进程宕机,那么会丢失最近 5 分钟的数据。
36 | - RDB 每次在 fork 子进程来执行 RDB 快照数据文件生成的时候,如果数据文件特别大,可能会导致对客户端提供的服务暂停数毫秒,或者甚至数秒。
37 |
38 | #### AOF 优缺点
39 | - AOF 可以更好的保护数据不丢失,一般 AOF 会每隔 1 秒,通过一个后台线程执行一次`fsync`操作,最多丢失 1 秒钟的数据。
40 | - AOF 日志文件以 `append-only` 模式写入,所以没有任何磁盘寻址的开销,写入性能非常高,而且文件不容易破损,即使文件尾部破损,也很容易修复。
41 | - AOF 日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。因为在 `rewrite` log 的时候,会对其中的指令进行压缩,创建出一份需要恢复数据的最小日志出来。在创建新日志文件的时候,老的日志文件还是照常写入。当新的 merge 后的日志文件 ready 的时候,再交换新老日志文件即可。
42 | - AOF 日志文件的命令通过非常可读的方式进行记录,这个特性非常**适合做灾难性的误删除的紧急恢复**。比如某人不小心用 `flushall` 命令清空了所有数据,只要这个时候后台 `rewrite` 还没有发生,那么就可以立即拷贝 AOF 文件,将最后一条 `flushall` 命令给删了,然后再将该 `AOF` 文件放回去,就可以通过恢复机制,自动恢复所有数据。
43 | - 对于同一份数据来说,AOF 日志文件通常比 RDB 数据快照文件更大。
44 | - AOF 开启后,支持的写 QPS 会比 RDB 支持的写 QPS 低,因为 AOF 一般会配置成每秒 `fsync` 一次日志文件,当然,每秒一次 `fsync`,性能也还是很高的。(如果实时写入,那么 QPS 会大降,redis 性能会大大降低)
45 | - 以前 AOF 发生过 bug,就是通过 AOF 记录的日志,进行数据恢复的时候,没有恢复一模一样的数据出来。所以说,类似 AOF 这种较为复杂的基于命令日志 / merge / 回放的方式,比基于 RDB 每次持久化一份完整的数据快照文件的方式,更加脆弱一些,容易有 bug。不过 AOF 就是为了避免 rewrite 过程导致的 bug,因此每次 rewrite 并不是基于旧的指令日志进行 merge 的,而是**基于当时内存中的数据进行指令的重新构建**,这样健壮性会好很多。
46 |
47 | ### RDB 和 AOF 到底该如何选择
48 | - 不要仅仅使用 RDB,因为那样会导致你丢失很多数据;
49 | - 也不要仅仅使用 AOF,因为那样有两个问题:第一,你通过 AOF 做冷备,没有 RDB 做冷备来的恢复速度更快;第二,RDB 每次简单粗暴生成数据快照,更加健壮,可以避免 AOF 这种复杂的备份和恢复机制的 bug;
50 | - redis 支持同时开启开启两种持久化方式,我们可以综合使用 AOF 和 RDB 两种持久化机制,用 AOF 来保证数据不丢失,作为数据恢复的第一选择; 用 RDB 来做不同程度的冷备,在 AOF 文件都丢失或损坏不可用的时候,还可以使用 RDB 来进行快速的数据恢复。
51 |
--------------------------------------------------------------------------------
/docs/high-concurrency/redis-production-environment.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | 生产环境中的 redis 是怎么部署的?
3 |
4 | ## 面试官心理分析
5 | 看看你了解不了解你们公司的 redis 生产集群的部署架构,如果你不了解,那么确实你就很失职了,你的 redis 是主从架构?集群架构?用了哪种集群方案?有没有做高可用保证?有没有开启持久化机制确保可以进行数据恢复?线上 redis 给几个 G 的内存?设置了哪些参数?压测后你们 redis 集群承载多少 QPS?
6 |
7 | 兄弟,这些你必须是门儿清的,否则你确实是没好好思考过。
8 |
9 | ## 面试题剖析
10 | redis cluster,10 台机器,5 台机器部署了 redis 主实例,另外 5 台机器部署了 redis 的从实例,每个主实例挂了一个从实例,5 个节点对外提供读写服务,每个节点的读写高峰qps可能可以达到每秒 5 万,5 台机器最多是 25 万读写请求/s。
11 |
12 | 机器是什么配置?32G 内存+ 8 核 CPU + 1T 磁盘,但是分配给 redis 进程的是10g内存,一般线上生产环境,redis 的内存尽量不要超过 10g,超过 10g 可能会有问题。
13 |
14 | 5 台机器对外提供读写,一共有 50g 内存。
15 |
16 | 因为每个主实例都挂了一个从实例,所以是高可用的,任何一个主实例宕机,都会自动故障迁移,redis 从实例会自动变成主实例继续提供读写服务。
17 |
18 | 你往内存里写的是什么数据?每条数据的大小是多少?商品数据,每条数据是 10kb。100 条数据是 1mb,10 万条数据是 1g。常驻内存的是 200 万条商品数据,占用内存是 20g,仅仅不到总内存的 50%。目前高峰期每秒就是 3500 左右的请求量。
19 |
20 | 其实大型的公司,会有基础架构的 team 负责缓存集群的运维。
--------------------------------------------------------------------------------
/docs/high-concurrency/redis-single-thread-model.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | redis 和 memcached 有什么区别?redis 的线程模型是什么?为什么 redis 单线程却能支撑高并发?
3 |
4 | ## 面试官心理分析
5 | 这个是问 redis 的时候,最基本的问题吧,redis 最基本的一个内部原理和特点,就是 redis 实际上是个**单线程工作模型**,你要是这个都不知道,那后面玩儿 redis 的时候,出了问题岂不是什么都不知道?
6 |
7 | 还有可能面试官会问问你 redis 和 memcached 的区别,但是 memcached 是早些年各大互联网公司常用的缓存方案,但是现在近几年基本都是 redis,没什么公司用 memcached 了。
8 |
9 | ## 面试题剖析
10 |
11 | ### redis 和 memcached 有啥区别?
12 |
13 | #### redis 支持复杂的数据结构
14 | redis 相比 memcached 来说,拥有[更多的数据结构](/docs/high-concurrency/redis-data-types.md),能支持更丰富的数据操作。如果需要缓存能够支持更复杂的结构和操作, redis 会是不错的选择。
15 |
16 | #### redis 原生支持集群模式
17 | 在 redis3.x 版本中,便能支持 cluster 模式,而 memcached 没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据。
18 |
19 | #### 性能对比
20 | 由于 redis 只使用**单核**,而 memcached 可以使用**多核**,所以平均每一个核上 redis 在存储小数据时比 memcached 性能更高。而在 100k 以上的数据中,memcached 性能要高于 redis。虽然 redis 最近也在存储大数据的性能上进行优化,但是比起 memcached,还是稍有逊色。
21 |
22 | ### redis 的线程模型
23 | redis 内部使用文件事件处理器 `file event handler`,这个文件事件处理器是单线程的,所以 redis 才叫做单线程的模型。它采用 IO 多路复用机制同时监听多个 socket,将产生事件的 socket 压入内存队列中,事件分派器根据 socket 上的事件类型来选择对应的事件处理器进行处理。
24 |
25 | 文件事件处理器的结构包含 4 个部分:
26 |
27 | - 多个 socket
28 | - IO 多路复用程序
29 | - 文件事件分派器
30 | - 事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)
31 |
32 | 多个 socket 可能会并发产生不同的操作,每个操作对应不同的文件事件,但是 IO 多路复用程序会监听多个 socket,会将产生事件的 socket 放入队列中排队,事件分派器每次从队列中取出一个 socket,根据 socket 的事件类型交给对应的事件处理器进行处理。
33 |
34 | 来看客户端与 redis 的一次通信过程:
35 |
36 | 
37 |
38 | 要明白,通信是通过 socket 来完成的,不懂的同学可以先去看一看 socket 网络编程。
39 |
40 | 首先,redis 服务端进程初始化的时候,会将 server socket 的 `AE_READABLE` 事件与连接应答处理器关联。
41 |
42 | 客户端 socket01 向 redis 进程的 server socket 请求建立连接,此时 server socket 会产生一个 `AE_READABLE` 事件,IO 多路复用程序监听到 server socket 产生的事件后,将该 socket 压入队列中。文件事件分派器从队列中获取 socket,交给**连接应答处理器**。连接应答处理器会创建一个能与客户端通信的 socket01,并将该 socket01 的 `AE_READABLE` 事件与命令请求处理器关联。
43 |
44 | 假设此时客户端发送了一个 `set key value` 请求,此时 redis 中的 socket01 会产生 `AE_READABLE` 事件,IO 多路复用程序将 socket01 压入队列,此时事件分派器从队列中获取到 socket01 产生的 `AE_READABLE` 事件,由于前面 socket01 的 `AE_READABLE` 事件已经与命令请求处理器关联,因此事件分派器将事件交给命令请求处理器来处理。命令请求处理器读取 socket01 的 `key value` 并在自己内存中完成 `key value` 的设置。操作完成后,它会将 socket01 的 `AE_WRITABLE` 事件与命令回复处理器关联。
45 |
46 | 如果此时客户端准备好接收返回结果了,那么 redis 中的 socket01 会产生一个 `AE_WRITABLE` 事件,同样压入队列中,事件分派器找到相关联的命令回复处理器,由命令回复处理器对 socket01 输入本次操作的一个结果,比如 `ok`,之后解除 socket01 的 `AE_WRITABLE` 事件与命令回复处理器的关联。
47 |
48 | 这样便完成了一次通信。关于 Redis 的一次通信过程,推荐读者阅读《[Redis 设计与实现——黄健宏](https://github.com/doocs/technical-books#database)》进行系统学习。
49 |
50 | ### 为啥 redis 单线程模型也能效率这么高?
51 | - 纯内存操作。
52 | - 核心是基于非阻塞的 IO 多路复用机制。
53 | - C 语言实现,一般来说,C 语言实现的程序“距离”操作系统更近,执行速度相对会更快。
54 | - 单线程反而避免了多线程的频繁上下文切换问题,预防了多线程可能产生的竞争问题。
55 |
--------------------------------------------------------------------------------
/docs/high-concurrency/why-cache.md:
--------------------------------------------------------------------------------
1 | ## 面试题
2 | 项目中缓存是如何使用的?为什么要用缓存?缓存使用不当会造成什么后果?
3 |
4 | ## 面试官心理分析
5 | 这个问题,互联网公司必问,要是一个人连缓存都不太清楚,那确实比较尴尬。
6 |
7 | 只要问到缓存,上来第一个问题,肯定是先问问你项目哪里用了缓存?为啥要用?不用行不行?如果用了以后可能会有什么不良的后果?
8 |
9 | 这就是看看你对缓存这个东西背后有没有思考,如果你就是傻乎乎的瞎用,没法给面试官一个合理的解答,那面试官对你印象肯定不太好,觉得你平时思考太少,就知道干活儿。
10 |
11 |
12 | ## 面试题剖析
13 | ### 项目中缓存是如何使用的?
14 | 这个,需要结合自己项目的业务来。
15 |
16 | ### 为什么要用缓存?
17 | 用缓存,主要有两个用途:**高性能**、**高并发**。
18 |
19 | #### 高性能
20 | 假设这么个场景,你有个操作,一个请求过来,吭哧吭哧你各种乱七八糟操作 mysql,半天查出来一个结果,耗时 600ms。但是这个结果可能接下来几个小时都不会变了,或者变了也可以不用立即反馈给用户。那么此时咋办?
21 |
22 | 缓存啊,折腾 600ms 查出来的结果,扔缓存里,一个 key 对应一个 value,下次再有人查,别走 mysql 折腾 600ms 了,直接从缓存里,通过一个 key 查出来一个 value,2ms 搞定。性能提升 300 倍。
23 |
24 | 就是说对于一些需要复杂操作耗时查出来的结果,且确定后面不怎么变化,但是有很多读请求,那么直接将查询出来的结果放在缓存中,后面直接读缓存就好。
25 |
26 | #### 高并发
27 | mysql 这么重的数据库,压根儿设计不是让你玩儿高并发的,虽然也可以玩儿,但是天然支持不好。mysql 单机支撑到 `2000QPS` 也开始容易报警了。
28 |
29 | 所以要是你有个系统,高峰期一秒钟过来的请求有 1万,那一个 mysql 单机绝对会死掉。你这个时候就只能上缓存,把很多数据放缓存,别放 mysql。缓存功能简单,说白了就是 `key-value` 式操作,单机支撑的并发量轻松一秒几万十几万,支撑高并发 so easy。单机承载并发量是 mysql 单机的几十倍。
30 |
31 | > 缓存是走内存的,内存天然就支撑高并发。
32 |
33 | ### 用了缓存之后会有什么不良后果?
34 | 常见的缓存问题有以下几个:
35 | - [缓存与数据库双写不一致](/docs/high-concurrency/redis-consistence.md)
36 | - [缓存雪崩、缓存穿透](/docs/high-concurrency/redis-caching-avalanche-and-caching-penetration.md)
37 | - [缓存并发竞争](/docs/high-concurrency/redis-cas.md)
38 |
39 | 后面再详细说明。
--------------------------------------------------------------------------------
/images/PreferFunctionalStaffOrganization.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/PreferFunctionalStaffOrganization.png
--------------------------------------------------------------------------------
/images/async-replication-data-lose-case.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/async-replication-data-lose-case.png
--------------------------------------------------------------------------------
/images/basic-pipeline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/basic-pipeline.png
--------------------------------------------------------------------------------
/images/bulkhead-partition.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/bulkhead-partition.jpg
--------------------------------------------------------------------------------
/images/consistent-hashing-algorithm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/consistent-hashing-algorithm.png
--------------------------------------------------------------------------------
/images/conways-law.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/conways-law.png
--------------------------------------------------------------------------------
/images/database-id-sequence-step.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/database-id-sequence-step.png
--------------------------------------------------------------------------------
/images/database-shard-method-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/database-shard-method-1.png
--------------------------------------------------------------------------------
/images/database-shard-method-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/database-shard-method-2.png
--------------------------------------------------------------------------------
/images/database-split-horizon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/database-split-horizon.png
--------------------------------------------------------------------------------
/images/database-split-vertically.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/database-split-vertically.png
--------------------------------------------------------------------------------
/images/decentralised-data.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/decentralised-data.png
--------------------------------------------------------------------------------
/images/distributed-system-request-sequence.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/distributed-system-request-sequence.png
--------------------------------------------------------------------------------
/images/distributed-transaction-TCC.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/distributed-transaction-TCC.png
--------------------------------------------------------------------------------
/images/distributed-transaction-XA.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/distributed-transaction-XA.png
--------------------------------------------------------------------------------
/images/distributed-transaction-local-message-table.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/distributed-transaction-local-message-table.png
--------------------------------------------------------------------------------
/images/distributed-transaction-reliable-message.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/distributed-transaction-reliable-message.png
--------------------------------------------------------------------------------
/images/dubbo-keep-connection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/dubbo-keep-connection.png
--------------------------------------------------------------------------------
/images/dubbo-not-keep-connection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/dubbo-not-keep-connection.png
--------------------------------------------------------------------------------
/images/dubbo-operating-principle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/dubbo-operating-principle.png
--------------------------------------------------------------------------------
/images/dubbo-service-invoke-road.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/dubbo-service-invoke-road.png
--------------------------------------------------------------------------------
/images/dubbo-spi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/dubbo-spi.png
--------------------------------------------------------------------------------
/images/e-commerce-website-detail-page-architecture-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/e-commerce-website-detail-page-architecture-1.png
--------------------------------------------------------------------------------
/images/e-commerce-website-detail-page-architecture-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/e-commerce-website-detail-page-architecture-2.png
--------------------------------------------------------------------------------
/images/es-cluster-0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/es-cluster-0.png
--------------------------------------------------------------------------------
/images/es-cluster.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/es-cluster.png
--------------------------------------------------------------------------------
/images/es-index-type-mapping-document-field.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/es-index-type-mapping-document-field.png
--------------------------------------------------------------------------------
/images/es-search-process.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/es-search-process.png
--------------------------------------------------------------------------------
/images/es-write-detail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/es-write-detail.png
--------------------------------------------------------------------------------
/images/es-write.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/es-write.png
--------------------------------------------------------------------------------
/images/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/favicon-16x16.png
--------------------------------------------------------------------------------
/images/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/favicon-32x32.png
--------------------------------------------------------------------------------
/images/get-up-and-study.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/get-up-and-study.png
--------------------------------------------------------------------------------
/images/hash-slot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/hash-slot.png
--------------------------------------------------------------------------------
/images/hash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/hash.png
--------------------------------------------------------------------------------
/images/high-concurrency-system-design.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/high-concurrency-system-design.png
--------------------------------------------------------------------------------
/images/hystrix-process.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/hystrix-process.png
--------------------------------------------------------------------------------
/images/hystrix-request-cache.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/hystrix-request-cache.png
--------------------------------------------------------------------------------
/images/hystrix-semphore-thread-pool.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/hystrix-semphore-thread-pool.png
--------------------------------------------------------------------------------
/images/hystrix-semphore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/hystrix-semphore.png
--------------------------------------------------------------------------------
/images/hystrix-thread-pool-isolation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/hystrix-thread-pool-isolation.png
--------------------------------------------------------------------------------
/images/hystrix-thread-pool-queue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/hystrix-thread-pool-queue.png
--------------------------------------------------------------------------------
/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/icon.png
--------------------------------------------------------------------------------
/images/kafka-after.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/kafka-after.png
--------------------------------------------------------------------------------
/images/kafka-before.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/kafka-before.png
--------------------------------------------------------------------------------
/images/kafka-order-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/kafka-order-01.png
--------------------------------------------------------------------------------
/images/kafka-order-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/kafka-order-02.png
--------------------------------------------------------------------------------
/images/kafka-order-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/kafka-order-1.png
--------------------------------------------------------------------------------
/images/kafka-order-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/kafka-order-2.png
--------------------------------------------------------------------------------
/images/limaojishuwo.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/limaojishuwo.jpeg
--------------------------------------------------------------------------------
/images/micro-deployment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/micro-deployment.png
--------------------------------------------------------------------------------
/images/mq-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/mq-1.png
--------------------------------------------------------------------------------
/images/mq-10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/mq-10.png
--------------------------------------------------------------------------------
/images/mq-11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/mq-11.png
--------------------------------------------------------------------------------
/images/mq-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/mq-2.png
--------------------------------------------------------------------------------
/images/mq-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/mq-3.png
--------------------------------------------------------------------------------
/images/mq-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/mq-4.png
--------------------------------------------------------------------------------
/images/mq-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/mq-5.png
--------------------------------------------------------------------------------
/images/mq-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/mq-6.png
--------------------------------------------------------------------------------
/images/mq-7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/mq-7.png
--------------------------------------------------------------------------------
/images/mq-8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/mq-8.png
--------------------------------------------------------------------------------
/images/mysql-master-slave.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/mysql-master-slave.png
--------------------------------------------------------------------------------
/images/rabbitmq-message-lose-solution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/rabbitmq-message-lose-solution.png
--------------------------------------------------------------------------------
/images/rabbitmq-message-lose.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/rabbitmq-message-lose.png
--------------------------------------------------------------------------------
/images/rabbitmq-order-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/rabbitmq-order-01.png
--------------------------------------------------------------------------------
/images/rabbitmq-order-02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/rabbitmq-order-02.png
--------------------------------------------------------------------------------
/images/rabbitmq-order-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/rabbitmq-order-1.png
--------------------------------------------------------------------------------
/images/rabbitmq-order-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/rabbitmq-order-2.png
--------------------------------------------------------------------------------
/images/redis-caching-avalanche-solution.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/redis-caching-avalanche-solution.png
--------------------------------------------------------------------------------
/images/redis-caching-avalanche.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/redis-caching-avalanche.png
--------------------------------------------------------------------------------
/images/redis-caching-penetration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/redis-caching-penetration.png
--------------------------------------------------------------------------------
/images/redis-cluster-split-brain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/redis-cluster-split-brain.png
--------------------------------------------------------------------------------
/images/redis-gossip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/redis-gossip.png
--------------------------------------------------------------------------------
/images/redis-junior-inconsistent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/redis-junior-inconsistent.png
--------------------------------------------------------------------------------
/images/redis-master-slave-replication-detail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/redis-master-slave-replication-detail.png
--------------------------------------------------------------------------------
/images/redis-master-slave-replication.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/redis-master-slave-replication.png
--------------------------------------------------------------------------------
/images/redis-master-slave.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/redis-master-slave.png
--------------------------------------------------------------------------------
/images/redis-redlock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/redis-redlock.png
--------------------------------------------------------------------------------
/images/redis-single-thread-model.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/redis-single-thread-model.png
--------------------------------------------------------------------------------
/images/serialize-deserialize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/serialize-deserialize.png
--------------------------------------------------------------------------------
/images/service-invoke-road.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/service-invoke-road.png
--------------------------------------------------------------------------------
/images/simple-distributed-system-oa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/simple-distributed-system-oa.png
--------------------------------------------------------------------------------
/images/sketch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/sketch.png
--------------------------------------------------------------------------------
/images/where-is-my-offer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/where-is-my-offer.png
--------------------------------------------------------------------------------
/images/zookeeper-active-standby.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/zookeeper-active-standby.png
--------------------------------------------------------------------------------
/images/zookeeper-centralized-storage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/zookeeper-centralized-storage.png
--------------------------------------------------------------------------------
/images/zookeeper-distributed-coordination.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/zookeeper-distributed-coordination.png
--------------------------------------------------------------------------------
/images/zookeeper-distributed-lock-demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/zookeeper-distributed-lock-demo.png
--------------------------------------------------------------------------------
/images/zookeeper-distributed-lock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/zookeeper-distributed-lock.png
--------------------------------------------------------------------------------
/images/zookeeper-meta-data-manage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shishan100/Java-Interview-Advanced/519a1e865b11fa06b6e012d3464db3c4121d782e/images/zookeeper-meta-data-manage.png
--------------------------------------------------------------------------------