first commit
256
README.md
Executable file
@ -0,0 +1,256 @@
|
||||
# 中华石杉--互联网Java进阶面试训练营
|
||||
|
||||
[![original](https://badgen.net/badge/original/%E4%B8%AD%E5%8D%8E%E7%9F%B3%E6%9D%89/orange)]
|
||||
[![open-source-organization](https://badgen.net/badge/organization/join%20us/138c7b)]
|
||||
[![reading](https://badgen.net/badge/books/read%20together/cyan)]
|
||||
[![coding](https://badgen.net/badge/leetcode/coding%20together/cyan)]
|
||||
[![sharing](https://badgen.net/badge/readers/share%20together/cyan)]
|
||||
[![stars](https://badgen.net/github/stars/doocs/wulimax/reactApp)]
|
||||
[![forks](https://badgen.net/github/forks/wulimax/reactApp)]
|
||||
[![contributors](https://badgen.net/github/contributors/wulimax/reactApp)]
|
||||
[![help-wanted](https://badgen.net/github/label-issues/wulimax/reactApp/help%20wanted/open)]
|
||||
[![issues](https://badgen.net/github/open-issues/wulimax/reactApp)]
|
||||
[![PRs Welcome](https://badgen.net/badge/PRs/welcome/green)](http://makeapullrequest.com)
|
||||
|
||||
|
||||
|
||||
### 内容说明:
|
||||
本仓库存放的是公众号【狸猫技术窝】和**中华石杉**老师合作的课程《**互联网Java进阶面试训练营**》的笔记,版权归狸猫技术窝所有,侵权将追究法律责任
|
||||
|
||||
训练营详细信息请关注公众号【狸猫技术窝】了解
|
||||
### 公众号:狸猫技术窝
|
||||
|
||||
更多技术干货,请扫描下方二维码,关注公众号狸猫技术窝
|
||||
|
||||
![我的公众号](/images/limaojishuwo.jpeg)
|
||||
|
||||
|
||||
|
||||
|
||||
## 目录
|
||||
|
||||
- [互联网Java面试指南](#面试指南)
|
||||
- [备战面试](#备战面试)
|
||||
- [常见面试题总结](#常见面试题总结)
|
||||
- [面经](#面经)
|
||||
- [互联网Java面试突击第一季](#面试突击第一季)
|
||||
- [分布式消息队列](#分布式消息队列)
|
||||
- [分布式搜索引擎](#搜索引擎)
|
||||
- [分布式缓存](#分布式缓存)
|
||||
- [分库分表](#分库分表)
|
||||
- [分布式锁](#分布式锁)
|
||||
- [分布式会话](#分布式会话)
|
||||
- [分布式事务](#分布式事务)
|
||||
- [分布式限流降级](#分布式事务)
|
||||
- [分布式服务框架Dubbo](#分布式服务框架Dubbo)
|
||||
- [互联网Java进阶面试训练营](#互联网Java进阶面试训练营)
|
||||
- [第一季:分布式](#第一季-分布式)
|
||||
- [第二季:高并发](#第二季-高并发)
|
||||
- [第三季:微服务](#第三季-微服务)
|
||||
- [第四季:海量数据](#第四季-海量数据)
|
||||
- [第五季:高性能](#第五季-高性能)
|
||||
- [第六季:高可用](#第六季-高可用)
|
||||
|
||||
|
||||
## 面试指南
|
||||
|
||||
### 备战面试
|
||||
- [面试一线互联网大厂?那这道题目你必须得会!](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484645&idx=1&sn=663238af983603a4c0b33cf42c3ebbcf&chksm=fba6ece6ccd165f0d78f271a21fdc1b91ad8d3def896e2f4df79d9c8d4cf99e3b2978d703dde&mpshare=1&scene=1&srcid=0608edSfhNw7AIjzl9R54Sih%23rd)
|
||||
- [阿里三面,P9面试官是如何360°无死角考察候选人的?](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247485021&idx=1&sn=936b0ecbbe8bd633b1a6c10127eaf4c4&chksm=fba6ee5eccd167483e2a5b17df3f3d1f38f9b98b894f3c47d6b365821338e1380f7c6af1a49d&mpshare=1&scene=1&srcid=0608bZo70WnyWgBMGZs9aAPA%23rd)
|
||||
- [互联网公司的面试官是如何360°无死角考察候选人的?(上篇)](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484144&idx=1&sn=a6b86d38a762e317ba78e2500fb1a8ff&chksm=fba6eaf3ccd163e5403a01be51216780040511b2ddc4d5750ace6e46b4242ceaf77d0432c680&mpshare=1&scene=1&srcid=0608Ls6BQxXTdAQKvDeZx8f0%23rd)
|
||||
- [互联网公司面试官是如何360°无死角考察候选人的?(下篇)](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484148&idx=1&sn=a2e05fed6b2dda661b4da11036b883a9&chksm=fba6eaf7ccd163e19013c4204fd0997159b04cd37a235d05dab4f645b61b2f8f9e21a98614c8&mpshare=1&scene=1&srcid=0608k7qLNodHSqW0SbfpZLRG%23rd)
|
||||
- [中小公司的Java工程师应该如何逆袭冲进BAT?](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484442&idx=1&sn=610f02aa18ef6a5d8c80a74959be0333&chksm=fba6ec19ccd1650fc265ac6f7f462157a7b274e358282bb7fc029e9366cfac656c58300b98c5&mpshare=1&scene=1&srcid=06089lyagf3w18D90N7RcB8q%23rd)
|
||||
- [【offer收割机必备】我简历上的Java项目都好low,怎么办?](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484583&idx=1&sn=a9d43c3ee63c8e5a37c073c2b8c43fba&chksm=fba6eca4ccd165b2602a462c5589fa8dacd78558bdee7e0138b02bb26370637714f1094f4e9f&mpshare=1&scene=1&srcid=0608607GubfCXM2YaAqOLXET%23rd)
|
||||
- [Java工程师如何在1个月内做好面试准备?](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484575&idx=1&sn=7075fb3a42ef62fb5e69c868f29c8c61&chksm=fba6ec9cccd1658a391bc4e60faa35b44b947dbb6f535042e392c668693524447a2604955fd8&mpshare=1&scene=1&srcid=0608BvwQetAYtHkxZX7X7r8F%23rd)
|
||||
### 常见面试题总结
|
||||
- [互联网大厂Java面试题:使用无界队列的线程池会导致内存飙升吗?](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484480&idx=1&sn=1c7262d7f185ad6f99b840fb7779a575&chksm=fba6ec43ccd16555d826772a530c280548d8fd9785a9169b87bb4ed82d8b12ad75154c98b957&mpshare=1&scene=1&srcid=0608DxO0IKPDPxNOoN1la590%23rd)
|
||||
- [阿里一面:关于【缓存穿透、缓存击穿、缓存雪崩、热点数据失效】问题的解决方案](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484884&idx=1&sn=ceb798b6e8ef0ee608a992385f7d8568&chksm=fba6edd7ccd164c155271811f7948b476955cab41b23f2333847b8c268b31cc9f3332c2e3926&mpshare=1&scene=1&srcid=0608pIX1L8Fja1H99IyorW2X%23rd)
|
||||
- [大白话聊聊Java并发面试问题之volatile到底是什么?](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484058&idx=1&sn=d5c1533204ea655e65947ec57f924799&chksm=fba6ea99ccd1638f945c585cf3b2df6f4d4112b17ea3648730d50fdb5508555d5f30316f4186&mpshare=1&scene=1&srcid=0608cDtcDBaGNgIU9v4zxS3f%23rd)
|
||||
- [大白话聊聊Java并发面试问题之Java 8如何优化CAS性能?](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484070&idx=1&sn=c1d49bce3c9da7fcc7e057d858e21d69&chksm=fba6eaa5ccd163b3a935303f10a54a38f15f3c8364c7c1d489f0b1aa1b2ef293a35c565d2fda&mpshare=1&scene=1&srcid=0608QzOXG2l0z2QyfVaCKqRH%23rd)
|
||||
- [大白话聊聊Java并发面试问题之谈谈你对AQS的理解?](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484094&idx=1&sn=b337161f934b1c27ff1f059350ef5e65&chksm=fba6eabdccd163abc8978b65e155d79a133f20ee8a5bff79a33ed20a050c2bd576581db69fe6&mpshare=1&scene=1&srcid=0608yIcfsyrDG1NIBSsF58jq%23rd)
|
||||
- [大白话聊聊Java并发面试问题之公平锁与非公平锁是啥?](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484095&idx=1&sn=aa915ae16d0a550bbe7ae4b6fec99173&chksm=fba6eabcccd163aa2bc0e880d7d3929eee5ff834a73a6ccc3a53237537a4555ef7fd4d9e70d0&mpshare=1&scene=1&srcid=0608QNgPOxWhMZfdNvGvcoUW%23rd)
|
||||
- [大白话聊聊Java并发面试问题之微服务注册中心的读写锁优化?](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484129&idx=1&sn=d2a95310db5751b152ba070caee4ebae&chksm=fba6eae2ccd163f48aef9d98a4dbb55d578a24af710e1436cc876fe3119b03135532e16d80bc&mpshare=1&scene=1&srcid=06089KYIxoL86LbBEP44hsnV%23rd)
|
||||
- [消息中间件集群崩溃,如何保证百万生产数据不丢失?](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484257&idx=1&sn=e7704f92a1008ab7a292e2826bd079aa&chksm=fba6eb62ccd1627451d439bbc21e46e6fc1d7bfbe2a431fd887cf974a7bd0d9d482697f0e4fd&mpshare=1&scene=1&srcid=0608mcZB6SlZ2JGY46F7giS3%23rd)
|
||||
- [哥们,消息中间件在你们项目里是如何落地的?](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484191&idx=1&sn=fac0c513cf9ad480fc39c5b51f6c4fde&chksm=fba6eb1cccd1620aa0b48c72d1c6b51706400f24268db6c774bac6ec02a0f31885db9b7d6cad&mpshare=1&scene=1&srcid=0608ZI28nnj1eXjYIlBg0oVb%23rd)
|
||||
- [哥们,那你说说系统架构引入消息中间件有什么缺点?](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484157&idx=1&sn=f4644be2db6b1c230846cb4d62ae5be9&chksm=fba6eafeccd163e817b420d57478829d92251a6a5fd446f81805f0983a0d95cb6853a6735c4b&mpshare=1&scene=1&srcid=06083A6RVW3ZtKQRy6Ttq8tK%23rd)
|
||||
- [哥们,你们的系统架构中为什么要引入消息中间件?](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484149&idx=1&sn=98186297335e13ec7222b3fd43cfae5a&chksm=fba6eaf6ccd163e0c2c3086daa725de224a97814d31e7b3f62dd3ec763b4abbb0689cc7565b0&mpshare=1&scene=1&srcid=0608fz8HKZvYxRhzFqyJ4Isq%23rd)
|
||||
- [线上服务宕机时,如何保证数据100%不丢失?](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484204&idx=1&sn=6fc43b0620857b653dbef20693d1c6c6&chksm=fba6eb2fccd16239056e4b52dc0895585292b830bfd2652dea81b7360556fe36aceac0951761&mpshare=1&scene=1&srcid=0608W9lqShQsPrfETC90Acwm%23rd)
|
||||
|
||||
|
||||
### 面经
|
||||
- [小公司面试10连挂之后,我拿到了互联网一线大厂offer!](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484955&idx=1&sn=be39f51e00d78eb7d3a4ae6b7137e62c&chksm=fba6ee18ccd1670ec7dbf62f2c73d65b241cfb6897bac9316981c1e7936e31c1caee5ccee87e&mpshare=1&scene=1&srcid=0608zdpqBAGKWQr6ExuWOvtg%23rd)
|
||||
- [尴尬的面试现场:说说你们系统有多大QPS?系统到底怎么抗住高并发的?](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484908&idx=1&sn=6acc6ff3ce5e2ca1d0c2639868356a5e&chksm=fba6edefccd164f92d15faab6b8f77e4118c299ea5b1c366ac2db2aad9f12c761ef051355600&mpshare=1&scene=1&srcid=0608rMH6pNVzMB7wHy5caCrN%23rd)
|
||||
- [面对BAT大厂的竞争对手时,小公司Java工程师是如何败北的?](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484786&idx=1&sn=be07d63f36ee97031031dc455c03e3ca&chksm=fba6ed71ccd164677ef4e94ad64409783ec4a35d0cf8cfc2f2672a58099a382a496db2abf313&mpshare=1&scene=1&srcid=0608FUyrpWhHO2WyA36i9JK9%23rd)
|
||||
- [我一连面试了十个Java岗,统统石沉大海!](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484590&idx=1&sn=9d63dd0c4ab9150f6ac32f327d349d3b&chksm=fba6ecadccd165bb3c96ebd792d677ce25614f1cf48dbbe255534c149fe447c88761077f16b4&mpshare=1&scene=1&srcid=0608MowbddtGYWq6Fa26nPIJ%23rd)
|
||||
- [面试最让你手足无措的一个问题:你的系统如何支撑高并发?](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484429&idx=1&sn=d8038c21ecd733b8bb7ff784014243f9&chksm=fba6ec0eccd165189e92a294ab2b7cd6796982c188befe05c27f4e96ae5cd39f2baf436cf37d&mpshare=1&scene=1&srcid=0608ttwG3fBdBUt7pdxL5IhX%23rd)
|
||||
- [【斩获7枚offer,入职阿里平台事业部】横扫阿里、美团、京东、 去哪儿之后,我写下了这篇面经!](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247485090&idx=1&sn=5502672d9bf52551038b911d7ab623b9&chksm=fba6eea1ccd167b73a542b76dad423da21a2b452f768aac996cb50eeac1adc5d4978afe762ce&mpshare=1&scene=1&srcid=0608mo3eKwh686hXNzvRQfEB%23rd)
|
||||
- [三年努力,梦归阿里!](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247485010&idx=1&sn=cd158d8358a0758fa81af094d58e2ea2&chksm=fba6ee51ccd1674753d77c8ab2a522cd8e32373b0a104eb9ecd6008cd12b6457eaade77e0514&mpshare=1&scene=1&srcid=0608LIOSiYzoUmlBHC4ZhnnZ%23rd)
|
||||
- [二本出身、逆袭网易、一路孤独、一路狂欢!](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484844&idx=1&sn=cfa78df2943567269909f87217fa25c8&chksm=fba6edafccd164b9f6c22162a6386734010aeee9a084de720dacbb72d58bd1c20c0f961f5315&mpshare=1&scene=1&srcid=0608Ufv5zYZu66XnNn89WYEU%23rd)
|
||||
- [小公司出身的我,是如何拿下知名独角兽公司offer的?](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484813&idx=1&sn=4c9a43e51e1cf114efcf938e60ad58fd&chksm=fba6ed8eccd16498840a715659b8a29cf3368d28cf67c6fb27255277abe63421bca9ceb2cae7&mpshare=1&scene=1&srcid=06083zOsdotiVg1juwK3MYxZ%23rd)
|
||||
- [【行走的Offer收割机】记一位朋友斩获BAT技术专家Offer的面试经历](https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247484170&idx=1&sn=6c178884c1c5399e37562b9dc66cff6c&chksm=fba6eb09ccd1621ff8821b37f12d6df8a1d269ddc95ad10c0a4e71a3bf0017952bf19978d8ec&mpshare=1&scene=1&srcid=0608ezj6dEIln43Sl011MZz3%23rd)
|
||||
|
||||
|
||||
|
||||
|
||||
## 面试突击第一季
|
||||
|
||||
### [分布式消息队列](/docs/high-concurrency/mq-interview.md)
|
||||
- [为什么使用消息队列?消息队列有什么优点和缺点?Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么优点和缺点?](/docs/high-concurrency/why-mq.md)
|
||||
- [如何保证消息队列的高可用?](/docs/high-concurrency/how-to-ensure-high-availability-of-message-queues.md)
|
||||
- [如何保证消息不被重复消费?(如何保证消息消费的幂等性)](/docs/high-concurrency/how-to-ensure-that-messages-are-not-repeatedly-consumed.md)
|
||||
- [如何保证消息的可靠性传输?(如何处理消息丢失的问题)](/docs/high-concurrency/how-to-ensure-the-reliable-transmission-of-messages.md)
|
||||
- [如何保证消息的顺序性?](/docs/high-concurrency/how-to-ensure-the-order-of-messages.md)
|
||||
- [如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万消息持续积压几小时,说说怎么解决?](/docs/high-concurrency/mq-time-delay-and-expired-failure.md)
|
||||
- [如果让你写一个消息队列,该如何进行架构设计啊?说一下你的思路。](/docs/high-concurrency/mq-design.md)
|
||||
|
||||
### 搜索引擎
|
||||
- [lucene 和 es 的前世今生](/docs/high-concurrency/es-introduction.md)
|
||||
- [es 的分布式架构原理能说一下么(es 是如何实现分布式的啊)?](/docs/high-concurrency/es-architecture.md)
|
||||
- [es 写入数据的工作原理是什么啊?es 查询数据的工作原理是什么啊?底层的 lucene 介绍一下呗?倒排索引了解吗?](/docs/high-concurrency/es-write-query-search.md)
|
||||
- [es 在数据量很大的情况下(数十亿级别)如何提高查询效率啊?](/docs/high-concurrency/es-optimizing-query-performance.md)
|
||||
- [es 生产集群的部署架构是什么?每个索引的数据量大概有多少?每个索引大概有多少个分片?](/docs/high-concurrency/es-production-cluster.md)
|
||||
|
||||
### 分布式缓存
|
||||
- [在项目中缓存是如何使用的?缓存如果使用不当会造成什么后果?](/docs/high-concurrency/why-cache.md)
|
||||
- [Redis 和 Memcached 有什么区别?Redis 的线程模型是什么?为什么单线程的 Redis 比多线程的 Memcached 效率要高得多?](/docs/high-concurrency/redis-single-thread-model.md)
|
||||
- [Redis 都有哪些数据类型?分别在哪些场景下使用比较合适?](/docs/high-concurrency/redis-data-types.md)
|
||||
- [Redis 的过期策略都有哪些?手写一下 LRU 代码实现?](/docs/high-concurrency/redis-expiration-policies-and-lru.md)
|
||||
- [如何保证 Redis 高并发、高可用?Redis 的主从复制原理能介绍一下么?Redis 的哨兵原理能介绍一下么?](/docs/high-concurrency/how-to-ensure-high-concurrency-and-high-availability-of-redis.md)
|
||||
- [Redis 的持久化有哪几种方式?不同的持久化机制都有什么优缺点?持久化机制具体底层是如何实现的?](/docs/high-concurrency/redis-persistence.md)
|
||||
- [Redis 集群模式的工作原理能说一下么?在集群模式下,Redis 的 key 是如何寻址的?分布式寻址都有哪些算法?了解一致性 hash 算法吗?如何动态增加和删除一个节点?](/docs/high-concurrency/redis-cluster.md)
|
||||
- [了解什么是 redis 的雪崩、穿透和击穿?Redis 崩溃之后会怎么样?系统该如何应对这种情况?如何处理 Redis 的穿透?](/docs/high-concurrency/redis-caching-avalanche-and-caching-penetration.md)
|
||||
- [如何保证缓存与数据库的双写一致性?](/docs/high-concurrency/redis-consistence.md)
|
||||
- [Redis 的并发竞争问题是什么?如何解决这个问题?了解 Redis 事务的 CAS 方案吗?](/docs/high-concurrency/redis-cas.md)
|
||||
- [生产环境中的 Redis 是怎么部署的?](/docs/high-concurrency/redis-production-environment.md)
|
||||
|
||||
### 分库分表
|
||||
- [为什么要分库分表(设计高并发系统的时候,数据库层面该如何设计)?用过哪些分库分表中间件?不同的分库分表中间件都有什么优点和缺点?你们具体是如何对数据库如何进行垂直拆分或水平拆分的?](/docs/high-concurrency/database-shard.md)
|
||||
- [现在有一个未分库分表的系统,未来要分库分表,如何设计才可以让系统从未分库分表动态切换到分库分表上?](/docs/high-concurrency/database-shard-method.md)
|
||||
- [如何设计可以动态扩容缩容的分库分表方案?](/docs/high-concurrency/database-shard-dynamic-expand.md)
|
||||
- [分库分表之后,id 主键如何处理?](/docs/high-concurrency/database-shard-global-id-generate.md)
|
||||
- [如何实现 MySQL 的读写分离?MySQL 主从复制原理是啥?如何解决 MySQL 主从同步的延时问题?](/docs/high-concurrency/mysql-read-write-separation.md)
|
||||
|
||||
|
||||
### 分布式服务框架Dubbo
|
||||
- [面试连环炮](/docs/distributed-system/distributed-system-interview.md)
|
||||
- [如何设计一个高并发系统?](/docs/high-concurrency/high-concurrency-design.md)
|
||||
- [说一下 Dubbo 的工作原理?注册中心挂了可以继续通信吗?](/docs/distributed-system/dubbo-operating-principle.md)
|
||||
- [Dubbo 支持哪些序列化协议?说一下 Hessian 的数据结构?PB 知道吗?为什么 PB 的效率是最高的?](/docs/distributed-system/dubbo-serialization-protocol.md)
|
||||
- [Dubbo 负载均衡策略和集群容错策略都有哪些?动态代理策略呢?](/docs/distributed-system/dubbo-load-balancing.md)
|
||||
- [Dubbo 的 spi 思想是什么?](/docs/distributed-system/dubbo-spi.md)
|
||||
- [如何基于 Dubbo 进行服务治理、服务降级、失败重试以及超时重试?](/docs/distributed-system/dubbo-service-management.md)
|
||||
- [分布式服务接口的幂等性如何设计(比如不能重复扣款)?](/docs/distributed-system/distributed-system-idempotency.md)
|
||||
- [分布式服务接口请求的顺序性如何保证?](/docs/distributed-system/distributed-system-request-sequence.md)
|
||||
- [如何自己设计一个类似 Dubbo 的 RPC 框架?](/docs/distributed-system/dubbo-rpc-design.md)[手写rpc代码下载!](https://github.com/shishan100/Java-Interview-Advanced/raw/master/docs/distributed-system/code/rpc-demo.zip)
|
||||
- [为什么要进行系统拆分?如何进行系统拆分?拆分后不用 Dubbo 可以吗?](/docs/distributed-system/why-dubbo.md)
|
||||
|
||||
|
||||
### 分布式锁
|
||||
- [Zookeeper 都有哪些应用场景?](/docs/distributed-system/zookeeper-application-scenarios.md)
|
||||
- [使用 Redis 如何设计分布式锁?使用 Zookeeper 来设计分布式锁可以吗?以上两种分布式锁的实现方式哪种效率比较高?](/docs/distributed-system/distributed-lock-redis-vs-zookeeper.md)
|
||||
|
||||
### 分布式事务
|
||||
- [分布式事务了解吗?你们如何解决分布式事务问题的?TCC 如果出现网络连不通怎么办?XA 的一致性如何保证?](/docs/distributed-system/distributed-transaction.md)
|
||||
- [关于如何实现一个TCC分布式事务框架的一点思考](http://www.bytesoft.org)
|
||||
|
||||
### 分布式会话
|
||||
- [集群部署时的分布式 Session 如何实现?](/docs/distributed-system/distributed-session.md)
|
||||
|
||||
## 分布式限流降级
|
||||
- [Hystrix 介绍](/docs/high-availability/hystrix-introduction.md)
|
||||
- [电商网站详情页系统架构](/docs/high-availability/e-commerce-website-detail-page-architecture.md)
|
||||
- [Hystrix 线程池技术实现资源隔离](/docs/high-availability/hystrix-thread-pool-isolation.md)
|
||||
- [Hystrix 信号量机制实现资源隔离](/docs/high-availability/hystrix-semphore-isolation.md)
|
||||
- [Hystrix 隔离策略细粒度控制](/docs/high-availability/hystrix-execution-isolation.md)
|
||||
- [深入 Hystrix 执行时内部原理](/docs/high-availability/hystrix-process.md)
|
||||
- [基于 request cache 请求缓存技术优化批量商品数据查询接口](/docs/high-availability/hystrix-request-cache.md)
|
||||
- [基于本地缓存的 fallback 降级机制](/docs/high-availability/hystrix-fallback.md)
|
||||
- [深入 Hystrix 断路器执行原理](/docs/high-availability/hystrix-circuit-breaker.md)
|
||||
- [深入 Hystrix 线程池隔离与接口限流](/docs/high-availability/hystrix-thread-pool-current-limiting.md)
|
||||
- [基于 timeout 机制为服务接口调用超时提供安全保护](/docs/high-availability/hystrix-timeout.md)
|
||||
|
||||
|
||||
|
||||
## 互联网Java进阶面试训练营
|
||||
|
||||
### 第一季-分布式
|
||||
- [01、互联网大厂面试要求:技术广度、技术深度、系统设计以及项目经验](/docs/distributed-system/distributed-design.md)
|
||||
- [02、Java工程师面试突击第一季总结:你离一次成功的面试还差多少?](/docs/distributed-system/java-interview-season-1-summary.md)
|
||||
- [03、《21天互联网Java进阶面试训练营》的课程说明](/docs/distributed-system/21-day-course-instructions.md)
|
||||
- [04、作业:系统分析一下,自己距离大厂offer差在哪里?](/docs/distributed-system/homework.md)
|
||||
- [05、感受一下BAT面试官对分布式技术的十几个面试连环炮!](/docs/distributed-system/BAT-interview-fire.md)
|
||||
- [06、你们公司用的Dubbo?那你再额外说说Spring Cloud的核心架构原理?](/docs/distributed-system/core-architecture-principle%20.md)
|
||||
- [07、基于Dubbo和Spring Cloud分别搭建一个电商系统来快速体验一下!](/docs/distributed-system/Dubbo-SpringCloud-experience.md)[代码下载点击这里哦!](https://github.com/shishan100/Java-Interview-Advanced/raw/master/docs/distributed-system/code/code.zip)
|
||||
- [08、作业:你们的系统使用了哪种服务框架?为什么要这样技术选型?](/docs/distributed-system/distributed-framework-selection.md)
|
||||
- [09、看过Dubbo源码吗?说说Dubbo的底层架构原理?](/docs/distributed-system/dubbo-framework-principle.md)
|
||||
- [10、咱们来聊点深入的,说说Dubbo底层的网络通信机制原理!](/docs/distributed-system/dubbo-rock-bottom.md)
|
||||
- [11、Dubbo框架从架构设计角度,是怎么保证极高的可扩展性的?](/docs/distributed-system/dubbo-augmentability.md)
|
||||
- [12、作业:自己独立画出Dubbo的底层架构原理图](/docs/distributed-system/dubbo-independent-framework.md)
|
||||
- [13、如果让你设计一个RPC框架,网络通信、代理机制、负载均衡等该如何设](/docs/distributed-system/rpc-design.md)
|
||||
- [14、平时除了使用外,有研究过Spring Cloud的底层架构原理么?](/docs/distributed-system/springCloud-study-theory.md)
|
||||
- [15、从底层实现原理的角度,对比一下Dubbo和Spring Cloud的优劣!](/docs/distributed-system/dubbo-vs-springCloud.md)
|
||||
- [16、作业:自己独立画出Spring Cloud的架构原理图,RPC框架架构设计图!](/docs/distributed-system/springCloud-and-rpc-framework.md)
|
||||
- [17、面试官:你们的服务注册中心进行过选型调研吗?对比一下各种服务注册中心!](/docs/distributed-system/registration-center-%20guide.md)
|
||||
- [18、画图阐述一下你们的服务注册中心部署架构,生产环境下怎么保证高可用?](/docs/distributed-system/register-high-availability.md)
|
||||
- [19、你们系统遇到过服务发现过慢的问题吗?怎么优化和解决的?](/docs/distributed-system/service-register-discovery.md)
|
||||
- [20、作业:说一下自己公司的服务注册中心怎么技术选型的?生产环境中应该怎么优化?](/docs/distributed-system/register-production-optimize.md)
|
||||
- [21、你们对网关的技术选型是怎么考虑的?能对比一下各种网关技术的优劣吗?](/docs/distributed-system/gateway-model-selection.md)
|
||||
- [22、说说生产环境下,你们是怎么实现网关对服务的动态路由的?](/docs/distributed-system/dynamic-route.md)[代码下载点击这里哦!](https://github.com/shishan100/Java-Interview-Advanced/raw/master/docs/distributed-system/code/code2.zip)
|
||||
- [23、如果网关需要抗每秒10万的高并发访问,你应该怎么对网关进行生产优化?](/docs/distributed-system/gateway-high-concurrency.md)
|
||||
- [24、作业:你们公司的网关是怎么技术选型的,假设有高并发场景怎么优化?](/docs/distributed-system/gateway-technical.md)
|
||||
- [25、如果需要部署上万服务实例,现有的服务注册中心能否抗住?如何优化?](/docs/distributed-system/registration-center-optimize.md)
|
||||
- [26、你们是如何基于网关实现灰度发布的?说说你们的灰度发布方案?](/docs/distributed-system/gray-environment.md)[代码下载点击这里哦!](https://github.com/shishan100/Java-Interview-Advanced/raw/master/docs/distributed-system/code/code3.zip)
|
||||
- [27、说说你们一个服务从开发到上线,服务注册、网关路由、服务调用的流程?](/docs/distributed-system/service-register-gateway-router.md)
|
||||
- [28、作业:看看你们公司的服务注册中心能否支撑上万服务实例的大规模场景?](/docs/distributed-system/work-register.md)
|
||||
- [29、画一下你们系统的整体架构图,说说各个服务在生产环境怎么部署的?](/docs/distributed-system/system-framework.md)
|
||||
- [30、你们系统每天有多大访问量?每个服务高峰QPS多少?压测过服务最大QPS吗?](/docs/distributed-system/system-qps.md)
|
||||
- [31、如果系统访问量比现在增加10倍,你们考虑过系统的扩容方案吗?](/docs/distributed-system/system-dilatation.md)
|
||||
- [32、作业:独立画出自己系统的生产部署架构图,梳理系统和服务的QPS以及扩容方案](/docs/distributed-system/work-system-dilatation.md)
|
||||
- [33、你们生产环境的服务是怎么配置超时和重试参数的?为什么要这样配置?](/docs/distributed-system/service-request-time-out.md)[代码下载点击这里哦!](https://github.com/shishan100/Java-Interview-Advanced/raw/master/docs/distributed-system/code/code4.zip)
|
||||
- [34、如果出现服务请求重试,会不会出现类似重复下单的问题?](/docs/distributed-system/request-retry.md)
|
||||
- [35、对于核心接口的防重幂等性,你们是怎么设计的?怎么防止重复下单问题?](/docs/distributed-system/interface-idempotence.md)
|
||||
- [36、作业:看看自己系统的核心接口有没有设计幂等性方案?如果没有,应该怎么设计?](/docs/distributed-system/work-interface-idempotence.md)
|
||||
- [37、画一下你们电商系统的核心交易链路图,说说分布式架构下存在什么问题?](/docs/distributed-system/deal-line.md)
|
||||
- [38、针对电商核心交易链路,你们是怎么设计分布式事务技术方案的?](/docs/distributed-system/work-distributed-transaction.md)
|
||||
- [39、对于TCC事务、最终一致性事务的技术选型,你们是怎么做的?如何调研的?](/docs/distributed-system/distributed-transaction-tcc.md)
|
||||
- [40、作业:你们公司的核心链路是否有事务问题?分布式事务方案怎么调研选型?](/docs/distributed-system/work-distributed-transaction.md)
|
||||
- [41、在搭建好的电商系统里,落地开发对交易链路的TCC分布式事务方案](/docs/distributed-system/tcc-landing-scheme.md)
|
||||
- [42、你能说说一个TCC分布式事务框架的核心架构原理吗?](/docs/distributed-system/tcc-framework-principle.md)
|
||||
- [43、现有的TCC事务方案的性能瓶颈在哪里?能支撑高并发交易场景吗?如何优化?](/docs/distributed-system/tcc-high-concurrence.md)
|
||||
- [44、作业:如果对自己的系统核心链路落地TCC事务,应该如何落地实现?](/docs/distributed-system/work-tcc-landing-scheme.md)
|
||||
- [45、你了解RocketMQ对分布式事务支持的底层实现原理吗?](/docs/distributed-system/rocketmq-transaction.md)
|
||||
- [46、在搭建好的电商系统里,如何基于RocketMQ最终一致性事务进行落地开发?](/docs/distributed-system/rocketmq-eventual-consistency.md)
|
||||
- [47、如果公司没有RocketMQ中间件,那你们如何实现最终一致性事务?](/docs/distributed-system/eventual-consistency.md)
|
||||
- [48、作业:如果对自己的系统落地最终一致性事务,如何落地实现?](/docs/distributed-system/work-eventual-consistency.md)
|
||||
- [49、你们生产系统中有哪个业务场景是需要用分布式锁的?为什么呢?](/docs/distributed-system/distributed-lock.md)
|
||||
- [50、你们是用哪个开源框架实现的Redis分布式锁?能说说其核心原理么?](/docs/distributed-system/redis-distribute-lock.md)
|
||||
- [51、如果Redis是集群部署的,那么集群故障时分布式锁还有效么?](/docs/distributed-system/hitch-redis-distribute-lock.md)
|
||||
- [52、作业:自己梳理出来Redis分布式锁的生产问题解决方案](/docs/distributed-system/work-redis-distribute-lock.md)
|
||||
- [53、如果要实现ZooKeeper分布式锁,一般用哪个开源框架?核心原理是什么?](/docs/distributed-system/zookeeper-distribute-lock.md)
|
||||
- [54、对于ZooKeeper的羊群效应,分布式锁实现应该如何优化?](/docs/distributed-system/zookeeper-distribute-lock-optimize.md)
|
||||
- [55、如果遇到ZooKeeper脑裂问题,分布式锁应该如何保证健壮性?](/docs/distributed-system/zookeeper-distribute-lock-split-brain.md)
|
||||
- [56、作业:自己梳理出来ZooKeeper分布式锁的生产问题解决方案](/docs/distributed-system/zookeeper-distribute-lock-scheme.md)
|
||||
- [57、在搭建好的电商系统中,落地开发分布式锁保证库存数据准确的方案](/docs/distributed-system/floor-distribute-lock.md)
|
||||
- [58、你们的分布式锁做过高并发优化吗?能抗下每秒上万并发吗?](/docs/distributed-system/highly-concurrent-distribute-lock.md)
|
||||
- [59、淘宝和京东的库存是怎么实现的?能不能不用分布式锁实现高并发库存更新?](/docs/distributed-system/distributed-lock-taobao-and-jingdong.md)
|
||||
- [60、作业:自己系统的分布式锁在高并发场景下应该如何优化?](/docs/distributed-system/highly-concurrent-majorization-distributed-lock.md)
|
||||
- [61、互联网Java工程师面试突击前两季总结以及下一季的规划展望](/docs/distributed-system/java-internet-interview-outlook.md)
|
||||
|
||||
|
||||
|
||||
### 第二季-高并发
|
||||
### 第三季-微服务
|
||||
### 第四季-海量数据
|
||||
### 第五季-高性能
|
||||
### 第六季-高可用
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
171
docs/distributed-system/21-day-course-instructions.md
Executable file
@ -0,0 +1,171 @@
|
||||
|
||||
技术广度的积累,问题不太大,面试突击第一季好好看完,把对应的一些技术都自己去找一些资料简单学习一下
|
||||
|
||||
项目经验、生产经验、技术深度、系统设计
|
||||
|
||||
6季,**分布式**、**微服务**、**海量数据**、**高性能**、**高并发**、**高可用**
|
||||
|
||||
## 第1季:分布式
|
||||
|
||||
每一季,都是把对应的技术主题中的相关的技术在项目里落地的细节,生产经验,架构经验,技术深度,系统设计,给大家结合很多的案例来进行讲解
|
||||
|
||||
每一季是持续21天,三周,每周的周一~周五会更新课程,15天,每天是更新4讲内容,每天的内容量大概在1小时左右,最后总课程时长大概在1000分钟左右
|
||||
知己知彼
|
||||
一线互联网公司面试分析
|
||||
|
||||
01、互联网大厂面试要求:技术广度、技术深度、系统设计以及项目经验
|
||||
|
||||
02、Java工程师面试突击第一季总结:你离一次成功的面试还差多少?
|
||||
|
||||
03、《21天互联网Java进阶面试训练营》的课程说明
|
||||
|
||||
04、作业:系统分析一下,自己距离大厂offer差在哪里?
|
||||
|
||||
### Dubbo vs Spring Cloud
|
||||
两大核心分布式服务框架初探
|
||||
|
||||
05、感受一下BAT面试官对分布式技术的十几个面试连环炮!
|
||||
|
||||
06、你们公司用的Dubbo?那你再额外说说Spring Cloud的核心架构原理?
|
||||
|
||||
07、基于Dubbo和Spring Cloud分别搭建一个电商系统来快速体验一下!
|
||||
|
||||
08、作业:你们的系统使用了哪种服务框架?为什么要这样技术选型?
|
||||
|
||||
|
||||
|
||||
### 深入底层Dubbo与Spring Cloud的架构原理剖析
|
||||
|
||||
09、看过Dubbo源码吗?说说Dubbo的底层架构原理?
|
||||
|
||||
10、咱们来聊点深入的,说说Dubbo底层的网络通信机制原理!
|
||||
|
||||
11、Dubbo框架从架构设计角度,是怎么保证极高的可扩展性的?
|
||||
|
||||
12、作业:自己独立画出Dubbo的底层架构原理图
|
||||
|
||||
13、如果让你设计一个RPC框架,网络通信、代理机制、负载均衡等该如何设计?
|
||||
|
||||
14、平时除了使用外,有研究过Spring Cloud的底层架构原理么?
|
||||
|
||||
15、从底层实现原理的角度,对比一下Dubbo和Spring Cloud的优劣!
|
||||
|
||||
16、作业:自己独立画出Spring Cloud的架构原理图,RPC框架架构设计图!
|
||||
|
||||
|
||||
### 服务注册中心与服务网关的生产实践
|
||||
|
||||
17、面试官:你们的服务注册中心进行过选型调研吗?对比一下各种服务注册中心!
|
||||
|
||||
18、画图阐述一下你们的服务注册中心部署架构,生产环境下怎么保证高可用?
|
||||
|
||||
19、你们系统遇到过服务发现过慢的问题吗?怎么优化和解决的?
|
||||
|
||||
20、作业:说一下自己公司的服务注册中心怎么技术选型的?生产环境中应该怎么优化?
|
||||
21、你们对网关的技术选型是怎么考虑的?能对比一下各种网关技术的优劣吗?
|
||||
|
||||
22、说说生产环境下,你们是怎么实现网关对服务的动态路由的?
|
||||
|
||||
23、如果网关需要抗每秒10万的高并发访问,你应该怎么对网关进行生产优化?
|
||||
|
||||
24、作业:你们公司的网关是怎么技术选型的,假设有高并发场景怎么优化?
|
||||
|
||||
25、如果需要部署上万服务实例,现有的服务注册中心能否抗住?如何优化?
|
||||
|
||||
26、你们是如何基于网关实现灰度发布的?说说你们的灰度发布方案?
|
||||
|
||||
27、说说你们一个服务从开发到上线,服务注册、网关路由、服务调用的流程!
|
||||
|
||||
28、作业:看看你们公司的服务注册中心能否支撑上万服务实例的大规模场景?
|
||||
|
||||
|
||||
### 分布式系统的生产实践
|
||||
|
||||
29、画一下你们系统的整体架构图,说说各个服务在生产环境怎么部署的?
|
||||
|
||||
30、你们系统每天有多大访问量?每个服务高峰QPS多少?压测过服务最大QPS吗?
|
||||
|
||||
31、如果系统访问量比现在增加10倍,你们考虑过系统的扩容方案吗?
|
||||
|
||||
32、作业:独立画出自己系统的生产部署架构图,梳理系统和服务的QPS以及扩容方案
|
||||
|
||||
33、你们生产环境的服务是怎么配置超时和重试参数的?为什么要这样配置?
|
||||
|
||||
34、如果出现服务请求重试,会不会出现类似重复下单的问题?
|
||||
|
||||
35、对于核心接口的防重幂等性,你们是怎么设计的?怎么防止重复下单问题?
|
||||
|
||||
36、作业:看看自己系统的核心接口有没有设计幂等性方案?如果没有,应该怎么设计?
|
||||
|
||||
|
||||
### 分布式事务在项目中的落地实践与生产经验
|
||||
|
||||
37、画一下你们电商系统的核心交易链路图,说说分布式架构下存在什么问题?
|
||||
|
||||
38、针对电商核心交易链路,你们是怎么设计分布式事务技术方案的?
|
||||
|
||||
39、对于TCC事务、最终一致性事务的技术选型,你们是怎么做的?如何调研的?
|
||||
|
||||
40、作业:你们公司的核心链路是否有事务问题?分布式事务方案怎么调研选型?
|
||||
|
||||
41、在搭建好的电商系统里,落地开发对交易链路的TCC分布式事务方案
|
||||
|
||||
42、你能说说一个TCC分布式事务框架的核心架构原理吗?
|
||||
|
||||
43、现有的TCC事务方案的性能瓶颈在哪里?能支撑高并发交易场景吗?如何优化?
|
||||
|
||||
44、作业:如果对自己的系统核心链路落地TCC事务,应该如何落地实现?
|
||||
|
||||
45、在搭建好的电商系统里,如何基于RocketMQ最终一致性事务进行落地开发?
|
||||
|
||||
46、你了解RocketMQ对分布式事务支持的底层实现原理吗?
|
||||
|
||||
47、基于RocketMQ实现的最终一致性事务,如何抗住高并发交易场景?
|
||||
|
||||
48、作业:如果对自己的系统落地最终一致性事务,如何落地实现?
|
||||
|
||||
|
||||
### 分布式锁在项目中的落地实践与生产经验
|
||||
|
||||
49、你们是用哪个开源框架实现的Redis分布式锁?能说说其核心原理么?
|
||||
|
||||
50、如果Redis是集群部署的,那么分布式锁的实现原理是什么?
|
||||
|
||||
51、在Redis集群出现故障的时候,会导致分布式锁失效吗?
|
||||
|
||||
52、作业:自己梳理出来Redis分布式锁的生产问题解决方案
|
||||
|
||||
53、如果要实现ZooKeeper分布式锁,一般用哪个开源框架?核心原理是什么?
|
||||
|
||||
54、对于ZooKeeper的羊群效应,分布式锁实现应该如何优化?
|
||||
|
||||
55、如果遇到ZooKeeper脑裂问题,分布式锁应该如何保证健壮性?
|
||||
|
||||
56、作业:自己梳理出来ZooKeeper分布式锁的生产问题解决方案
|
||||
|
||||
57、在搭建好的电商系统中,落地开发分布式锁保证库存数据准确的方案
|
||||
|
||||
58、你们的分布式锁做过高并发优化吗?能抗下每秒上万并发吗?
|
||||
|
||||
59、淘宝和京东的库存是怎么实现的?能不能不用分布式锁实现高并发库存更新?
|
||||
|
||||
60、作业:自己系统的分布式锁在高并发场景下应该如何优化?
|
||||
|
||||
|
||||
我们的课程每天都会有一个作业,引导大家把学习到的项目经验、技术方案和生产优化落地到自己负责的项目中去,让大家出去面试的时候,可以把各种技术结合自己的项目来回答面试官的各种深度拷问
|
||||
|
||||
大家不要小看这个,根据我多年的面试经验来看,拥有这个技能的人凤毛麟角,这种人出去绝对是各大公司争抢的对象。
|
||||
|
||||
**所以希望大家好好完成每天的作业,我布置的大量作业,就是为了帮你锻造出这种能力**
|
||||
|
||||
**学习课程以及完成作业的过程中,大家一定会有很多的问题,可以到专栏的评论区去提问**
|
||||
|
||||
**每天我都会和之前带出来的一批阿里、蚂蚁金服、滴滴的优秀同学给大家进行答疑,并且我们还有专门的付费用户的微信群,大家可以在微信群里跟我们一起进行技术交流**
|
||||
|
||||
**如果你能坚持下来,学满6季,还可以获取私人定制的面试一条龙VIP服务**
|
||||
|
||||
**如果是连续6季面试训练营都购买的同学,还可以获取面试一条龙VIP服务**
|
||||
|
||||
**具体信息大家看“狸猫技术窝”公众号的知识店铺内的训练营详情即可**
|
||||
|
||||
**具体可参见训练营目录下的《训练营专属服务》文档。简单来说,这个私人定制的面试VIP服务,会为你的跳槽面试全程保驾护航**
|
61
docs/distributed-system/BAT-interview-fire.md
Executable file
@ -0,0 +1,61 @@
|
||||
针对面试突击第一季关于分布式这块的内容,相对应的做一个回顾和总结
|
||||
|
||||
面试突击第一季总共四五十讲,每个技术专题大概也是有十来讲
|
||||
|
||||
#### (1)为什么要把系统拆分成分布式的?为啥要用dubbo?
|
||||
#### (2)dubbo的工作原理是啥?注册中心挂了可以继续通信吗?
|
||||
#### (3)dubbo都支持哪些通信协议以及序列化协议?
|
||||
#### (4)dubbo支持哪些负载均衡、高可用以及动态代理的策略?
|
||||
#### (5)SPI是啥思想?dubbo的SPI机制是怎么玩儿的?
|
||||
#### (6)基于dubbo如何做服务治理、服务降级以及重试?
|
||||
|
||||
这些问题在面试突击第一季里,我们都讲解过了,都是非常高简单的一些问题,作为一个合格的工程师,如果你是用了分布式系统架构,也就是把大的系统拆分为了多个子系统,或者是 多个服务
|
||||
|
||||
你肯定会用到一种服务框架,Dubbo、Spring Cloud、gRPC、Thrift
|
||||
|
||||
你必须 对这些服务框架的核心的架构原理,有一个认识和了解,服务注册和发现,通信和序列化,负载均衡,扩展机制,请求重试,请求超时
|
||||
|
||||
#### (7)分布式系统中接口的幂等性该如何保证?比如不能重复扣款?
|
||||
#### (8)分布式系统中的接口调用如何保证顺序性?
|
||||
|
||||
接口幂等性,分布式系统,如果不保证,是否会发生类似重复下单,重复扣款之类的问题
|
||||
|
||||
#### (9)如何设计一个类似dubbo的rpc框架?架构上该如何考虑?
|
||||
|
||||
自己看过一些dubbo、spring cloud的源码,对一款服务框架底层的实现原理,有一定的了解和认识,此时如果说他希望能够深入的考察你一下,看看你的水平,这个时候就有可能会问你这个问题
|
||||
|
||||
#### (10)说说zookeeper一般都有哪些使用场景?
|
||||
#### (11)分布式锁是啥?对比下redis和zk两种分布式锁的优劣?
|
||||
|
||||
拆分成了分布式系统,就说明有很多子系统在同时的运作,如果说两个子系统都需要对某个数据资源进行一系列复杂的操作,在复杂操作期间,不能让数据被其他任何人来改变。分布式锁,技术实现原理
|
||||
|
||||
#### (13)说说你们的分布式session方案是啥?怎么做的?
|
||||
|
||||
前后端分离之后,一般是前端那边来care session之类的问题,对于后端来说,玩儿分布式session玩儿的很少了
|
||||
|
||||
#### (14)了解分布式事务方案吗?你们都咋做的?有啥坑?
|
||||
|
||||
|
||||
**我们的课程每天都会有一个作业,引导大家把学习到的项目经验、技术方案和生产优化落地到自己负责的项目中去,让大家出去面试的时候,可以把各种技术结合自己的项目来回答面试官的各种深度拷问**
|
||||
|
||||
**大家不要小看这个,根据我多年的面试经验来看,拥有这个技能的人凤毛麟角,这种人出去绝对是各大公司争抢的对象。**
|
||||
|
||||
**所以希望大家好好完成每天的作业,我布置的大量作业,就是为了帮你锻造出这种能力**
|
||||
|
||||
**学习课程以及完成作业的过程中,大家一定会有很多的问题,可以到专栏的评论区去提问**
|
||||
|
||||
**每天我都会和之前带出来的一批阿里、蚂蚁金服、滴滴的优秀同学给大家进行答疑,并且我们还有专门的付费用户的微信群,大家可以在微信群里跟我们一起进行技术交流**
|
||||
|
||||
**如果你能坚持下来,学满6季,还可以获取私人定制的面试一条龙VIP服务**
|
||||
|
||||
**如果是连续6季面试训练营都购买的同学,还可以获取面试一条龙VIP服务**
|
||||
|
||||
**具体信息大家看“狸猫技术窝”公众号的知识店铺内的训练营详情即可**
|
||||
|
||||
**具体可参见训练营目录下的《训练营专属服务》文档。简单来说,这个私人定制的面试VIP服务,会为你的跳槽面试全程保驾护航**
|
||||
|
||||
**“狸猫技术窝”**,找到我们的训练营的详情页面
|
||||
|
||||
|
||||
|
||||
|
9
docs/distributed-system/Dubbo-SpringCloud-experience.md
Executable file
@ -0,0 +1,9 @@
|
||||
Spring Cloud来搭建了一套
|
||||
|
||||
http://localhost:9000/order/order/create?productId=1&userId=1&count=3&totalPrice=300
|
||||
|
||||
刚开始几次请求会出现请求超时的问题,这个问题大家别纠结,后续要给大家讲spring cloud生产系统的优化
|
||||
|
||||
小小的小作业,参考一下dubbo的官方文档,搭建一个电商系统的dubbo版本的案例出来,我后面会搭建好的
|
||||
|
||||
[代码下载点击这里哦!](https://github.com/shishan100/Java-Interview-Advanced/raw/master/docs/distributed-system/code/code.zip)
|
1
docs/distributed-system/README.md
Executable file
@ -0,0 +1 @@
|
||||
# 分布式系统
|
BIN
docs/distributed-system/code/code.zip
Executable file
BIN
docs/distributed-system/code/code2.zip
Executable file
BIN
docs/distributed-system/code/code3.zip
Executable file
BIN
docs/distributed-system/code/code4.zip
Executable file
BIN
docs/distributed-system/code/rpc-demo.zip
Executable file
44
docs/distributed-system/core-architecture-principle .md
Executable file
@ -0,0 +1,44 @@
|
||||
如果聊分布式这块的技术,围绕**Dubbo来拷问**的,但是呢,现在其实非常流行的是**Spring Cloud,Dubbo和Spring Cloud以及阿里系的一些技术**,现在正在融合,**Spring Cloud Alibaba,只不过现在用的公司暂时还没那么多而已**
|
||||
|
||||
作为合格的工程师,行业里主流的**分布式服务技术栈**,**Dubbo**和**Spring Cloud**两种,有的公司他是用**Dubbo**的,不用**Spring Cloud**的,有的公司是用**Spring Cloud**的,不用**Dubbo**的,他们是代表了两种主流技术栈
|
||||
|
||||
Java工程师,Dubbo和Spring Cloud起码是基本原理,都有一定的了解
|
||||
|
||||
**大白话 + 现场画图**
|
||||
|
||||
上网看一些博客资料,或者是买一些Spring Cloud的书,可能没考虑过一个事儿,第一篇必须是用非常通俗的语言,把一个系统如果用Spring Cloud来做分布式架构的话,那么他需要用到Spring Cloud哪些组件,为什么
|
||||
|
||||
跟着书或者博客,直接上手开始搭建demo,开始做起来了
|
||||
|
||||
**分别用Dubbo和Spring Cloud做两个最基本的Demo工程**,用电商背景来搭建几个服务
|
||||
|
||||
比如说,现在我们有一个电商系统
|
||||
|
||||
用户现在需要下单购买一些东西这样子,订单系统、库存系统、仓储系统、积分系统
|
||||
|
||||
不太可能说用单块的架构,电商系统你想支撑多少用户量?10万注册用户,日活1000用户来你这里来购买?
|
||||
|
||||
百万级用户,十万级日活,单块系统就不太合适了,背后有几十个人的团队在协作开发,此时单块系统是绝对不合适的
|
||||
|
||||
梳理和明确一个概念:电商系统,拆分为了多个子系统,一次下订单的请求需要多个子系统协作完成,每个子系统都完成一部分的功能,多个子系统分别完成自己负责的事情,最终这个请求就处理完毕
|
||||
|
||||
我们不会让每个视频太长,按照我们大纲来讲,说是60讲,粗略的大纲,其实最终会拆分成可能上百讲,Spring Cloud架构原理,我们就要分为上下两讲来说
|
||||
![Spring Cloud核心架构原理](/docs/distributed-system/images/SpringCloud-core-architecture.png)
|
||||
|
||||
### Spring Cloud
|
||||
|
||||
#### Eureka:服务注册中心
|
||||
#### Feign:服务调用
|
||||
#### Ribbon:负载均衡
|
||||
#### Zuul/Spring Cloud Gatway:网关
|
||||
|
||||
这么多的系统,电商系统包含了20个子系统,每个子系统有20个核心接口,一共电商系统有400个接口,这么多的接口,直接对外暴露,前后端分离的架构,难道你让前端的同学必须记住你的20个系统的部署的机器,他们去做负载均衡,记住400个接口
|
||||
|
||||
|
||||
微服务那块,**网关**
|
||||
|
||||
**灰度发布**、**统一熔断**、**统一降级**、**统一缓存**、**统一限流**、**统一授权认证**
|
||||
|
||||
|
||||
|
||||
**Hystrix**、**链路追踪**、**stream**、很多组件,Hystrix这块东西,其实是会放在高可用的环节去说的,并不是说一个普通系统刚开始就必须得用的,没有用好的话,反而会出问题,**Hystrix线路熔断的框架**,必须得设计对应的一整套的限流方案、熔断方案、资源隔离、降级机制,配合降级机制来做
|
37
docs/distributed-system/deal-line.md
Executable file
@ -0,0 +1,37 @@
|
||||
|
||||
分布式系统核心的问题,服务框架、注册中心、网关系统、部署架构、超时重试、幂等防重,生产相关的问题,都搞定了,还是针对面试这块,人家到时候问你很多的生产问题,你必须回答的很好,你可以自己主动聊,说我们在生产环境里做了哪些优化
|
||||
|
||||
分布式事务,分布式锁
|
||||
|
||||
核心交易链路,核心数据链路,核心计算链路,核心业务链路,都建议要上分布式事务,保证核心链路的数据一致性
|
||||
|
||||
面试突击第一季,如果你没看过,务必去看一下,分布式事务这块,几种技术方案,我当时都讲解过了,离落地还有一段距离
|
||||
|
||||
分布式锁,在分布式系统中用的是非常多的,单块系统,不需要分布式事务,一个系统对应一个数据库,事务都是本地数据库的事务就可以了;锁,很多地方多线程并发修改一些共享资源,在单块系统内部用synchronized锁就可以搞定了
|
||||
|
||||
|
||||
|
||||
分布式系统,事务 -> 分布式事务,锁 -> 分布式锁
|
||||
|
||||
|
||||
|
||||
|
||||
订单服务 -> 创建订单
|
||||
-> 库存服务 -> 扣减库存
|
||||
-> 积分服务 -> 增加积分
|
||||
-> 仓储服务 -> 通知发货
|
||||
|
||||
|
||||
|
||||
微服务架构里,哪怕你就部署了一个MySQL在一台高配物理机上,但是在这个MySQL实例中会创建不同的database,db_order,db_inventory,db_credit,db_wms,订单服务涉及到5张表,db_order中就会有5张表
|
||||
|
||||
|
||||
|
||||
已经在自己本地插入了一条订单数据了,调用库存服务扣减库存,在db_inventory里执行sql扣减库存,此时库存服务执行失败了,但是对于订单服务,他可能是没有感知到,他的订单还是创建成功了,调用积分服务和仓储服务,积分增加了,还打算对商品进行发货
|
||||
|
||||
|
||||
订单服务 -> 创建了订单,库存服务 -> 扣减了库存,积分服务 -> 增加积分失败,一旦回滚了之后,就会导致创建的订单被取消了,没了,create语句,放在本地事务里,一旦发现失败了,此时就会回滚,就会导致
|
||||
|
||||
|
||||
|
||||
|
118
docs/distributed-system/distributed-design.md
Executable file
@ -0,0 +1,118 @@
|
||||
### 技术广度,为什么要这么考察一个人的技术广度?
|
||||
|
||||
假设,现在咱们公司,咱们团队负责一个系统,Dubbo / Spring Cloud作为服务框架,MQ(RocketMQ / Kafka),缓存(Redis),搜索(Elasticsearch)
|
||||
|
||||
在互联网行业里 + 非互联网的IT公司里,本身是有一套主流技术栈的
|
||||
|
||||
假设,业务发展特别的迅猛,需要团队扩招5个人进来,此时就要在外面的招聘网站里发布对应的职位JD,跟猎头合作,捞一些比较合适的人的简历进来
|
||||
|
||||
最最起码的,你应该去从哪个角度来考察这个获选人呢?职位JD要求是工作经验在3年~5年,有一定的社会工作经验的
|
||||
|
||||
### (1)技术广度来考察
|
||||
|
||||
招聘过来一个有几年经验的人,就不要再去培养他了,候选人的整个技术栈是比较匹配我们团队的技术栈的
|
||||
|
||||
从广度上把各种技术都给他考察一下,尤其是我们团队负责的系统涉及到的技术
|
||||
|
||||
Dubbo,熟悉吗?看你简历之前你们公司也是用的这个服务框架?说一下他的基本的工作原理,从服务注册到发现,他是怎么来运行的呢?你们当时服务注册中心是用的什么技术跟Dubbo搭配起来的?
|
||||
|
||||
看你简历上,说你们之前的系统里用过RocketMQ,来聊一聊,先说你们公司当时为什么要用MQ呢?MQ是怎么部署的?集群架构?高可用是如何保证的?RocketMQ的核心架构原理?工作原理?当时有没有考虑过发送到RocketMQ里的消息可能会丢失?
|
||||
|
||||
缓存(Redis),集群部署,Redis集群运行原理,Reids高可用的原理,Redis单线程高并发的原理,ES分布式架构的原理,一般你们的ES是怎么优化性能的
|
||||
|
||||
JVM,数据库和并发,都是必考的
|
||||
|
||||
我们希望你能够进来之后对JVM的基本原理都有一定的了解,然后呢如果你负责的一个系统出现了JVM的一个问题,比如内存溢出,或者是GC频繁的问题,希望你能独立的去分析和解决
|
||||
|
||||
数据库,MySQL,包括事务的原理、索引的原理、常见的SQL优化的手段
|
||||
|
||||
并发,本身是属于Java编程语言层面的一个基本的功能,本身有一些深度和难度的地方,写出来高效率的正确的并发程序
|
||||
|
||||
到此为止,确定,他进来的话,立马可以上手熟悉你们的架构、系统和代码,技术上不用做特殊的培养,很快就可以上手开始干活,基于你们现有的架构、现有的技术栈,上手就可以开始开发各种业务功能模块
|
||||
|
||||
常见的技术方案也会设计,常见的一些问题可以自己处理,常见的优化可以做
|
||||
|
||||
薪资在20k左右,差不多
|
||||
|
||||
### (2)项目经验
|
||||
|
||||
你平时用的各种技术在你的项目中如何结合业务来进行落地,然后你在项目的生产环境中落地一个技术之后,对他进行的生产优化、架构优化、生产实践是怎么来做的
|
||||
|
||||
分库分表,你说你简历里用过Sharding-JDBC来做分库分表
|
||||
|
||||
首先给我说说,你们的系统有哪些库哪些表,对应的是哪些业务呢?然后告诉我,核心的表每天新增的数据量有多少,目前已经积累了多少数据了?单表是百万级?还是千万级?你们是什么时候分的表?什么时候分的库?为什么?
|
||||
|
||||
在没有分表之前,SQL的性能大概如何?分表之后SQL的性能大概如何?分库之前每个数据库服务器上放多少GB的数据?一台服务器可以抗多少数据?分库之后拆分到几台数据库服务器上去?每台服务器现在放多少GB的数据?
|
||||
|
||||
很多同学出去面试,学习了很多的技术,无论是跟着一些视频课程,在线培训课程,或者是网上的博客,或者是一些书,积累了很多的知识,Sharding-JDBC分库分表基本的原理,常见的分库分表的技术方案
|
||||
|
||||
但是呢,这些同学往往是为了面试去准备的一些技术,但是其实从没在自己的项目中实践过,也从没思考过这些技术在自己项目落地的各种细节应该是如何来进行设计的
|
||||
|
||||
出去面试的时候,往往被 面试官一通追问项目的各种细节,然后就直接死了
|
||||
|
||||
### (3)生产经验
|
||||
|
||||
分布式、微服务这块,你说用过网关,网关调研了哪几种技术?对比一下他们的优缺点?最后你们是怎么进行技术选型的?你们这个系统每天的访问量多高?高峰期QPS多高?你们网关要抗多高的QPS?网关是如何部署的?部署了几台机器?每台机器的配置如何,几个核CPU,几个GB内存?
|
||||
|
||||
比如你的服务里加了一个新的接口,总不能你每次都手动在网关里配置一些新的接口和服务的对应关系,网关的动态路由是怎么做的?每次上线服务或者新的接口,跟你的网关动态路由是如何搭配起来的?
|
||||
|
||||
线上网关部署的机器在生产环境,你们的访问压力下,平时的高峰期的CPU负载如何
|
||||
|
||||
有没有考虑过网关的扩容?如果压力过大如何进行扩容?
|
||||
|
||||
有没有测算过网关进行请求路由的性能如何?一般一个请求经过网关层的路由对时间的开销大概是多少?
|
||||
|
||||
现在的话呢,假设说,网关当时在线上部署之后生产环境运行的时候有没有遇到过什么问题?比如并发的问题,性能的问题?如果要对生产环境的网关进行高并发、高性能的优化,你们是怎么做的呢?如果要做,你觉得从哪些角度入手可以去做?
|
||||
|
||||
总结一下:项目经验 + 生产经验,薪资是28k,30k,或者是32k,高级~资深的工程师,经验5年~8年左右,希望你能够去带一两个小弟,或者是带一个小小组,当一个小小的team leader
|
||||
|
||||
我肯定是希望你能够把生产环境的各种细节都cover住
|
||||
|
||||
项目经验,技术在项目中如何落地,各种细节,如果你是一个带几个小弟的资深工程师的话,此时你就必须对你负责的这个项目进行所有细节的把控,希望你能够结合业务和项目的细节去考虑技术如何落地
|
||||
|
||||
生产经验,把控项目部署后的生产环境里的情况,对各种情况做出对应的举措和优化的手段,全面为自己的项目来进行负责
|
||||
|
||||
如果是很多的大厂,哪怕是三五年经验,或者二三年经验,也会来考察这块项目经验和生产经验,越是大厂,对你的能力里要求就越高,希望你进来以后越能独当一面,所以就希望你不光只是有技术广度
|
||||
|
||||
### (4)技术深度
|
||||
|
||||
你有没有读过哪些开源项目的源码,RocketMQ,RocketMQ的源码,Dubbo的源码,如果你精通一些技术的源码的话,为什么会特别的有价值,有竞争力,让面试官更加的倾向于用你呢?
|
||||
|
||||
技术深度决定了你的技术功底,决定了在生产环境随时你的系统使用的各种技术可能会遇到一些异常或者报错,导致系统挂掉
|
||||
|
||||
Dubbo、RocketMQ、Kafka、ES,随时可能有问题,比如说Dubbo随时可能会报错,RocketMQ突然异常了无法写入消息,ES突然性能巨慢,一次查询要十几秒的时间
|
||||
|
||||
必须需要那些精通一些技术源码的同学,现场根据异常去分析技术的源码,从源码级别定位到问题的所在,然后解决问题
|
||||
|
||||
大厂,很可能会考察你的技术深度,如果发现你没有什么技术深度,那么可能你就没有太大的竞争优势
|
||||
|
||||
### (5)系统设计
|
||||
|
||||
往简单了说,就是会考察一些问题,比如说让你来设计秒杀系统,设计一个12306火车票购票系统,支撑几亿用户买火车票,你会如何来设计,让你设计一个微信红包系统,你会如何来考虑
|
||||
|
||||
大厂,越是对你的能力要求很高,希望你进来以后独大是哪个一面,哪怕你就20k的薪资,也希望你是进来独当一面的,独立负责一块东西
|
||||
|
||||
独立的设计一块系统,独立的设计一个小的架构,此时就会要求你有一定的独立的系统设计的能力,30k,40k的薪资才会考察
|
||||
|
||||
30k,40k,50k,更高薪资的职位,技术专家,架构师,要求你本来在你们公司就负责了一大块系统的架构,带了10来个小弟,负责了一个大系统,有丰富的大型架构设计的经验,架构设计的方方面面,从理论到深度,再到经验,都很丰富
|
||||
|
||||
|
||||
|
||||
我们的课程每天都会有一个作业,引导大家把学习到的项目经验、技术方案和生产优化落地到自己负责的项目中去,让大家出去面试的时候,可以把各种技术结合自己的项目来回答面试官的各种深度拷问
|
||||
|
||||
大家不要小看这个,根据我多年的面试经验来看,拥有这个技能的人凤毛麟角,这种人出去绝对是各大公司争抢的对象。
|
||||
|
||||
|
||||
**所以希望大家好好完成每天的作业,我布置的大量作业,就是为了帮你锻造出这种能力**
|
||||
|
||||
**学习课程以及完成作业的过程中,大家一定会有很多的问题,可以到专栏的评论区去提问**
|
||||
|
||||
**每天我都会和之前带出来的一批阿里、蚂蚁金服、滴滴的优秀同学给大家进行答疑,并且我们还有专门的付费用户的微信群,大家可以在微信群里跟我们一起进行技术交流**
|
||||
|
||||
**如果你能坚持下来,学满6季,还可以获取私人定制的面试一条龙VIP服务**
|
||||
|
||||
**如果是连续6季面试训练营都购买的同学,还可以获取面试一条龙VIP服务**
|
||||
|
||||
**具体信息大家看“狸猫技术窝”公众号的知识店铺内的训练营详情即可**
|
||||
|
||||
**具体可参见训练营目录下的《训练营专属服务》文档。简单来说,这个私人定制的面试VIP服务,会为你的跳槽面试全程保驾护航**
|
3
docs/distributed-system/distributed-framework-selection.md
Executable file
@ -0,0 +1,3 @@
|
||||
**Spring Cloud**入门和使用级别的资料,建议大家自行百度,面试训练营,不是说针对每个技术详细给大家讲解的一个课程,我们会针对每个技术推出重磅的项目实战课程
|
||||
|
||||
**自己公司如果是分布式的架构,你们当前选用的是Spring Cloud?Dubbo?自己研发的服务框架?对比一下各种服务框架的优点和缺点,技术选型,为什么?**
|
346
docs/distributed-system/distributed-lock-redis-vs-zookeeper.md
Executable file
@ -0,0 +1,346 @@
|
||||
## 面试题
|
||||
一般实现分布式锁都有哪些方式?使用 redis 如何设计分布式锁?使用 zk 来设计分布式锁可以吗?这两种分布式锁的实现方式哪种效率比较高?
|
||||
|
||||
## 面试官心理分析
|
||||
其实一般问问题,都是这么问的,先问问你 zk,然后其实是要过渡到 zk 相关的一些问题里去,比如分布式锁。因为在分布式系统开发中,分布式锁的使用场景还是很常见的。
|
||||
|
||||
## 面试题剖析
|
||||
### redis 分布式锁
|
||||
|
||||
官方叫做 `RedLock` 算法,是 redis 官方支持的分布式锁算法。
|
||||
|
||||
这个分布式锁有 3 个重要的考量点:
|
||||
|
||||
- 互斥(只能有一个客户端获取锁)
|
||||
- 不能死锁
|
||||
- 容错(只要大部分 redis 节点创建了这把锁就可以)
|
||||
|
||||
#### redis 最普通的分布式锁
|
||||
|
||||
第一个最普通的实现方式,就是在 redis 里使用 `setnx` 命令创建一个 key,这样就算加锁。
|
||||
|
||||
|
||||
```r
|
||||
SET resource_name my_random_value NX PX 30000
|
||||
```
|
||||
|
||||
执行这个命令就 ok。
|
||||
|
||||
- `NX`:表示只有 `key` 不存在的时候才会设置成功。(如果此时 redis 中存在这个 key,那么设置失败,返回 `nil`)
|
||||
- `PX 30000`:意思是 30s 后锁自动释放。别人创建的时候如果发现已经有了就不能加锁了。
|
||||
|
||||
释放锁就是删除 key ,但是一般可以用 `lua` 脚本删除,判断 value 一样才删除:
|
||||
|
||||
```lua
|
||||
-- 删除锁的时候,找到 key 对应的 value,跟自己传过去的 value 做比较,如果是一样的才删除。
|
||||
if redis.call("get",KEYS[1]) == ARGV[1] then
|
||||
return redis.call("del",KEYS[1])
|
||||
else
|
||||
return 0
|
||||
end
|
||||
```
|
||||
|
||||
为啥要用 `random_value` 随机值呢?因为如果某个客户端获取到了锁,但是阻塞了很长时间才执行完,比如说超过了 30s,此时可能已经自动释放锁了,此时可能别的客户端已经获取到了这个锁,要是你这个时候直接删除 key 的话会有问题,所以得用随机值加上面的 `lua` 脚本来释放锁。
|
||||
|
||||
但是这样是肯定不行的。因为如果是普通的 redis 单实例,那就是单点故障。或者是 redis 普通主从,那 redis 主从异步复制,如果主节点挂了(key 就没有了),key 还没同步到从节点,此时从节点切换为主节点,别人就可以 set key,从而拿到锁。
|
||||
|
||||
#### RedLock 算法
|
||||
这个场景是假设有一个 redis cluster,有 5 个 redis master 实例。然后执行如下步骤获取一把锁:
|
||||
|
||||
1. 获取当前时间戳,单位是毫秒;
|
||||
2. 跟上面类似,轮流尝试在每个 master 节点上创建锁,过期时间较短,一般就几十毫秒;
|
||||
3. 尝试在**大多数节点**上建立一个锁,比如 5 个节点就要求是 3 个节点 `n / 2 + 1`;
|
||||
4. 客户端计算建立好锁的时间,如果建立锁的时间小于超时时间,就算建立成功了;
|
||||
5. 要是锁建立失败了,那么就依次之前建立过的锁删除;
|
||||
6. 只要别人建立了一把分布式锁,你就得**不断轮询去尝试获取锁**。
|
||||
|
||||
![redis-redlock](/images/redis-redlock.png)
|
||||
|
||||
[Redis 官方](https://redis.io/)给出了以上两种基于 Redis 实现分布式锁的方法,详细说明可以查看:https://redis.io/topics/distlock 。
|
||||
|
||||
### zk 分布式锁
|
||||
|
||||
zk 分布式锁,其实可以做的比较简单,就是某个节点尝试创建临时 znode,此时创建成功了就获取了这个锁;这个时候别的客户端来创建锁会失败,只能**注册个监听器**监听这个锁。释放锁就是删除这个 znode,一旦释放掉就会通知客户端,然后有一个等待着的客户端就可以再次重新加锁。
|
||||
|
||||
```java
|
||||
/**
|
||||
* ZooKeeperSession
|
||||
*
|
||||
* @author bingo
|
||||
* @since 2018/11/29
|
||||
*
|
||||
*/
|
||||
public class ZooKeeperSession {
|
||||
|
||||
private static CountDownLatch connectedSemaphore = new CountDownLatch(1);
|
||||
|
||||
private ZooKeeper zookeeper;
|
||||
private CountDownLatch latch;
|
||||
|
||||
public ZooKeeperSession() {
|
||||
try {
|
||||
this.zookeeper = new ZooKeeper("192.168.31.187:2181,192.168.31.19:2181,192.168.31.227:2181", 50000, new ZooKeeperWatcher());
|
||||
try {
|
||||
connectedSemaphore.await();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
System.out.println("ZooKeeper session established......");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分布式锁
|
||||
*
|
||||
* @param productId
|
||||
*/
|
||||
public Boolean acquireDistributedLock(Long productId) {
|
||||
String path = "/product-lock-" + productId;
|
||||
|
||||
try {
|
||||
zookeeper.create(path, "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
while (true) {
|
||||
try {
|
||||
// 相当于是给node注册一个监听器,去看看这个监听器是否存在
|
||||
Stat stat = zk.exists(path, true);
|
||||
|
||||
if (stat != null) {
|
||||
this.latch = new CountDownLatch(1);
|
||||
this.latch.await(waitTime, TimeUnit.MILLISECONDS);
|
||||
this.latch = null;
|
||||
}
|
||||
zookeeper.create(path, "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
|
||||
return true;
|
||||
} catch (Exception ee) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放掉一个分布式锁
|
||||
*
|
||||
* @param productId
|
||||
*/
|
||||
public void releaseDistributedLock(Long productId) {
|
||||
String path = "/product-lock-" + productId;
|
||||
try {
|
||||
zookeeper.delete(path, -1);
|
||||
System.out.println("release the lock for product[id=" + productId + "]......");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 建立zk session的watcher
|
||||
*
|
||||
* @author bingo
|
||||
* @since 2018/11/29
|
||||
*
|
||||
*/
|
||||
private class ZooKeeperWatcher implements Watcher {
|
||||
|
||||
public void process(WatchedEvent event) {
|
||||
System.out.println("Receive watched event: " + event.getState());
|
||||
|
||||
if (KeeperState.SyncConnected == event.getState()) {
|
||||
connectedSemaphore.countDown();
|
||||
}
|
||||
|
||||
if (this.latch != null) {
|
||||
this.latch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 封装单例的静态内部类
|
||||
*
|
||||
* @author bingo
|
||||
* @since 2018/11/29
|
||||
*
|
||||
*/
|
||||
private static class Singleton {
|
||||
|
||||
private static ZooKeeperSession instance;
|
||||
|
||||
static {
|
||||
instance = new ZooKeeperSession();
|
||||
}
|
||||
|
||||
public static ZooKeeperSession getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单例
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ZooKeeperSession getInstance() {
|
||||
return Singleton.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化单例的便捷方法
|
||||
*/
|
||||
public static void init() {
|
||||
getInstance();
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
也可以采用另一种方式,创建临时顺序节点:
|
||||
|
||||
如果有一把锁,被多个人给竞争,此时多个人会排队,第一个拿到锁的人会执行,然后释放锁;后面的每个人都会去监听**排在自己前面**的那个人创建的 node 上,一旦某个人释放了锁,排在自己后面的人就会被 zookeeper 给通知,一旦被通知了之后,就 ok 了,自己就获取到了锁,就可以执行代码了。
|
||||
```java
|
||||
public class ZooKeeperDistributedLock implements Watcher {
|
||||
|
||||
private ZooKeeper zk;
|
||||
private String locksRoot = "/locks";
|
||||
private String productId;
|
||||
private String waitNode;
|
||||
private String lockNode;
|
||||
private CountDownLatch latch;
|
||||
private CountDownLatch connectedLatch = new CountDownLatch(1);
|
||||
private int sessionTimeout = 30000;
|
||||
|
||||
public ZooKeeperDistributedLock(String productId) {
|
||||
this.productId = productId;
|
||||
try {
|
||||
String address = "192.168.31.187:2181,192.168.31.19:2181,192.168.31.227:2181";
|
||||
zk = new ZooKeeper(address, sessionTimeout, this);
|
||||
connectedLatch.await();
|
||||
} catch (IOException e) {
|
||||
throw new LockException(e);
|
||||
} catch (KeeperException e) {
|
||||
throw new LockException(e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new LockException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void process(WatchedEvent event) {
|
||||
if (event.getState() == KeeperState.SyncConnected) {
|
||||
connectedLatch.countDown();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.latch != null) {
|
||||
this.latch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
public void acquireDistributedLock() {
|
||||
try {
|
||||
if (this.tryLock()) {
|
||||
return;
|
||||
} else {
|
||||
waitForLock(waitNode, sessionTimeout);
|
||||
}
|
||||
} catch (KeeperException e) {
|
||||
throw new LockException(e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new LockException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean tryLock() {
|
||||
try {
|
||||
// 传入进去的locksRoot + “/” + productId
|
||||
// 假设productId代表了一个商品id,比如说1
|
||||
// locksRoot = locks
|
||||
// /locks/10000000000,/locks/10000000001,/locks/10000000002
|
||||
lockNode = zk.create(locksRoot + "/" + productId, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
|
||||
|
||||
// 看看刚创建的节点是不是最小的节点
|
||||
// locks:10000000000,10000000001,10000000002
|
||||
List<String> locks = zk.getChildren(locksRoot, false);
|
||||
Collections.sort(locks);
|
||||
|
||||
if(lockNode.equals(locksRoot+"/"+ locks.get(0))){
|
||||
//如果是最小的节点,则表示取得锁
|
||||
return true;
|
||||
}
|
||||
|
||||
//如果不是最小的节点,找到比自己小1的节点
|
||||
int previousLockIndex = -1;
|
||||
for(int i = 0; i < locks.size(); i++) {
|
||||
if(lockNode.equals(locksRoot + “/” + locks.get(i))) {
|
||||
previousLockIndex = i - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.waitNode = locks.get(previousLockIndex);
|
||||
} catch (KeeperException e) {
|
||||
throw new LockException(e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new LockException(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean waitForLock(String waitNode, long waitTime) throws InterruptedException, KeeperException {
|
||||
Stat stat = zk.exists(locksRoot + "/" + waitNode, true);
|
||||
if (stat != null) {
|
||||
this.latch = new CountDownLatch(1);
|
||||
this.latch.await(waitTime, TimeUnit.MILLISECONDS);
|
||||
this.latch = null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void unlock() {
|
||||
try {
|
||||
// 删除/locks/10000000000节点
|
||||
// 删除/locks/10000000001节点
|
||||
System.out.println("unlock " + lockNode);
|
||||
zk.delete(lockNode, -1);
|
||||
lockNode = null;
|
||||
zk.close();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (KeeperException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public class LockException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public LockException(String e) {
|
||||
super(e);
|
||||
}
|
||||
|
||||
public LockException(Exception e) {
|
||||
super(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### redis 分布式锁和 zk 分布式锁的对比
|
||||
|
||||
- redis 分布式锁,其实**需要自己不断去尝试获取锁**,比较消耗性能。
|
||||
- zk 分布式锁,获取不到锁,注册个监听器即可,不需要不断主动尝试获取锁,性能开销较小。
|
||||
|
||||
另外一点就是,如果是 redis 获取锁的那个客户端 出现 bug 挂了,那么只能等待超时时间之后才能释放锁;而 zk 的话,因为创建的是临时 znode,只要客户端挂了,znode 就没了,此时就自动释放锁。
|
||||
|
||||
redis 分布式锁大家没发现好麻烦吗?遍历上锁,计算时间等等......zk 的分布式锁语义清晰实现简单。
|
||||
|
||||
所以先不分析太多的东西,就说这两点,我个人实践认为 zk 的分布式锁比 redis 的分布式锁牢靠、而且模型简单易用。
|
6
docs/distributed-system/distributed-lock-taobao-and-jingdong.md
Executable file
@ -0,0 +1,6 @@
|
||||
|
||||
大公司一般有分布式kv存储,tair,redis,mongodb,高并发,每秒几万几十万都没问题,甚至每秒百万
|
||||
|
||||
实时库存数据放kv存储里去,先查库存再扣减库存,你在操作库存的时候,直接扣减,如果你发现扣减之后是负数的话,此时就认为库存超卖了,回滚刚才的扣减,返回提示给用户。对kv做的库存修改写MQ,异步同步落数据库,相当于异步双写,用分布式kv抗高并发,做好一致性方案
|
||||
|
||||
|
11
docs/distributed-system/distributed-lock.md
Executable file
@ -0,0 +1,11 @@
|
||||
|
||||
下订单的环节,支付之前,创建一个订单
|
||||
|
||||
![distributed-lock](/docs/distributed-system/images/distributed-lock.png)
|
||||
创建一个订单,订单里会指定对哪些商品要购买多少件,此时就需要走一个流程,校验一下库存
|
||||
|
||||
查库存,确认库存充足,锁定库存
|
||||
|
||||
这个过程必须用分布式锁,锁掉这个商品的库存,对一个商品的购买同一时间只能有一个人操作
|
||||
|
||||
redis和zookeeper实现分布式锁的原理,在之前面试突击第一季都讲过了,大家没看过的可以去看一下
|
129
docs/distributed-system/distributed-session.md
Executable file
@ -0,0 +1,129 @@
|
||||
## 面试题
|
||||
集群部署时的分布式 session 如何实现?
|
||||
|
||||
## 面试官心理分析
|
||||
面试官问了你一堆 dubbo 是怎么玩儿的,你会玩儿 dubbo 就可以把单块系统弄成分布式系统,然后分布式之后接踵而来的就是一堆问题,最大的问题就是**分布式事务**、**接口幂等性**、**分布式锁**,还有最后一个就是**分布式 session**。
|
||||
|
||||
当然了,分布式系统中的问题何止这么一点,非常之多,复杂度很高,这里只是说一下常见的几个问题,也是面试的时候常问的几个。
|
||||
|
||||
## 面试题剖析
|
||||
session 是啥?浏览器有个 cookie,在一段时间内这个 cookie 都存在,然后每次发请求过来都带上一个特殊的 `jsessionid cookie`,就根据这个东西,在服务端可以维护一个对应的 session 域,里面可以放点数据。
|
||||
|
||||
一般的话只要你没关掉浏览器,cookie 还在,那么对应的那个 session 就在,但是如果 cookie 没了,session 也就没了。常见于什么购物车之类的东西,还有登录状态保存之类的。
|
||||
|
||||
这个不多说了,懂 Java 的都该知道这个。
|
||||
|
||||
单块系统的时候这么玩儿 session 没问题,但是你要是分布式系统呢,那么多的服务,session 状态在哪儿维护啊?
|
||||
|
||||
其实方法很多,但是常见常用的是以下几种:
|
||||
|
||||
### 完全不用 session
|
||||
使用 JWT Token 储存用户身份,然后再从数据库或者 cache 中获取其他的信息。这样无论请求分配到哪个服务器都无所谓。
|
||||
|
||||
### tomcat + redis
|
||||
这个其实还挺方便的,就是使用 session 的代码,跟以前一样,还是基于 tomcat 原生的 session 支持即可,然后就是用一个叫做 `Tomcat RedisSessionManager` 的东西,让所有我们部署的 tomcat 都将 session 数据存储到 redis 即可。
|
||||
|
||||
在 tomcat 的配置文件中配置:
|
||||
|
||||
```xml
|
||||
<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />
|
||||
|
||||
<Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"
|
||||
host="{redis.host}"
|
||||
port="{redis.port}"
|
||||
database="{redis.dbnum}"
|
||||
maxInactiveInterval="60"/>
|
||||
```
|
||||
|
||||
然后指定 redis 的 host 和 port 就 ok 了。
|
||||
|
||||
```xml
|
||||
<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />
|
||||
<Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"
|
||||
sentinelMaster="mymaster"
|
||||
sentinels="<sentinel1-ip>:26379,<sentinel2-ip>:26379,<sentinel3-ip>:26379"
|
||||
maxInactiveInterval="60"/>
|
||||
```
|
||||
|
||||
还可以用上面这种方式基于 redis 哨兵支持的 redis 高可用集群来保存 session 数据,都是 ok 的。
|
||||
|
||||
### spring session + redis
|
||||
上面所说的第二种方式会与 tomcat 容器重耦合,如果我要将 web 容器迁移成 jetty,难道还要重新把 jetty 都配置一遍?
|
||||
|
||||
因为上面那种 tomcat + redis 的方式好用,但是会**严重依赖于web容器**,不好将代码移植到其他 web 容器上去,尤其是你要是换了技术栈咋整?比如换成了 spring cloud 或者是 spring boot 之类的呢?
|
||||
|
||||
所以现在比较好的还是基于 Java 一站式解决方案,也就是 spring。人家 spring 基本上承包了大部分我们需要使用的框架,spirng cloud 做微服务,spring boot 做脚手架,所以用 sping session 是一个很好的选择。
|
||||
|
||||
在 pom.xml 中配置:
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.springframework.session</groupId>
|
||||
<artifactId>spring-session-data-redis</artifactId>
|
||||
<version>1.2.1.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
<version>2.8.1</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
在 spring 配置文件中配置:
|
||||
```xml
|
||||
<bean id="redisHttpSessionConfiguration"
|
||||
class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
|
||||
<property name="maxInactiveIntervalInSeconds" value="600"/>
|
||||
</bean>
|
||||
|
||||
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
|
||||
<property name="maxTotal" value="100" />
|
||||
<property name="maxIdle" value="10" />
|
||||
</bean>
|
||||
|
||||
<bean id="jedisConnectionFactory"
|
||||
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" destroy-method="destroy">
|
||||
<property name="hostName" value="${redis_hostname}"/>
|
||||
<property name="port" value="${redis_port}"/>
|
||||
<property name="password" value="${redis_pwd}" />
|
||||
<property name="timeout" value="3000"/>
|
||||
<property name="usePool" value="true"/>
|
||||
<property name="poolConfig" ref="jedisPoolConfig"/>
|
||||
</bean>
|
||||
```
|
||||
|
||||
在 web.xml 中配置:
|
||||
```xml
|
||||
<filter>
|
||||
<filter-name>springSessionRepositoryFilter</filter-name>
|
||||
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
|
||||
</filter>
|
||||
<filter-mapping>
|
||||
<filter-name>springSessionRepositoryFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
```
|
||||
|
||||
示例代码:
|
||||
```java
|
||||
@RestController
|
||||
@RequestMapping("/test")
|
||||
public class TestController {
|
||||
|
||||
@RequestMapping("/putIntoSession")
|
||||
public String putIntoSession(HttpServletRequest request, String username) {
|
||||
request.getSession().setAttribute("name", "leo");
|
||||
return "ok";
|
||||
}
|
||||
|
||||
@RequestMapping("/getFromSession")
|
||||
public String getFromSession(HttpServletRequest request, Model model){
|
||||
String name = request.getSession().getAttribute("name");
|
||||
return name;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
上面的代码就是 ok 的,给 sping session 配置基于 redis 来存储 session 数据,然后配置了一个 spring session 的过滤器,这样的话,session 相关操作都会交给 spring session 来管了。接着在代码中,就用原生的 session 操作,就是直接基于 spring sesion 从 redis 中获取数据了。
|
||||
|
||||
实现分布式的会话有很多种方式,我说的只不过是比较常见的几种方式,tomcat + redis 早期比较常用,但是会重耦合到 tomcat 中;近些年,通过 spring session 来实现。
|
27
docs/distributed-system/distributed-system-idempotency.md
Executable file
@ -0,0 +1,27 @@
|
||||
## 面试题
|
||||
分布式服务接口的幂等性如何设计(比如不能重复扣款)?
|
||||
|
||||
## 面试官心理分析
|
||||
从这个问题开始,面试官就已经进入了**实际的生产问题**的面试了。
|
||||
|
||||
一个分布式系统中的某个接口,该如何保证幂等性?这个事儿其实是你做分布式系统的时候必须要考虑的一个生产环境的技术问题。啥意思呢?
|
||||
|
||||
你看,假如你有个服务提供一些接口供外部调用,这个服务部署在了 5 台机器上,接着有个接口就是**付款接口**。然后人家用户在前端上操作的时候,不知道为啥,总之就是一个订单**不小心发起了两次支付请求**,然后这俩请求分散在了这个服务部署的不同的机器上,好了,结果一个订单扣款扣两次。
|
||||
|
||||
或者是订单系统调用支付系统进行支付,结果不小心因为**网络超时**了,然后订单系统走了前面我们看到的那个重试机制,咔嚓给你重试了一把,好,支付系统收到一个支付请求两次,而且因为负载均衡算法落在了不同的机器上,尴尬了。。。
|
||||
|
||||
所以你肯定得知道这事儿,否则你做出来的分布式系统恐怕容易埋坑。
|
||||
|
||||
## 面试题剖析
|
||||
这个不是技术问题,这个没有通用的一个方法,这个应该**结合业务**来保证幂等性。
|
||||
|
||||
所谓**幂等性**,就是说一个接口,多次发起同一个请求,你这个接口得保证结果是准确的,比如不能多扣款、不能多插入一条数据、不能将统计值多加了 1。这就是幂等性。
|
||||
|
||||
其实保证幂等性主要是三点:
|
||||
- 对于每个请求必须有一个唯一的标识,举个栗子:订单支付请求,肯定得包含订单 id,一个订单 id 最多支付一次,对吧。
|
||||
- 每次处理完请求之后,必须有一个记录标识这个请求处理过了。常见的方案是在 mysql 中记录个状态啥的,比如支付之前记录一条这个订单的支付流水。
|
||||
- 每次接收请求需要进行判断,判断之前是否处理过。比如说,如果有一个订单已经支付了,就已经有了一条支付流水,那么如果重复发送这个请求,则此时先插入支付流水,orderId 已经存在了,唯一键约束生效,报错插入不进去的。然后你就不用再扣款了。
|
||||
|
||||
实际运作过程中,你要结合自己的业务来,比如说利用 redis,用 orderId 作为唯一键。只有成功插入这个支付流水,才可以执行实际的支付扣款。
|
||||
|
||||
要求是支付一个订单,必须插入一条支付流水,order_id 建一个唯一键 `unique key`。你在支付一个订单之前,先插入一条支付流水,order_id 就已经进去了。你就可以写一个标识到 redis 里面去,`set order_id payed`,下一次重复请求过来了,先查 redis 的 order_id 对应的 value,如果是 `payed` 就说明已经支付过了,你就别重复支付了。
|
30
docs/distributed-system/distributed-system-interview.md
Executable file
@ -0,0 +1,30 @@
|
||||
## 分布式系统面试连环炮
|
||||
有一些同学,之前呢主要是做传统行业,或者外包项目,一直是在那种小的公司,技术一直都搞的比较简单。他们有共同的一个问题,就是都没怎么搞过分布式系统,现在互联网公司,一般都是做分布式的系统,大家都不是做底层的分布式系统、分布式存储系统 hadoop hdfs、分布式计算系统 hadoop mapreduce / spark、分布式流式计算系统 storm。
|
||||
|
||||
分布式业务系统,就是把原来用 Java 开发的一个大块系统,给拆分成**多个子系统**,多个子系统之间互相调用,形成一个大系统的整体。假设原来你做了一个 OA 系统,里面包含了权限模块、员工模块、请假模块、财务模块,一个工程,里面包含了一堆模块,模块与模块之间会互相去调用,1 台机器部署。现在如果你把这个系统给拆开,权限系统、员工系统、请假系统、财务系统 4 个系统,4 个工程,分别在 4 台机器上部署。一个请求过来,完成这个请求,这个员工系统,调用权限系统,调用请假系统,调用财务系统,4 个系统分别完成了一部分的事情,最后 4 个系统都干完了以后,才认为是这个请求已经完成了。
|
||||
|
||||
![simple-distributed-system-oa](/images/simple-distributed-system-oa.png)
|
||||
|
||||
> 近几年开始兴起和流行 Spring Cloud,刚流行,还没开始普及,目前普及的是 dubbo,因此这里也主要讲 dubbo。
|
||||
|
||||
面试官可能会问你以下问题。
|
||||
### 为什么要进行系统拆分?
|
||||
- 为什么要进行系统拆分?如何进行系统拆分?拆分后不用dubbo可以吗?dubbo和thrift有什么区别呢?
|
||||
### 分布式服务框架
|
||||
- 说一下的 dubbo 的工作原理?注册中心挂了可以继续通信吗?
|
||||
- dubbo 支持哪些序列化协议?说一下 hessian 的数据结构?PB 知道吗?为什么 PB 的效率是最高的?
|
||||
- dubbo 负载均衡策略和高可用策略都有哪些?动态代理策略呢?
|
||||
- dubbo 的 spi 思想是什么?
|
||||
- 如何基于 dubbo 进行服务治理、服务降级、失败重试以及超时重试?
|
||||
- 分布式服务接口的幂等性如何设计(比如不能重复扣款)?
|
||||
- 分布式服务接口请求的顺序性如何保证?
|
||||
- 如何自己设计一个类似 dubbo 的 rpc 框架?
|
||||
|
||||
### 分布式锁
|
||||
- 使用 redis 如何设计分布式锁?使用 zk 来设计分布式锁可以吗?这两种分布式锁的实现方式哪种效率比较高?
|
||||
|
||||
### 分布式事务
|
||||
- 分布式事务了解吗?你们如何解决分布式事务问题的?TCC 如果出现网络连不通怎么办?XA 的一致性如何保证?
|
||||
|
||||
### 分布式会话
|
||||
- 集群部署时的分布式 session 如何实现?
|
20
docs/distributed-system/distributed-system-request-sequence.md
Executable file
@ -0,0 +1,20 @@
|
||||
## 面试题
|
||||
分布式服务接口请求的顺序性如何保证?
|
||||
|
||||
## 面试官心理分析
|
||||
其实分布式系统接口的调用顺序,也是个问题,一般来说是不用保证顺序的。但是**有时候**可能确实是需要**严格的顺序**保证。给大家举个例子,你服务 A 调用服务 B,先插入再删除。好,结果俩请求过去了,落在不同机器上,可能插入请求因为某些原因执行慢了一些,导致删除请求先执行了,此时因为没数据所以啥效果也没有;结果这个时候插入请求过来了,好,数据插入进去了,那就尴尬了。
|
||||
|
||||
本来应该是 “先插入 -> 再删除”,这条数据应该没了,结果现在 “先删除 -> 再插入”,数据还存在,最后你死都想不明白是怎么回事。
|
||||
|
||||
所以这都是分布式系统一些很常见的问题。
|
||||
|
||||
## 面试题剖析
|
||||
首先,一般来说,个人建议是,你们从业务逻辑上设计的这个系统最好是不需要这种顺序性的保证,因为一旦引入顺序性保障,比如使用**分布式锁**,会**导致系统复杂度上升**,而且会带来**效率低下**,热点数据压力过大等问题。
|
||||
|
||||
下面我给个我们用过的方案吧,简单来说,首先你得用 dubbo 的一致性 hash 负载均衡策略,将比如某一个订单 id 对应的请求都给分发到某个机器上去,接着就是在那个机器上,因为可能还是多线程并发执行的,你可能得立即将某个订单 id 对应的请求扔一个**内存队列**里去,强制排队,这样来确保他们的顺序性。
|
||||
|
||||
![distributed-system-request-sequence](/images/distributed-system-request-sequence.png)
|
||||
|
||||
但是这样引发的后续问题就很多,比如说要是某个订单对应的请求特别多,造成某台机器成**热点**怎么办?解决这些问题又要开启后续一连串的复杂技术方案......曾经这类问题弄的我们头疼不已,所以,还是建议什么呢?
|
||||
|
||||
最好是比如说刚才那种,一个订单的插入和删除操作,能不能合并成一个操作,就是一个删除,或者是其它什么,避免这种问题的产生。
|
22
docs/distributed-system/distributed-transaction-tcc.md
Executable file
@ -0,0 +1,22 @@
|
||||
|
||||
类似TCC事务的,开源框架,ByteTCC,Himly,个人技术高手自己写的,star也不少,也有一些中小型公司生产环境用了类似的分布式事务框架,知名度和普及型不高;很多公司,对类似的分布式事务,是自己写一些类似的框架
|
||||
|
||||
|
||||
|
||||
阿里开源了分布式事务框架,fescar,技术体系上有很多地方都是有自己的东西,seata,阿里开源的分布式事务框架,类似TCC事务,seata来做,这个框架是经历过阿里生产环境大量的考验的一个框架
|
||||
|
||||
支持dubbo、spring cloud两种服务框架,都是可以的
|
||||
|
||||
|
||||
|
||||
|
||||
可靠消息最终一致性方案,面试突击第一季里都说过,ActiveMQ封装一个可靠消息服务,基于RabbitMQ封装,自己开发一个可靠消息服务,收到一个消息之后,会尝试投递到MQ上去,投递失败,重试投递
|
||||
|
||||
人家消费成功了以后必须回调他一个接口,通知他消息处理成功,如果一段时间后发现消息还是没有处理成功,此时会再次投递消息到MQ上去,在本地数据库里存放一些消息,基于ActiveMQ / RabbitMQ来实现消息的异步投递和消费
|
||||
|
||||
|
||||
|
||||
RocketMQ,作为MQ中间件,提供了分布式事务支持,他把可靠消息服务需要实现的功能逻辑都做好了
|
||||
|
||||
|
||||
|
92
docs/distributed-system/distributed-transaction.md
Executable file
@ -0,0 +1,92 @@
|
||||
## 面试题
|
||||
分布式事务了解吗?你们是如何解决分布式事务问题的?
|
||||
|
||||
## 面试官心理分析
|
||||
只要聊到你做了分布式系统,必问分布式事务,你对分布式事务一无所知的话,确实会很坑,你起码得知道有哪些方案,一般怎么来做,每个方案的优缺点是什么。
|
||||
|
||||
现在面试,分布式系统成了标配,而分布式系统带来的**分布式事务**也成了标配了。因为你做系统肯定要用事务吧,如果是分布式系统,肯定要用分布式事务吧。先不说你搞过没有,起码你得明白有哪几种方案,每种方案可能有啥坑?比如 TCC 方案的网络问题、XA 方案的一致性问题。
|
||||
|
||||
## 面试题剖析
|
||||
分布式事务的实现主要有以下 5 种方案:
|
||||
|
||||
- XA 方案
|
||||
- TCC 方案
|
||||
- 本地消息表
|
||||
- 可靠消息最终一致性方案
|
||||
- 最大努力通知方案
|
||||
|
||||
### 两阶段提交方案/XA方案
|
||||
所谓的 XA 方案,即:两阶段提交,有一个**事务管理器**的概念,负责协调多个数据库(资源管理器)的事务,事务管理器先问问各个数据库你准备好了吗?如果每个数据库都回复 ok,那么就正式提交事务,在各个数据库上执行操作;如果任何其中一个数据库回答不 ok,那么就回滚事务。
|
||||
|
||||
这种分布式事务方案,比较适合单块应用里,跨多个库的分布式事务,而且因为严重依赖于数据库层面来搞定复杂的事务,效率很低,绝对不适合高并发的场景。如果要玩儿,那么基于 `Spring + JTA` 就可以搞定,自己随便搜个 demo 看看就知道了。
|
||||
|
||||
这个方案,我们很少用,一般来说**某个系统内部如果出现跨多个库**的这么一个操作,是**不合规**的。我可以给大家介绍一下, 现在微服务,一个大的系统分成几十个甚至几百个服务。一般来说,我们的规定和规范,是要求**每个服务只能操作自己对应的一个数据库**。
|
||||
|
||||
如果你要操作别的服务对应的库,不允许直连别的服务的库,违反微服务架构的规范,你随便交叉胡乱访问,几百个服务的话,全体乱套,这样的一套服务是没法管理的,没法治理的,可能会出现数据被别人改错,自己的库被别人写挂等情况。
|
||||
|
||||
如果你要操作别人的服务的库,你必须是通过**调用别的服务的接口**来实现,绝对不允许交叉访问别人的数据库。
|
||||
|
||||
![distributed-transacion-XA](/images/distributed-transaction-XA.png)
|
||||
|
||||
### TCC 方案
|
||||
TCC 的全称是:`Try`、`Confirm`、`Cancel`。
|
||||
|
||||
- Try 阶段:这个阶段说的是对各个服务的资源做检测以及对资源进行**锁定或者预留**。
|
||||
- Confirm 阶段:这个阶段说的是在各个服务中**执行实际的操作**。
|
||||
- Cancel 阶段:如果任何一个服务的业务方法执行出错,那么这里就需要**进行补偿**,就是执行已经执行成功的业务逻辑的回滚操作。(把那些执行成功的回滚)
|
||||
|
||||
这种方案说实话几乎很少人使用,我们用的也比较少,但是也有使用的场景。因为这个**事务回滚**实际上是**严重依赖于你自己写代码来回滚和补偿**了,会造成补偿代码巨大,非常之恶心。
|
||||
|
||||
比如说我们,一般来说跟**钱**相关的,跟钱打交道的,**支付**、**交易**相关的场景,我们会用 TCC,严格保证分布式事务要么全部成功,要么全部自动回滚,严格保证资金的正确性,保证在资金上不会出现问题。
|
||||
|
||||
而且最好是你的各个业务执行的时间都比较短。
|
||||
|
||||
但是说实话,一般尽量别这么搞,自己手写回滚逻辑,或者是补偿逻辑,实在太恶心了,那个业务代码是很难维护的。
|
||||
|
||||
![distributed-transacion-TCC](/images/distributed-transaction-TCC.png)
|
||||
|
||||
### 本地消息表
|
||||
本地消息表其实是国外的 ebay 搞出来的这么一套思想。
|
||||
|
||||
这个大概意思是这样的:
|
||||
|
||||
1. A 系统在自己本地一个事务里操作同时,插入一条数据到消息表;
|
||||
2. 接着 A 系统将这个消息发送到 MQ 中去;
|
||||
3. B 系统接收到消息之后,在一个事务里,往自己本地消息表里插入一条数据,同时执行其他的业务操作,如果这个消息已经被处理过了,那么此时这个事务会回滚,这样**保证不会重复处理消息**;
|
||||
4. B 系统执行成功之后,就会更新自己本地消息表的状态以及 A 系统消息表的状态;
|
||||
5. 如果 B 系统处理失败了,那么就不会更新消息表状态,那么此时 A 系统会定时扫描自己的消息表,如果有未处理的消息,会再次发送到 MQ 中去,让 B 再次处理;
|
||||
6. 这个方案保证了最终一致性,哪怕 B 事务失败了,但是 A 会不断重发消息,直到 B 那边成功为止。
|
||||
|
||||
这个方案说实话最大的问题就在于**严重依赖于数据库的消息表来管理事务**啥的,如果是高并发场景咋办呢?咋扩展呢?所以一般确实很少用。
|
||||
|
||||
![distributed-transaction-local-message-table](/images/distributed-transaction-local-message-table.png)
|
||||
|
||||
### 可靠消息最终一致性方案
|
||||
这个的意思,就是干脆不要用本地的消息表了,直接基于 MQ 来实现事务。比如阿里的 RocketMQ 就支持消息事务。
|
||||
|
||||
大概的意思就是:
|
||||
|
||||
1. A 系统先发送一个 prepared 消息到 mq,如果这个 prepared 消息发送失败那么就直接取消操作别执行了;
|
||||
2. 如果这个消息发送成功过了,那么接着执行本地事务,如果成功就告诉 mq 发送确认消息,如果失败就告诉 mq 回滚消息;
|
||||
3. 如果发送了确认消息,那么此时 B 系统会接收到确认消息,然后执行本地的事务;
|
||||
4. mq 会自动**定时轮询**所有 prepared 消息回调你的接口,问你,这个消息是不是本地事务处理失败了,所有没发送确认的消息,是继续重试还是回滚?一般来说这里你就可以查下数据库看之前本地事务是否执行,如果回滚了,那么这里也回滚吧。这个就是避免可能本地事务执行成功了,而确认消息却发送失败了。
|
||||
5. 这个方案里,要是系统 B 的事务失败了咋办?重试咯,自动不断重试直到成功,如果实在是不行,要么就是针对重要的资金类业务进行回滚,比如 B 系统本地回滚后,想办法通知系统 A 也回滚;或者是发送报警由人工来手工回滚和补偿。
|
||||
6. 这个还是比较合适的,目前国内互联网公司大都是这么玩儿的,要不你举用 RocketMQ 支持的,要不你就自己基于类似 ActiveMQ?RabbitMQ?自己封装一套类似的逻辑出来,总之思路就是这样子的。
|
||||
|
||||
![distributed-transaction-reliable-message](/images/distributed-transaction-reliable-message.png)
|
||||
|
||||
### 最大努力通知方案
|
||||
这个方案的大致意思就是:
|
||||
|
||||
1. 系统 A 本地事务执行完之后,发送个消息到 MQ;
|
||||
2. 这里会有个专门消费 MQ 的**最大努力通知服务**,这个服务会消费 MQ 然后写入数据库中记录下来,或者是放入个内存队列也可以,接着调用系统 B 的接口;
|
||||
3. 要是系统 B 执行成功就 ok 了;要是系统 B 执行失败了,那么最大努力通知服务就定时尝试重新调用系统 B,反复 N 次,最后还是不行就放弃。
|
||||
|
||||
### 你们公司是如何处理分布式事务的?
|
||||
如果你真的被问到,可以这么说,我们某某特别严格的场景,用的是 TCC 来保证强一致性;然后其他的一些场景基于阿里的 RocketMQ 来实现分布式事务。
|
||||
|
||||
你找一个严格资金要求绝对不能错的场景,你可以说你是用的 TCC 方案;如果是一般的分布式事务场景,订单插入之后要调用库存服务更新库存,库存数据没有资金那么的敏感,可以用可靠消息最终一致性方案。
|
||||
|
||||
友情提示一下,RocketMQ 3.2.6 之前的版本,是可以按照上面的思路来的,但是之后接口做了一些改变,我这里不再赘述了。
|
||||
|
||||
当然如果你愿意,你可以参考可靠消息最终一致性方案来自己实现一套分布式事务,比如基于 RocketMQ 来玩儿。
|
25
docs/distributed-system/dubbo-augmentability.md
Executable file
@ -0,0 +1,25 @@
|
||||
两点,第一点,是核心的组件全部接口化,组件和组件之间的调用,必须全部是依托于接口,去动态找配置的实现类,如果没有配置就用他自己默认的
|
||||
|
||||
第二点,提供一种自己实现的组件的配置的方式,比如说你要是自己实现了某个组件,配置一下,人家到时候运行的时候直接找你配置的那个组件即可,作为实现类,不用自己默认的组件了
|
||||
|
||||
|
||||
|
||||
|
||||
**我们的课程每天都会有一个作业,引导大家把学习到的项目经验、技术方案和生产优化落地到自己负责的项目中去,让大家出去面试的时候,可以把各种技术结合自己的项目来回答面试官的各种深度拷问**
|
||||
|
||||
**大家不要小看这个,根据我多年的面试经验来看,拥有这个技能的人凤毛麟角,这种人出去绝对是各大公司争抢的对象。**
|
||||
|
||||
**所以希望大家好好完成每天的作业,我布置的大量作业,就是为了帮你锻造出这种能力**
|
||||
|
||||
**学习课程以及完成作业的过程中,大家一定会有很多的问题,可以到专栏的评论区去提问**
|
||||
|
||||
**每天我都会和之前带出来的一批阿里、蚂蚁金服、滴滴的优秀同学给大家进行答疑,并且我们还有专门的付费用户的微信群,大家可以在微信群里跟我们一起进行技术交流**
|
||||
|
||||
**如果你能坚持下来,学满6季,还可以获取私人定制的面试一条龙VIP服务**
|
||||
|
||||
**如果是连续6季面试训练营都购买的同学,还可以获取面试一条龙VIP服务**
|
||||
|
||||
**具体信息大家看“狸猫技术窝”公众号的知识店铺内的训练营详情即可**
|
||||
|
||||
**具体可参见训练营目录下的《训练营专属服务》文档。简单来说,这个私人定制的面试VIP服务,会为你的跳槽面试全程保驾护航**
|
||||
|
73
docs/distributed-system/dubbo-framework-principle.md
Executable file
@ -0,0 +1,73 @@
|
||||
聊**分布式**这块,**Dubbo相关的原理**,**Spring Cloud相关的原理**,有的面试官可能会这样问,你有没有看过**Dubbo或者Spring Cloud的源码呢**?**技术广度**、**技术深度**、**项目经验**、**系统设计**、**基本功**
|
||||
|
||||
平时看你简历主要是用一些技术来开发一些系统,就会问问你了,对于一些你平时常用的技术,有没有关注过底层的原理,或者是看过源码,你要是说,90%的人,一般都会在这个时候支支吾吾的说
|
||||
|
||||
源码看过一点点,但是没怎么看过
|
||||
|
||||
在我们面试训练营里,能给你来分析源码吗?不太现实的,任何一个开源项目,**源码**少则几万行,多则几十万行,**Hadoop、Spark**,**面试训练营**,几讲的时间来讲透任何一个**开源项目**的**源码**,不现实
|
||||
|
||||
看源码技巧是有,但是,需要**技术功底**
|
||||
|
||||
就是说提炼一些**Dubbo、Spring Cloud**相关的一些底层的运行的原理,给大家来用大白话+现场画图的方式,说清楚,你就可以结合我们视频讲解的内容,去现场画图给面试官画一画一些技术底层的运行的一些原理
|
||||
|
||||
|
||||
我们的课程每天都会有一个作业,引导大家把学习到的项目经验、技术方案和生产优化落地到自己负责的项目中去,让大家出去面试的时候,可以把各种技术结合自己的项目来回答面试官的各种深度拷问
|
||||
|
||||
大家不要小看这个,根据我多年的面试经验来看,拥有这个技能的人凤毛麟角,这种人出去绝对是各大公司争抢的对象。
|
||||
|
||||
所以希望大家好好完成每天的作业,我布置的大量作业,就是为了帮你锻造出这种能力
|
||||
|
||||
学习课程以及完成作业的过程中,大家一定会有很多的问题,可以到专栏的评论区去提问
|
||||
|
||||
每天我都会和之前带出来的一批阿里、蚂蚁金服、滴滴的优秀同学给大家进行答疑,并且我们还有专门的付费用户的微信群,大家可以在微信群里跟我们一起进行技术交流
|
||||
|
||||
如果你能坚持下来,学满6季,还可以获取私人定制的面试一条龙VIP服务
|
||||
|
||||
如果是连续6季面试训练营都购买的同学,还可以获取面试一条龙VIP服务
|
||||
|
||||
具体信息大家看“狸猫技术窝”公众号的知识店铺内的训练营详情即可,
|
||||
|
||||
具体可参见训练营目录下的《训练营专属服务》文档。简单来说,这个私人定制的面试VIP服务,会为你的跳槽面试全程保驾护航
|
||||
|
||||
|
||||
|
||||
|
||||
分布式系统
|
||||
|
||||
拆分为了多个子系统之后,各个系统之间如何通过Spring Cloud服务框架来进行调用,Dubbo框架来进行调用
|
||||
|
||||
![Dubbo核心架构原理](/docs/distributed-system/images/dubbo-framework-principle.png)
|
||||
提供接口
|
||||
|
||||
服务注册中心:
|
||||
|
||||
###消费者
|
||||
|
||||
#### 动态代理:Proxy
|
||||
#### 负载均衡:Cluster,负载均衡,故障转移
|
||||
#### 注册中心:Registry
|
||||
#### 通信协议:Protocol,filter机制,http、rmi、dubbo等协议
|
||||
|
||||
#### http、rmi、dubbo
|
||||
|
||||
比如说,我现在其实想要调用的是,DemoService里的sayHello接口
|
||||
|
||||
你的请求用什么样的方式来组织发送过去呢?以一个什么样的格式来发送你的请求?
|
||||
|
||||
http,/demoService/sayHello?name=leo
|
||||
rmi,另外一种样子
|
||||
dubbo,另外一种样子,interface=demoService|method=sayHello|params=name:leo
|
||||
|
||||
信息交换:Exchange,Request和Response
|
||||
|
||||
对于你的协议的格式组织好的请求数据,需要进行一个封装,Request
|
||||
|
||||
##### 网络通信:Transport,netty、mina
|
||||
##### 序列化:封装好的请求如何序列化成二进制数组,通过netty/mina发送出去
|
||||
|
||||
提供者
|
||||
|
||||
#### 网络通信:Transport,基于netty/mina实现的Server
|
||||
#### 信息交换:Exchange,Response
|
||||
#### 通信协议:Protocol,filter机制
|
||||
#### 动态代理:Proxy
|
10
docs/distributed-system/dubbo-independent-framework.md
Executable file
@ -0,0 +1,10 @@
|
||||
|
||||
对**Dubbo**稍微做了一点进一步深入的讲解,但是远远是达不到精通源码的程度,只能说是相对于面试突击第一季要深入了一些,**Dubbo**一次服务请求调用,牵扯到了哪些组件,**负载均衡组件**、**注册中心**、**协议层**、**转换层**、**网络层(netty开发)**、**动态代理**,服务提供者也是类似的
|
||||
|
||||
网络通信的一些东西,是如何通过**NIO**的方式,**多线程**的方式,让一个服务提供者被多个服务消费者去并发的调用和请求
|
||||
|
||||
从整体架构原理的角度,说了一下如何进行扩展的
|
||||
|
||||
能说比普通的人稍微好一些,**技术深度**,那必须得是学其他的课程深入的理解他里面的源码,才能在面试的时候说,我精通一个技术的源码
|
||||
|
||||
**Dubbo底层架构原理的图**,自己手画出来,画的足够的熟练,如果有一些什么问题的话,可以提问
|
85
docs/distributed-system/dubbo-load-balancing.md
Executable file
@ -0,0 +1,85 @@
|
||||
## 面试题
|
||||
dubbo 负载均衡策略和集群容错策略都有哪些?动态代理策略呢?
|
||||
|
||||
## 面试官心理分析
|
||||
继续深问吧,这些都是用 dubbo 必须知道的一些东西,你得知道基本原理,知道序列化是什么协议,还得知道具体用 dubbo 的时候,如何负载均衡,如何高可用,如何动态代理。
|
||||
|
||||
说白了,就是看你对 dubbo 熟悉不熟悉:
|
||||
- dubbo 工作原理:服务注册、注册中心、消费者、代理通信、负载均衡;
|
||||
- 网络通信、序列化:dubbo 协议、长连接、NIO、hessian 序列化协议;
|
||||
- 负载均衡策略、集群容错策略、动态代理策略:dubbo 跑起来的时候一些功能是如何运转的?怎么做负载均衡?怎么做集群容错?怎么生成动态代理?
|
||||
- dubbo SPI 机制:你了解不了解 dubbo 的 SPI 机制?如何基于 SPI 机制对 dubbo 进行扩展?
|
||||
|
||||
## 面试题剖析
|
||||
### dubbo 负载均衡策略
|
||||
#### random loadbalance
|
||||
默认情况下,dubbo 是 random load balance ,即**随机**调用实现负载均衡,可以对 provider 不同实例**设置不同的权重**,会按照权重来负载均衡,权重越大分配流量越高,一般就用这个默认的就可以了。
|
||||
|
||||
#### roundrobin loadbalance
|
||||
这个的话默认就是均匀地将流量打到各个机器上去,但是如果各个机器的性能不一样,容易导致性能差的机器负载过高。所以此时需要调整权重,让性能差的机器承载权重小一些,流量少一些。
|
||||
|
||||
举个栗子。
|
||||
|
||||
跟运维同学申请机器,有的时候,我们运气好,正好公司资源比较充足,刚刚有一批热气腾腾、刚刚做好的虚拟机新鲜出炉,配置都比较高:8 核 + 16G 机器,申请到 2 台。过了一段时间,我们感觉 2 台机器有点不太够,我就去找运维同学说,“哥儿们,你能不能再给我一台机器”,但是这时只剩下一台 4 核 + 8G 的机器。我要还是得要。
|
||||
|
||||
这个时候,可以给两台 8 核 16G 的机器设置权重 4,给剩余 1 台 4 核 8G 的机器设置权重 2。
|
||||
|
||||
#### leastactive loadbalance
|
||||
这个就是自动感知一下,如果某个机器性能越差,那么接收的请求越少,越不活跃,此时就会给**不活跃的性能差的机器更少的请求**。
|
||||
|
||||
#### consistanthash loadbalance
|
||||
一致性 Hash 算法,相同参数的请求一定分发到一个 provider 上去,provider 挂掉的时候,会基于虚拟节点均匀分配剩余的流量,抖动不会太大。**如果你需要的不是随机负载均衡**,是要一类请求都到一个节点,那就走这个一致性 Hash 策略。
|
||||
|
||||
### dubbo 集群容错策略
|
||||
#### failover cluster 模式
|
||||
失败自动切换,自动重试其他机器,**默认**就是这个,常见于读操作。(失败重试其它机器)
|
||||
|
||||
可以通过以下几种方式配置重试次数:
|
||||
|
||||
```xml
|
||||
<dubbo:service retries="2" />
|
||||
```
|
||||
|
||||
或者
|
||||
|
||||
```xml
|
||||
<dubbo:reference retries="2" />
|
||||
```
|
||||
|
||||
或者
|
||||
|
||||
```xml
|
||||
<dubbo:reference>
|
||||
<dubbo:method name="findFoo" retries="2" />
|
||||
</dubbo:reference>
|
||||
```
|
||||
|
||||
#### failfast cluster 模式
|
||||
一次调用失败就立即失败,常见于非幂等性的写操作,比如新增一条记录(调用失败就立即失败)
|
||||
|
||||
#### failsafe cluster 模式
|
||||
出现异常时忽略掉,常用于不重要的接口调用,比如记录日志。
|
||||
|
||||
配置示例如下:
|
||||
|
||||
```xml
|
||||
<dubbo:service cluster="failsafe" />
|
||||
```
|
||||
|
||||
或者
|
||||
|
||||
```xml
|
||||
<dubbo:reference cluster="failsafe" />
|
||||
```
|
||||
|
||||
#### failback cluster 模式
|
||||
失败了后台自动记录请求,然后定时重发,比较适合于写消息队列这种。
|
||||
|
||||
#### forking cluster 模式
|
||||
**并行调用**多个 provider,只要一个成功就立即返回。常用于实时性要求比较高的读操作,但是会浪费更多的服务资源,可通过 `forks="2"` 来设置最大并行数。
|
||||
|
||||
#### broadcacst cluster
|
||||
逐个调用所有的 provider。任何一个 provider 出错则报错(从`2.1.0` 版本开始支持)。通常用于通知所有提供者更新缓存或日志等本地资源信息。
|
||||
|
||||
### dubbo动态代理策略
|
||||
默认使用 javassist 动态字节码生成,创建代理类。但是可以通过 spi 扩展机制配置自己的动态代理策略。
|
35
docs/distributed-system/dubbo-operating-principle.md
Executable file
@ -0,0 +1,35 @@
|
||||
## 面试题
|
||||
说一下的 dubbo 的工作原理?注册中心挂了可以继续通信吗?说说一次 rpc 请求的流程?
|
||||
|
||||
## 面试官心理分析
|
||||
MQ、ES、Redis、Dubbo,上来先问你一些**思考性的问题**、**原理**,比如 kafka 高可用架构原理、es 分布式架构原理、redis 线程模型原理、Dubbo 工作原理;之后就是生产环境里可能会碰到的一些问题,因为每种技术引入之后生产环境都可能会碰到一些问题;再来点综合的,就是系统设计,比如让你设计一个 MQ、设计一个搜索引擎、设计一个缓存、设计一个 rpc 框架等等。
|
||||
|
||||
那既然开始聊分布式系统了,自然重点先聊聊 dubbo 了,毕竟 dubbo 是目前事实上大部分公司的分布式系统的 rpc 框架标准,基于 dubbo 也可以构建一整套的微服务架构。但是需要自己大量开发。
|
||||
|
||||
当然去年开始 spring cloud 非常火,现在大量的公司开始转向 spring cloud 了,spring cloud 人家毕竟是微服务架构的全家桶式的这么一个东西。但是因为很多公司还在用 dubbo,所以 dubbo 肯定会是目前面试的重点,何况人家 dubbo 现在重启开源社区维护了,捐献给了 apache,未来应该也还是有一定市场和地位的。
|
||||
|
||||
既然聊 dubbo,那肯定是先从 dubbo 原理开始聊了,你先说说 dubbo 支撑 rpc 分布式调用的架构啥的,然后说说一次 rpc 请求 dubbo 是怎么给你完成的,对吧。
|
||||
|
||||
## 面试题剖析
|
||||
### dubbo 工作原理
|
||||
- 第一层:service 层,接口层,给服务提供者和消费者来实现的
|
||||
- 第二层:config 层,配置层,主要是对 dubbo 进行各种配置的
|
||||
- 第三层:proxy 层,服务代理层,无论是 consumer 还是 provider,dubbo 都会给你生成代理,代理之间进行网络通信
|
||||
- 第四层:registry 层,服务注册层,负责服务的注册与发现
|
||||
- 第五层:cluster 层,集群层,封装多个服务提供者的路由以及负载均衡,将多个实例组合成一个服务
|
||||
- 第六层:monitor 层,监控层,对 rpc 接口的调用次数和调用时间进行监控
|
||||
- 第七层:protocal 层,远程调用层,封装 rpc 调用
|
||||
- 第八层:exchange 层,信息交换层,封装请求响应模式,同步转异步
|
||||
- 第九层:transport 层,网络传输层,抽象 mina 和 netty 为统一接口
|
||||
- 第十层:serialize 层,数据序列化层
|
||||
|
||||
### 工作流程
|
||||
- 第一步:provider 向注册中心去注册
|
||||
- 第二步:consumer 从注册中心订阅服务,注册中心会通知 consumer 注册好的服务
|
||||
- 第三步:consumer 调用 provider
|
||||
- 第四步:consumer 和 provider 都异步通知监控中心
|
||||
|
||||
![dubbo-operating-principle](/images/dubbo-operating-principle.png)
|
||||
|
||||
### 注册中心挂了可以继续通信吗?
|
||||
可以,因为刚开始初始化的时候,消费者会将提供者的地址等信息**拉取到本地缓存**,所以注册中心挂了可以继续通信。
|
27
docs/distributed-system/dubbo-rock-bottom.md
Executable file
@ -0,0 +1,27 @@
|
||||
|
||||
![Dubbo底层通信原理](/docs/distributed-system/images/dubbo-rock-bottom.png)
|
||||
如果问到Dubbo底层原理,肯定除了上一讲的底层架构,你能说出来之外,还很可能会追问几个问题,网络通信这块原理的话
|
||||
|
||||
netty来举例,NIO来实现的,一台机器同时抗高并发的请求
|
||||
|
||||
|
||||
|
||||
**所以希望大家好好完成每天的作业,我布置的大量作业,就是为了帮你锻造出这种能力**
|
||||
|
||||
**学习课程以及完成作业的过程中,大家一定会有很多的问题,可以到专栏的评论区去提问**
|
||||
|
||||
**每天我都会和之前带出来的一批阿里、蚂蚁金服、滴滴的优秀同学给大家进行答疑,并且我们还有专门的付费用户的微信群,大家可以在微信群里跟我们一起进行技术交流**
|
||||
|
||||
**如果你能坚持下来,学满6季,还可以获取私人定制的面试一条龙VIP服务**
|
||||
|
||||
**如果是连续6季面试训练营都购买的同学,还可以获取面试一条龙VIP服务**
|
||||
|
||||
**具体信息大家看“狸猫技术窝”公众号的知识店铺内的训练营详情即可**
|
||||
|
||||
**具体可参见训练营目录下的《训练营专属服务》文档。简单来说,这个私人定制的面试VIP服务,会为你的跳槽面试全程保驾护航**
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
22
docs/distributed-system/dubbo-rpc-design.md
Executable file
@ -0,0 +1,22 @@
|
||||
## 面试题
|
||||
如何自己设计一个类似 Dubbo 的 RPC 框架?
|
||||
|
||||
## 面试官心理分析
|
||||
说实话,就这问题,其实就跟问你如何自己设计一个 MQ 一样的道理,就考两个:
|
||||
- 你有没有对某个 rpc 框架原理有非常深入的理解。
|
||||
- 你能不能从整体上来思考一下,如何设计一个 rpc 框架,考考你的系统设计能力。
|
||||
|
||||
## 面试题剖析
|
||||
其实问到你这问题,你起码不能认怂,因为是知识的扫盲,那我不可能给你深入讲解什么 kafka 源码剖析,dubbo 源码剖析,何况我就算讲了,你要真的消化理解和吸收,起码个把月以后了。
|
||||
|
||||
所以我给大家一个建议,遇到这类问题,起码从你了解的类似框架的原理入手,自己说说参照 dubbo 的原理,你来设计一下,举个例子,dubbo 不是有那么多分层么?而且每个分层是干啥的,你大概是不是知道?那就按照这个思路大致说一下吧,起码你不能懵逼,要比那些上来就懵,啥也说不出来的人要好一些。
|
||||
|
||||
举个栗子,我给大家说个最简单的回答思路:
|
||||
- 上来你的服务就得去注册中心注册吧,你是不是得有个注册中心,保留各个服务的信息,可以用 zookeeper 来做,对吧。
|
||||
- 然后你的消费者需要去注册中心拿对应的服务信息吧,对吧,而且每个服务可能会存在于多台机器上。
|
||||
- 接着你就该发起一次请求了,咋发起?当然是基于动态代理了,你面向接口获取到一个动态代理,这个动态代理就是接口在本地的一个代理,然后这个代理会找到服务对应的机器地址。
|
||||
- 然后找哪个机器发送请求?那肯定得有个负载均衡算法了,比如最简单的可以随机轮询是不是。
|
||||
- 接着找到一台机器,就可以跟它发送请求了,第一个问题咋发送?你可以说用 netty 了,nio 方式;第二个问题发送啥格式数据?你可以说用 hessian 序列化协议了,或者是别的,对吧。然后请求过去了。
|
||||
- 服务器那边一样的,需要针对你自己的服务生成一个动态代理,监听某个网络端口了,然后代理你本地的服务代码。接收到请求的时候,就调用对应的服务代码,对吧。
|
||||
|
||||
这就是一个最最基本的 rpc 框架的思路,先不说你有多牛逼的技术功底,哪怕这个最简单的思路你先给出来行不行?
|
73
docs/distributed-system/dubbo-serialization-protocol.md
Executable file
@ -0,0 +1,73 @@
|
||||
## 面试题
|
||||
dubbo 支持哪些通信协议?支持哪些序列化协议?说一下 Hessian 的数据结构?PB 知道吗?为什么 PB 的效率是最高的?
|
||||
|
||||
## 面试官心理分析
|
||||
上一个问题,说说 dubbo 的基本工作原理,那是你必须知道的,至少要知道 dubbo 分成哪些层,然后平时怎么发起 rpc 请求的,注册、发现、调用,这些是基本的。
|
||||
|
||||
接着就可以针对底层进行深入的问问了,比如第一步就可以先问问序列化协议这块,就是平时 RPC 的时候怎么走的?
|
||||
|
||||
## 面试题剖析
|
||||
**序列化**,就是把数据结构或者是一些对象,转换为二进制串的过程,而**反序列化**是将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程。
|
||||
|
||||
![serialize-deserialize](/images/serialize-deserialize.png)
|
||||
|
||||
### dubbo 支持不同的通信协议
|
||||
- dubbo 协议
|
||||
|
||||
**默认**就是走 dubbo 协议,单一长连接,进行的是 NIO 异步通信,基于 hessian 作为序列化协议。使用的场景是:传输数据量小(每次请求在 100kb 以内),但是并发量很高。
|
||||
|
||||
为了要支持高并发场景,一般是服务提供者就几台机器,但是服务消费者有上百台,可能每天调用量达到上亿次!此时用长连接是最合适的,就是跟每个服务消费者维持一个长连接就可以,可能总共就 100 个连接。然后后面直接基于长连接 NIO 异步通信,可以支撑高并发请求。
|
||||
|
||||
长连接,通俗点说,就是建立连接过后可以持续发送请求,无须再建立连接。
|
||||
|
||||
![dubbo-keep-connection](/images/dubbo-keep-connection.png)
|
||||
|
||||
而短连接,每次要发送请求之前,需要先重新建立一次连接。
|
||||
|
||||
![dubbo-not-keep-connection](/images/dubbo-not-keep-connection.png)
|
||||
|
||||
- rmi 协议
|
||||
|
||||
走 Java 二进制序列化,多个短连接,适合消费者和提供者数量差不多的情况,适用于文件的传输,一般较少用。
|
||||
|
||||
- hessian 协议
|
||||
|
||||
走 hessian 序列化协议,多个短连接,适用于提供者数量比消费者数量还多的情况,适用于文件的传输,一般较少用。
|
||||
|
||||
- http 协议
|
||||
|
||||
走 json 序列化。
|
||||
|
||||
- webservice
|
||||
|
||||
走 SOAP 文本序列化。
|
||||
|
||||
### dubbo 支持的序列化协议
|
||||
dubbo 支持 hession、Java 二进制序列化、json、SOAP 文本序列化多种序列化协议。但是 hessian 是其默认的序列化协议。
|
||||
|
||||
### 说一下 Hessian 的数据结构
|
||||
Hessian 的对象序列化机制有 8 种原始类型:
|
||||
|
||||
- 原始二进制数据
|
||||
- boolean
|
||||
- 64-bit date(64 位毫秒值的日期)
|
||||
- 64-bit double
|
||||
- 32-bit int
|
||||
- 64-bit long
|
||||
- null
|
||||
- UTF-8 编码的 string
|
||||
|
||||
另外还包括 3 种递归类型:
|
||||
|
||||
- list for lists and arrays
|
||||
- map for maps and dictionaries
|
||||
- object for objects
|
||||
|
||||
还有一种特殊的类型:
|
||||
|
||||
- ref:用来表示对共享对象的引用。
|
||||
|
||||
### 为什么 PB 的效率是最高的?
|
||||
可能有一些同学比较习惯于 `JSON` or `XML` 数据存储格式,对于 `Protocol Buffer` 还比较陌生。`Protocol Buffer` 其实是 Google 出品的一种轻量并且高效的结构化数据存储格式,性能比 `JSON`、`XML` 要高很多。
|
||||
|
||||
其实 PB 之所以性能如此好,主要得益于两个:**第一**,它使用 proto 编译器,自动进行序列化和反序列化,速度非常快,应该比 `XML` 和 `JSON` 快上了 `20~100` 倍;**第二**,它的数据压缩效果好,就是说它序列化后的数据量体积小。因为体积小,传输起来带宽和速度上会有优化。
|
110
docs/distributed-system/dubbo-service-management.md
Executable file
@ -0,0 +1,110 @@
|
||||
## 面试题
|
||||
如何基于 dubbo 进行服务治理、服务降级、失败重试以及超时重试?
|
||||
|
||||
## 面试官心理分析
|
||||
服务治理,这个问题如果问你,其实就是看看你有没有**服务治理**的思想,因为这个是做过复杂微服务的人肯定会遇到的一个问题。
|
||||
|
||||
**服务降级**,这个是涉及到复杂分布式系统中必备的一个话题,因为分布式系统互相来回调用,任何一个系统故障了,你不降级,直接就全盘崩溃?那就太坑爹了吧。
|
||||
|
||||
**失败重试**,分布式系统中网络请求如此频繁,要是因为网络问题不小心失败了一次,是不是要重试?
|
||||
|
||||
**超时重试**,跟上面一样,如果不小心网络慢一点,超时了,如何重试?
|
||||
|
||||
## 面试题剖析
|
||||
### 服务治理
|
||||
#### 1. 调用链路自动生成
|
||||
一个大型的分布式系统,或者说是用现在流行的微服务架构来说吧,**分布式系统由大量的服务组成**。那么这些服务之间互相是如何调用的?调用链路是啥?说实话,几乎到后面没人搞的清楚了,因为服务实在太多了,可能几百个甚至几千个服务。
|
||||
|
||||
那就需要基于 dubbo 做的分布式系统中,对各个服务之间的调用自动记录下来,然后自动将**各个服务之间的依赖关系和调用链路生成出来**,做成一张图,显示出来,大家才可以看到对吧。
|
||||
|
||||
![dubbo-service-invoke-road](/images/dubbo-service-invoke-road.png)
|
||||
|
||||
#### 2. 服务访问压力以及时长统计
|
||||
需要自动统计**各个接口和服务之间的调用次数以及访问延时**,而且要分成两个级别。
|
||||
|
||||
- 一个级别是接口粒度,就是每个服务的每个接口每天被调用多少次,TP50/TP90/TP99,三个档次的请求延时分别是多少;
|
||||
- 第二个级别是从源头入口开始,一个完整的请求链路经过几十个服务之后,完成一次请求,每天全链路走多少次,全链路请求延时的 TP50/TP90/TP99,分别是多少。
|
||||
|
||||
这些东西都搞定了之后,后面才可以来看当前系统的压力主要在哪里,如何来扩容和优化啊。
|
||||
|
||||
#### 3. 其它
|
||||
- 服务分层(避免循环依赖)
|
||||
- 调用链路失败监控和报警
|
||||
- 服务鉴权
|
||||
- 每个服务的可用性的监控(接口调用成功率?几个 9?99.99%,99.9%,99%)
|
||||
|
||||
### 服务降级
|
||||
比如说服务 A 调用服务 B,结果服务 B 挂掉了,服务 A 重试几次调用服务 B,还是不行,那么直接降级,走一个备用的逻辑,给用户返回响应。
|
||||
|
||||
举个栗子,我们有接口 `HelloService`。`HelloServiceImpl` 有该接口的具体实现。
|
||||
|
||||
```java
|
||||
public interface HelloService {
|
||||
void sayHello();
|
||||
}
|
||||
|
||||
public class HelloServiceImpl implements HelloService {
|
||||
public void sayHello() {
|
||||
System.out.println("hello world......");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
|
||||
|
||||
<dubbo:application name="dubbo-provider" />
|
||||
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
|
||||
<dubbo:protocol name="dubbo" port="20880" />
|
||||
<dubbo:service interface="com.zhss.service.HelloService" ref="helloServiceImpl" timeout="10000" />
|
||||
<bean id="helloServiceImpl" class="com.zhss.service.HelloServiceImpl" />
|
||||
|
||||
</beans>
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
|
||||
|
||||
<dubbo:application name="dubbo-consumer" />
|
||||
|
||||
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
|
||||
|
||||
<dubbo:reference id="fooService" interface="com.test.service.FooService" timeout="10000" check="false" mock="return null">
|
||||
</dubbo:reference>
|
||||
|
||||
</beans>
|
||||
|
||||
```
|
||||
|
||||
我们调用接口失败的时候,可以通过 `mock` 统一返回 null。
|
||||
|
||||
mock 的值也可以修改为 true,然后再跟接口同一个路径下实现一个 Mock 类,命名规则是 “接口名称+`Mock`” 后缀。然后在 Mock 类里实现自己的降级逻辑。
|
||||
|
||||
```java
|
||||
public class HelloServiceMock implements HelloService {
|
||||
public void sayHello() {
|
||||
// 降级逻辑
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 失败重试和超时重试
|
||||
所谓失败重试,就是 consumer 调用 provider 要是失败了,比如抛异常了,此时应该是可以重试的,或者调用超时了也可以重试。配置如下:
|
||||
|
||||
```xml
|
||||
<dubbo:reference id="xxxx" interface="xx" check="true" async="false" retries="3" timeout="2000"/>
|
||||
```
|
||||
|
||||
举个栗子。
|
||||
|
||||
某个服务的接口,要耗费 5s,你这边不能干等着,你这边配置了 timeout 之后,我等待 2s,还没返回,我直接就撤了,不能干等你。
|
||||
|
||||
可以结合你们公司具体的场景来说说你是怎么设置这些参数的:
|
||||
|
||||
- `timeout`:一般设置为 `200ms`,我们认为不能超过 `200ms` 还没返回。
|
||||
- `retries`:设置 retries,一般是在读请求的时候,比如你要查询个数据,你可以设置个 retries,如果第一次没读到,报错,重试指定的次数,尝试再次读取。
|
89
docs/distributed-system/dubbo-spi.md
Executable file
@ -0,0 +1,89 @@
|
||||
## 面试题
|
||||
dubbo 的 spi 思想是什么?
|
||||
|
||||
## 面试官心理分析
|
||||
继续深入问呗,前面一些基础性的东西问完了,确定你应该都 ok,了解 dubbo 的一些基本东西,那么问个稍微难一点点的问题,就是 spi,先问问你 spi 是啥?然后问问你 dubbo 的 spi 是怎么实现的?
|
||||
|
||||
其实就是看看你对 dubbo 的掌握如何。
|
||||
|
||||
## 面试题剖析
|
||||
### spi 是啥?
|
||||
spi,简单来说,就是 `service provider interface`,说白了是什么意思呢,比如你有个接口,现在这个接口有 3 个实现类,那么在系统运行的时候对这个接口到底选择哪个实现类呢?这就需要 spi 了,需要**根据指定的配置**或者是**默认的配置**,去**找到对应的实现类**加载进来,然后用这个实现类的实例对象。
|
||||
|
||||
举个栗子。
|
||||
|
||||
你有一个接口 A。A1/A2/A3 分别是接口A的不同实现。你通过配置 `接口 A = 实现 A2`,那么在系统实际运行的时候,会加载你的配置,用实现 A2 实例化一个对象来提供服务。
|
||||
|
||||
spi 机制一般用在哪儿?**插件扩展的场景**,比如说你开发了一个给别人使用的开源框架,如果你想让别人自己写个插件,插到你的开源框架里面,从而扩展某个功能,这个时候 spi 思想就用上了。
|
||||
|
||||
### Java spi 思想的体现
|
||||
spi 经典的思想体现,大家平时都在用,比如说 jdbc。
|
||||
|
||||
Java 定义了一套 jdbc 的接口,但是 Java 并没有提供 jdbc 的实现类。
|
||||
|
||||
但是实际上项目跑的时候,要使用 jdbc 接口的哪些实现类呢?一般来说,我们要**根据自己使用的数据库**,比如 mysql,你就将 `mysql-jdbc-connector.jar` 引入进来;oracle,你就将 `oracle-jdbc-connector.jar` 引入进来。
|
||||
|
||||
在系统跑的时候,碰到你使用 jdbc 的接口,他会在底层使用你引入的那个 jar 中提供的实现类。
|
||||
|
||||
### dubbo 的 spi 思想
|
||||
dubbo 也用了 spi 思想,不过没有用 jdk 的 spi 机制,是自己实现的一套 spi 机制。
|
||||
```java
|
||||
Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
|
||||
```
|
||||
|
||||
Protocol 接口,在系统运行的时候,,dubbo 会判断一下应该选用这个 Protocol 接口的哪个实现类来实例化对象来使用。
|
||||
|
||||
它会去找一个你配置的 Protocol,将你配置的 Protocol 实现类,加载到 jvm 中来,然后实例化对象,就用你的那个 Protocol 实现类就可以了。
|
||||
|
||||
|
||||
上面那行代码就是 dubbo 里大量使用的,就是对很多组件,都是保留一个接口和多个实现,然后在系统运行的时候动态根据配置去找到对应的实现类。如果你没配置,那就走默认的实现好了,没问题。
|
||||
```java
|
||||
@SPI("dubbo")
|
||||
public interface Protocol {
|
||||
|
||||
int getDefaultPort();
|
||||
|
||||
@Adaptive
|
||||
<T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
|
||||
|
||||
@Adaptive
|
||||
<T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
|
||||
|
||||
void destroy();
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
在 dubbo 自己的 jar 里,在`/META_INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol`文件中:
|
||||
```xml
|
||||
dubbo=com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol
|
||||
http=com.alibaba.dubbo.rpc.protocol.http.HttpProtocol
|
||||
hessian=com.alibaba.dubbo.rpc.protocol.hessian.HessianProtocol
|
||||
```
|
||||
|
||||
所以说,这就看到了 dubbo 的 spi 机制默认是怎么玩儿的了,其实就是 Protocol 接口,`@SPI("dubbo")` 说的是,通过 SPI 机制来提供实现类,实现类是通过 dubbo 作为默认 key 去配置文件里找到的,配置文件名称与接口全限定名一样的,通过 dubbo 作为 key 可以找到默认的实现类就是 `com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol`。
|
||||
|
||||
|
||||
如果想要动态替换掉默认的实现类,需要使用 `@Adaptive` 接口,Protocol 接口中,有两个方法加了 `@Adaptive` 注解,就是说那俩接口会被代理实现。
|
||||
|
||||
啥意思呢?
|
||||
|
||||
比如这个 Protocol 接口搞了俩 `@Adaptive` 注解标注了方法,在运行的时候会针对 Protocol 生成代理类,这个代理类的那俩方法里面会有代理代码,代理代码会在运行的时候动态根据 url 中的 protocol 来获取那个 key,默认是 dubbo,你也可以自己指定,你如果指定了别的 key,那么就会获取别的实现类的实例了。
|
||||
|
||||
### 如何自己扩展 dubbo 中的组件
|
||||
下面来说说怎么来自己扩展 dubbo 中的组件。
|
||||
|
||||
自己写个工程,要是那种可以打成 jar 包的,里面的 `src/main/resources` 目录下,搞一个 `META-INF/services`,里面放个文件叫:`com.alibaba.dubbo.rpc.Protocol`,文件里搞一个`my=com.bingo.MyProtocol`。自己把 jar 弄到 nexus 私服里去。
|
||||
|
||||
然后自己搞一个 `dubbo provider` 工程,在这个工程里面依赖你自己搞的那个 jar,然后在 spring 配置文件里给个配置:
|
||||
|
||||
```xml
|
||||
<dubbo:protocol name=”my” port=”20000” />
|
||||
```
|
||||
provider 启动的时候,就会加载到我们 jar 包里的`my=com.bingo.MyProtocol` 这行配置里,接着会根据你的配置使用你定义好的 MyProtocol 了,这个就是简单说明一下,你通过上述方式,可以替换掉大量的 dubbo 内部的组件,就是扔个你自己的 jar 包,然后配置一下即可。
|
||||
|
||||
![dubbo-spi](/images/dubbo-spi.png)
|
||||
|
||||
dubbo 里面提供了大量的类似上面的扩展点,就是说,你如果要扩展一个东西,只要自己写个 jar,让你的 consumer 或者是 provider 工程,依赖你的那个 jar,在你的 jar 里指定目录下配置好接口名称对应的文件,里面通过 `key=实现类`。
|
||||
|
||||
然后对于对应的组件,类似 `<dubbo:protocol>` 用你的那个 key 对应的实现类来实现某个接口,你可以自己去扩展 dubbo 的各种功能,提供你自己的实现。
|
46
docs/distributed-system/dubbo-vs-springCloud.md
Executable file
@ -0,0 +1,46 @@
|
||||
底层架构原理是类似的
|
||||
|
||||
**Dubbo,RPC的性能比HTTP的性能更好,并发能力更强,经过深度优化的RPC服务框架,性能和并发能力是更好一些**
|
||||
|
||||
很多中小型公司而言,其实稍微好一点的性能,**Dubbo一次请求10ms,Spring Cloud耗费20ms**,对很多中小型公司而言,性能、并发,并不是最主要的因素
|
||||
|
||||
**Spring Cloud这套架构原理,走HTTP接口和HTTP请求,就足够满足性能和并发的需要了,没必要使用高度优化的RPC服务框架**
|
||||
|
||||
|
||||
|
||||
Dubbo之前的一个定位,就是一个单纯的服务框架而已,不提供任何其他的功能,配合的网关还得选择其他的一些技术
|
||||
|
||||
**Spring Cloud**,中小型公司用的特别多,老系统从**Dubbo迁移到Spring Cloud**,新系统都是用**Spring Cloud来进行开发,全家桶,主打的是微服务架构里,组件齐全,功能齐全。网关直接提供了,分布式配置中心,授权认证,服务调用链路追踪,Hystrix可以做服务的资源隔离、熔断降级、服务请求QPS监控、契约测试、消息中间件封装、ZK封装**
|
||||
|
||||
|
||||
剩是剩在功能齐全,中小型公司开箱即用,直接满足系统的开发需求
|
||||
|
||||
|
||||
**Spring Cloud**原来支持的一些技术慢慢的未来会演变为,跟阿里技术体系进行融合,**Spring Cloud Alibaba**,阿里技术会融入**Spring Cloud**里面去
|
||||
|
||||
|
||||
|
||||
|
||||
**我们的课程每天都会有一个作业,引导大家把学习到的项目经验、技术方案和生产优化落地到自己负责的项目中去,让大家出去面试的时候,可以把各种技术结合自己的项目来回答面试官的各种深度拷问**
|
||||
|
||||
**大家不要小看这个,根据我多年的面试经验来看,拥有这个技能的人凤毛麟角,这种人出去绝对是各大公司争抢的对象。**
|
||||
|
||||
**我们的课程每天都会有一个作业,引导大家把学习到的项目经验、技术方案和生产优化落地到自己负责的项目中去,让大家出去面试的时候,可以把各种技术结合自己的项目来回答面试官的各种深度拷问**
|
||||
|
||||
**大家不要小看这个,根据我多年的面试经验来看,拥有这个技能的人凤毛麟角,这种人出去绝对是各大公司争抢的对象。**
|
||||
|
||||
**所以希望大家好好完成每天的作业,我布置的大量作业,就是为了帮你锻造出这种能力**
|
||||
|
||||
**学习课程以及完成作业的过程中,大家一定会有很多的问题,可以到专栏的评论区去提问**
|
||||
|
||||
**每天我都会和之前带出来的一批阿里、蚂蚁金服、滴滴的优秀同学给大家进行答疑,并且我们还有专门的付费用户的微信群,大家可以在微信群里跟我们一起进行技术交流**
|
||||
|
||||
**如果你能坚持下来,学满6季,还可以获取私人定制的面试一条龙VIP服务**
|
||||
|
||||
**如果是连续6季面试训练营都购买的同学,还可以获取面试一条龙VIP服务**
|
||||
|
||||
**具体信息大家看“狸猫技术窝”公众号的知识店铺内的训练营详情即可**
|
||||
|
||||
**具体可参见训练营目录下的《训练营专属服务》文档。简单来说,这个私人定制的面试VIP服务,会为你的跳槽面试全程保驾护航**
|
||||
|
||||
**“狸猫技术窝”**,找到我们的训练营的详情页面
|
22
docs/distributed-system/dynamic-route.md
Executable file
@ -0,0 +1,22 @@
|
||||
```
|
||||
CREATE TABLE `gateway_api_route` (
|
||||
`id` varchar(50) NOT NULL,
|
||||
`path` varchar(255) NOT NULL,
|
||||
`service_id` varchar(50) DEFAULT NULL,
|
||||
`url` varchar(255) DEFAULT NULL,
|
||||
`retryable` tinyint(1) DEFAULT NULL,
|
||||
`enabled` tinyint(1) NOT NULL,
|
||||
`strip_prefix` int(11) DEFAULT NULL,
|
||||
`api_name` varchar(255) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8
|
||||
|
||||
INSERT INTO gateway_api_route (id, path, service_id, retryable, strip_prefix, url, enabled) VALUES ('order-service', '/order/**', 'order-service',0,1, NULL, 1);
|
||||
|
||||
```
|
||||
|
||||
你可以自己用简单的spring mvc+前端页面封装一个可视化的网关管理工作台,如果新开发了一个服务之后,就可以在这个界面上配置一下,说某个服务对应某个url路径,修改,增删改查
|
||||
|
||||
http://localhost:9000/order/order/create?productId=1&userId=1&count=2&totalPrice=50
|
||||
|
||||
生产级,企业级的功能,网关的动态路由
|
8
docs/distributed-system/eventual-consistency.md
Executable file
@ -0,0 +1,8 @@
|
||||
|
||||
其实也很简单,自己写一个可靠消息服务即可,接收人家发送的half message,然后返回响应给人家,如果Producer没收到响应,则重发。然后Producer执行本地事务,接着发送commit/rollback给可靠消息服务。
|
||||
|
||||
可靠消息服务启动一个后台线程定时扫描本地数据库表中所有half message,超过一定时间没commit/rollback就回调Producer接口,确认本地事务是否成功,获取commit/rollback
|
||||
|
||||
如果消息被rollback就废弃掉,如果消息被commit就发送这个消息给下游服务,或者是发送给RabbitMQ/Kafka/ActiveMQ,都可以,然后下游服务消费了,必须回调可靠消息服务接口进行ack
|
||||
|
||||
如果一段时间都没收到ack,则重发消息给下游服务
|
2
docs/distributed-system/floor-distribute-lock.md
Executable file
@ -0,0 +1,2 @@
|
||||
|
||||
《亿级流量电商详情页系统实战》,部署redis和zookeeper,redisson做分布式锁,curator做分布式锁,试一试
|
23
docs/distributed-system/gateway-high-concurrency.md
Executable file
@ -0,0 +1,23 @@
|
||||
|
||||
第一个是高并发,第二个是如何优化
|
||||
|
||||
![高性能网关Zuul](/docs/distributed-system/images/gateway-high-concurrency.png)
|
||||
**Zuul**网关部署的是什么配置的机器,**部署32核64G,对网关路由转发的请求**,**每秒抗个小几万请求是不成问题的,几台Zuul网关机器**
|
||||
|
||||
**每秒是1万请求,8核16G的机器部署Zuul网关,5台机器就够了**
|
||||
|
||||
### 生产级的网关,应该具备我刚才说的几个特点和功能:
|
||||
|
||||
#### (1)动态路由:新开发某个服务,动态把请求路径和服务的映射关系热加载到网关里去;服务增减机器,网关自动热感知
|
||||
#### (2)灰度发布:基于现成的开源插件来做
|
||||
#### (3)授权认证
|
||||
#### (4)限流熔断
|
||||
#### (5)性能监控:每个API接口的耗时、成功率、QPS
|
||||
#### (6)系统日志
|
||||
#### (7)数据缓存
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
40
docs/distributed-system/gateway-model-selection.md
Executable file
@ -0,0 +1,40 @@
|
||||
|
||||
### 网关的核心功能
|
||||
|
||||
#### (1)动态路由:新开发某个服务,动态把请求路径和服务的映射关系热加载到网关里去;服务增减机器,网关自动热感知
|
||||
#### (2)灰度发布
|
||||
#### (3)授权认证
|
||||
#### (4)性能监控:每个API接口的耗时、成功率、QPS
|
||||
#### (5)系统日志
|
||||
#### (6)数据缓存
|
||||
#### (7)限流熔断
|
||||
|
||||
|
||||
### 几种技术选型
|
||||
|
||||
#### Kong、Zuul、Nginx+Lua(OpenResty)、自研网关
|
||||
|
||||
**Kong:Nginx里面的一个基于lua写的模块,实现了网关的功能**
|
||||
**Zuul:Spring Cloud来玩儿微服务技术架构,Zuul**
|
||||
|
||||
**Nginx+Lua(OpenResty):课程目录里面,有一个文档,课程免费学习,亿级流量系统架构的课程,详细讲解了Nginx+Lua的开发**,基于lua自己写类似Kong的网关
|
||||
**自研网关:自己来写类似Zuul的网关,基于Servlet、Netty来做网关,实现上述所有的功能**
|
||||
|
||||
|
||||
大厂:BAT、京东、美团、滴滴之类的,自研网关,都是基于Netty等技术自研网关;Nginx + Lua(Tengine)来做,封装网关的功能
|
||||
|
||||
中小型公司:Spring Cloud技术栈主要是用Zuul,Gateway;如果是Dubbo等技术栈,有的采用Kong等网关,也可以直接不用网关,很多公司压根儿就没用网关,直接Nginx反向代理+负载均衡;
|
||||
|
||||
Zuul:基于Java开发,核心网关功能都比较简单,但是比如灰度发布、限流、动态路由之类的,很多都要自己做二次开发
|
||||
|
||||
Kong:依托于Nginx实现,OpenResty,lua实现的模块,现成的一些插件,可以直接使用
|
||||
|
||||
|
||||
|
||||
Zuul(Servlet、Java):高并发能力不强,部署到一些机器上去,还要基于Tomcat来部署,Spring Boot用Tomcat把网关系统跑起来;Java语言开发,可以直接把控源码,可以做二次开发封装各种需要的功能
|
||||
|
||||
Nginx(Kong、Nginx+Lua):Nginx抗高并发的能力很强,少数几台机器部署一下,就可以抗很高的并发,精通Nginx源码,很难,c语言,很难说从Nginx内核层面去做一些二次开发和源码定制
|
||||
|
||||
|
||||
Java技术栈为主的大厂,很多其实用Java、Servlet、Netty来开发高并发、高性能的网关系统,自己可以把控一切
|
||||
|
6
docs/distributed-system/gateway-technical.md
Executable file
@ -0,0 +1,6 @@
|
||||
|
||||
服务框架的原理和技术选型,你们公司到底是怎么选,为什么?
|
||||
|
||||
服务注册中心,思考,你们公司到底是怎么选的,生产环境有没有做一些优化,如果没有,哪些地方是有优化空间的?
|
||||
|
||||
网关系统,思考,你们公司是怎么选型的,为什么?生产环境是否对类似动态路由的功能做过优化,如果没有是否有优化空间?
|
76
docs/distributed-system/gray-environment.md
Executable file
@ -0,0 +1,76 @@
|
||||
|
||||
#### 准备一个数据库和一个表(也可以用Apollo配置中心、Redis、ZooKeeper,其实都可以),放一个灰度发布启用表
|
||||
|
||||
```
|
||||
id service_id path enable_gray_release
|
||||
|
||||
CREATE TABLE `gray_release_config` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`service_id` varchar(255) DEFAULT NULL,
|
||||
`path` varchar(255) DEFAULT NULL,
|
||||
`enable_gray_release` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8
|
||||
|
||||
|
||||
|
||||
在zuul里面加入下面的filter,可以在zuul的filter里定制ribbon的负载均衡策略
|
||||
|
||||
<dependency>
|
||||
<groupId>io.jmnarloch</groupId>
|
||||
<artifactId>ribbon-discovery-filter-spring-cloud-starter</artifactId>
|
||||
<version>2.1.0</version>
|
||||
</dependency>
|
||||
|
||||
写一个zuul的filter,对每个请求,zuul都会调用这个filter
|
||||
|
||||
@Configuration
|
||||
public class GrayReleaseFilter extends ZuulFilter {
|
||||
|
||||
@Autowired
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
@Override
|
||||
public int filterOrder() {
|
||||
return PRE_DECORATION_FILTER_ORDER - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String filterType() {
|
||||
return PRE_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldFilter() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object run() {
|
||||
RequestContext ctx = RequestContext.getCurrentContext();
|
||||
HttpServletRequest request = ctx.getRequest();
|
||||
|
||||
Random random = new Random();
|
||||
int seed = random.getInt() * 100;
|
||||
|
||||
if (seed = 50) {
|
||||
// put the serviceId in `RequestContext`
|
||||
RibbonFilterContextHolder.getCurrentContext()
|
||||
.add("version", "new");
|
||||
} else {
|
||||
RibbonFilterContextHolder.getCurrentContext()
|
||||
.add("version", "old");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
eureka:
|
||||
instance:
|
||||
metadata-map:
|
||||
version: new
|
||||
|
||||
|
||||
|
26
docs/distributed-system/highly-concurrent-distribute-lock.md
Executable file
@ -0,0 +1,26 @@
|
||||
|
||||
分段加锁
|
||||
|
||||
有好多同学出去面试,聊到分布式锁这块,都被人考察分布式锁能不能抗高并发的问题了
|
||||
|
||||
对某个商品下单,对一个分布式锁每秒突然有上万请求过来,都要进行加锁,此时怎么办呢?可能就会导致你
|
||||
|
||||
|
||||
|
||||
比如你的苹果库存有10000个,此时你在数据库中创建10个库存字段
|
||||
|
||||
一个表里有10个库存字段,stock_01,stock_02,每个库存字段里放1000个库存
|
||||
|
||||
此时这个库存的分布式锁,对应10个key,product_1_stock_01,product_1_stock_02
|
||||
|
||||
请求过来之后,你从10个key随机选择一个key,去加锁就可以了,每秒过来1万个请求,此时他们会对10个库存分段key加锁,每个key就1000个请求,每台服务器就1000个请求而已
|
||||
|
||||
|
||||
万一说某个库存分段仅仅剩余10个库存了,此时我下订单要买20个苹果,合并扣减库存,你对product_1_stock_5,加锁了,此时查询对应的数据库中的库存,此时库存是10个,不够买20个苹果
|
||||
|
||||
你可以尝试去锁product_1_stock_1,再查询他的库存可能有30个
|
||||
|
||||
此时你就可以下订单,锁定库存的时候,就对product_1_stock_5锁定10个库存,对product_1_stock1锁定10个库存,锁定了20个库存
|
||||
|
||||
|
||||
分段加锁 + 合并扣减
|
@ -0,0 +1,2 @@
|
||||
|
||||
想想自己的分布式锁用在业务系统中,有没有高并发问题,如果有,如何用分段加锁思路来解决,或者用kv存储来存放实时库存抗并发,直接在kv里扣减,避免用分布式锁
|
4
docs/distributed-system/hitch-redis-distribute-lock.md
Executable file
@ -0,0 +1,4 @@
|
||||
|
||||
瞬时故障问题
|
||||
|
||||
彻底解决这个问题,很难,除非你修改一些redis和redisson框架的源码,源码级的二次开发,加锁,必须是master和slave同时写成功,才算是加锁成功
|
21
docs/distributed-system/homework.md
Executable file
@ -0,0 +1,21 @@
|
||||
|
||||
结合自身的情况来分析一下
|
||||
|
||||
结合面试突击第一季的课程,在“狸猫技术窝”公众号的知识店铺里去,在里面会有一个免费的课程,就是面试突击第一季,大家去里面找就可以了
|
||||
|
||||
可以把免费的面试突击第一季和我们现在付费的后续面试训练营系统同时同步一起看
|
||||
|
||||
技术广度的一些,各种技术
|
||||
|
||||
### (1)自己在技术广度上做的如何?你现在主流技术栈哪些技术都有一定的了解,包括核心原理和常见技术方案
|
||||
|
||||
### (2)自己在项目经验和生产经验上做的如何?你会的这些技术,自己在项目里到底用过多少?用的有多复杂?用的时候考虑了哪些项目细节和生产细节?
|
||||
|
||||
### (3)技术深度,你现在对哪些技术是除了核心原理以及基础知识之外,对一些技术的底层的概念和原理有一定的了解
|
||||
|
||||
### (4)系统设计,你目前自己独立负责过设计的系统和架构有多复杂?如果让你来独立设计秒杀系统、红包系统、12306系统,或者是一些其他大型的架构,你会如何来设计呢?
|
||||
|
||||
能力差距在哪里,肯定会有很多的疑问,第一周是预售周,是除了这4讲试看以外,其他的是不更新的,从第一周预售周结束之后会开始每日更新课程,可以把面试突击第一季复习巩固一下,没看过的人正好借着这一周把面试突击第一季先去看一下
|
||||
|
||||
而且可以对自己的能力模型做一个详细的梳理,看看自己现在能力有多强,差距在哪里
|
||||
|
BIN
docs/distributed-system/images/SpringCloud-core-architecture.png
Executable file
After Width: | Height: | Size: 215 KiB |
BIN
docs/distributed-system/images/async-replication-data-lose-case.png
Executable file
After Width: | Height: | Size: 7.3 KiB |
BIN
docs/distributed-system/images/consistent-hashing-algorithm.png
Executable file
After Width: | Height: | Size: 108 KiB |
BIN
docs/distributed-system/images/distributed-lock.png
Executable file
After Width: | Height: | Size: 91 KiB |
BIN
docs/distributed-system/images/distributed-system-request-sequence.png
Executable file
After Width: | Height: | Size: 15 KiB |
BIN
docs/distributed-system/images/distributed-transaction-TCC.png
Executable file
After Width: | Height: | Size: 16 KiB |
BIN
docs/distributed-system/images/distributed-transaction-XA.png
Executable file
After Width: | Height: | Size: 6.2 KiB |
BIN
docs/distributed-system/images/distributed-transaction-local-message-table.png
Executable file
After Width: | Height: | Size: 32 KiB |
BIN
docs/distributed-system/images/distributed-transaction-reliable-message.png
Executable file
After Width: | Height: | Size: 40 KiB |
BIN
docs/distributed-system/images/dubbo-framework-principle.png
Executable file
After Width: | Height: | Size: 166 KiB |
BIN
docs/distributed-system/images/dubbo-keep-connection.png
Executable file
After Width: | Height: | Size: 8.5 KiB |
BIN
docs/distributed-system/images/dubbo-not-keep-connection.png
Executable file
After Width: | Height: | Size: 4.8 KiB |
BIN
docs/distributed-system/images/dubbo-operating-principle.png
Executable file
After Width: | Height: | Size: 58 KiB |
BIN
docs/distributed-system/images/dubbo-rock-bottom.png
Executable file
After Width: | Height: | Size: 129 KiB |
BIN
docs/distributed-system/images/dubbo-service-invoke-road.png
Executable file
After Width: | Height: | Size: 6.8 KiB |
BIN
docs/distributed-system/images/dubbo-spi.png
Executable file
After Width: | Height: | Size: 11 KiB |
BIN
docs/distributed-system/images/e-commerce-website-detail-page-architecture-1.png
Executable file
After Width: | Height: | Size: 8.2 KiB |
BIN
docs/distributed-system/images/e-commerce-website-detail-page-architecture-2.png
Executable file
After Width: | Height: | Size: 17 KiB |
BIN
docs/distributed-system/images/eureka-register.png
Executable file
After Width: | Height: | Size: 28 KiB |
BIN
docs/distributed-system/images/favicon-16x16.png
Executable file
After Width: | Height: | Size: 1.2 KiB |
BIN
docs/distributed-system/images/favicon-32x32.png
Executable file
After Width: | Height: | Size: 2.4 KiB |
BIN
docs/distributed-system/images/gateway-high-concurrency.png
Executable file
After Width: | Height: | Size: 248 KiB |
BIN
docs/distributed-system/images/hash-slot.png
Executable file
After Width: | Height: | Size: 3.9 KiB |
BIN
docs/distributed-system/images/hash.png
Executable file
After Width: | Height: | Size: 3.7 KiB |
BIN
docs/distributed-system/images/icon.png
Executable file
After Width: | Height: | Size: 74 KiB |
BIN
docs/distributed-system/images/redis-distribute-lock.png
Executable file
After Width: | Height: | Size: 351 KiB |
BIN
docs/distributed-system/images/registration-center-optimize.png
Executable file
After Width: | Height: | Size: 77 KiB |
BIN
docs/distributed-system/images/rocketmq-transaction.png
Executable file
After Width: | Height: | Size: 166 KiB |
BIN
docs/distributed-system/images/serialize-deserialize.png
Executable file
After Width: | Height: | Size: 4.9 KiB |
BIN
docs/distributed-system/images/service-invoke-road.png
Executable file
After Width: | Height: | Size: 3.7 KiB |
BIN
docs/distributed-system/images/simple-distributed-system-oa.png
Executable file
After Width: | Height: | Size: 16 KiB |
BIN
docs/distributed-system/images/springCloud-study-theory.png
Executable file
After Width: | Height: | Size: 150 KiB |
BIN
docs/distributed-system/images/zookeeper-active-standby.png
Executable file
After Width: | Height: | Size: 12 KiB |
BIN
docs/distributed-system/images/zookeeper-centralized-storage.png
Executable file
After Width: | Height: | Size: 3.8 KiB |
BIN
docs/distributed-system/images/zookeeper-distribute-lock-optimize.png
Executable file
After Width: | Height: | Size: 50 KiB |
BIN
docs/distributed-system/images/zookeeper-distribute-lock.png
Executable file
After Width: | Height: | Size: 88 KiB |
BIN
docs/distributed-system/images/zookeeper-distributed-coordination.png
Executable file
After Width: | Height: | Size: 15 KiB |
BIN
docs/distributed-system/images/zookeeper-distributed-lock-demo.png
Executable file
After Width: | Height: | Size: 14 KiB |
BIN
docs/distributed-system/images/zookeeper-distributed-lock.png
Executable file
After Width: | Height: | Size: 8.0 KiB |
BIN
docs/distributed-system/images/zookeeper-meta-data-manage.png
Executable file
After Width: | Height: | Size: 14 KiB |
BIN
docs/distributed-system/images/zookeeper-register.png
Executable file
After Width: | Height: | Size: 42 KiB |
84
docs/distributed-system/interface-idempotence.md
Executable file
@ -0,0 +1,84 @@
|
||||
|
||||
接口幂等性实现起来非常的简单,不打算带着大家手写代码
|
||||
|
||||
(1)数据库唯一索引
|
||||
(2)基于Redis实现一套幂等性防重框架
|
||||
|
||||
|
||||
|
||||
对于插入类的操作,一般都是建议大家要在数据库表中设计一些唯一索引
|
||||
|
||||
|
||||
你如果有一个订单被支付了,此时就要通知wms创建一个对应发货单,也是数据库里的一个表,仓库里的人会看到这个发货单,此时他就会根据发货单的信息从仓库里进行拣货,打包,封装,交给物流公司
|
||||
|
||||
|
||||
|
||||
发货单
|
||||
|
||||
id order_id 订单金额 发货地址 xxxx
|
||||
|
||||
对order_id就可以建立一个唯一索引,你插入发货单的时候,同一个order_id最多只能对应一个发货单,不可能说同样的一个order_id对应了多个发货单
|
||||
|
||||
|
||||
订单服务 -> wms服务,出现了重试,导致第二次请求再次让人家创建这个订单的发货单,create语句,order_id触发了唯一索引约束
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
扣减库存、累加积分,更新,很难通过数据库唯一索引来保证
|
||||
|
||||
|
||||
基于Redis实现一套接口的防重框架
|
||||
|
||||
你得做一个类似spring mvc里的拦截器这样的东西,在这个拦截器里,他会拦截所有的请求,对所有的请求都会提取请求对应的参数,GET请求、POST请求、PUT请求,有些参数是跟在URL地址里的,?xx=xx&xx=xx
|
||||
|
||||
POST、PUT,可能是请求体里的,可能是一个JSON格式
|
||||
|
||||
把参数拼接在一起,作为key去redis中判断一下,是否存在这个key,之前附加这些参数的请求是否发起过,如果没有的话,此时就可以把这些参数+接口名称,作为一个key,存储到redis中去
|
||||
|
||||
然后呢,把请求放行,去执行这个请求
|
||||
|
||||
如果说人家重试再次发起一个这个请求,此时就可以判断出来,参数组成的key在redis中已经存在了,此时就不让执行这个请求了,认为是重复调用了
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
考虑很多问题,幂等不幂等,通用框架,需要一个公司所有的接口都按照指定的参数来传递,还有很多业务语义的问题
|
||||
|
||||
第一次发起一个请求,直接把请求key放入redis,但是他执行的过程中失败了,而且还阻塞了一段时间,此时人家再次重试发起第二次请求,这个时候按照上述的框架逻辑,就会把请求拦截下来了
|
||||
|
||||
|
||||
到底是不是要对所有接口都开启这么一个东西呢?
|
||||
|
||||
|
||||
每个接口如果执行成功了之后,我可以设置一个每个接口调用的时候执行成功之后,做一个后拦截器,如果成功了,就把请求对应的参数拼接为key放入redis中
|
||||
|
||||
有没有可能是第一次请求发送过来,在执行过程中,时间长了,比如需要1.3秒才执行完毕;此时人家发现超过1s了,直接重试,第二次请求过来了,也在正常的执行
|
||||
|
||||
第一次请求1.3秒之后执行成功了,第二次请求也执行成功了
|
||||
|
||||
只要一个服务希望对自己的接口开启幂等性防重功能,就把你开发好的拦截器对应的jar包,通过maven引入一个依赖就可以了
|
||||
|
||||
|
||||
|
||||
中大型互联网公司里也没做一个统一的防重幂等框架,其实一般都是各个服务对自己核心的接口,如果要保证幂等性的话,每个服务根据自己的业务逻辑来实现,而且仅仅是对少数核心接口做幂等性保障
|
||||
|
||||
|
||||
核心接口,库存服务,扣减库存接口
|
||||
|
||||
定制化的去针对接口开发幂等性的机制,比如说一旦库存扣减成功之后,就立马要写一条数据到redis里去,order_id_11356_stock_deduct,写入redis中,如果写入成功,就说明之前这个订单的库存扣减,没人执行过
|
||||
|
||||
但是如果此时有一些重试的请求过来了,调用了你的库存扣减接口,他同时也进行了库存的扣减,但是他用同样的一个key,order_id_11356_stock_deduct,写入redis中,此时会发现已经有人写过key,key已经存在了
|
||||
|
||||
此时你就应该直接对刚才的库存扣减逻辑做一个反向的回滚逻辑,update product_stock set stock = stock - 100,update product_stock set stock = stock + 100,反向逻辑,回滚掉,自己避免说重复扣减库存
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
核心接口,幂等性都是自己保证的,人家可能会重试调用你的接口,对于create类的操作,用唯一索引来保证;对update类的操作,建议在核心接口里基于自己的业务逻辑,配合上redis,来保证幂等性
|
||||
|
||||
|
27
docs/distributed-system/java-internet-interview-outlook.md
Executable file
@ -0,0 +1,27 @@
|
||||
|
||||
快速扫盲,MQ、ES、Dubbo、分布式事务、分布式锁、缓存架构、高并发、高可用,各种常考的技术问题,都拎出来,重点的讲解一下
|
||||
|
||||
21天互联网Java工程师面试训练营(分布式篇),互联网Java工程师面试突击训练(第二季)
|
||||
|
||||
对第一季的分布式面试题,进一步加深了,分布式这块再抗一堆连环炮都没问题
|
||||
|
||||
接着对后面几季的内容,会考虑一下形式,可能会考虑把五季合并为一季,作为面试突击第三季,形式上会综合考虑是继续用视频,还是用文章形式更便于大家日常学习
|
||||
|
||||
微服务、海量数据、高性能、高并发、高可用,五季
|
||||
|
||||
互联网Java工程师面试突击训练营(第三季)
|
||||
|
||||
视频,路上,在公司里不方便看视频,等到回家,晚上来一局王者荣耀
|
||||
|
||||
文章,上下班路上,在公司里,支持在PC端可以看文章,自己写写代码,做点实验
|
||||
|
||||
狸猫技术窝,知识店铺,有一个文章专栏,救火队队长,《从0开始带你成为JVM实战高手》,一步一图,大白话,通俗易懂,1个多月,将近2000人买了专栏,普遍好评,非常的好,看的浅显易懂,实战型强,就知道生产环境jvm如何优化
|
||||
|
||||
|
||||
|
||||
后台观察一下购买面试训练营第二季的同学学习的进度,没时间看视频,赶进度一个过程中,学习中,第三季,那一定是观察大部分同学都得把第二季学的差不多,重磅推出第三季,加量不加价
|
||||
|
||||
|
||||
付费微信群,里面有很多我这两年带出来的大厂的同学,滴滴、阿里、百度、美团、美菜、每日优鲜、vipkid,热火朝天聊技术问题
|
||||
|
||||
学习+作业+思考+复习+提问+答疑
|
46
docs/distributed-system/java-interview-season-1-summary.md
Executable file
@ -0,0 +1,46 @@
|
||||
|
||||
### 系统性的分析了一下大厂对一个工程师的要:
|
||||
**数据结构和算法**,**软素质**,**工程素养**,**履历背景**,**学历**,**带团队管理**,真正在招人的时候,会考虑很多的方面,**技术广度**、**技术深度**、**项目经验**、**系统设计**,技术上的要求
|
||||
|
||||
发布过:《互联网Java工程师面试突击(第一季)》
|
||||
|
||||
Spring MVC、Spring、Lucene、Activiti,单块系统,做的项目很多都是那种OA系统,财务系统,CRM系统,工厂管理系统,类似这样的一些东西
|
||||
|
||||
跟上国内主流的技术栈
|
||||
|
||||
MQ,消息丢失,消息重复,高可用部署,原理;缓存,数据库和缓存双写怎么保证一致性;分布式锁,实现原理;分布式事务的常见方案;Dubbo、Spring Cloud
|
||||
|
||||
定位,面试突击第一季的定位,就是把常见互联网技术栈里的技术和主流技术方案给大家分析一下,做一个扫盲,避免说出去面试一问三不知
|
||||
|
||||
数据库原理和优化,JVM原理和优化,并发的原理和优化
|
||||
|
||||
已经帮助了数以千计的同学了,不完全统计,从去年到今年,看过面试突击第一季的同学,估算人数在5000人以上,帮助大量的同学快速扫盲,积累了很多互联网主流技术栈,出去面试,很多人给我们发感谢信
|
||||
|
||||
我们也收到了很多同学的反馈,老师,但是还是有很多的问题,项目经验、生产经验、技术深度:
|
||||
|
||||
**(1)项目经验:分库分表深挖我的项目细节,死磕到底架势,我直接挂掉了**
|
||||
|
||||
**(2)生产经验:Spring Cloud Zuul网关在生产环境如何进行优化,分布式锁会不会导致并发能力降低,如何优化,分布式事务会不会导致交易TPS降低,如何优化,服务注册中心如果发现过慢如何解决,访问量有多大怎么部署的,需要多少台机器**
|
||||
|
||||
**(3)技术深度:Kafka基本原理、RocketMQ基本原理,一问到深度点的东西,比如Kafka底层的分布式架构,副本同步机制,推还是拉,生产者底层的网络通信机制**
|
||||
|
||||
**(4)系统设计:面试官现场出系统设计的问题,让我结合某个业务场景现场设计一个什么什么方案或者架构,让我给思路**
|
||||
|
||||
|
||||
我们的课程每天都会有一个作业,引导大家把学习到的项目经验、技术方案和生产优化落地到自己负责的项目中去,让大家出去面试的时候,可以把各种技术结合自己的项目来回答面试官的各种深度拷问
|
||||
|
||||
大家不要小看这个,根据我多年的面试经验来看,拥有这个技能的人凤毛麟角,这种人出去绝对是各大公司争抢的对象。
|
||||
|
||||
所以希望大家好好完成每天的作业,我布置的大量作业,就是为了帮你锻造出这种能力
|
||||
|
||||
学习课程以及完成作业的过程中,大家一定会有很多的问题,可以到专栏的评论区去提问
|
||||
|
||||
每天我都会和之前带出来的一批阿里、蚂蚁金服、滴滴的优秀同学给大家进行答疑,并且我们还有专门的付费用户的微信群,大家可以在微信群里跟我们一起进行技术交流
|
||||
|
||||
如果你能坚持下来,学满6季,还可以获取私人定制的面试一条龙VIP服务
|
||||
|
||||
如果是连续6季面试训练营都购买的同学,还可以获取面试一条龙VIP服务
|
||||
|
||||
具体信息大家看“狸猫技术窝”公众号的知识店铺内的训练营详情即可,
|
||||
|
||||
具体可参见训练营目录下的《训练营专属服务》文档。简单来说,这个私人定制的面试VIP服务,会为你的跳槽面试全程保驾护航
|
36
docs/distributed-system/redis-distribute-lock.md
Executable file
@ -0,0 +1,36 @@
|
||||
|
||||
面试突击第二季
|
||||
![distributed-lock](/docs/distributed-system/images/redis-distribute-lock.png)
|
||||
Redis分布式锁,很少自己撸,Redisson框架,他基于Redis实现了一系列的开箱即用的高级功能,比如说分布式锁
|
||||
|
||||
引入maven依赖,他示例代码就几行
|
||||
|
||||
比如说,苹果这个商品的id是1
|
||||
|
||||
redisson.lock(“product_1_stock”)
|
||||
|
||||
key的业务语义,就是针对product_id = 1的商品的库存,也就就是苹果的库存,进行加锁
|
||||
|
||||
如果要学习redis技术的,跟我之前录制的《亿级流量商品详情页系统》去学习,在训练营的课程目录里有一个文档,有我之前的课程的地址
|
||||
|
||||
|
||||
product_1_stock: {
|
||||
“xxxx”: 1
|
||||
}
|
||||
|
||||
生存时间:30s
|
||||
|
||||
watchdog,redisson框架后台执行一段逻辑,每隔10s去检查一下这个锁是否还被当前客户端持有,如果是的话,重新刷新一下key的生存时间为30s
|
||||
|
||||
其他客户端尝试加锁,这个时候发现“product_1_stock”这个key已经存在了,里面显示被别的客户端加锁了,此时他就会陷入一个无限循环,阻塞住自己,不能干任何事情,必须在这里等待
|
||||
|
||||
|
||||
第一个客户端加锁成功了,此时有两种情况,第一种情况,这个客户端操作完毕之后,主动释放锁;第二种情况,如果这个客户端宕机了,那么这个客户端的redisson框架之前启动的后台watchdog线程,就没了
|
||||
|
||||
此时最多30s,key-value就消失了,自动释放了宕机客户端之前持有的锁
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
0
docs/distributed-system/register-high-availability.md
Executable file
34
docs/distributed-system/register-production-optimize.md
Executable file
@ -0,0 +1,34 @@
|
||||
|
||||
#### 分布式系统架构的
|
||||
|
||||
**服务注册中心,eureka、zk、consul,原理画图画清楚**
|
||||
|
||||
**数据一致性,CP、AP**
|
||||
|
||||
服务注册、故障 和发现的时效性是多长时间
|
||||
|
||||
注册中心最大能支撑多少服务实例
|
||||
|
||||
如何部署的,几台机器,每台机器的配置如何,会用比较高配置的机器来做,8核16G,16核32G的高配置机器来搞,基本上可以做到每台机器每秒钟的请求支撑几千绝对没问题
|
||||
|
||||
可用性如何来保证
|
||||
|
||||
**有没有做过一些优化,服务注册、故障以及发现的时效性,是否可以优化一下,用eureka的话,可以尝试一下,配合我们讲解的那些参数,优化一下时效性,服务上线、故障到发现是几秒钟的时效性**
|
||||
|
||||
**zk,一旦服务挂掉,zk感知到以及通知其他服务的时效性,服务注册到zk之后通知到其他服务的时效性,leader挂掉之后可用性是否会出现短暂的问题,为了去换取一致性**
|
||||
|
||||
|
||||
**所以希望大家好好完成每天的作业,我布置的大量作业,就是为了帮你锻造出这种能力**
|
||||
|
||||
**学习课程以及完成作业的过程中,大家一定会有很多的问题,可以到专栏的评论区去提问**
|
||||
|
||||
**每天我都会和之前带出来的一批阿里、蚂蚁金服、滴滴的优秀同学给大家进行答疑,并且我们还有专门的付费用户的微信群,大家可以在微信群里跟我们一起进行技术交流**
|
||||
|
||||
**如果你能坚持下来,学满6季,还可以获取私人定制的面试一条龙VIP服务**
|
||||
|
||||
**如果是连续6季面试训练营都购买的同学,还可以获取面试一条龙VIP服务**
|
||||
|
||||
**具体信息大家看“狸猫技术窝”公众号的知识店铺内的训练营详情即可**
|
||||
|
||||
**具体可参见训练营目录下的《训练营专属服务》文档。简单来说,这个私人定制的面试VIP服务,会为你的跳槽面试全程保驾护航**
|
||||
|
54
docs/distributed-system/registration-center- guide.md
Executable file
@ -0,0 +1,54 @@
|
||||
|
||||
非常常见的一个技术面试题,但凡只要是聊到分布式这块,一定会问问你,**Dubbo,Spring Cloud,服务注册中心**,你们当时是怎么选型和调研的,你们最终是选择了哪块技术呢?你选择这块技术的原因和理由是什么呢?
|
||||
|
||||
**Eureka、ZooKeeper**
|
||||
|
||||
**Dubbo**作为服务框架的,一般注册中心会选择zk
|
||||
|
||||
**Spring Cloud**作为服务框架的,**一般服务注册中心会选择Eureka**
|
||||
|
||||
**Consul、Nacos,**普及型还没那么广泛,我会在面试训练营课程里增加对应的内容,给大家去进行补充
|
||||
|
||||
#### (1)服务注册发现的原理
|
||||
|
||||
集群模式
|
||||
![ZooKeeper](/docs/distributed-system/images/eureka-register.png)
|
||||
|
||||
**Eureka,peer-to-pee**r,部署一个集群,**但是集群里每个机器的地位是对等的,各个服务可以向任何一个Eureka实例服务注册和服务发现,集群里任何一个Euerka实例接收到写请求之后,会自动同步给其他所有的Eureka实例**
|
||||
![ZooKeeper](/docs/distributed-system/images/zookeeper-register.png)
|
||||
|
||||
**ZooKeeper,服务注册和发现的原理,Leader + Follower两种角色,只有Leader可以负责写也就是服务注册,他可以把数据同步给Follower,读的时候leader/follower都可以读**
|
||||
|
||||
#### (2)一致性保障:CP or AP
|
||||
|
||||
**CAP,C是一致性,A是可用性,P是分区容错性**
|
||||
|
||||
**CP,AP**
|
||||
|
||||
**ZooKeeper是有一个leader节点会接收数据, 然后同步写其他节点,一旦leader挂了,要重新选举leader,这个过程里为了保证C,就牺牲了A,不可用一段时间,但是一个leader选举好了,那么就可以继续写数据了,保证一致性**
|
||||
|
||||
Eureka是peer模式,可能还没同步数据过去,结果自己就死了,此时还是可以继续从别的机器上拉取注册表,但是看到的就不是最新的数据了,但是保证了可用性,强一致,最终一致性
|
||||
|
||||
(3)服务注册发现的时效性
|
||||
|
||||
zk,时效性更好,注册或者是挂了,一般秒级就能感知到
|
||||
|
||||
eureka,默认配置非常糟糕,服务发现感知要到几十秒,甚至分钟级别,上线一个新的服务实例,到其他人可以发现他,极端情况下,可能要1分钟的时间,ribbon去获取每个服务上缓存的eureka的注册表进行负载均衡
|
||||
|
||||
服务故障,隔60秒才去检查心跳,发现这个服务上一次心跳是在60秒之前,隔60秒去检查心跳,超过90秒没有心跳,才会认为他死了,2分钟都过去
|
||||
|
||||
30秒,才会更新缓存,30秒,其他服务才会来拉取最新的注册表
|
||||
|
||||
三分钟都过去了,如果你的服务实例挂掉了,此时别人感知到,可能要两三分钟的时间,一两分钟的时间,很漫长
|
||||
|
||||
#### (4)容量
|
||||
|
||||
zk,不适合大规模的服务实例,因为服务上下线的时候,需要瞬间推送数据通知到所有的其他服务实例,所以一旦服务规模太大,到了几千个服务实例的时候,会导致网络带宽被大量占用
|
||||
|
||||
eureka,也很难支撑大规模的服务实例,因为每个eureka实例都要接受所有的请求,实例多了压力太大,扛不住,也很难到几千服务实例
|
||||
|
||||
之前dubbo技术体系都是用zk当注册中心,spring cloud技术体系都是用eureka当注册中心这两种是运用最广泛的,但是现在很多中小型公司以spring cloud居多,所以后面基于eureka说一下服务注册中心的生产优化
|
||||
|
||||
(5)多机房、多数据中心、健康检查
|
||||
|
||||
|
6
docs/distributed-system/registration-center-optimize.md
Executable file
@ -0,0 +1,6 @@
|
||||
|
||||
![分布式注册中心](/docs/distributed-system/images/registration-center-optimize.png)
|
||||
#### eureka:peer-to-peer,每台机器都是高并发请求,有瓶颈
|
||||
#### zookeeper:服务上下线,全量通知其他服务,网络带宽被打满,有瓶颈
|
||||
|
||||
#### 分布式服务注册中心,分片存储服务注册表,横向扩容,每台机器均摊高并发请求,各个服务主动拉取,避免反向通知网卡被打满
|
16
docs/distributed-system/request-retry.md
Executable file
@ -0,0 +1,16 @@
|
||||
|
||||
订单服务 -> 创建订单
|
||||
|
||||
-> 库存服务 -> 扣减库存
|
||||
-> wms服务 -> 通知发货
|
||||
-> 积分服务 -> 增加积分
|
||||
|
||||
订单服务调用库存服务的时候,因为网络抖动,请求超时了,超过了秒钟,此时订单服务会重试,再次调用一下库存服务,发送一模一样的请求过去
|
||||
|
||||
|
||||
|
||||
比如说,订单服务第一次请求库存服务,库存服务其实是把扣减库存的业务逻辑执行成功了,只不过网络问题,导致响应迟迟没有返回给订单服务,可能在1.2s之后返回了响应给订单服务
|
||||
|
||||
订单服务就认为请求超时了,他就再次发送了一个一模一样的请求给库存服务,库存服务可能会再次对库存进行扣减
|
||||
|
||||
|
6
docs/distributed-system/rocketmq-eventual-consistency.md
Executable file
@ -0,0 +1,6 @@
|
||||
|
||||
seata,作业,参考官网示例,自己玩儿,在自己本地部署一个单机版的RocketMQ,做实验,参考示例代码,实现一下发送消息,回调接口,一个是事务消息,一个是消费者ack
|
||||
|
||||
面试训练营,讲究必须留作业给你自己动手
|
||||
|
||||
如果要看详细的项目实战类课程,参考训练营的课程目录中有一个文档,里面有我之前的课程,《亿级流量电商详情页系统实战》,一步一步带着手敲代码,可以去看看
|
40
docs/distributed-system/rocketmq-transaction.md
Executable file
@ -0,0 +1,40 @@
|
||||
|
||||
类似TCC事务的落地的一些东西,技术选型,业务场景需要分布式事务,结合我个人亲身经历的一个创业公司APP的一个事故,给大家介绍了一下,对于系统核心链路,为什么必须要上分布式事务
|
||||
|
||||
seata,github上,都会提供sample,跟dubbo,官方的同学是定义为double,spring cloud,seata都提供了sample,知道如何把分布式事务框架整合到框架里去了
|
||||
|
||||
|
||||
![核心交易链路](/docs/distributed-system/images/rocketmq-transaction.png)
|
||||
核心交易链路,分布式事务框架
|
||||
|
||||
|
||||
|
||||
有些服务之间的调用是走异步的,下成功了订单之后,你会通知一个wms服务去发货,这个过程可以是异步的,可以是走一个MQ的,发送一个消息到MQ里去,由wms服务去从MQ里消费消息
|
||||
|
||||
|
||||
MQ,消息中间件,面试突击第一季,刚开头我就讲过消息中间件的面试连环炮
|
||||
|
||||
|
||||
|
||||
可靠消息最终一致性方案,参考面试突击第一季
|
||||
|
||||
|
||||
|
||||
落地,RocketMQ来实现可靠消息最终一致性事务方案
|
||||
|
||||
|
||||
Producer向RocketMQ发送一个half message
|
||||
|
||||
RocketMQ返回一个half message success的响应给Producer,这个时候就形成了一个half message了,此时这个message是不能被消费的
|
||||
|
||||
注意,这个步骤可能会因为网络等原因失败,可能你没收到RocketMQ返回的响应,那么就需要重试发送half message,直到一个half message成功建立为止
|
||||
|
||||
接着Producer本地执行数据库操作
|
||||
|
||||
Producer根据本地数据库操作的结果发送commit/rollback给RocketMQ,如果本地数据库执行成功,那么就发送一个commit给RocketMQ,让他把消息变为可以被消费的;如果本地数据库执行失败,那么就发送一个rollback给RocketMQ,废弃之前的message
|
||||
|
||||
注意,这个步骤可能失败,就是Producer可能因为网络原因没成功发送commit/rollback给RocketMQ,此时RocketMQ自己过一段时间发现一直没收到message的commit/rollback,就回调你服务提供的一个接口
|
||||
|
||||
此时在这个接口里,你需要自己去检查之前执行的本地数据库操作是否成功了,然后返回commit/rollback给RocketMQ
|
||||
|
||||
只要message被commit了,此时下游的服务就可以消费到这个消息,此时还需要结合ack机制,下游消费必须是消费成功了返回ack给RocketMQ,才可以认为是成功了,否则一旦失败没有ack,则必须让RocketMQ重新投递message给其他consumer
|
59
docs/distributed-system/rpc-design.md
Executable file
@ -0,0 +1,59 @@
|
||||
这个面试题还是挺常见的,在面试突击第一季里,基本上带了一下,当时但是没有细讲,是因为当时面试突击第一季里对服务框架的原理没有做一个相对深入一点点的分析,当时主要就是讲了一些最基本的概念
|
||||
|
||||
人家并不是要你手撸一个**RPC框架**,资料,现场手撸一个**RPC框架**,撸的特别的简单,人家也不是要你手撸,也不是说让你进来了以后就是让你来研发RPC框架的
|
||||
|
||||
系统设计的问题,就是让你站在系统设计的角度,来考虑一下,到底如果要设计一个RPC框架,你会如何来考虑
|
||||
|
||||
动态代理:比如消费者和提供者,其实都是需要一个实现某个接口的动态代理的,RPC框架的一切的逻辑细节,都是在这个动态代理中实现的,动态代理里面的代码逻辑就是你的RPC框架核心的逻辑
|
||||
|
||||
JDK提供了API,去创建针对某个接口的动态代理
|
||||
|
||||
调用动态代理对象的方法之后,此时就应该先干一个事情,通过Cluster层的一些组件,服务注册中心,是用什么技术来进行实现呢?往简单了说,服务注册中心也可以是你自己手撸一个,也不难
|
||||
|
||||
自己手撸一个,服务去注册,其他服务去拉取注册表进行发现
|
||||
|
||||
**ZooKeeper**,稍微自己上网百度搜索一下,**ZooKeeper**入门使用教程,基本概念和原理,还有基本的使用,了解一下
|
||||
|
||||
**Cluster层**,从本地缓存的服务注册表里获取到要调用的服务的机器列表
|
||||
|
||||
**负载均衡**,**面试突击第一季**里,我们分析过**Dubbo的负载均衡策略**,此时你就可以把那些策略说一说,我要设计多少种策略,从服务的机器列表中采用负载均衡算法从里面选择出来一台机器
|
||||
|
||||
选择好了机器,知道了对方的端口号,而且知道你的请求调用,调用哪个Interface的哪个方法,把这些信息交给协议层
|
||||
|
||||
把数据组织一下,**协议**,**序列化机制**,**底层用什么网络通信框架**,比如**netty,mina**现在用的比较少,序列化和反序列化有没有概念,**Java基础概念,一个复杂的请求数据序列化成二进制的字节数组**
|
||||
|
||||
**反序列化就是从字节数组变成请求数据结构**
|
||||
|
||||
按照那个协议的规范对请求数据进行组织,不同的协议,组织出来的数据看起来是不一样的
|
||||
|
||||
**netty基本的原理**
|
||||
|
||||
解析完毕了之后,就知道,应该调用自己本地哪个Interface的实现类的哪个方法
|
||||
|
||||
|
||||
|
||||
**我们的课程每天都会有一个作业,引导大家把学习到的项目经验、技术方案和生产优化落地到自己负责的项目中去,让大家出去面试的时候,可以把各种技术结合自己的项目来回答面试官的各种深度拷问**
|
||||
|
||||
**大家不要小看这个,根据我多年的面试经验来看,拥有这个技能的人凤毛麟角,这种人出去绝对是各大公司争抢的对象。**
|
||||
|
||||
**我们的课程每天都会有一个作业,引导大家把学习到的项目经验、技术方案和生产优化落地到自己负责的项目中去,让大家出去面试的时候,可以把各种技术结合自己的项目来回答面试官的各种深度拷问**
|
||||
|
||||
**大家不要小看这个,根据我多年的面试经验来看,拥有这个技能的人凤毛麟角,这种人出去绝对是各大公司争抢的对象。**
|
||||
|
||||
**所以希望大家好好完成每天的作业,我布置的大量作业,就是为了帮你锻造出这种能力**
|
||||
|
||||
**学习课程以及完成作业的过程中,大家一定会有很多的问题,可以到专栏的评论区去提问**
|
||||
|
||||
**每天我都会和之前带出来的一批阿里、蚂蚁金服、滴滴的优秀同学给大家进行答疑,并且我们还有专门的付费用户的微信群,大家可以在微信群里跟我们一起进行技术交流**
|
||||
|
||||
**如果你能坚持下来,学满6季,还可以获取私人定制的面试一条龙VIP服务**
|
||||
|
||||
**如果是连续6季面试训练营都购买的同学,还可以获取面试一条龙VIP服务**
|
||||
|
||||
**具体信息大家看“狸猫技术窝”公众号的知识店铺内的训练营详情即可**
|
||||
|
||||
**具体可参见训练营目录下的《训练营专属服务》文档。简单来说,这个私人定制的面试VIP服务,会为你的跳槽面试全程保驾护航**
|
||||
|
||||
**“狸猫技术窝”**,找到我们的训练营的详情页面
|
||||
|
||||
|
14
docs/distributed-system/service-register-discovery.md
Executable file
@ -0,0 +1,14 @@
|
||||
|
||||
**zk,一般来说还好,服务注册和发现,都是很快的**
|
||||
|
||||
**eureka,必须优化参数**
|
||||
|
||||
**eureka.server.responseCacheUpdateIntervalMs = 3000**
|
||||
**eureka.client.registryFetchIntervalSeconds = 30000**
|
||||
|
||||
**eureka.client.leaseRenewalIntervalInSeconds = 30**
|
||||
**eureka.server.evictionIntervalTimerInMs = 60000**
|
||||
**eureka.instance.leaseExpirationDurationInSeconds = 90**
|
||||
|
||||
**服务发现的时效性变成秒级,几秒钟可以感知服务的上线和下线**
|
||||
|
12
docs/distributed-system/service-register-gateway-router.md
Executable file
@ -0,0 +1,12 @@
|
||||
|
||||
#### 生产环境,微服务生产实践
|
||||
|
||||
开发了一个新的服务,线上部署,配合网关动态路由的功能,在网关里配置一下路径和新服务的映射关系,此时请求过来直接就可以走到新的服务里去
|
||||
|
||||
对已有服务进行迭代和开发,新版本,灰度发布,新版本部署少数几台机器,通过一个界面,开启这个服务的灰度发布,**此时zuul filter启用,按照你的规则,把少量的流量打入到新版本部署的机器上去**
|
||||
|
||||
观察一下少量流量在新版本的机器上运行是否正常
|
||||
|
||||
版本改成current,全量机器部署,关闭灰度发布功能,网关就会把流量均匀分发给那个服务了
|
||||
|
||||
|