├── .gitignore ├── Book ├── assets │ ├── fig1-1.png │ └── fig2-5.png ├── 数据系统的基石.md └── 设计数据密集型应用.md ├── Elasticsearch ├── ELK环境搭建.md ├── Elasticsearch基本概念.md ├── Search API.md ├── assets │ ├── image-20201226193050881.png │ ├── image-20201226195911107.png │ ├── image-20201226202630374.png │ ├── image-20201226213336829.png │ ├── image-20201226213339559.png │ └── image-20201226214318986.png └── 倒排索引与分词.md ├── Java ├── JVM │ ├── README.md │ ├── assets │ │ ├── image-20190809184556232.png │ │ ├── image-20190809213138155.png │ │ ├── image-20190809213206559.png │ │ ├── image-20190809213227263.png │ │ ├── image-20190809213354622.png │ │ ├── image-20190809233744925.png │ │ ├── image-20190809233759640.png │ │ ├── image-20190809234222898.png │ │ ├── image-20190810001204867.png │ │ ├── image-20190810100312084.png │ │ ├── image-20190810101801242.png │ │ ├── image-20190810102209644.png │ │ ├── image-20190810111220152.png │ │ ├── image-20190810124001748.png │ │ ├── image-20190810125718250.png │ │ ├── image-20190810125721842.png │ │ ├── image-20190810130611648.png │ │ ├── image-20190810131400840.png │ │ ├── image-20190810131416724.png │ │ ├── image-20190810131455814.png │ │ ├── image-20190810131643315.png │ │ ├── image-20190810132816398.png │ │ ├── image-20190810134220882.png │ │ ├── image-20190810135525925.png │ │ ├── image-20190810160314453.png │ │ ├── image-20190810160625045.png │ │ ├── image-20190810161012999.png │ │ ├── image-20190810161110410.png │ │ ├── image-20190810161112399.png │ │ ├── image-20190810161213183.png │ │ ├── image-20190810161245804.png │ │ ├── image-20190810161307014.png │ │ ├── image-20190810164314989.png │ │ └── image-20190810185425567.png │ ├── 垃圾回收与内存分配.md │ ├── 类加载机制.md │ ├── 类文件结构.md │ └── 运行时数据区.md ├── Spring │ ├── README.md │ ├── Spring.md │ ├── SpringCloud.md │ ├── SpringMVC.md │ └── assets │ │ ├── 1525575656796.png │ │ ├── 1525597885059.png │ │ ├── 1525675648881.png │ │ ├── image-20190801120936322.png │ │ ├── image-20190801120950594.png │ │ ├── image-20190801165304565.png │ │ ├── image-20190801182414489.png │ │ ├── image-20190801183407085.png │ │ ├── image-20190801192923059.png │ │ └── image-20190801194432543.png ├── 并发 │ ├── Java内存模型.md │ ├── README.md │ ├── assets │ │ ├── image-20190810201359397.png │ │ ├── image-20190810202917398.png │ │ ├── image-20190810204940193.png │ │ ├── image-20190810233122603.png │ │ ├── image-20190810235324534.png │ │ ├── image-20190810235345562.png │ │ └── image-20190810235402490.png │ └── 线程安全与锁优化.md └── 集合源码 │ ├── ArrayList.md │ ├── HashMap.md │ ├── LinkedList.md │ └── README.md ├── Kafak ├── README.md ├── assets │ ├── image-20201116154746665.png │ ├── image-20201116160550922.png │ ├── image-20201116165017477.png │ ├── image-20201117111504796.png │ ├── image-20201117111710505.png │ ├── image-20201117112328727.png │ ├── image-20201117113546744.png │ ├── image-20201117113714731.png │ ├── image-20201117113840468.png │ ├── image-20201117115615180.png │ ├── image-20201117121232180.png │ ├── image-20201117121546501.png │ ├── image-20201117122055550.png │ ├── image-20201117135431323.png │ ├── image-20201117135525546.png │ ├── image-20201117135527747.png │ ├── image-20201117135634699.png │ ├── image-20201117135919354.png │ ├── image-20201117141115198.png │ ├── image-20201117144130794.png │ ├── image-20201117144300666.png │ ├── image-20201117144351188.png │ ├── image-20201117144404722.png │ ├── image-20201117144637861.png │ ├── image-20201117151308554.png │ ├── image-20201117151345409.png │ ├── image-20201117151458554.png │ ├── image-20201117153841961.png │ ├── image-20201117165458303.png │ ├── image-20201117165634846.png │ ├── image-20201117170831893.png │ ├── image-20201117172842893.png │ ├── image-20201117173646332.png │ ├── image-20201117173708012.png │ ├── image-20201117175619100.png │ ├── image-20201120155008553.png │ ├── image-20201120162752598.png │ ├── image-20201120162844543.png │ ├── image-20201120173439666.png │ ├── image-20201120173722670.png │ ├── image-20201120173909162.png │ ├── image-20201120173957801.png │ ├── image-20201120174448026.png │ ├── image-20201120174515721.png │ ├── image-20201120174628295.png │ ├── image-20201120174850203.png │ ├── image-20201120174911282.png │ ├── image-20201120175119704.png │ ├── image-20201120175319860.png │ ├── image-20201120175357410.png │ ├── image-20201120175607860.png │ ├── image-20201120175702583.png │ ├── image-20201120175737611.png │ └── image-20201120180129563.png ├── 主题与分区.md ├── 基本概念.md ├── 日志存储.md ├── 服务端.md ├── 消费者.md └── 生产者.md ├── Kubernetes ├── Kubernetes基本概念.md ├── Pod.md ├── README.md ├── assets │ ├── 16c095d6efb8d8c226ad9b098689f306.png │ ├── 8a7b5cfabaab2d877a1d4566961edd5f.png │ ├── 8c016391b4b17923f38547c498e434cf.png │ ├── 8ee9f2fa987eccb490cfaa91c6484f67.png │ └── d1bb34cda8744514ba4c233435bf4e96.jpg └── 容器.md ├── README.md ├── Redis ├── README.md ├── RedLock分布式锁.md ├── assets │ ├── image-20190725133718995.png │ ├── image-20190725142329193.png │ ├── image-20190725143445249.png │ ├── image-20190725143859365.png │ ├── image-20190725144528525.png │ ├── image-20190725145100209.png │ ├── image-20190725151235195.png │ ├── image-20190725151251825.png │ ├── image-20190725151306686.png │ ├── image-20190725151318404.png │ ├── image-20190725162737431.png │ ├── image-20190725163018827.png │ ├── image-20190728091518132.png │ ├── image-20190728094130889.png │ ├── image-20190728134118436.png │ ├── image-20190728134308856.png │ ├── image-20190729152939908.png │ └── image-20190730124116313.png ├── 一些场景问题.md ├── 主从复制和高可用集群.md ├── 数据库与持久化.md └── 数据结构与对象.md ├── 分布式 ├── assets │ ├── 1525529091749.png │ ├── 1525529671801.png │ ├── 1525530657919.png │ ├── 1525530804753.png │ ├── 1525532344817.png │ ├── 1526860071166.png │ ├── image-20190730155048201.png │ ├── image-20190730155052026.png │ ├── image-20190730184938904.png │ ├── image-20190730190533235.png │ ├── image-20190730192913945.png │ ├── image-20190730193221987.png │ ├── image-20190730193408341.png │ ├── image-20190730193458258.png │ ├── image-20190730193504134.png │ └── image-20190730193530011.png ├── 一致性协议.md ├── 分布式架构.md └── 微服务.md ├── 掘金Mysql小册精简 ├── 01.重新认识Mysql.md ├── 02.字符集与比较规则.md ├── 03.Innodb记录结构.md ├── 04.Innodb数据页结构.md ├── 05.B+树索引.md ├── 06.B+树索引的使用.md ├── 07.Mysql目录结构.md ├── 08.InnoDB的表空间.md ├── 09.单表访问方法.md ├── 10.连接的原理.md ├── 11.基于成本的优化.md ├── 12.InnoDB 统计数据是如何收集的.md ├── 13.Mysql基于规则的优化.md ├── 14.Explain 详解.md ├── 15.optimizer trace 表.md ├── 16.InnoDB 的 Buffer Pool.md ├── 17.事务.md ├── 18.redo日志.md ├── 19.undo日志.md ├── 20.事务隔离级别和MVCC.md ├── 21. 锁.md └── assets │ ├── image-20190710142826837.png │ ├── image-20190710151542780.png │ ├── image-20190710153004692.png │ ├── image-20190710153355829.png │ ├── image-20190710153500452.png │ ├── image-20190710154642358.png │ ├── image-20190710154716274.png │ ├── image-20190710154744227.png │ ├── image-20190710154826244.png │ ├── image-20190710154844202.png │ ├── image-20190710154916604.png │ ├── image-20190710154940478.png │ ├── image-20190710161752427.png │ ├── image-20190710161932337.png │ ├── image-20190710162240894.png │ ├── image-20190710162757194.png │ ├── image-20190710163019075.png │ ├── image-20190710163336969.png │ ├── image-20190710163352925.png │ ├── image-20190710165257045.png │ ├── image-20190710165431539.png │ ├── image-20190710165445272.png │ ├── image-20190710170644606.png │ ├── image-20190710170726206.png │ ├── image-20190710171634768.png │ ├── image-20190710172425288.png │ ├── image-20190710172707152.png │ ├── image-20190710172744491.png │ ├── image-20190710172932794.png │ ├── image-20190710173014175.png │ ├── image-20190710173606736.png │ ├── image-20190710173713620.png │ ├── image-20190710173850067.png │ ├── image-20190710173925879.png │ ├── image-20190710174054376.png │ ├── image-20190710175154158.png │ ├── image-20190710175305846.png │ ├── image-20190710175340275.png │ ├── image-20190710175408125.png │ ├── image-20190710175512689.png │ ├── image-20190710175514456.png │ ├── image-20190710175631122.png │ ├── image-20190711140712530.png │ ├── image-20190711141411056.png │ ├── image-20190711141636448.png │ ├── image-20190711141741720.png │ ├── image-20190711142250628.png │ ├── image-20190711142301078.png │ ├── image-20190711142422467.png │ ├── image-20190711142556685.png │ ├── image-20190711142857785.png │ ├── image-20190711142935883.png │ ├── image-20190712103450970.png │ ├── image-20190712103853882.png │ ├── image-20190712105752472.png │ ├── image-20190712105903377.png │ ├── image-20190712110454051.png │ ├── image-20190712110834976.png │ ├── image-20190712111337355.png │ ├── image-20190712111624533.png │ ├── image-20190712160851745.png │ ├── image-20190712165142921.png │ ├── image-20190712165205998.png │ ├── image-20190712173028964.png │ ├── image-20190712173514433.png │ ├── image-20190712173526667.png │ ├── image-20190712173559992.png │ ├── image-20190712173710859.png │ ├── image-20190712175254961.png │ ├── image-20190712175359520.png │ ├── image-20190714173457099.png │ ├── image-20190714174132968.png │ ├── image-20190714180355233.png │ ├── image-20190714180517760.png │ ├── image-20190714182422469.png │ ├── image-20190714182709944.png │ ├── image-20190714183204766.png │ ├── image-20190714183434761.png │ ├── image-20190714184036398.png │ ├── image-20190714195943414.png │ ├── image-20190714200119993.png │ ├── image-20190714200702858.png │ ├── image-20190714201420265.png │ ├── image-20190714201813740.png │ ├── image-20190714220000411.png │ ├── image-20190714220440338.png │ ├── image-20190714220709887.png │ ├── image-20190714222215921.png │ ├── image-20190714222759171.png │ ├── image-20190715140313217.png │ ├── image-20190715140648227.png │ ├── image-20190715141331782.png │ ├── image-20190715145056733.png │ ├── image-20190715145126768.png │ ├── image-20190715145240949.png │ ├── image-20190715154306751.png │ ├── image-20190715154308331.png │ ├── image-20190715154339793.png │ ├── image-20190715155947003.png │ ├── image-20190715172451857.png │ ├── image-20190715172725767.png │ ├── image-20190715172730227.png │ ├── image-20190715173458697.png │ ├── image-20190715174542674.png │ ├── image-20190716214518564.png │ ├── image-20190716215112184.png │ ├── image-20190716220713606.png │ ├── image-20190716221846362.png │ ├── image-20190717100212209.png │ ├── image-20190717100330032.png │ ├── image-20190717100943644.png │ ├── image-20190717101343927.png │ ├── image-20190717103115139.png │ ├── image-20190717103215216.png │ ├── image-20190717103248746.png │ ├── image-20190717103733568.png │ ├── image-20190717103847974.png │ ├── image-20190717104447445.png │ ├── image-20190717104626751.png │ ├── image-20190717104704512.png │ ├── image-20190717104726794.png │ ├── image-20190717105240186.png │ ├── image-20190717105436458.png │ ├── image-20190717110010350.png │ ├── image-20190717110059761.png │ ├── image-20190717110335505.png │ ├── image-20190717112349490.png │ ├── image-20190717112428358.png │ ├── image-20190717113314041.png │ ├── image-20190717113738572.png │ ├── image-20190717113851944.png │ ├── image-20190717113923435.png │ ├── image-20190717114026869.png │ ├── image-20190717114217587.png │ ├── image-20190717114342453.png │ ├── image-20190717114527423.png │ ├── image-20190717114630983.png │ ├── image-20190718092638632.png │ ├── image-20190718093412360.png │ ├── image-20190718093804019.png │ ├── image-20190718104449930.png │ ├── image-20190718105912168.png │ ├── image-20190718110411591.png │ ├── image-20190718110931736.png │ ├── image-20190718111451894.png │ ├── image-20190718111525394.png │ ├── image-20190718121100412.png │ ├── image-20190718121138252.png │ ├── image-20190718121935383.png │ ├── image-20190718122048287.png │ ├── image-20190718122154061.png │ ├── image-20190718122255895.png │ ├── image-20190718124314985.png │ ├── image-20190718124840202.png │ ├── image-20190718125015663.png │ ├── image-20190718125541742.png │ ├── image-20190718130010210.png │ ├── image-20190718131226945.png │ ├── image-20190718131626550.png │ ├── image-20190718131821660.png │ ├── image-20190718131915391.png │ ├── image-20190718140444119.png │ ├── image-20190718141217625.png │ ├── image-20190718141544295.png │ ├── image-20190718141619824.png │ ├── image-20190718141735266.png │ └── image-20190718141831621.png ├── 操作系统 └── Linux.md ├── 数据库 └── leetcode.md ├── 算法 ├── bytedance.md ├── cyc题目.md ├── leetcode-TOP100.md ├── 剑指Offer.md ├── 基础算法.md ├── 字节跳动题库.md └── 腾讯题库.md ├── 系统设计 ├── assets │ ├── image-20190730231224593.png │ ├── image-20190804213406361.png │ ├── image-20190804213447835.png │ ├── image-20190804215043251.png │ ├── image-20190804230529069.png │ ├── image-20190804230613264.png │ ├── image-20190804230736540.png │ ├── image-20190804231212870.png │ ├── image-20190804231421908.png │ ├── image-20190806164132345.png │ ├── image-20190806164644434.png │ ├── image-20190806164840016.png │ ├── image-20190806192106918.png │ ├── image-20190806195852238.png │ ├── image-20190806203124953.png │ ├── image-20190806210654541.png │ ├── image-20190806213923841.png │ ├── image-20190806220658575.png │ ├── image-20190806225942551.png │ ├── image-20190806232711281.png │ ├── image-20190807002318014.png │ ├── image-20190807193917981.png │ ├── image-20190807205738080.png │ └── image-20190807225638075.png ├── 消息队列.md ├── 网络攻击与安全算法.md └── 设计模式.md ├── 网络 ├── assets │ ├── image-20190803112837126.png │ ├── image-20190803112849922.png │ ├── image-20190803112906970.png │ ├── image-20190803112929377.png │ ├── image-20190803112942000.png │ ├── image-20190803113115316.png │ ├── image-20190803113848257.png │ ├── image-20190803113934388.png │ ├── image-20190803114155913.png │ ├── image-20190803114210615.png │ ├── image-20190803114222157.png │ ├── image-20190803114234109.png │ ├── image-20190803120713093.png │ ├── image-20190803125537154.png │ └── image-20190803135321710.png └── 比较重要的概念.md └── 面经 └── 阿里 ├── 1.md ├── 2.md ├── 3.md ├── README.md └── assets └── image-20190827193159404.png /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | 35 | .DS_Store -------------------------------------------------------------------------------- /Book/assets/fig1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Book/assets/fig1-1.png -------------------------------------------------------------------------------- /Book/assets/fig2-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Book/assets/fig2-5.png -------------------------------------------------------------------------------- /Book/数据系统的基石.md: -------------------------------------------------------------------------------- 1 | ### 数据密集型应用 2 | 3 | 数据密集型应用通常由标准组件构建而成,标准组件提供了很多通用的功能: 4 | 5 | - 存储数据——数据库 6 | - 加快读取速度——缓存 7 | - 允许用户按关键字搜索数据,或以各种方式对数据进行过滤——搜索索引 8 | - 向其他进程发送消息,进行异步处理——流处理 9 | - 定期处理积累的大批量数据——批处理 10 | 11 | 12 | 13 | 近些年来,出现了许多新的数据存储工具与数据处理工具,他们针对不同场景进行优化,使得类别之间的界限变得越来越模糊: 14 | 15 | - 数据存储可以被当成消息队列用(Redis) 16 | - 消息队列带有类似数据库的持久保证(Apache Kafka) 17 | 18 | 其次,越来越多的应用程序有着各种严格而广泛地要求,单个工具不足以满足所有的数据处理和存储需求。取而代之的是,总体工作被拆分成一系列能被单个工具高效完成的任务,并通过应用代码将他们封合起来。 19 | 20 | 21 | 22 | 如果将缓存和全文搜索功能从数据库剥离出来,那么使缓存/索引与主数据库保持同步通常是应用代码的责任。架构可能是这样子的: 23 | 24 | ![img](assets/fig1-1.png) 25 | 26 | 27 | 28 | ### 数据模型 29 | 30 | #### 关系模型与文档模型 31 | 32 | 关系模型: 33 | 34 | - 数据被组织成关系,其中每个关系是元组的无序集合。 35 | 36 | 文档模型: 37 | 38 | - 更好的可扩展性,包括非常大的数据集或者非常高的写入吞吐量 39 | - 更具多动态性和表现力的数据模型 40 | 41 | 如果应用程序中的数据具有类似文档的结构(一对多关系树,通常一次性加载整个树),那么实用文档模型可能会比较好。将类似文档的结构分解成多个表的关系技术可能导致繁琐的模式和不必要的复杂的应用程序代码。 42 | 43 | 文档模型有一定的局限性:不能直接饮用文档中的嵌套项目,而是需要说“用户251的位置列表中的第二项”。只要文件嵌套不太深,通常都不是问题。 44 | 45 | 文档数据库对连接的支持也比较糟糕,需要在应用程序中进行模拟连接,可能会导致应用程序代码更加复杂、性能更差。 46 | 47 | #### 文档模型中的架构灵活性 48 | 49 | 文档数据库有时候称为**无模式**,也就是**读时模式**,数据的结构是隐含的,只有在数据被读取时才被解释。相应的是**写时模型**,即传统的关系型数据库方法中,模式明确,保证所有的数据都符合其模式。 50 | 51 | 当由于某种原因,集合中的项目并不都具有相同的结构式,读时模式更具优势: 52 | 53 | - 存在许多不同类型的对象,将每种类型的对象放在自己的表中是不现实的。 54 | - 数据的结构由外部系统决定。无法控制外部系统且它随时可能变化。 55 | 56 | #### 查询的数据局部性 57 | 58 | 文档通常以单个连续字符串形式进行存储,编码为JSON、XML、BSON等。如果应用程序经常需要访问整个文档,那么存储局部性能带来性能优势。 59 | 60 | 局部性仅仅适用于同时需要文档绝大部分内容的情况。数据库通常需要加载整个文档,即使只访问其中的一小部分,这对于大型文档来说是很浪费的。更新文档时,通常需要整个重写,只有不改变文档大小的修改才可以容易地原地执行,因此建议保持相对小的文档,并避免增加文档大小的写入。 61 | 62 | #### 图数据模型 63 | 64 | 关系模型可以处理多对多的简单情况,但是随着数据之间的连接变得更加复杂,将数据建模为图形显得更加自然。 65 | 66 | 一个图由两种对象组成:顶点、边。多种数据可以被建模为一个图形: 67 | 68 | ***社交图谱*** 69 | 70 | 顶点是人,边指示哪些人彼此认识。 71 | 72 | ***网络图谱*** 73 | 74 | 顶点是网页,边表示指向其他页面的HTML链接。 75 | 76 | ***公路或铁路网络*** 77 | 78 | 顶点是交叉路口,边代表它们之间的道路或铁路线。 79 | 80 | 图提供了一种一致的方式,用来在单个数据存储中存储完全不同类型的对象: 81 | 82 | ![img](assets/fig2-5.png) 83 | 84 | ####属性图 85 | 86 | 在属性图模型中,每个顶点包括: 87 | 88 | - 唯一的标识符 89 | - 一组出边 90 | - 一组入边 91 | - 一组属性(键值对) 92 | 93 | 每条边包括: 94 | 95 | - 唯一标识符 96 | - 边的起点/尾部顶点 97 | - 边的终点/头部顶点 98 | - 描述两个顶点之间关系类型的标签 99 | - 一组属性(键值对) 100 | 101 | 可以将图存储看作是有两个关系表组成:一个存储顶点,另一个存储边,头部和尾部顶点用来存储每一条边。 102 | 103 | ```sql 104 | CREATE TABLE vertices ( 105 | vertex_id INTEGER PRIMARY KEY, 106 | properties JSON 107 | ); 108 | 109 | CREATE TABLE edges ( 110 | edge_id INTEGER PRIMARY KEY, 111 | tail_vertex INTEGER REFERENCES vertices (vertex_id), 112 | head_vertex INTEGER REFERENCES vertices (vertex_id), 113 | label TEXT, 114 | properties JSON 115 | ); 116 | 117 | CREATE INDEX edges_tails ON edges (tail_vertex); 118 | CREATE INDEX edges_heads ON edges (head_vertex); 119 | ``` 120 | 121 | 这个模型的一些特点: 122 | 123 | - 任何顶点都可以有一条边连接到任何其他顶点。没有模式限制哪种事物可不可以关联。 124 | - 给定任何顶点,可以高效找到它的入边和出边,从而遍历图,即沿着一系列顶点的路径前后移动。 125 | - 通过对不同类型的关系使用不同的标签,可以在一个图中存储几种不同的信息,同时仍然保持一个清晰的数据模型。 126 | 127 | -------------------------------------------------------------------------------- /Book/设计数据密集型应用.md: -------------------------------------------------------------------------------- 1 | #### 数据密集型应用 2 | 3 | 现今很多应用程序都是 **数据密集型** 的,而非 **计算密集型** 的,因此 CPU 很少成为这类应用的瓶颈,更大的问题通常来自数据量、数据复杂性、以及数据的变更速度。 4 | 5 | [数据系统的基石](数据系统的基石.md) 6 | 7 | -------------------------------------------------------------------------------- /Elasticsearch/ELK环境搭建.md: -------------------------------------------------------------------------------- 1 | 1. 安装 `docker` 和 `docker-compose`,保证机器有至少 `16g` 内存 2 | 3 | 2. 创建 `docker-compose.yaml`文件,内容如下: 4 | 5 | ``` yaml 6 | version: '3.8' 7 | services: 8 | cerebro: 9 | container_name: cerebro 10 | image: lmenezes/cerebro:0.8.3 11 | ports: 12 | - 9000:9000 13 | command: 14 | - -Dhosts.0.host=http://es01:9200 15 | networks: 16 | - elastic 17 | kibana: 18 | container_name: kibana 19 | image: kibana:7.10.1 20 | environment: 21 | - I18N_LOCALE=zh-CN 22 | - XPACK_GRAPH_ENABLED=true 23 | - TIMELION_ENABLED=true 24 | - XPACK_MONITORING_COLLECTION_ENABLED="true" 25 | - ELASTICSEARCH_HOSTS="http://es01:9200" 26 | ports: 27 | - 5601:5601 28 | networks: 29 | - elastic 30 | logstash: 31 | container_name: logstash 32 | image: logstash:7.10.1 33 | volumes: 34 | - ./data/logstash/conf/logstash.conf:/usr/share/logstash/pipeline/logstash.conf 35 | - ./data/logstash/data:/usr/share/logstash/data 36 | networks: 37 | - elastic 38 | es01: 39 | image: elasticsearch:7.10.1 40 | container_name: es01 41 | environment: 42 | - node.name=es01 43 | - cluster.name=lollipop 44 | - discovery.seed_hosts=es02 45 | - cluster.initial_master_nodes=es01,es02 46 | - bootstrap.memory_lock=true 47 | - "ES_JAVA_OPTS=-Xms512m -Xmx512m" 48 | ulimits: 49 | memlock: 50 | soft: -1 51 | hard: -1 52 | volumes: 53 | - ./data/elasticsearch/es01/data:/usr/share/elasticsearch/data 54 | - ./data/elasticsearch/es01/logs:/usr/share/elasticsearch/logs 55 | ports: 56 | - 9200:9200 57 | - 9300:9300 58 | networks: 59 | - elastic 60 | es02: 61 | image: elasticsearch:7.10.1 62 | container_name: es02 63 | environment: 64 | - node.name=es02 65 | - cluster.name=lollipop 66 | - discovery.seed_hosts=es01 67 | - cluster.initial_master_nodes=es01,es02 68 | - bootstrap.memory_lock=true 69 | - "ES_JAVA_OPTS=-Xms512m -Xmx512m" 70 | ulimits: 71 | memlock: 72 | soft: -1 73 | hard: -1 74 | volumes: 75 | - ./data/elasticsearch/es02/data:/usr/share/elasticsearch/data 76 | - ./data/elasticsearch/es02/logs:/usr/share/elasticsearch/logs 77 | ports: 78 | - 9201:9200 79 | - 9301:9300 80 | networks: 81 | - elastic 82 | 83 | networks: 84 | elastic: 85 | driver: bridge 86 | ``` 87 | 88 | 3. 进入 `docker-compose.yaml` 同级目录 89 | 90 | 4. 递归创建目录 `data/logstash/conf` 91 | 92 | 5. 进入 `data/logstash/conf` 目录,创建 `logstash.conf` 文件,内容如下: 93 | 94 | ``` json 95 | input { 96 | file { 97 | path => "/usr/share/logstash/data/movies.csv" 98 | start_position => "beginning" 99 | sincedb_path => "/dev/null" 100 | } 101 | } 102 | filter { 103 | csv { 104 | separator => "," 105 | columns => ["id","content","genre"] 106 | } 107 | 108 | mutate { 109 | split => { "genre" => "|" } 110 | remove_field => ["path", "host","@timestamp","message"] 111 | } 112 | 113 | mutate { 114 | split => ["content", "("] 115 | add_field => { "title" => "%{[content][0]}"} 116 | add_field => { "year" => "%{[content][1]}"} 117 | } 118 | 119 | mutate { 120 | convert => { 121 | "year" => "integer" 122 | } 123 | strip => ["title"] 124 | remove_field => ["path", "host","@timestamp","message","content"] 125 | } 126 | 127 | } 128 | output { 129 | elasticsearch { 130 | hosts => "http://es01:9200" 131 | index => "movies" 132 | document_id => "%{id}" 133 | } 134 | stdout {} 135 | } 136 | 137 | ``` 138 | 139 | 6. 进入 `docker-compose.yaml` 同级目录 140 | 141 | 7. 执行 `docker-compose up -d` 命令启动 `elk` 142 | 143 | 8. 如果遇到容器启动失败,请手动调整 `docker` 内存资源大小 144 | 145 | -------------------------------------------------------------------------------- /Elasticsearch/Elasticsearch基本概念.md: -------------------------------------------------------------------------------- 1 | #### 文档(Document) 2 | 3 | - Elasticsearch 是面向文档的,文档是所有可搜索数据的最小单位,可以对比为关系型数据库的一条记录。 4 | - 文档会被序列化为 JSON 格式,保存在 Elasticsearch 中 5 | - 每个文档都有一个 Unique ID 6 | 7 | 8 | 9 | #### 文档的元数据 10 | 11 | - 元数据,用于标注文档的相关信息 12 | - _index : 文档所属的索引名 13 | - _type : 文档所属的类型名 14 | - _id : 文档唯一Id 15 | - _source: 文档的原始 JSON 数据 16 | - _all : 整合所有字段内容到该字段,已被废除 17 | - _version : 文档的版本信息 18 | - _score : 相关性打分 19 | 20 | 21 | 22 | #### 索引 23 | 24 | - Index : 索引是文档的容器,是一类文档的结合 25 | - Index 体现了逻辑空间的概念:每个索引都有自己的 Mapping 定义,用于定义包含的文档的字段名和字段类型。 26 | - Shard 体现了物理空间的概念:索引中的数据分散在 Shard 上 27 | - 索引的 Mapping 与 Settings 28 | - Mapping 定义文档字段的类型 29 | - Setting 定义不同的数据分布 30 | 31 | 32 | 33 | #### 抽象与类比 34 | 35 | | RDBMS | Elasticsearch | 36 | | :----: | :-----------: | 37 | | Table | Index | 38 | | Row | Document | 39 | | Column | Filed | 40 | | Schema | Mapping | 41 | | SQL | DSL | 42 | 43 | - 传统关系型数据库和 Elasticsearch 的区别 44 | - Elasticsearch : Schemaless / 相关性 / 高性能全文检索 45 | - RDMS : 事务性 / join 46 | 47 | 48 | 49 | #### 文档的 CRUD 50 | 51 | | index | PUT my_index/_doc/1
{"user":"lollipop", "comment":"You know, for search"} | 52 | | :----: | :----------------------------------------------------------: | 53 | | Create | PUT my_index/_create/1
{"user":"lollipop", "comment": "You know, for search"}
POST my_index/_doc(不指定ID, 自动生成)
{"user": "lollipop", "comment": "You know, for search"} | 54 | | Read | GET my_index/_doc/1 | 55 | | Update | POST my_index/_update/1
{"doc": {"user":"lollipop","comment": "You know, Elasticsearch"}} | 56 | | Delete | DELETE my_index/_doc/1 | 57 | 58 | - Type 名,ES7约定都用 _doc 59 | - Create 如果ID存在,创建失败 60 | - Index 如果ID存在先删除现有文档,再创建新的文档,版本会增加 61 | - Update 文档必须已经存在,更新只会对相应字段做增量更新 62 | 63 | #### Demo 64 | 65 | ``` json 66 | // create document. 自动生成 _id 67 | POST users/_doc 68 | { 69 | "user": "lollipop", 70 | "post_date": "2020-12-21T21:40:22", 71 | "message": "trying out Kibana" 72 | } 73 | 74 | // create document. 指定Id,如果Id已经存在,则报错 75 | PUT users/_doc/1?op_type=create 76 | { 77 | "user": "lollipop1", 78 | "post_date": "2020-12-21T21:40:22", 79 | "message": "trying out Elasticsearch" 80 | } 81 | 82 | // create document. 指定Id,如果Id已经存在,则报错 83 | PUT users/_create/1 84 | { 85 | "user": "lollipop2", 86 | "post_date": "2020-12-21T21:40:22", 87 | "message": "trying out Elasticsearch" 88 | } 89 | 90 | // get document by Id 91 | GET users/_doc/1 92 | 93 | 94 | // index document. 指定Id,如果Id已经存在,则删除重建 95 | PUT users/_doc/1 96 | { 97 | "user": "lollipop3" 98 | } 99 | 100 | // update document. 在原文档上增加字段 101 | POST users/_update/1 102 | { 103 | "doc": { 104 | "post_date": "2020-12-21T21:40:22", 105 | "message": "trying out Elasticsearch" 106 | } 107 | } 108 | 109 | // delete document by Id. 删除文档 110 | DELETE users/_doc/1 111 | 112 | // Bulk 操作. 支持在一次 API 调用中,对不同的索引进行操作,单条操作失败,并不会影响其他操作,返回结果包括了每一条操作执行的结果. 113 | POST _bulk 114 | {"index": {"_index": "test", "_id": "1"}} 115 | {"field1": "value1"} 116 | {"delete": {"_index": "test", "_id": "2"}} 117 | {"create": {"_index": "test2", "_id": "3"}} 118 | {"field1": "value3"} 119 | {"update": {"_id": "1", "_index": "test"}} 120 | {"doc": {"field2": "value2"}} 121 | 122 | // mget 操作,批量读取,减少网络开销 123 | GET /_mget 124 | { 125 | "docs": [ 126 | { 127 | "_index": "test", 128 | "_id": "1" 129 | }, 130 | { 131 | "_index": "test", 132 | "_id": "2" 133 | } 134 | ] 135 | } 136 | ``` 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /Elasticsearch/assets/image-20201226193050881.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Elasticsearch/assets/image-20201226193050881.png -------------------------------------------------------------------------------- /Elasticsearch/assets/image-20201226195911107.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Elasticsearch/assets/image-20201226195911107.png -------------------------------------------------------------------------------- /Elasticsearch/assets/image-20201226202630374.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Elasticsearch/assets/image-20201226202630374.png -------------------------------------------------------------------------------- /Elasticsearch/assets/image-20201226213336829.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Elasticsearch/assets/image-20201226213336829.png -------------------------------------------------------------------------------- /Elasticsearch/assets/image-20201226213339559.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Elasticsearch/assets/image-20201226213339559.png -------------------------------------------------------------------------------- /Elasticsearch/assets/image-20201226214318986.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Elasticsearch/assets/image-20201226214318986.png -------------------------------------------------------------------------------- /Elasticsearch/倒排索引与分词.md: -------------------------------------------------------------------------------- 1 | ### 正排索引和倒排索引 2 | 3 | ![image-20201226193050881](assets/image-20201226193050881.png) 4 | 5 | ### 倒排索引的核心组成 6 | 7 | #### 倒排索引包含两个部分 8 | 9 | - 单词词典,记录所有文档的单词,记录单词到倒排列表的关联关系 10 | - 单词词典一般比较大,可以通过 `B+` 树或哈希拉链法实现,以满足高性能的插入与查询 11 | - 倒排列表,记录了单词对应的文档集合,由倒排索引项组成 12 | - 倒排索引项 13 | - 文档ID 14 | - 词频 TF,该单词在文档中出现的次数,用于相关性评分 15 | - 位置,单词在文档中分词的位置,用于语句搜索 16 | - 偏移量,记录单词的开始结束位置,实现高亮显示 17 | 18 | #### 一个例子 —— "Elasticsearch" 19 | 20 | ![image-20201226195911107](assets/image-20201226195911107.png) 21 | 22 | ### Elasticsearch 的倒排索引 23 | 24 | - Elasticsearch 的 JSON 文档中的每个字段,都有自己的倒排索引 25 | - 可以制定对某些字段不做索引 26 | - 优点:节省存储空间 27 | - 缺点:字段无法被搜索 28 | 29 | ### 通过 Analyzer 进行分词 30 | 31 | #### Analysis 与 Analyzer 32 | 33 | - Analysis,文本分析是把全文本转换为一系列单词的过程,也叫分词 34 | - Analysis 是通过 Analyzer 来实现的 35 | - 可使用 Elasticsearch 内置的分析器或者按需求定制化分析器 36 | - 除了在数据写入时转换词条,匹配 Query 语句时候也需要用相同的分析器对查询语句进行分析 37 | 38 | #### Analyzer 的组成 39 | 40 | - 分词器是专门处理分词的组件,Analyzer 由三部分组成 41 | - Character Filters (针对原始文本处理,例如取出 html ) / Tokenizer (按照规则切分为单词) / Token Filter (将切分的单词进行加工,小写,删除 stopwords,增加同义词) 42 | 43 | ![image-20201226202630374](assets/image-20201226202630374.png) 44 | 45 | #### 使用 _analyer API 46 | 47 | ``` json 48 | // 直接指定 Analyzer 进行测试 49 | GET /_analyze 50 | { 51 | "analyzer": "standard", 52 | "text": "Mastering Elasticsearch, elasticsearch in Action" 53 | } 54 | 55 | // 指定索引的字段进行测试 56 | POST books/_analyze 57 | { 58 | "field": "title", 59 | "text": "Mastering Elasticsearch" 60 | } 61 | 62 | // 自定义分词器进行测试 63 | POST /_analyze 64 | { 65 | "tokenizer": "standard", 66 | "filter": ["lowercase"], 67 | "text": "Mastering Elasticsearch" 68 | } 69 | ``` 70 | 71 | -------------------------------------------------------------------------------- /Java/JVM/README.md: -------------------------------------------------------------------------------- 1 | [运行时数据区](运行时数据区.md) 2 | 3 | [垃圾回收与内存分配](垃圾回收与内存分配.md) 4 | 5 | [类文件结构](类文件结构.md) 6 | 7 | [类加载机制](类加载机制.md) 8 | 9 | 10 | 11 | ### 参考资料 12 | 13 | 《深入理解Java虚拟机第二版》 14 | 15 | - [CyC2018](https://github.com/CyC2018/CS-Notes) 16 | - [JavaGuide](https://github.com/Snailclimb/JavaGuide) 17 | 18 | -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190809184556232.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190809184556232.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190809213138155.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190809213138155.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190809213206559.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190809213206559.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190809213227263.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190809213227263.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190809213354622.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190809213354622.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190809233744925.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190809233744925.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190809233759640.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190809233759640.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190809234222898.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190809234222898.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810001204867.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810001204867.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810100312084.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810100312084.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810101801242.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810101801242.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810102209644.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810102209644.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810111220152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810111220152.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810124001748.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810124001748.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810125718250.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810125718250.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810125721842.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810125721842.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810130611648.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810130611648.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810131400840.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810131400840.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810131416724.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810131416724.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810131455814.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810131455814.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810131643315.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810131643315.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810132816398.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810132816398.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810134220882.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810134220882.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810135525925.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810135525925.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810160314453.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810160314453.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810160625045.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810160625045.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810161012999.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810161012999.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810161110410.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810161110410.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810161112399.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810161112399.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810161213183.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810161213183.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810161245804.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810161245804.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810161307014.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810161307014.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810164314989.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810164314989.png -------------------------------------------------------------------------------- /Java/JVM/assets/image-20190810185425567.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/JVM/assets/image-20190810185425567.png -------------------------------------------------------------------------------- /Java/JVM/运行时数据区.md: -------------------------------------------------------------------------------- 1 | ## 运行时数据区 2 | 3 | Java虚拟机在执行Java程序的过程中,会把它所管理的内存划分为若干个不同的数据区域。 4 | 5 | **JDK1.6:** 6 | 7 | ![image-20190809213227263](assets/image-20190809213227263.png) 8 | 9 | **JDK1.8:** 10 | 11 | ![image-20190809213206559](assets/image-20190809213206559.png) 12 | 13 | 左边绿色部分是线程私有区域,右边蓝色部分是线程共享区域。 14 | 15 | #### 程序计数器 16 | 17 | 程序计数器(线程私有)是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器,如果是Native方法,这个计数器的值为空。字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,诸如分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。 18 | 19 | 程序计数器是JVM中唯一一个没有`OutOfMemoryError`情况的区域。 20 | 21 | ### 虚拟机栈 22 | 23 | 虚拟机栈(线程私有)的生命周期和线程相同,描述的是Java方法执行的内存模型:每个方法执行的时候都会创建一个栈帧,用于存放局部变量表、操作数栈、动态链接、方法出口等信息。每个方法从调用到完成的过程,就对应着一个栈帧在虚拟机栈中入栈出栈的过程。 24 | 25 | 虚拟机栈中有两种异常情况: 26 | 27 | - 当线程请求的栈深度大于虚拟机所允许的深度,将抛出`StackOverflowError`错误。 28 | - 当虚拟机栈动态扩展过程中无法申请到足够的内存时,就会抛出`OutOfMemoryError`错误。 29 | 30 | **局部变量表** 31 | 32 | 用于存放方法参数和方法内部定义的局部变量,存放了编译器可知的各种基本数据类型、对象引用和returnAddress类型。(指向了一条字节码指令的地址)。局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在栈帧中分配多大的局部变量空间是完全确定的,运行期间大小不会改变。 33 | 34 | **操作数栈** 35 | 36 | 操作数栈用弹栈/压栈来访问,是JVM栈中的一个用于计算的临时数据存储区,数据运算的地方大多数指令都在操作数栈弹栈运算,然后结果压栈。 37 | 38 | **动态链接** 39 | 40 | 每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接。每一个`class`文件有一个常量池,用以存放它所有的符号引用,字节码中的方法调用指令就是以常量池中指向方法的符号引用作为参数。这些符号引用一部分会在类加载阶段或第一次使用时转化为直接引用,这种转化称为静态解析。另一部分将在每一次运行期间转化为直接引用,这部分称为动态连接。 41 | 42 | **方法出口** 43 | 44 | 当一个方法执行后,只有两种方式退出当前方法: 45 | 46 | - 当执行遇到返回指令,会将返回值传递给上层的方法调用者,这种退出的方式称为正常完成出口,一般来说,调用者的PC计数器可以作为返回地址。 47 | - 当执行遇到异常,并且当前方法体内没有得到处理,就会导致方法退出,此时是没有返回值的,称为异常完成出口,返回地址要通过异常处理器表来确定。 48 | 49 | 当方法返回时,可能进行3个操作: 50 | 51 | - 恢复上层方法的局部变量表和操作数栈 52 | - 把返回值压入调用者调用者栈帧的操作数栈 53 | - 调整 PC 计数器的值以指向方法调用指令后面的一条指令 54 | 55 | ### 本地方法栈 56 | 57 | 本地方法栈(线程私有)与虚拟机栈之间的不同是,本地方法栈为JVM执行Native方法服务,而虚拟机栈为JVM执行Java方法服务。在HotSpot中,直接将本地方法栈和虚拟机栈合二为一。 58 | 59 | 与虚拟机栈一样,本地方法栈也会抛出`StackOverflowError`和`OutOfMemoryError`错误。 60 | 61 | ### 堆 62 | 63 | 大多数情况下,堆(线程共享)是JVM管理的内存中最大的一块。堆唯一的目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。 64 | 65 | 堆是GC的主要区域,分为新生代和老年代: 66 | 67 | **新生代区域:** 68 | 69 | - Eden空间 70 | - From Survivor空间(S0) 71 | - To Survivor空间(S1) 72 | 73 | ![image-20190809213354622](assets/image-20190809213354622.png) 74 | 75 | 大部分情况,对象都会首先在 Eden 区域分配(大对象直接分配在老年代),在一次新生代垃圾回收后,如果对象还存活,则会进入 s0 或者 s1,并且对象的年龄还会加 1,当它的年龄增加到一定程度(默认为 15 岁),就会被晋升到老年代中。对象晋升到老年代的年龄阈值,可以通过参数 `-XX:MaxTenuringThreshold` 来设置。 76 | 77 | 通过`-Xms`,`-Xmx`,`-Xss`等参数可以对堆内存大小进行调整: 78 | 79 | - `Xss`规定了每个线程堆栈的大小。 80 | - `Xms`规定了堆的初始分配大小。 81 | - `Xmx`规定了堆的最大分配大小。 82 | 83 | 在堆中没有内存完成实例分配并且无法扩展时,将会抛出`OutOfMemoryError`错误。 84 | 85 | ### 方法区 86 | 87 | 方法区(线程共享)用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。对这块区域进行垃圾回收的主要目标是对常量池的回收和对类的卸载,但是一般比较难实现。JDK1.7把它当成永久代来进行垃圾回收,但很难确定永久代的大小,因为它受到很多因素影响,并且每次 Full GC 之后永久代的大小都会改变,所以经常会抛出`OutOfMemoryError`异常。为了更容易管理方法区,从 `JDK 1.8` 开始,移除永久代,并把方法区移至元空间,它位于本地内存中,而不是虚拟机内存中。原来永久代的数据被分到了堆和元空间中。元空间存储类的元信息,Class对象、静态变量和字符串常量池等放入堆中。元数据并不是类的Class对象,Class对象是加载的最终产品,静态变量位于 Class对象内,而类的方法代码,变量名,方法名,访问权限,返回值等元数据都是在方法区的。 88 | 89 | 当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常。 90 | 91 | ### 运行时常量池 92 | 93 | 运行时常量池是方法区的一部分,Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放在编译器生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池。除了在编译期生成的常量,还允许动态生成,例如 String 类的 intern()。 94 | 95 | ### 直接内存 96 | 97 | 在 JDK 1.4 中新引入了`NIO`类,它可以使用 Native 函数库直接分配堆外内存,然后通过 Java 堆里的 `DirectByteBuffer` 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在堆内存和堆外内存来回拷贝数据。 98 | 99 | ## 对象的创建 100 | 101 | **类加载检查** 102 | 103 | JVM遇到一条`new`指令时,首先去检查这个指令的参数是否能在字符串常量池中定位到一个类的符号引用,并检查这个符号引用代表的类是否已经被加载、解析和初始化过,如果没有则先执行响应的类的加载过程。 104 | 105 | **分配内存** 106 | 107 | 对象所需的大小在类加载完成后便可完全确定,为对象分配空间的任务等同于把一块确定大小的内存从Java堆中划分出来。根据堆内存是否绝对规整,有两种内存分配方式: 108 | 109 | - **指针碰撞(堆内存绝对规整)**:所有用过的内存放在一边,空闲内存放在另一边,中间用一个指针作为分界点带的指示器,分配内存就是把指针向空闲空间挪动一段与对象大小相等的距离。 110 | - **空闲列表(堆内存不规整)**:JVM维护一个列表,记录那些内存块是可用的,在分配的时候,从列表中找到一块足够大的空间划分给对象实例。 111 | 112 | 是否规整取决于所使用的的垃圾收集器是否**标记-清除**还是**标记-整理**。 113 | 114 | 内存分配时可能会有线程安全问题,此时有两种解决方案: 115 | 116 | - 对分配内存空间的动作进行同步处理,采用CAS失败重试方式保证更新操作的原子性。 117 | - 每个线程在堆中预分配一小块内存,成为本地线程分配缓冲(TLAB),哪个线程需要分配内存,就在哪个线程的TLAB上分配,只有TLAB用完并分配新TLAB时,才需要同步锁定。 118 | 119 | **初始化零值** 120 | 121 | 这一步保证了对象实例的字段不需要赋值就可以直接使用,程序能访问到这些字段的数据类型对应的零值。 122 | 123 | **对象头设置** 124 | 125 | 设置对象的的一些头部信息,例如这个对象是哪个类的实例、如何找到这个类的元数据信息、对象的HashCode、对象的GC分代年龄等信息。另外,根据虚拟机当前运行状态的不同,如是否启用偏向锁等,会对象头有不同的设置方式。 126 | 127 | **执行``方法** 128 | 129 | 上面工作都完成之后,从虚拟机的视角来看,一个新的对象已经产生了,但从 Java 程序的视角来看,对象创建才刚开始,`` 方法还没有执行,所有的字段都还为零。所以一般来说,执行 new 指令之后会接着执行 `` 方法,把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才算完全产生出来。 130 | 131 | ## 对象的内存布局 132 | 133 | `Hotspot`虚拟机中,对象在内存中的布局可以分为 3 块区域:**对象头**、**实例数据**和**对齐填充**。 134 | 135 | - 对象头包括两部分信息: 136 | 137 | - 用于存储对象自身的运行时数据:如HashCode、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等。 138 | - 类型指针:指向它的类元数据的指针,通过这个指针来确定这个对象是那个类的实例。 139 | 140 | 如果是数组,还需要一个字段用来记录数组长度。 141 | 142 | - 实例数据:对象真正存储的有效信息,即程序中所定义的各种类型的字段内容。 143 | 144 | - 对齐填充:并不是必然的,仅仅起占位符的作用,使得对象头部正好是8字节的倍数。 145 | 146 | ### 对象访问定位 147 | 148 | 建立对象是为了使用对象,JVM通过栈上的reference数据来操作堆上的具体对象,目前主流的访问方式有使用句柄和直接指针两种。 149 | 150 | **使用句柄访问** 151 | 152 | Java堆中会划分出来一块内存作为句柄池,reference中存储的就是对象的句柄地址,句柄中包含了对象实例数据与类型数据各自的具体地址信息。使用句柄访问最大的好处就是reference中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而reference本身不需要改变。 153 | 154 | ![image-20190809233759640](assets/image-20190809233759640.png) 155 | 156 | **直接使用指针访问** 157 | 158 | 如果直接使用指针访问,那么堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,而reference中存储的直接就是对象地址。 159 | 160 | ![image-20190809234222898](assets/image-20190809234222898.png) 161 | 162 | 使用句柄访问最大的好处就是reference中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而reference本身不需要改变。使用直接指针访问最大的好处就是速度快,节省了一次指针定位的时间开销。 163 | 164 | -------------------------------------------------------------------------------- /Java/Spring/README.md: -------------------------------------------------------------------------------- 1 | [Spring](Spring.md) 2 | 3 | [SpringMVC](SpringMVC.md) 4 | 5 | [SpringCloud](SpringCloud.md) 6 | 7 | 8 | 9 | ### 参考资料 10 | 11 | - [JavaGuide](https://github.com/Snailclimb/JavaGuide/blob/master/docs/system-design/framework/spring/SpringMVC-Principle.md) 12 | 13 | - [Spring Boot自动配置原理实战](https://mp.weixin.qq.com/s/gs2zLSH6m9ijO0-pP2sr9Q) 14 | 15 | -------------------------------------------------------------------------------- /Java/Spring/SpringCloud.md: -------------------------------------------------------------------------------- 1 | SpringCloud作为Spring家族中的一员,它将现在非常流行的一些技术整合到一起,实现了微服务中诸如:配置管理,服务发现,智能路由,负载均衡,熔断器,控制总线,集群状态等功能。 2 | 3 | ### SpringCloud Netflix中的主要组件 4 | 5 | - Eureka:注册中心 6 | - Zuul:服务网关 7 | - Ribbon:负载均衡 8 | - Hystix:熔断器 9 | - Feign:服务调用 10 | 11 | 组件的调用的关系: 12 | 13 | ![1525575656796](assets/1525575656796.png) 14 | 15 | ### Eureka注册中心 16 | 17 | Eureka主要用于服务注册与发现。 18 | 19 | Eureka包含两个组件:Eureka Server和Eureka Client。 20 | 21 | 1. 服务提供者在启动时,向注册中心注册自己提供的服务。 22 | 2. 服务消费者在启动时,向注册中心订阅自己所需的服务。 23 | 3. 注册中心返回服务提供者地址给消费者。 24 | 4. 服务消费者从提供者地址中调用消费者。 25 | 26 | #### Eureka Server 27 | 28 | 提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,包括主机与端口号、服务版本号、通讯协议等。这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。 29 | 30 | Eureka服务端支持集群模式部署,首尾相连形成一个闭环即可。集群中的的不同服务注册中心通过异步模式互相复制各自的状态,这也意味着在给定的时间点每个实例关于所有服务的状态可能存在不一致的现象。 31 | 32 | #### Eureka Client 33 | 34 | 主要处理服务的注册和发现。客户端服务通过注册和参数配置的方式,嵌入在客户端应用程序的代码中。在应用程序启动时,Eureka客户端向服务注册中心注册自身提供的服务,并周期性的发送心跳来更新它的服务租约。同时,他也能从服务端查询当前注册的服务信息并把它们缓存到本地并周期行的刷新服务状态。 35 | 36 | #### 服务调用 37 | 服务消费者在获取服务清单后,通过服务名可以获取具体提供服务的实例名和该实例的元数据信息。 38 | 因为有这些服务实例的详细信息,所以客户端可以根据自己的需要决定具体调用哪个实例。 39 | 在`Ribbon`中会默认采用轮询的方式进行调用,从而实现客户端的负载均衡。 40 | 41 | ![1525597885059](assets/1525597885059.png) 42 | 43 | #### Eureka高可用 44 | 45 | Eureka Server在Eureka服务治理设计中,所有节点既是服务的提供方,也是服务的消费方,服务注册中心也不例外。Eureka Server的高可用实际上就是将自己做为服务向其他服务注册中心注册自己。**这样就可以形成一组互相注册的服务注册中心,以实现服务清单的互相同步,达到高可用的效果**。 46 | 47 | - Eureka Server的同步遵循着一个非常简单的原则:只要有一条边将节点连接,就可以进行信息传播与同步。 48 | 可以采用两两注册的方式实现集群中节点完全对等的效果,实现最高可用性集群,任何一台注册中心故障都不会影响服务的注册与发现。 49 | - 在注册服务之后,服务提供者会维护一个心跳用来持续汇报Eureka Server,我们称之为服务续约。 50 | 否则Eureka Server的剔除任务会将该服务实例从服务列表中排除出去。默认情况下,如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,Eureka Server将会注销该实例。 51 | 52 | - 但是当网络分区故障发生时,微服务与Eureka Server之间无法正常通信,以上行为可能变得非常危险了。因为微服务本身其实是健康的,此时本不应该注销这个微服务。Eureka通过“自我保护模式”来解决这个问题。当Eureka Server节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。一旦进入该模式,Eureka Server就会保护服务注册表中的信息,不再删除服务注册表中的数据。 53 | 当网络故障恢复后,该Eureka Server节点会自动退出自我保护模式。 54 | 55 | ### API网关Zuul 56 | 57 | #### 微服务网关 58 | 59 | 不同的微服务一般有不同的网络地址,而外部的客户端可能需要调用多个服务的接口才能完成一个业务需求。比如一个电影购票的收集APP,可能回调用电影分类微服务,用户微服务,支付微服务等。如果客户端直接和微服务进行通信,会存在一下问题: 60 | 61 | - 客户端会多次请求不同微服务,增加客户端的复杂性 62 | - 存在跨域请求,在一定场景下处理相对复杂 63 | - 认证复杂,每一个服务都需要独立认证 64 | - 难以重构,随着项目的迭代,可能需要重新划分微服务,如果客户端直接和微服务通信,那么重构会难以实施 65 | - 某些微服务可能使用了其他协议,直接访问有一定困难 66 | 67 | 上述问题,都可以借助微服务网管解决。微服务网管是介于客户端和服务器端之间的中间层,所有的外部请求都会先经过微服务网关,架构演变成: 68 | 69 | ![1525675648881](assets/1525675648881.png) 70 | 71 | 这样客户端只需要和网关交互,而无需直接调用特定微服务的接口,而且方便监控,易于认证,减少客户端和各个微服务之间的交互次数。 72 | 73 | #### Zuul 74 | 75 | Zuul是Netflix开源的微服务网关,他可以和Eureka,Ribbon,Hystrix等组件配合使用。Zuul组件的核心是一系列的过滤器,这些过滤器可以完成以下功能: 76 | 77 | - 身份认证和安全: 识别每一个资源的验证要求,并拒绝那些与要求不符的请求 78 | 79 | - 审查与监控:在边缘位置追踪有意义的数据和统计结果,从而带来精确的生产视图。 80 | 81 | - 动态路由:动态地将请求路由到不同后端集群 82 | 83 | - 压力测试:逐渐增加指向集群的流量,以了解性能 84 | 85 | - 负载分配:为每一种负载类型分配对应容量,并弃用超出限定值的请求 86 | 87 | - 静态响应处理:在边缘位置直接建立部分响应,避免转发到内部集群 88 | 89 | - 多区域弹性:跨域AWS Region进行请求路由,旨在实现ELB使用多样化,以及让系统的边缘更贴近系统的使用者 90 | 91 | ### 负载均衡Robbin 92 | Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它可以将面向服务的RestTemplate请求自动转换成客户端负载均衡的服务调用。Ribbon几乎存在于每一个微服务中,包括`Feign(服务调用)`也是基于Ribbon实现的。 93 | 94 | #### 服务端负载均衡 95 | 96 | 负载均衡是对系统的高可用、网络压力的缓解和处理能力扩容的重要手段之一。我们通常所说的负载均衡都指的是服务端负载均衡,硬件负载均衡会维护一个下挂可用的服务端清单,通过心跳检测来剔除故障的服务端节点以保证清单中都是可以正常访问的服务端节点。当客户端发送请求到负载均衡设备的时候,该设备按某种算法从维护的可用服务端清单中取出一台服务端地址,然后进行转发。(用户请求到zuul,对用户来说是服务端负载均衡) 97 | 98 | #### 客户端负载均衡 99 | 100 | 所有客户端节点都维护着自己要访问的服务端清单,而这些服务端端清单来自于服务注册中心(Eureka)。同服务端负载均衡的架构类似,在客户端负载均衡中也需要心跳去维护服务端清单的健康性。(zuul用ribbon请求服务,对于zuul来说是客户端负载均衡) 101 | 102 | #### 负载均衡策略 103 | 104 | Ribbon默认的负载均衡策略是简单的轮询。 105 | 106 | 负载均衡有好几种实现策略,常见的有: 107 | 108 | 1. 随机 (Random) 109 | 2. 轮询 (RoundRobin) 110 | 3. 一致性哈希 (ConsistentHash) 111 | 4. 哈希 (Hash) 112 | 5. 加权轮询 113 | 6. 加权随机 114 | 115 | ### Hystrix熔断器 116 | 117 | 在分布式系统架构中多个系统之间通常是通过远程调用进行通信,比如 A 系统调用 B 系统服务,B 系统调用 C 系统的服务。当尾部应用 C 发生故障而系统 B 没有服务降级时候可能会导致 B,甚至系统 A 瘫痪,这种现象被称为雪崩现象。所以在系统设计时候要使用一定的降级策略,来保证当服务提供方服务不可用时候,服务调用方可以切换到降级后的策略进行执行。 118 | 119 | Hystrix是容错管理工具c,作用是通过隔离、控制服务从而对延迟和故障提供更强大的容错能力,避免整个系统被拖垮。Hystrix提供的熔断器,当在一定时间段内服务调用方调用服务提供方的服务的次数达到设定的阈值,并且出错的次数也达到设置的出错阈值,就会进行服务降级,让服务调用方之间执行本地设置的降级策略,而不再发起远程调用。但是Hystrix提供的熔断器具有自我反馈,自我恢复的功能,Hystrix会根据调用接口的情况,让熔断器在closed,open,half-open三种状态之间自动切换。 120 | 121 | - open状态说明打开熔断,也就是服务调用方执行本地降级策略,不进行远程调用。 122 | - closed状态说明关闭了熔断,这时候服务调用方直接发起远程调用。 123 | - half-open状态,则是一个中间状态,当熔断器处于这种状态时候,直接发起远程调用。 124 | 125 | 三种状态的转换: 126 | 127 | - closed->open:正常情况下熔断器为closed状态,当访问同一个接口次数超过设定阈值并且错误比例超过设置错误阈值时候,就会打开熔断机制。 128 | - open->half-open:当服务接口对应的熔断器状态为open状态时候,所有服务调用方调用该服务方法时候都是执行本地降级方法。这时Hystrix提供了一种测试策略,也就是设置了一个时间窗口,从熔断器状态变为open状态开始的一个时间窗口内,调用该服务接口时候都委托服务降级方法进行执行。如果时间超过了时间窗口,则熔断状态从open->half-open,这时候服务调用方调用服务接口时候,就可以发起远程调用了,如果还是失败,则重新设置熔断器状态为open状态,重新记录时间窗口开始时间。 129 | - half-open->closed:当熔断器状态为half-open,这时候服务调用方调用服务接口时候,就可以发起远程调用而不再使用本地降级接口,如果发起远程调用成功,则重新设置熔断器状态为closed状态。 130 | 131 | ### Feign远程调用 132 | 133 | Feign是一种声明式、模块化的HTTP客户端,可以用来便捷优雅的进行HTTP API调用。在Spring Cloud中对Feign的使用非常简单,只需要在接口上加一些注解代码就可以了。Feign中集成了Ribbon、Eureka Client和Hystrix,从而让Feign的使用更加方便。 -------------------------------------------------------------------------------- /Java/Spring/SpringMVC.md: -------------------------------------------------------------------------------- 1 | ### Servlet 2 | 3 | Servlet是一个基于http协议,在Servlet容器中运行的,按照Servlet规范编写的一个Java类。客户端发送请求至服务器端,服务器端将请求发送至Servlet,Servlet生成响应内容并将其传给服务器。 4 | 5 | ### Servlet的生命周期 6 | 7 | 1. 创建 Servlet 对象,通过服务器反射机制创建 Servlet 对象,第一次请求时才会创建。 8 | 2. 调用 Servlet 对象的 init()方法,初始化 Servlet 的信息,init()方法只会在创建后被调用一次; 9 | 3. 响应请求,调用 service()或者是 doGet(),doPost()方法来处理请求,这些方法是运行的在多线程状态下的。 10 | 4. 在长时间没有被调用或者是服务器关闭时,会调用 destroy()方法来销毁 Servlet 对象。 11 | 12 | **MVC 的原理:** 13 | 14 | ![image-20190801182414489](assets/image-20190801182414489.png) 15 | 16 | ### SpringMVC 工作原理 17 | 18 | SpringMVC 框架是以请求为驱动,围绕 Servlet 设计,将请求发给控制器,然后通过模型对象,分派器来展示请求结果视图。其中核心类是 DispatcherServlet,它是一个 Servlet,顶层是实现的Servlet接口。 19 | 20 | **简单来说SpringMVC的流程是这样的:** 21 | 22 | 客户端发送请求 -> 前端控制器 DispatcherServlet 接受客户端请求 -> 找到处理器映射 HandlerMapping 解析请求对应的 Handler-> HandlerAdapter 会根据 Handler 来调用真正的处理器开处理请求,并处理相应的业务逻辑 -> 处理器返回一个模型视图 ModelAndView -> 视图解析器进行解析 -> 返回一个视图对象->前端控制器 DispatcherServlet 渲染数据(Moder)->将得到视图对象返回给用户 23 | 24 | ![image-20190801183407085](assets/image-20190801183407085.png) 25 | 26 | 1. 客户端(浏览器)发送请求,直接请求到 `DispatcherServlet`。 27 | 2. `DispatcherServlet` 根据请求信息调用 `HandlerMapping`,解析请求对应的 `Handler`。 28 | 3. 解析到对应的 `Handler`( `Controller`)后,开始由 `HandlerAdapter` 适配器处理。 29 | 4. `HandlerAdapter` 会根据 `Handler `来调用真正的处理器开处理请求,并处理相应的业务逻辑。 30 | 5. 处理器处理完业务后,会返回一个 `ModelAndView` 对象,`Model` 是返回的数据对象,`View` 是个逻辑上的 `View`。 31 | 6. `ViewResolver` 会根据逻辑 `View` 查找实际的 `View`。 32 | 7. `DispaterServlet` 把返回的 `Model` 传给 `View`(视图渲染)。 33 | 8. 把 `View` 返回给请求者(浏览器) 34 | 35 | -------------------------------------------------------------------------------- /Java/Spring/assets/1525575656796.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/Spring/assets/1525575656796.png -------------------------------------------------------------------------------- /Java/Spring/assets/1525597885059.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/Spring/assets/1525597885059.png -------------------------------------------------------------------------------- /Java/Spring/assets/1525675648881.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/Spring/assets/1525675648881.png -------------------------------------------------------------------------------- /Java/Spring/assets/image-20190801120936322.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/Spring/assets/image-20190801120936322.png -------------------------------------------------------------------------------- /Java/Spring/assets/image-20190801120950594.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/Spring/assets/image-20190801120950594.png -------------------------------------------------------------------------------- /Java/Spring/assets/image-20190801165304565.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/Spring/assets/image-20190801165304565.png -------------------------------------------------------------------------------- /Java/Spring/assets/image-20190801182414489.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/Spring/assets/image-20190801182414489.png -------------------------------------------------------------------------------- /Java/Spring/assets/image-20190801183407085.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/Spring/assets/image-20190801183407085.png -------------------------------------------------------------------------------- /Java/Spring/assets/image-20190801192923059.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/Spring/assets/image-20190801192923059.png -------------------------------------------------------------------------------- /Java/Spring/assets/image-20190801194432543.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/Spring/assets/image-20190801194432543.png -------------------------------------------------------------------------------- /Java/并发/Java内存模型.md: -------------------------------------------------------------------------------- 1 | ### 硬件效率与一致性 2 | 3 | 基于高速缓存的存储交互很好地解决了处理器与内存的速度矛盾,但是也**引入了一个新问题:缓存一致性**。在多处理器系统中,每个处理器都有自己的高速缓存,而它们又共享同一主内存。所以当多个处理器的运算任务都涉及同一块主内存区域时,可能会导致各自的缓存数据不一致。因此各个处理器在访问内存时都需要遵循一些协议。 4 | 5 | **内存模型** 就是对特定的内存或者高速缓存进行读写访问的过程的抽象,不同的物理机器可以拥有不同的内存模型。类似的Java虚拟机也有自己的**内存模型**。 6 | 7 | ![image-20190810201359397](assets/image-20190810201359397.png) 8 | 9 | 处理器可能会对输入代码进行乱序执行优化,计算之后再进行结果重组,使得与顺序执行的结果一致,因此各个语句计算的先后顺序与代码中的顺序可能不一致。类似的,Java虚拟机中也有类似的**指令重排序**优化。 10 | 11 | ### Java内存模型 12 | 13 | Java内存模型是一种抽象模型,用来屏蔽掉各种硬件和操作系统的内存访问差异,让Java程序可以在各种平台下都达到一致的内存访问效果。Java内存模型的主要目标是定义程序中个变量(实例字段、静态字段、构成数组对象的元素)的访问规则,为了获得较好的执行效能,java内存模型并没有限制执行引擎使用处理器的特定寄存器或者缓存来和主内存进行交互也,没有限制即时编译器进行代码执行顺序这类优化措施。 14 | 15 | 所有的变量都存储在主内存中,每个线程还有自己的工作内存,工作内存存储在高速缓存或者寄存器中,保存了该线程使用的变量的主内存副本拷贝。线程只能直接操作工作内存中的变量,不同线程之间的变量值传递需要通过主内存来完成。 16 | 17 | ![image-20190810202917398](assets/image-20190810202917398.png) 18 | 19 | ### 内存间交互操作 20 | 21 | Java内存模型定义了 8 个操作来完成主内存和工作内存的交互操作。 22 | 23 | ![image-20190810204940193](assets/image-20190810204940193.png) 24 | 25 | - lock:作用于主内存的变量,把一个变量标识为一条线程独占状态。 26 | - unlock:作用于主内存的变量,释放一个变量的锁定状态。 27 | 28 | - read:作用于主内存的变量,把一个变量的值从主内存传输到工作内存中。 29 | - load:作用于工作内存的变量,在read之后执行,把read得到的值放入工作内存的变量副本中。 30 | - use:作用于工作内存的变量,把工作内存中一个变量的值传递给执行引擎。 31 | - assign:作用于工作内存的变量,把一个从执行引擎接收到的值赋给工作内存的变量。 32 | - store:作用于工作内存的变量,把工作内存的一个变量的值传送到主内存中。 33 | - write:作用于主内存的变量,在 store 之后执行,把 store 得到的值放入主内存的变量中。 34 | 35 | ### 原子性 36 | 37 | Java 内存模型保证了 read、load、use、assign、store、write、lock 和 unlock 操作具有原子性,例如对一个 int 类型的变量执行 assign 赋值操作,这个操作就是原子性的。 38 | 39 | 如果应用场景需要一个更大范围的原子性保证,可以通过 lock 和 unlock 操作来满足,即使用 monitorenter 和 monitorexit 来隐式地使用这两个操作,对应到java代码中就是 synchronized 关键字。 40 | 41 | ### 可见性 42 | 43 | 当一个线程修改了共享变量的值,其他线程能够立刻得知这个修改。Java 内存模型是通过在变量修改后将新值同步回主内存,在变量读取前从主内存刷新变量值来实现可见性的。 44 | 45 | Java中有三种方式保证可见性: 46 | 47 | - volatile 48 | - synchronized:对一个变量执行 unlock 操作之前,必须把变量值同步回主内存。 49 | - final:被 final 关键字修饰的字段在构造器中一旦初始化完成,并且没有发生 this 逃逸(其它线程通过 this 引用访问到初始化了一半的对象),那么其它线程就能看见 final 字段的值。 50 | 51 | ### 有序性 52 | 53 | 在本线程内观察,所有操作都是有序的;在一个线程观察另一个线程,所有操作都是无序的,无序是因为发生了指令重排序。 54 | 55 | volatile 关键字通过添加内存屏障的方式来禁止指令重排,即重排序时不能把后面的指令放到内存屏障之前。 56 | 57 | 也可以通过 synchronized 来保证有序性,它保证每个时刻只有一个线程执行同步代码,相当于是让线程顺序执行同步代码。 58 | 59 | ### 先行发生原则 60 | 61 | Java中有一个先行发生原则(happens-before),他是判断数据是否存在竞争、线程是否安全的主要依据。先行发生关系无需任何同步操作就可以直接编码使用: 62 | 63 | **程序次序规则** 64 | 65 | 在一个线程内,书写在前面的操作先行发生于后面的操作。 66 | 67 | **管程锁定规则** 68 | 69 | 一个 unlock 操作先行发生于后面对同一个锁的 lock 操作。 70 | 71 | **volatile变量规则** 72 | 73 | 对一个 volatile 变量的写操作先行发生于后面对这个变量的读操作。 74 | 75 | **线程启动规则** 76 | 77 | Thread 对象的 start() 方法调用先行发生于此线程的每一个动作。 78 | 79 | **线程终止规则** 80 | 81 | 线程中的所有操作都先行发生于对此线程的终止检测。 82 | 83 | **线程中断规则** 84 | 85 | 对线程 interrupt() 方法的调用先行发生于被中断线程的代码检测到中断事件的发生,可以通过 interrupted() 方法检测到是否有中断发生。 86 | 87 | **传递性** 88 | 89 | 如果操作 A 先行发生于操作 B,操作 B 先行发生于操作 C,那么操作 A 先行发生于操作 C。 90 | 91 | -------------------------------------------------------------------------------- /Java/并发/README.md: -------------------------------------------------------------------------------- 1 | [Java内存模型](Java内存模型.md) 2 | 3 | [线程安全与锁优化](线程安全与锁优化.md) 4 | 5 | 6 | 7 | 8 | 9 | ### 参考资料 10 | 11 | 《深入理解Java虚拟机第二版》 12 | 13 | - [CyC2018](https://github.com/CyC2018/CS-Notes) 14 | 15 | -------------------------------------------------------------------------------- /Java/并发/assets/image-20190810201359397.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/并发/assets/image-20190810201359397.png -------------------------------------------------------------------------------- /Java/并发/assets/image-20190810202917398.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/并发/assets/image-20190810202917398.png -------------------------------------------------------------------------------- /Java/并发/assets/image-20190810204940193.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/并发/assets/image-20190810204940193.png -------------------------------------------------------------------------------- /Java/并发/assets/image-20190810233122603.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/并发/assets/image-20190810233122603.png -------------------------------------------------------------------------------- /Java/并发/assets/image-20190810235324534.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/并发/assets/image-20190810235324534.png -------------------------------------------------------------------------------- /Java/并发/assets/image-20190810235345562.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/并发/assets/image-20190810235345562.png -------------------------------------------------------------------------------- /Java/并发/assets/image-20190810235402490.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Java/并发/assets/image-20190810235402490.png -------------------------------------------------------------------------------- /Java/集合源码/README.md: -------------------------------------------------------------------------------- 1 | [ArrayList](ArrayList.md) 2 | 3 | [LinkedList](LinkedList.md) 4 | 5 | [HashMap](HashMap.md) 6 | 7 | -------------------------------------------------------------------------------- /Kafak/README.md: -------------------------------------------------------------------------------- 1 | #### Kafka 2 | 3 | `Kafka` 起初只是一个分布式消息系统,随着不断的发展,如今已经被定位成一个分布式流式处理平台。具有 **高吞吐**、**可持久化**、**可水平扩展**、**支持流数据处理** 等多种特性,因而受到越来越多的青睐。 4 | 5 | [基本概念](基本概念.md) 6 | 7 | [生产者](生产者.md) 8 | 9 | [消费者](消费者.md) 10 | 11 | [主题与分区](主题与分区.md) 12 | 13 | [日志存储](日志存储.md) 14 | 15 | [服务端](./服务端.md) -------------------------------------------------------------------------------- /Kafak/assets/image-20201116154746665.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201116154746665.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201116160550922.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201116160550922.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201116165017477.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201116165017477.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117111504796.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117111504796.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117111710505.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117111710505.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117112328727.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117112328727.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117113546744.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117113546744.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117113714731.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117113714731.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117113840468.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117113840468.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117115615180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117115615180.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117121232180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117121232180.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117121546501.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117121546501.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117122055550.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117122055550.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117135431323.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117135431323.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117135525546.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117135525546.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117135527747.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117135527747.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117135634699.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117135634699.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117135919354.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117135919354.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117141115198.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117141115198.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117144130794.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117144130794.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117144300666.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117144300666.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117144351188.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117144351188.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117144404722.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117144404722.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117144637861.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117144637861.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117151308554.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117151308554.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117151345409.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117151345409.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117151458554.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117151458554.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117153841961.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117153841961.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117165458303.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117165458303.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117165634846.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117165634846.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117170831893.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117170831893.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117172842893.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117172842893.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117173646332.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117173646332.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117173708012.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117173708012.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201117175619100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201117175619100.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201120155008553.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201120155008553.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201120162752598.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201120162752598.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201120162844543.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201120162844543.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201120173439666.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201120173439666.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201120173722670.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201120173722670.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201120173909162.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201120173909162.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201120173957801.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201120173957801.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201120174448026.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201120174448026.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201120174515721.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201120174515721.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201120174628295.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201120174628295.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201120174850203.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201120174850203.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201120174911282.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201120174911282.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201120175119704.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201120175119704.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201120175319860.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201120175319860.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201120175357410.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201120175357410.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201120175607860.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201120175607860.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201120175702583.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201120175702583.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201120175737611.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201120175737611.png -------------------------------------------------------------------------------- /Kafak/assets/image-20201120180129563.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kafak/assets/image-20201120180129563.png -------------------------------------------------------------------------------- /Kafak/主题与分区.md: -------------------------------------------------------------------------------- 1 | 主题作为消息的归类,可以再细分为一个或多个分区,分区也可以看作对消息的二次归类。分区的划分不仅为 `Kafka` 提供了可伸缩性、水平扩展的功能,还通过多副本机制来为 `Kafka` 提供数据冗余以提高数据可靠性。从 `Kafka` 的底层实现来说,主题和分区都是逻辑上的概念,分区可以有一至多个副本,每个副本对应一个日志文件,每个日志文件对应一至多个日志分段(`LogSegment`),每个日志分段还可以细分为索引文件、日志存储文件和快照文件等。 2 | 3 | ### 创建主题 4 | 5 | 如果 `broker` 端配置参数 `auto.create.topics.enable` 设置为 `true`(默认值就是 `true` ),那么当生产者向一个尚未创建的主题发送消息时,会自动创建一个分区数为 `num.partitions` (默认值为 `1` )、副本因子为 `default.replication.factor` (默认值为 `1` )的主题。除此之外,当一个消费者开始从未知主题中读取消息时,或者当任意一个客户端向未知主题发送元数据请求时,都会按照配置参数值来创建一个相应的主题。很多时候,这种自动创建主题的行为都是非预期的,一般不建议将 `auto.create.topics.enable` 参数设置为 `true` ,这个参数会增加主题的管理与维护的难度。更加推荐也更加通用的方式是通过 `kafka-topics.sh` 脚本来创建主题。 6 | 7 | ![image-20201117135431323](assets/image-20201117135431323.png) 8 | 9 | 上面的示例中创建了一个分区数为 `4` 、副本因子为 `2` 的主题。示例中的环境是一个包含 `3` 个 `broker` 节点的集群,每个节点的名称和 `brokerId` 的对照关系如下: 10 | 11 | ![image-20201117135527747](assets/image-20201117135527747.png) 12 | 13 | 在执行完脚本之后, `Kafka` 会在 `log.dir` 或 `log.dirs` 参数所配置的目录下创建相应的主题分区,默认情况下这个目录为 `/tmp/kafka-logs/`。 14 | 15 | 以 `node1` 为例: 16 | 17 | ![image-20201117135634699](assets/image-20201117135634699.png) 18 | 19 | 可以看到 `node1` 节点中创建了 `2` 个文件夹 `topic-create-0` 和 `topic-create-1`,对应主题 `topic-create` 的 `2` 个分区编号为 `0` 和 `1` 的分区,命名方式可以概括为 `<topic>-<partition>` 。默认情况下 `kafka` 为各 `broker` 分配的分区都是最优选择。 20 | 21 | 主题、分区、副本和 `Log`(日志)的关系如下图所示,主题和分区都是提供给上层用户的抽象,而在副本层面或更加确切地说是 `Log` 层面才有实际物理上的存在。同一个分区中的多个副本必须分布在不同的 `broker` 中,这样才能提供有效的数据冗余。 22 | 23 | ![image-20201117135919354](assets/image-20201117135919354.png) 24 | 25 | ### 分区副本的分配 26 | 27 | 在创建主题时,如果使用了 `replica-assignment` 参数,那么就按照指定的方案来进行分区副本的创建;如果没有使用 `replica-assignment` 参数,那么就需要按照内部的逻辑来计算分配方案了。使用 `kafka-topics.sh` 脚本创建主题时的内部分配逻辑按照机架信息划分成两种策略:未指定机架信息和指定机架信息。如果集群中所有的 `broker` 节点都没有配置 `broker.rack` 参数,或者使用 `disable-rack-aware` 参数来创建主题,那么采用的就是未指定机架信息的分配策略。这里通过源码来分析未指定机架信息的分配策略,所对应的具体实现为 `kafka.admin.AdminUtils.scala` 文件中的 `assignReplicasToBrokersRackUnaware()` 方法,该方法的内容如下: 28 | 29 | ![image-20201117141115198](assets/image-20201117141115198.png) 30 | 31 | ### 分区管理 32 | 33 | 分区管理包括优先副本的选举、分区重分配、复制限流、修改副本因子等内容。 34 | 35 | #### 优先副本选举 36 | 37 | 分区使用多副本机制来提升可靠性,但只有 `leader` 副本对外提供读写服务,而 `follower` 副本只负责在内部进行消息的同步。如果一个分区的 `leader` 副本不可用,那么就意味着整个分区变得不可用,此时就需要 `Kafka` 从剩余的 `follower` 副本中挑选一个新的 `leader` 副本来继续对外提供服务。在创建主题的时候,该主题的分区及副本会尽可能均匀地分布到 `Kafka` 集群的各个 `broker` 节点上,对应的 `leader` 副本的分配也比较均匀。针对同一个分区而言,同一个 `broker` 节点中不可能出现它的多个副本,即 `Kafka` 集群的一个 `broker` 中最多只能有它的一个副本。 38 | 39 | 随着时间的更替,`Kafka` 集群的 `broker` 节点不可避免地会遇到宕机或崩溃的问题,当分区的 `leader` 节点发生故障时,其中一个 `follower` 节点就会成为新的 `leader` 节点,这样就会导致集群的负载不均衡,从而影响整体的健壮性和稳定性。当原来的 `leader` 节点恢复之后重新加入集群时,它只能成为一个新的`follower` 节点而不再对外提供服务。 40 | 41 | 为了能够有效地治理负载失衡的情况,`Kafka` 引入了优先副本(`preferredreplica`)的概念。所谓的优先副本是指在 `AR` 集合列表中的第一个副本。理想情况下,优先副本就是该分区的 `leader` 副本,所以也可以称之为 `preferred leader` 。`Kafka` 要确保所有主题的优先副本在 `Kafka` 集群中均匀分布,这样就保证了所有分区的 `leader` 均衡分布。如果 `leader` 分布过于集中,就会造成集群负载不均衡。所谓的优先副本的选举是指通过一定的方式促使优先副本选举为 `leader` 副本,以此来促进集群的负载均衡,这一行为也可以称为 `分区平衡` 。 42 | 43 | 在 `Kafka` 中可以提供分区自动平衡的功能,与此对应的 `broker` 端参数是 `auto.leader.rebalance.enable` ,此参数的默认值为 `true` ,即默认情况下此功能是开启的。如果开启分区自动平衡的功能,则 `Kafka` 的控制器会启动一个定时任务,这个定时任务会轮询所有的 `broker` 节点,计算每个 `broker` 节点的分区不平衡率(`broker` 中的不平衡率 = 非优先副本的 `leader` 个数 / 分区总数)是否超过 `leader.imbalance.per.broker.percentage` 参数配置的比值,默认值为 `10%` ,如果超过设定的比值则会自动执行优先副本的选举动作以求分区平衡。执行周期由参数 `leader.imbalance.check.interval.seconds `控制,默认值为 `300` 秒,即 `5` 分钟。不过在生产环境中不建议将 `auto.leader.rebalance.enable` 设置为默认的 `true` ,因为这可能引起负面的性能问题,执行的时间无法自主掌控,在执行关键任务的关卡上执行优先副本的自动选举操作,势必会有业务阻塞、频繁超时之类的风险。 44 | 45 | `Kafka` 中 `kafka-perferred-replica-election.sh` 脚本提供了对分区 `leader` 副本进行重新平衡的功能。优先副本的选举过程是一个安全的过程,`Kafka` 客户端可以自动感知分区 `leader` 副本的变更。 46 | 47 | ![image-20201117144130794](assets/image-20201117144130794.png) 48 | 49 | 这种使用方式会将集群上所有的分区都执行一遍优先副本的选举操作,分区数越多打印出来的信息也就越多。`leader` 副本的转移也是一项高成本的工作,如果要执行的分区数很多,那么必然会对客户端造成一定的影响。如果集群中包含大量的分区,那么上面的这种使用方式有可能会失效。在优先副本的选举过程中,具体的元数据信息会被存入 `ZooKeeper` 的 `/admin/preferred_replica_election` 节点,如果这些数据超过了 `ZooKeeper` 节点所允许的大小,那么选举就会失败。默认情况下 `ZooKeeper` 所允许的节点数据大小为 `1MB`。 50 | 51 | `kafka-perferred-replica-election.sh` 脚本中还提供了 `path-to-json-file` 参数来小批量地对部分分区执行优先副本的选举操作。通过 `path-to-json-file` 参数来指定一个 `JSON` 文件,这个 `JSON` 文件里保存需要执行优先副本选举的分区清单。举个例子,我们将集群中 `brokerId` 为 `2` 的节点重启,不过我们现在只想对主题 `topic-partitions` 执行优先副本的选举操作,那么先创建一个 `JSON` 文件,文件名假定为 `election.json` ,文件的内容如下: 52 | 53 | ![image-20201117144300666](assets/image-20201117144300666.png) 54 | 55 | 然后通过 `kafka-perferred-replica-election.sh` 脚本配合 `path-to-json-file` 参数来对主题 `topic-partitions` 执行优先副本的选举操作: 56 | 57 | ![image-20201117144637861](assets/image-20201117144637861.png) 58 | 59 | 在实际生产环境中,一般使用 `path-to-json-file` 参数来分批、手动地执行优先副本的选举操作。尤其是在应对大规模的 `Kafka` 集群时,理应杜绝采用非 `path-to-json-file` 参数的选举操作方式。同时,优先副本的选举操作也要注意避开业务高峰期,以免带来性能方面的负面影响。 60 | 61 | #### 分区重分配 62 | 63 | 当集群中的一个节点突然宕机下线时,如果节点上的分区是多副本的,那么位于这个节点上的 `leader` 副本的角色会转交到集群的其他 `follower` 副本中。总而言之,这个节点上的分区副本都已经处于功能失效的状态,`Kafka` 并不会将这些失效的分区副本自动地迁移到集群中剩余的可用 `broker` 节点上,如果放任不管,则不仅会影响整个集群的均衡负载,还会影响整体服务的可用性和可靠性。 64 | 65 | 当要对集群中的一个节点进行有计划的下线操作时,我们希望通过某种方式能够将该节点上的分区副本迁移到其他的可用节点上。当集群中新增 `broker` 节点时,只有新创建的主题分区才有可能被分配到这个节点上,而之前的主题分区并不会自动分配到新加入的节点中,因为在它们被创建时还没有这个新节点,这样新节点的负载和原先节点的负载之间严重不均衡。为了解决上述问题,需要让分区副本再次进行合理的分配,也就是所谓的分区重分配。`Kafka` 提供了 `kafka-reassign-partitions.sh` 脚本来执行分区重分配的工作,它可以在集群扩容、`broker` 节点失效的场景下对分区进行迁移。 66 | 67 | 首先在一个由 `3` 个节点(`broker 0`、`broker 1`、`broker 2`)组成的集群中创建一个主题 `topic-reassign`。由于某种原因,我们想要下线 `brokerId` 为 `1` 的`broker` 节点,在此之前,我们要做的就是将其上的分区副本迁移出去。使用 `kafka-reassign-partitions.sh` 脚本的第一步就是要创建一个 `JSON` 文件(假定为`reassign.json`),文件内容为要进行分区重分配的主题清单。对主题 `topic-reassign` 而言,示例如下: 68 | 69 | ![image-20201117151308554](assets/image-20201117151308554.png) 70 | 71 | 第二步就是根据这个 `JSON` 文件和指定所要分配的 `broker` 节点列表来生成一份候选的重分配方案,具体内容参考如下: 72 | 73 | ![image-20201117151345409](assets/image-20201117151345409.png) 74 | 75 | 上面示例中打印出了两个 `JSON` 格式的内容。第一个 `Current partition replicaassignment` 所对应的 `JSON` 内容为当前的分区副本分配情况,在执行分区重分配的时候最好将这个内容保存起来,以备后续的回滚操作。第二个 `Proposedpartition reassignment configuration` 所对应的 `JSON` 内容为重分配的候选方案,注意这里只是生成一份可行性的方案,并没有真正执行重分配的动作。 76 | 77 | 第三步执行具体的重分配动作: 78 | 79 | ![image-20201117151458554](assets/image-20201117151458554.png) 80 | 81 | 分区重分配的基本原理是先通过控制器为每个分区添加新副本,新的副本将从分区的 `leader` 副本那里复制所有的数据。根据分区的大小不同,复制过程可能需要花一些时间,因为数据是通过网络复制到新副本上的。在复制完成之后,控制器将旧副本从副本清单里移除。注意在重分配的过程中要确保有足够的空间。分区重分配对集群的性能有很大的影响,需要占用额外的资源,比如网络和磁盘。在实际操作中,我们将降低重分配的粒度,分成多个小批次来执行,以此来将负面的影响降到最低,这一点和优先副本的选举有异曲同工之妙。还需要注意的是,如果要将某个 `broker` 下线,那么在执行分区重分配动作之前最好先关闭或重启`broker` 。这样这个 `broker` 就不再是任何分区的 `leader` 节点了,它的分区就可以被分配给集群中的其他 `broker` 。这样可以减少 `broker` 间的流量复制,以此提升重分配的性能,以及减少对集群的影响。 -------------------------------------------------------------------------------- /Kafak/基本概念.md: -------------------------------------------------------------------------------- 1 | `Kafka` 一共扮演了三种角色: 2 | 3 | 1. **消息系统:** `Kafka` 具备系统解耦、冗余存储、流量削峰、缓冲、异步通信、扩展性、可恢复性等功能,并且提供了大多数消息系统难以实现的 **消息顺序性保障** 及 **回溯消费** 的功能。 4 | 2. **存储系统:** `Kafka` 把消息持久化到磁盘,可以作为长期的数据存储系统来使用。 5 | 3. **流式处理平台。** 6 | 7 | #### `Kafka` 体系架构 8 | 9 | 一个典型的 `Kafka` 体系架构包括若干 `Producer`、 `Broker`、 `Consumer` 以及一个 `Zookeeper` 集群。`Zookeeper` 负责管理 `Kafka` 的集群元数据、控制器的选举等操作。`Producer` 将消息发送到 `Broker`, `Broker` 负责将收到的消息存储到磁盘中, `Consumer` 负责从 `Broker` 订阅并消费消息。 10 | 11 | ![image-20201116154746665](assets/image-20201116154746665.png) 12 | 13 | `kafka` 中有两个特别重要的概念——主题(`Topic`)和分区(`Partition`),生产者将消息发送到特定的主题,消费者订阅主题进行消费。主题是一个逻辑上的概念,它还可以细分为多个分区,一个分区只属于一个主题。同一主题下的每个分区所包含的消息是不一样的,分区在存储层面可以看做是一个可追加的日志文件,消息在被追加到分区日志文件的时候都会分配一个特定的偏移量(`offset`)。`offset` 是消息在分区中的唯一标识,`kafka` 用 `offset` 来保证消息在分区内的顺序性。由于 `offset` 并不是跨分区的,所以 `kafka` 不能保证消息在主题内的顺序性。 14 | 15 | ![image-20201116160550922](assets/image-20201116160550922.png) 16 | 17 | 每一条消息被发送到 `broker` 之前,会根据分区规则选择存储到哪个具体的分区。如果分区规则设定的合理,所有的消息都可以均匀的分配到不同的分区中。如果一个主题只对应一个文件,那么这个文件所在的机器 `I/O` 将会成为这个主题的性能瓶颈,而分区解决了这个问题,可以实现水平扩展。 18 | 19 | `Kafka` 为分区引入了副本机制,同一分区的不同副本中保存的是相同的消息,副本之间是 “一主多从” 的关系, `Leader` 副本负责处理读写请求, `follow` 副本只负责与 `leader` 副本的消息同步。副本处于不同的 `Broker` 中,当 `leader` 副本出现故障时,从 `follower` 副本中重新选举新的 `leader` 副本对外提供服务。 20 | 21 | `Kafka` 消费端也具有一定的容灾能力。 `Consumer` 使用拉(`Pull`) 模式从服务端拉取消息,并且保存消费的具体位置,当消费者宕机恢复上线时,可以根据之前保存的消费位置重新拉取需要的消息进行消费,这样就不会造成消息的丢失。 22 | 23 | 分区中的所有副本统称为 `AR`, 所有与 `leader` 副本保持一定程度同步的副本(包括 `leader`)组成 `ISR`(`In-Sync Replicas`)。与 `leader` 副本同步滞后过多的副本组成 `OSR` (`Out-of-Sync Replicas`)。默认情况下当 `leader` 副本发生故障时,只有在 `ISR` 集合中的副本才有资格被选举为新的 `leader`。`ISR` 与 `HW` 和 `LEO` 也有紧密的关系。 `HW` 是 `High Watermark` 的缩写,俗称高水位,它标识了一个特定的消息偏移量(`offset`),消费者只能拉取到这个 `offset` 之前的消息。`LEO` 是 `Log End Offset` 的缩写,它标识了当前日志文件中下一条待写入消息的偏移量,`LEO` 的大小相当于当前日志分区中最后一条消息的偏移量加 `1` 。分区中每个副本都会维护自身的 `LEO` ,`ISR` 中最小的 `LEO` 即为 `HW`,所以对于消费者来说,最多只能消费到 `HW` 之前的消息。 -------------------------------------------------------------------------------- /Kafak/服务端.md: -------------------------------------------------------------------------------- 1 | `Kafka` 经常被用作高性能、可扩展的消息中间件。 `Kafka` 自定义了一组基于 `TCP` 的二进制协议,只要遵守这组协议的格式,就可以向 `Kafka` 发送消息,也可以从 `Kafka` 中拉取消息,或者做一些其他的事情,比如提交消费位移等。在 `Kafka 2.0.0` 中,一共包含了 `43` 种协议类型,每种协议类型都有对应的请求和响应,它们都遵守特定的协议模式。每种类型的 `Request` 都包含相同结构的协议请求头和不同结构的协议请求体。 2 | 3 | ![image-20201120174448026](assets/image-20201120174448026.png) 4 | 5 | ![image-20201120174515721](assets/image-20201120174515721.png) 6 | 7 | 每种类型的 `Response` 也包含相同结构的协议响应头和不同结构的响应体。 8 | 9 | ![image-20201120174628295](assets/image-20201120174628295.png) 10 | 11 | 以最常见的消息发送和消息拉取的两种协议类型做细致的讲解。消息发送的协议类型,即 `ProduceRequest/ProduceResponse` ,对应的 `api_key = 0` ,表示 `PRODUCE` 。`ProduceRequest` 的组织结构如图所示: 12 | 13 | ![image-20201120174850203](assets/image-20201120174850203.png) 14 | 15 | ![image-20201120174911282](assets/image-20201120174911282.png) 16 | 17 | 每个分区中的消息是顺序追加的,那么在客户端中按照分区归纳好之后就可以省去在服务端中转换的操作了,这样将负载的压力分摊给了客户端,从而使服务端可以专注于它的分内之事,如此也可以提升整体的性能。 18 | 19 | 如果参数 `acks` 设置非 `0` 值,那么生产者客户端在发送 `ProduceRequest` 请求之后就需要(异步)等待服务端的响应 `ProduceResponse` 。 20 | 21 | ![image-20201120175319860](assets/image-20201120175319860.png) 22 | 23 | ![image-20201120175357410](assets/image-20201120175357410.png) 24 | 25 | 消息追加是针对单个分区而言的,那么响应也是针对分区粒度来进行划分的,这样 `ProduceRequest` 和 `ProduceResponse` 做到了一一对应。 26 | 27 | 拉取消息的协议类型,即 `FetchRequest/FetchResponse` ,对应的 `api_key = 1` ,表示 `FETCH` : 28 | 29 | ![image-20201120175607860](assets/image-20201120175607860.png) 30 | 31 | ![image-20201120175702583](assets/image-20201120175702583.png) 32 | 33 | ![image-20201120175737611](assets/image-20201120175737611.png) 34 | 35 | 不管是 `follower` 副本还是普通的消费者客户端,如果要拉取某个分区中的消息,就需要指定详细的拉取信息,也就是需要设定 `partition` 、`fetch_offset` 、 `log_start_offset` 和 `max_bytes` 这 `4` 个域的具体值,那么对每个分区而言,就需要占用 `4B + 8B + 8B + 4B = 24B` 的空间。一般情况下,不管是 `follower` 副本还是普通的消费者,它们的订阅信息是长期固定的。也就是说,`FetchRequest` 中的 `topics` 域的内容是长期固定的,只有在拉取开始时或发生某些异常时会有所变动。`FetchRequest` 请求是一个非常频繁的请求,如果要拉取的分区数有很多,比如有 `1000` 个分区,那么在网络上频繁交互 `FetchRequest` 时就会有固定的 `1000 × 24B ≈ 24KB` 的字节的内容在传动,如果可以将这 `24KB` 的状态保存起来,那么就可以节省这部分所占用的带宽。`Kafka` 针对 `FetchRequest` 引入了 `session_id` 、`epoch` 和 `forgotten_topics_data` 等域,`session_id` 和 `epoch` 确定一条拉取链路的 `fetchsession` ,当 `session` 建立或变更时会发送全量式的 `FetchRequest` ,所谓的全量式就是指请求体中包含所有需要拉取的分区信息;当 `session` 稳定时则会发送增量式的 `FetchRequest` 请求,里面的 `topics` 域为空,因为 `topics` 域的内容已经被缓存在了 `session` 链路的两侧。如果需要从当前 `fetch session` 中取消对某些分区的拉取订阅,则可以使用 `forgotten_topics_data` 字段来实现。 36 | 37 | 这个改进在大规模的 `Kafka` 集群中非常有用,它可以提升集群间的网络带宽的有效使用率。不过对客户端而言效果不是那么明显,一般情况下单个客户端不会订阅太多的分区,不过总体上这也是一个很好的优化改进。与 `FetchRequest` 对应的 `FetchResponse` 的组织结构: 38 | 39 | ![image-20201120180129563](assets/image-20201120180129563.png) 40 | 41 | `FetchResponse` 结构中的域也很多,它主要分为 `4` 层,第 `1` 层包含 `throttle_time_ms` 、 `error_code` 、 `session_id` 和 `responses` 。`responses` 是一个数组类型,表示响应的具体内容,也就是 `FetchResponse` 结构中的第 `2` 层,具体地细化到每个分区的响应。第 `3` 层中包含分区的元数据信息及具体的消息内容( `record_set` ),`aborted_transactions` 和事务相关。 42 | 43 | -------------------------------------------------------------------------------- /Kafak/消费者.md: -------------------------------------------------------------------------------- 1 | 消费者(`Consumer`)负责订阅 `Kafka` 中的主题(`Topic`),并且从订阅的主题上拉取消息。在Kafka的消费理念中还有一层消费组的概念,每个消费者都有一个对应的消费组。当消息发布到主题后,只会被投递给订阅它的每个消费组中的一个消费者。消费者与消费组这种模型可以让整体的消费能力具备横向伸缩性,我们可以增加(或减少)消费者的个数来提高(或降低)整体的消费能力。对于分区数固定的情况,一味地增加消费者并不会让消费能力一直得到提升,如果消费者过多,出现了消费者的个数大于分区个数的情况,就会有消费者分配不到任何分区。 2 | 3 | Kafka 同时支持两种消息投递模式:点对点(`P2P`,`Point-to-Point`)模式和发布/订阅(`Pub/Sub`)模式。 4 | 5 | - 如果所有的消费者都隶属于同一个消费组,那么所有的消息都会被均衡地投递给每一个消费者,即每条消息只会被一个消费者处理,这就相当于点对点模式的应用。 6 | 7 | - 如果所有的消费者都隶属于不同的消费组,那么所有的消息都会被广播给所有的消费者,即每条消息会被所有的消费者处理,这就相当于发布/订阅模式的应用。 8 | 9 | 一个正常的消费逻辑需要具备以下几个步骤: 10 | 11 | 1. 配置消费者客户端参数及创建相应的消费者实例。 12 | 2. 订阅主题。 13 | 3. 拉取消息并消费。 14 | 4. 提交消费位移。 15 | 5. 关闭消费者实例。 16 | 17 | #### 位移提交 18 | 19 | `Kafka` 中的消费是基于拉模式的,是一个不断轮询的过程,消费者所要做的就是重复地调用 `poll()` 方法,而 `poll()` 方法返回的是所订阅的主题(分区)上的一组消息。消费者消费到的每条消息的类型为 `ConsumerRecord` 。`poll()` 内部逻辑而言并不简单,它涉及消费位移、消费者协调器、组协调器、消费者的选举、分区分配的分发、再均衡的逻辑、心跳等内容 20 | 21 | 在每次调用 `poll()` 方法时,它返回的是还没有被消费过的消息集,因此需要记录上一次消费时的消费位移,并做持久化保存。在消费者客户端中,消费位移存储在 `Kafka` 内部的主题 `__consumer_offsets` 中。这里把将消费位移存储起来(持久化)的动作称为“提交”,消费者在消费完消息之后需要执行消费位移的提交。 22 | 23 | 用 `x` 表示某一次拉取操作中此分区消息的最大偏移量,假设当前消费者已经消费了 `x` 位置的消息,那么我们就可以说消费者的消费位移为 `x` 。不过需要非常明确的是,当前消费者需要提交的消费位移并不是 `x` ,而是 `x + 1` ,它表示下一条需要拉取的消息的位置。 24 | 25 | 在默认的方式下,消费者每隔 `5` 秒会将拉取到的每个分区中最大的消息位移进行提交。自动位移提交的动作是在 `poll()` 方法的逻辑里完成的,在每次真正向服务端发起拉取请求之前会检查是否可以进行位移提交,如果可以,那么就会提交上一次轮询的位移。自动提交消费位移免去了复杂的位移提交逻辑,让编码更简洁,但随之而来的是重复消费和消息丢失的问题。 26 | 27 | 在 `Kafka` 中还提供了手动位移提交的方式,这样可以使得开发人员对消费位移的管理控制更加灵活。手动提交可以细分为同步提交和异步提交,对应于 `KafkaConsumer` 中的 `commitSync()` 和 `commitAsync()` 两种类型的方法。 28 | 29 | 同步提交示例: 30 | 31 | ![image-20201117111504796](assets/image-20201117111504796.png) 32 | 33 | 示例中将拉取到的消息存入缓存 `buffer` ,等到积累到足够多的时候,再做相应的批量处理,之后再做批量提交。如果在业务逻辑处理完之后,并且在同步位移提交前,程序出现了崩溃,那么待恢复之后又只能从上一次位移提交的地方拉取消息,由此在两次位移提交的窗口中出现了重复消费的现象。 34 | 35 | 异步提交示例: 36 | 37 | ![image-20201117111710505](assets/image-20201117111710505.png) 38 | 39 | 异步提交的时候同样会有失败的情况发生,如果某一次异步提交的消费位移为 `x`,但是提交失败了,然后下一次又异步提交了消费位移为 `x + y` ,这次成功了。如果这里引入了重试机制,前一次的异步提交的消费位移在重试的时候提交成功了,那么此时的消费位移又变为了 `x 。如果此时发生异常(或者再均衡),那么恢复之后的消费者(或者新的消费者)就会从 `x` 处开始消费消息,这样就发生了重复消费的问题。为此我们可以设置一个递增的序号来维护异步提交的顺序,每次位移提交之后就增加序号相对应的值。在遇到位移提交失败需要重试的时候,可以检查所提交的位移和序号的值的大小,如果前者小于后者,则说明有更大的位移已经提交了,不需要再进行本次重试;如果两者相同,则说明可以进行重试提交。除非程序编码错误,否则不会出现前者大于后者的情况。 40 | 41 | 在一般情况下,位移提交失败的情况很少发生,不重试也没有关系,后面的提交也会有成功的。重试会增加代码逻辑的复杂度,不重试会增加重复消费的概率。如果消费者异常退出,那么这个重复消费的问题就很难避免,因为这种情况下无法及时提交消费位移;如果消费者正常退出或发生再均衡的情况,那么可以在退出或再均衡执行之前使用同步提交的方式做最后的把关。 42 | 43 | ![image-20201117112328727](assets/image-20201117112328727.png) 44 | 45 | #### 指定位移消费 46 | 47 | 正是有了消费位移的持久化,才使消费者在关闭、崩溃或者在遇到再均衡的时候,可以让接替的消费者能够根据存储的消费位移继续进行消费。 48 | 49 | 当一个新的消费组建立的时候,它根本没有可以查找的消费位移,此时就会根据消费者客户端参数 `auto.offset.reset` 的配置来决定从何处开始进行消费,这个参数的默认值为 `latest` ,表示从分区末尾开始消费消息。如果将 `auto.offset.reset` 参数配置为 `earliest` ,那么消费者会从起始处,也就是 `0` 开始消费。 50 | 51 | 消息的拉取是根据 `poll()` 方法中的逻辑来处理的, `poll()` 方法中的逻辑对于普通的开发人员而言是一个黑盒,无法精确地掌控其消费的起始位置。有些时候,我们需要一种更细粒度的掌控,可以让我们从特定的位移处开始拉取消息,而 `KafkaConsumer` 中的 `seek()` 方法正好提供了这个功能,让我们得以追前消费或回溯消费。`seek()` 方法的具体定义如下: 52 | 53 | ![image-20201117113546744](assets/image-20201117113546744.png) 54 | 55 | `seek()` 方法只能重置消费者分配到的分区的消费位置,而分区的分配是在 `poll()` 方法的调用过程中实现的。也就是说,在执行 `seek()` 方法之前需要先执行一次 `poll()` 方法,等到分配到分区之后才可以重置消费位置。 56 | 57 | ![image-20201117113840468](assets/image-20201117113840468.png) 58 | 59 | 如果消费组内的消费者在启动的时候能够找到消费位移,除非发生位移越界,否则 `auto.offset.reset` 参数并不会奏效,此时如果想指定从开头或末尾开始消费,就需要 `seek()` 方法的帮助了。 `seek()` 方法为我们提供了从特定位置读取消息的能力,我们可以通过这个方法来向前跳过若干消息,也可以通过这个方法来向后回溯若干消息,这样为消息的消费提供了很大的灵活性。`seek()` 方法也为我们提供了将消费位移保存在外部存储介质中的能力,还可以配合再均衡监听器来提供更加精准的消费能力。 60 | 61 | #### 再均衡 62 | 63 | 再均衡是指分区的所属权从一个消费者转移到另一消费者的行为,它为消费组具备高可用性和伸缩性提供保障,使我们可以既方便又安全地删除消费组内的消费者或往消费组内添加消费者。不过在再均衡发生期间,消费组会变得不可用,消费者当前的状态也会丢失。比如消费者消费完某个分区中的一部分消息时还没有来得及提交消费位移就发生了再均衡操作,之后这个分区又被分配给了消费组内的另一个消费者,原来被消费完的那部分消息又被重新消费一遍,也就是发生了重复消费。一般情况下,应尽量避免不必要的再均衡的发生。 64 | 65 | 在 `subscribe(Collection<String> topics,ConsumerRebalanceListener listener)` 和 `subscribe(Pattern pattern,ConsumerRebalanceListener listener)`方法中都有它的身影。再均衡监听器用来设定发生再均衡动作前后的一些准备或收尾的动作。 66 | 67 | `ConsumerRebalanceListener` 是一个接口,包含 `2` 个方法: 68 | 69 | 1. `void onPartitionsRevoked(Collection<TopicPartition>partitions)` 这个方法会在再均衡开始之前和消费者停止读取消息之后被调用。可以通过这个回调方法来处理消费位移的提交,以此来避免一些不必要的重复消费现象的发生。 70 | 2. `void onPartitionsAssigned(Collection<TopicPartition>partitions)` 这个方法会在重新分配分区之后和消费者开始读取消费之前被调用。 71 | 72 | ![image-20201117115615180](assets/image-20201117115615180.png) 73 | 74 | #### 多线程实现 75 | 76 | `KafkaProducer` 是线程安全的,然而 `KafkaConsumer` 却是非线程安全的。`KafkaConsumer` 中定义了一个 `acquire()` 方法,用来检测当前是否只有一个线程在操作,若有其他线程正在操作则会抛出 `ConcurrentModifcationException` 异常。`KafkaConsumer` 中的每个公用方法在执行所要执行的动作之前都会调用这个`acquire()` 方法,只有 `wakeup()` 方法是个例外。 `acquire()` 方法和我们通常所说的锁不同,它不会造成阻塞等待,我们可以将其看作一个轻量级锁,它仅通过线程操作计数标记的方式来检测线程是否发生了并发操作,以此保证只有一个线程在操作。`acquire()` 方法和 `release()` 方法成对出现,表示相应的加锁和解锁操作。 `acquire()` 方法和 `release()` 方法都是私有方法,因此在实际应用中不需要我们显式地调用。 77 | 78 | `KafkaConsumer` 非线程安全并不意味着只能以单线程的方式执行。如果生产者发送消息的速度大于消费者处理消息的速度,那么就会有越来越多的消息得不到及时的消费。由于 `Kafka` 中消息保留机制的作用,有些消息有可能在被消费之前就被清理了,从而造成消息的丢失。我们可以通过多线程的方式来实现消息消费,提高整体的消费能力。 79 | 80 | 多线程的实现方式有多种: 81 | 82 | 1. 线程封闭,为每个线程实例化一个 `KafkaConsumer` 对象,我们可以称之为消费线程。一个消费线程可以消费一个或多个分区中的消息,所有的消费线程都隶属于同一个消费组。这种实现方式的并发度受限于分区的实际个数。 83 | 2. 多个消费线程同时消费同一个分区,通过 `assign()`、 `seek()` 等方法实现,可以打破原有的消费线程的个数不能超过分区数的限制,进一步提高了消费的能力。不过这种实现方式对于位移提交和顺序控制的处理就会变得非常复杂,实际应用中使用得极少。 84 | 3. 将处理消息模块改成多线程的实现方式。第一种方式中,每个消费线程都要维护一个独立的 `TCP` 连接,如果分区数和 `consumerThreadNum` 的值都很大,那么会造成不小的系统开销。一般而言,`poll()` 拉取消息的速度是相当快的,而整体消费的瓶颈也正是在处理消息这一块,如果我们通过一定的方式来改进这一部分,那么我们就能带动整体消费性能的提升。 85 | 86 | 第三种方式示意图: 87 | 88 | ![image-20201117121546501](assets/image-20201117121546501.png) 89 | 90 | 每一个处理消息的 `RecordHandler` 类在处理完消息之后都将对应的消费位移保存到共享变量 `offsets` 中, `KafkaConsumerThread` 在每一次 `poll()` 方法之后都读取 `offsets` 中的内容并对其进行位移提交。但是这种位移提交的方式会有数据丢失的风险。对于同一个分区中的消息,假设一个处理线程 `RecordHandler1` 正在处理 `offset` 为 `0~99` 的消息,而另一个处理线程 `RecordHandler2` 已经处理完了 `offset` 为 `100~199` 的消息并进行了位移提交,此时如果 `RecordHandler1` 发生异常,则之后的消费只能从 `200` 开始而无法再次消费 `0~99` 的消息,从而造成了消息丢失的现象。 91 | 92 | 对此就要引入更加复杂的处理机制,总体结构上是基于滑动窗口实现的,所呈现的结构是通过消费者拉取分批次的消息,然后提交给多线程进行处理,而这里的滑动窗口式的实现方式是将拉取到的消息暂存起来,多个消费线程可以拉取暂存的消息,这个用于暂存消息的缓存大小即为滑动窗口的大小,总体上而言没有太多的变化,不同的是对于消费位移的把控。 93 | 94 | ![image-20201117122055550](assets/image-20201117122055550.png) 95 | 96 | 每一个方格代表一个批次的消息,一个滑动窗口包含若干方格,`startOffset` 标注的是当前滑动窗口的起始位置, `endOffset` 标注的是末尾位置。每当 `startOffset` 指向的方格中的消息被消费完成,就可以提交这部分的位移,与此同时,窗口向前滑动一格,删除原来 `startOffset` 所指方格中对应的消息,并且拉取新的消息进入窗口。滑动窗口的大小固定,所对应的用来暂存消息的缓存大小也就固定了。如果一个方格内的消息无法被标记为消费完成,那么就会造成 `startOffset` 的悬停。为了使窗口能够继续向前滑动,那么就需要设定一个阈值,当 `startOffset` 悬停一定的时间后就对这部分消息进行本地重试消费,如果重试失败就转入重试队列,如果还不奏效就转入死信队列。 97 | 98 | -------------------------------------------------------------------------------- /Kafak/生产者.md: -------------------------------------------------------------------------------- 1 | 从编程的角度而言,生产者就是负责向 `Kafka` 发送消息的应用程序。 2 | 3 | 一个正常的生产逻辑需要具备以下几个步骤: 4 | 5 | 1. 配置生产者客户端参数及创建相应的生产者实例。 6 | 2. 构建待发送的消息。 7 | 3. 发送消息。 8 | 4. 关闭生产者实例。 9 | 10 | 生产者客户端的消息在真正发往 `kafka` 之前,有可能需要经过拦截器(`Interceptor`)、序列化器(`Serializer`)、 分区器(`Partitioner`)等一系列的作用。 11 | 12 | ![image-20201116165017477](assets/image-20201116165017477.png) 13 | 14 | 整个生产者客户端有两个线程协调运行,这两个线程分别为主线程和 `Sender` 线程(发送线程)。在主线程中由 `KafkaProducer` 创建消息,然后通过可能的拦截器、序列化器和分区器的作用后缓存到消息累加器(RecordAccumulator)中。`Sender` 线程负责从 `RecordAccumulator` 中获取消息并将其发送到 `kafka` 中。 15 | 16 | `RecordAccumulator` 主要用来缓存消息以便 `Sender` 线程可以批量发送,进而减少网络传输的资源消耗以提升性能。 `RecordAccumulator` 缓存的大小默认为 `32MB` 。 如果生产者发送消息的速度超过发送到服务器的速度,则会导致生产者空间不足,这个时候 `kafkaProducer.send()` 方法调用要么被阻塞要么抛出异常。 17 | 18 | 在 `RecordAccumulator` 的内部为每一个分区维护了一个双端队列,队列的内容就是 `ProducerBatch`。消息写入时都会被追加到队尾,`Sender` 读取消息时,从双端队列头部读取。`ProducerBatch` 是一个消息批次, `ProducerRecord` 会被包含在 `ProducerBatch` 中,这样可以使字节的使用更加紧凑,并且减少网络传输开销。 19 | 20 | `Sender` 从 `RecordAccumulator` 中获取缓存的消息后,将原本的 `>` 的保存形式转变成了 `>` 的形式,其中 `Node` 表示 `kafka` 集群的 `broker` 节点。对于网络连接来说,生产者客户端是与具体的 `broker` 节点建立的连接,向具体的 `broker` 节点发送消息,而并不关心消息属于哪个分区。之后 `Sender` 还会进一步封装成 `` 的形式,这样就可以将 `Request` 请求发往各个 `Node `了,`Request` 是指 `kafka` 的各种协议请求,对于消息发送而言就是 `ProducerRequest`。 21 | 22 | 请求从 `Sender` 线程发往 `kafka` 之前还会保存到 `InFlightRequests` 中,具体保存形式为 `Map>`,用于缓存已经发出去但还没有收到响应的请求。当 `Node` 中堆积了很多未响应的消息时,说明这个 `Node` 节点负载较大或者网络连接有问题。`InFlightRequests` 还可以获取 `LeastLoadedNode`,即所有 `Node` 中负载最小的那个。 23 | 24 | -------------------------------------------------------------------------------- /Kubernetes/Kubernetes基本概念.md: -------------------------------------------------------------------------------- 1 | ### Kubernetes的本质 2 | 3 | 容器是一个由 Linux Namespace、Linux Cgroups 和 rootfs 三种技术构建出来的进程的隔离环境。所以一个正在运行的 Linux 容器,可以被“一分为二”地看待: 4 | 5 | 1. 一组联合挂载在 /var/lib/docker/aufs/mnt 上的 rootfs,这一部分我们称为“容器镜像”,是容器的静态视图。 6 | 2. 一个由 Namespace + Cgroups 构成的隔离环境,这一部分我们称为“容器运行时”,是容器的动态视图。 7 | 8 | 真正承载着容器信息进行传递的,是容器镜像。容器编排技术是一种能将用户提交的 Docker 镜像以容器的方式运行起来的承载点,最具代表性的容器编排工具有: 9 | 10 | 1. Docker Compose + Swarm 组合,比较轻量适用于个人学习。 11 | 2. Kubernetes 项目,为用户提供一个具有普遍意义的容器编排工具,能够胜任大规模集群中的容器编排任务。 12 | 13 | Kubernetes 能够将容器镜像在一个给定的集群上运行起来,同时还能提供路由网关、水平扩展、监控、备份、灾难恢复等一系列运维能力。 14 | 15 | ![img](assets/8ee9f2fa987eccb490cfaa91c6484f67.png) 16 | 17 | 从上图可以看出,Kubernetes 由 Master 和 Node 两种节点组成,分别对应着控制节点和计算节点。 18 | 19 | 1. 控制节点由三个独立组件组合而成,分别是负责 API 服务的 kube-apiserver、负责调度的 kube-scheduler,和负责容器编排的 kube-controller-manager。整个集群的持久化数据,则由 kube-apiserver 处理后保存在 Etcd 中。 20 | 21 | 2. 计算节点上最核心的部分是 kubelet 组件,主要负责同容器运行时打交道。这个交互所依赖的,是 CRI(Container Runtime Interface)远程调用接口,这个接口定义了容器运行时的各项核心操作,比如:启动一个容器需要的所有参数。所以只要容器运行时能够运行标准的容器镜像,它就可以通过实现 CRI 接入到 Kubernetes 项目当中。而具体的容器运行时,比如 Docker 项目,则一般通过 OCI 这个容器运行时规范同底层的 Linux 操作系统进行交互,即:把 CRI 请求翻译成对 Linux 操作系统的调用(操作 Linux Namespace 和 Cgroups 等)。 22 | 23 | kubelet 通过 gRPC 协议同 Device Plugin 插件进行交互。它是 Kubernetes 项目用来管理 GPU 等宿主机物理设备的主要组件,也是基于 Kubernetes 项目进行机器学习训练、高性能作业支持等工作必须关注的功能。kubelet 的另一个重要功能,是调用网络插件和存储插件为容器配置网络和持久化存储。这两个插件与 kubelet 进行交互的接口,分别是 CNI(Container Networking Interface)和 CSI(Container Storage Interface)。 24 | 25 | **Kubernetes 没有像其他“容器云”项目那样,把 Docker 作为整个架构的核心,而仅仅把它作为最底层的一个容器运行时实现。Kubernetes 着重解决的问题是如何处理运行在大规模集群中的各种任务之间的关系,这是作业编排和管理系统最困难的地方。** 26 | 27 | **Kubernetes 最主要的设计思想是,从更宏观的角度,以统一的方式来定义任务之间的各种关系,并且为将来支持更多种类的关系留有余地。** 28 | 29 | > 常见的容器间“紧密交互”关系: 30 | > 31 | > 通常一些应用往往会被直接部署在同一台机器上,通过 localhost 通信,通过本地磁盘目录交换文件。而在 Kubernetes 中,这些容器则会被划分为一个 Kubernetes 中最基础的对象“Pod”,Pod 里的容器共享同一个 Network Namespace、同一组数据卷,从而达到高效率交换信息的目的。 32 | > 33 | > 又比如 Web 应用与数据库之间的访问关系,Kubernetes 项目则提供了一种叫作“Service”的服务。像这样的两个应用,往往故意不部署在同一台机器上,这样即使 Web 应用所在的机器宕机了,数据库也完全不受影响。对于一个容器来说,它的 IP 地址等信息不是固定的,所以 Kubernetes 给 Pod 绑定一个 Service 服务,而 Service 服务声明的 IP 地址等信息是“终生不变”的。它作为 Pod 的代理入口(Portal),从而代替 Pod 对外暴露一个固定的网络地址。这样,对于 Web 应用的 Pod 来说,它需要关心的就是数据库 Pod 的 Service 信息。而 Service 后端真正代理的 Pod 的 IP 地址、端口等信息的自动更新、维护,则是 Kubernetes 项目的职责。 34 | 35 | ![img](assets/16c095d6efb8d8c226ad9b098689f306.png) 36 | 37 | 按照上图的线索,从容器这个最基础的概念出发: 38 | 39 | 1. 首先遇到了容器间“紧密协作”关系的难题,于是就扩展到了 Pod 40 | 2. 有了 Pod 之后,希望能一次启动多个应用的实例,这样就需要 Deployment 这个 Pod 的多实例管理器 41 | 3. 一组相同的 Pod 后,需要通过一个固定的 IP 地址和端口以负载均衡的方式访问它,于是就有了 Service 42 | 4. 如果两个不同 Pod 之间不仅有“访问关系”,要求在发起时加上授权信息。于是就有了 Secret 对象,它是一个保存在 Etcd 里的键值对数据。把 Credential 信息以 Secret 的方式存在 Etcd 里,Kubernetes 就会在指定的 Pod 启动时,自动把 Secret 里的数据以 Volume 的方式挂载到容器里。 43 | 44 | **除了应用与应用之间的关系外,应用运行的形态是影响“如何容器化这个应用”的第二个重要因素。** 45 | 46 | Kubernetes 定义了基于 Pod 改进后的对象。 47 | 48 | 1. Job,用来描述一次性运行的 Pod(比如,大数据任务) 49 | 2. DaemonSet,用来描述每个宿主机上必须且只能运行一个副本的守护进程服务 50 | 3. CronJob,用于描述定时任务 51 | 52 | Kubernetes 中所推崇的使用方法是: 53 | 54 | 1. 首先,通过一个“编排对象”,比如 Pod、Job、CronJob 等,来描述试图管理的应用 55 | 2. 然后,再为它定义一些“服务对象”,比如 Service、Secret、Horizontal Pod Autoscaler 等。这些对象,会负责具体的平台级功能。 56 | 57 | 这种使用方法,就是“声明式 API”。这种 API 对应的“编排对象”和“服务对象”,都是 Kubernetes 项目中的 API 对象(API Object)。 -------------------------------------------------------------------------------- /Kubernetes/README.md: -------------------------------------------------------------------------------- 1 | ### Kubernetes 2 | 3 | `Kubernetes` 是一种容器编排技术 4 | 5 | [容器](./容器.md) 6 | 7 | [Kubernetes基本概念](./Kubernetes基本概念) 8 | 9 | [Pod](./Pod.md) 10 | 11 | -------------------------------------------------------------------------------- /Kubernetes/assets/16c095d6efb8d8c226ad9b098689f306.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kubernetes/assets/16c095d6efb8d8c226ad9b098689f306.png -------------------------------------------------------------------------------- /Kubernetes/assets/8a7b5cfabaab2d877a1d4566961edd5f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kubernetes/assets/8a7b5cfabaab2d877a1d4566961edd5f.png -------------------------------------------------------------------------------- /Kubernetes/assets/8c016391b4b17923f38547c498e434cf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kubernetes/assets/8c016391b4b17923f38547c498e434cf.png -------------------------------------------------------------------------------- /Kubernetes/assets/8ee9f2fa987eccb490cfaa91c6484f67.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kubernetes/assets/8ee9f2fa987eccb490cfaa91c6484f67.png -------------------------------------------------------------------------------- /Kubernetes/assets/d1bb34cda8744514ba4c233435bf4e96.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Kubernetes/assets/d1bb34cda8744514ba4c233435bf4e96.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 算法 2 | 3 | [基础算法](算法/基础算法.md) 4 | 5 | [剑指Offer](./算法/剑指Offer.md) 6 | 7 | [leetcode-TOP100](./算法/leetcode-TOP100.md) 8 | 9 | [bytedance题目](./算法/bytedance.md) 10 | 11 | [cyc题目](./算法/cyc题目.md) 12 | 13 | ### 操作系统 14 | 15 | [Linux](./操作系统/Linux.md) 16 | 17 | ## Java 18 | 19 | [Spring](Java/Spring/README.md) 20 | 21 | [集合源码](/Java/集合源码/README.md) 22 | 23 | [JVM](Java/JVM/README.md) 24 | 25 | [并发](Java/并发/README.md) 26 | 27 | ## 网络 28 | 29 | [比较重要的概念](网络/比较重要的概念.md) 30 | 31 | ## 数据库 32 | 33 | [leetcode](./数据库/leetcode.md) 34 | 35 | [redis](Redis/README.md) 36 | 37 | ## 分布式 38 | 39 | [分布式架构](分布式/分布式架构.md) 40 | 41 | [一致性协议](分布式/一致性协议.md) 42 | 43 | [微服务](分布式/微服务.md) 44 | 45 | ## 系统设计 46 | 47 | [消息队列](系统设计/消息队列.md) 48 | 49 | [网络攻击与安全算法](系统设计/网络攻击与安全算法.md) 50 | 51 | [设计模式](系统设计/设计模式.md) 52 | 53 | ### 📚 54 | 55 | [设计数据密集型应用](Book/设计数据密集型应用.md) -------------------------------------------------------------------------------- /Redis/README.md: -------------------------------------------------------------------------------- 1 | ### redis 简介 2 | 3 | 简单来说 redis 就是一个数据库,不过与传统数据库不同的是 redis 的数据是存在内存中的,所以读写速度非常快,因此 redis 被广泛应用于缓存方向。另外,redis 也经常用来做分布式锁。redis 提供了多种数据类型来支持不同的业务场景。 4 | 5 | [数据结构与对象](数据结构与对象.md) 6 | 7 | [数据库与持久化](数据库与持久化.md) 8 | 9 | [主从复制和高可用集群](主从复制和高可用集群.md) 10 | 11 | [RedLock分布式锁](RedLock分布式锁.md) 12 | 13 | [一些场景问题](一些场景问题.md) 14 | 15 | 16 | 17 | 18 | 19 | ### 参考资料 20 | 21 | - 《redis设计与实现第二版》 22 | - [RedLock官方文档翻译](http://ifeve.com/redis-lock/) 23 | - [JavaGuide](https://github.com/Snailclimb/JavaGuide/blob/master/docs/database/Redis/Redlock分布式锁.md) 24 | - [互联网 Java 工程师进阶知识完全扫盲](https://github.com/doocs/advanced-java) 25 | 26 | -------------------------------------------------------------------------------- /Redis/RedLock分布式锁.md: -------------------------------------------------------------------------------- 1 | ### 使用分布式锁主要的两个场景: 2 | 3 | 1. 提升效率,用锁来保证一个任务没有必要被执行两次。比如很昂贵的计算。 4 | 2. 保证正确,使用锁来保证任务按照正常的步骤执行,防止两个节点同时操作一份数据,造成文件冲突,数据丢失。 5 | 6 | ### 单节点上实现分布式锁 7 | 8 | 依靠`SET resource_name my_random_value NX PX 30000`命令,该命令仅当 Key 不存在时(NX保证)set 值,并且设置过期时间 3000ms (PX保证),值 my_random_value 必须是所有 client 和所有锁请求发生期间唯一的,释放锁(利用lua脚本保证原子性)的逻辑是: 9 | 10 | ```lua 11 | if redis.call("get",KEYS[1]) == ARGV[1] then 12 | return redis.call("del",KEYS[1]) 13 | else 14 | return 0 15 | end 16 | ``` 17 | 18 | 上述实现可以避免释放另一个client创建的锁,如果只有 del 命令的话,那么如果 client1 拿到 lock1 之后因为某些操作阻塞了很长时间,此时 Redis 端 lock1 已经过期了并且已经被重新分配给了 client2,那么 client1 此时再去释放这把锁就会造成 client2 原本获取到的锁被 client1 无故释放了,但现在为每个 client 分配一个 unique 的 string 值可以避免这个问题。至于如何去生成这个 unique string,方法很多随意选择一种就行了。 19 | 20 | ### RedLock分布式锁 21 | 22 | Redis 官方提出了一种权威的基于 Redis 实现分布式锁的方式名叫 *Redlock*,此种方式比原先的单节点的方法更安全。它可以保证以下特性: 23 | 24 | 1. 安全特性:互斥访问,即永远只有一个 client 能拿到锁 25 | 2. 避免死锁:最终 client 都可能拿到锁,不会出现死锁的情况,即使原本锁住某资源的 client crash 了或者出现了网络分区 26 | 3. 容错性:只要大部分 Redis 节点存活就可以正常提供服务 27 | 28 | ### Redlock 算法 29 | 30 | 算法很易懂,起 5 个 master 节点,分布在不同的机房尽量保证可用性。为了获得锁,client 会进行如下操作: 31 | 32 | 1. 得到当前的时间,微秒单位 33 | 2. 尝试顺序地在 5 个实例上申请锁,当然需要使用相同的 key 和 random value,这里一个 client 需要合理设置与 master 节点沟通的 timeout 大小,避免长时间和一个 fail 了的节点浪费时间 34 | 3. 当 client 在大于等于 3 个 master 上成功申请到锁的时候,且它会计算申请锁消耗了多少时间,这部分消耗的时间采用获得锁的当下时间减去第一步获得的时间戳得到,如果锁的持续时长(失效时长)比流逝的时间(加锁的时间)多的话,那么锁就真正获取到了。 35 | 4. 如果锁申请到了,那么锁真正的持续时长应该是之前的持续时长减去申请锁期间流逝的时间。 36 | 5. 如果 client 申请锁失败了,不管是因为获取成功的锁不超过一半,还是因为总消耗时间超过了锁释放时间,客户端都会到每个master节点上释放锁,即便是那些他认为没有获取成功的锁。 37 | 38 | ### 失败重试 39 | 40 | 如果一个 client 申请锁失败了,那么它需要稍等一会在重试避免多个 client 同时申请锁的情况,最好的情况是一个 client 需要几乎同时向 5 个 master 发起锁申请。另外就是如果 client 申请锁失败了它需要尽快在它曾经申请到锁的 master 上执行 unlock 操作,便于其他 client 获得这把锁,避免这些锁过期造成的时间浪费,当然如果这时候网络分区使得 client 无法联系上这些 master,那么这种浪费就是不得不付出的代价了。 41 | 42 | ### 放锁 43 | 44 | 放锁操作很简单,就是依次释放所有节点上的锁就行了 45 | 46 | ### 性能、崩溃恢复和 fsync 47 | 48 | 如果我们的节点没有持久化机制,client 从 5 个 master 中的 3 个处获得了锁,然后其中一个重启了,这是注意 **整个环境中又出现了 3 个 master 可供另一个 client 申请同一把锁!** 违反了互斥性。如果我们开启了 AOF 持久化那么情况会稍微好转一些,因为 Redis 的过期机制是语义层面实现的,所以在 server 挂了的时候时间依旧在流逝,重启之后锁状态不会受到污染。但是考虑断电之后呢,AOF部分命令没来得及刷回磁盘直接丢失了,除非我们配置刷回策略为 fsnyc = always,但这会损伤性能。解决这个问题的方法是,当一个节点重启之后,我们规定在 max TTL 期间它是不可用的,这样它就不会干扰原本已经申请到的锁,等到它 crash 前的那部分锁都过期了,环境不存在历史锁了,那么再把这个节点加进来正常工作。 49 | 50 | ### 使用选择 51 | 52 | 对于需求性能的分布式锁应用它太重了且成本高;对于需求正确性的应用来说它不够安全。如果应用只需要高性能的分布式锁不要求多高的正确性,那么单节点 Redis 够了;如果应用想要保住正确性,那么不建议 Redlock(在客户端进行写操作时,无法保证客户端能在写入数据之前感知到锁过期),建议使用一个合适的一致性协调系统,例如 Zookeeper,且保证存在 fencing token。 53 | 54 | -------------------------------------------------------------------------------- /Redis/assets/image-20190725133718995.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Redis/assets/image-20190725133718995.png -------------------------------------------------------------------------------- /Redis/assets/image-20190725142329193.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Redis/assets/image-20190725142329193.png -------------------------------------------------------------------------------- /Redis/assets/image-20190725143445249.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Redis/assets/image-20190725143445249.png -------------------------------------------------------------------------------- /Redis/assets/image-20190725143859365.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Redis/assets/image-20190725143859365.png -------------------------------------------------------------------------------- /Redis/assets/image-20190725144528525.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Redis/assets/image-20190725144528525.png -------------------------------------------------------------------------------- /Redis/assets/image-20190725145100209.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Redis/assets/image-20190725145100209.png -------------------------------------------------------------------------------- /Redis/assets/image-20190725151235195.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Redis/assets/image-20190725151235195.png -------------------------------------------------------------------------------- /Redis/assets/image-20190725151251825.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Redis/assets/image-20190725151251825.png -------------------------------------------------------------------------------- /Redis/assets/image-20190725151306686.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Redis/assets/image-20190725151306686.png -------------------------------------------------------------------------------- /Redis/assets/image-20190725151318404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Redis/assets/image-20190725151318404.png -------------------------------------------------------------------------------- /Redis/assets/image-20190725162737431.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Redis/assets/image-20190725162737431.png -------------------------------------------------------------------------------- /Redis/assets/image-20190725163018827.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Redis/assets/image-20190725163018827.png -------------------------------------------------------------------------------- /Redis/assets/image-20190728091518132.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Redis/assets/image-20190728091518132.png -------------------------------------------------------------------------------- /Redis/assets/image-20190728094130889.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Redis/assets/image-20190728094130889.png -------------------------------------------------------------------------------- /Redis/assets/image-20190728134118436.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Redis/assets/image-20190728134118436.png -------------------------------------------------------------------------------- /Redis/assets/image-20190728134308856.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Redis/assets/image-20190728134308856.png -------------------------------------------------------------------------------- /Redis/assets/image-20190729152939908.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Redis/assets/image-20190729152939908.png -------------------------------------------------------------------------------- /Redis/assets/image-20190730124116313.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/Redis/assets/image-20190730124116313.png -------------------------------------------------------------------------------- /Redis/一些场景问题.md: -------------------------------------------------------------------------------- 1 | ### 为什么要用 redis? 2 | 3 | 这个问题也可以描述为为什么要用缓存。主要从**高性能**和**高并发**这两点来看待这个问题。 4 | 5 | **高性能:** 6 | 7 | 用户首次访问数据库中的某些数据时会比较慢,因为是从硬盘上读取的。将该用户访问的数据存在数缓存中,这样下一次再访问这些数据的时候就可以直接从缓存中获取了。操作缓存就是直接操作内存,所以速度相当快。如果数据库中的对应数据改变的之后,同步改变缓存中相应的数据即可! 8 | 9 | **高并发:** 10 | 11 | 直接操作缓存能够承受的请求是远远大于直接访问数据库的,所以我们可以考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用经过数据库。 12 | 13 | ### 缓存雪崩 14 | 15 | 简介:由于缓存机器意外宕机等原因导致缓存同一时间大面积的失效,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。 16 | 17 | 解决办法: 18 | 19 | - 事前:尽量保证整个 redis 集群的高可用性,发现机器宕机尽快补上。选择合适的内存淘汰策略。 20 | - 事中:本地ehcache缓存 + hystrix限流&降级,避免MySQL崩掉 21 | - 事后:利用 redis 持久化机制保存的数据尽快恢复缓存 22 | 23 | ### 缓存穿透 24 | 25 | 简介:一般是黑客故意去请求缓存中不存在的数据,导致所有的请求都落到数据库上,造成数据库短时间内承受大量请求而崩掉。 26 | 27 | 解决办法: 有很多种方法可以有效地解决缓存穿透问题,最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。另外也有一个更为简单粗暴的方法,如果一个查询返回的数据为空,我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。 28 | 29 | ### 缓存击穿 30 | 31 | 简介:某个 key 非常热点,访问非常频繁,处于集中式高并发访问的情况,当这个 key 在失效的瞬间,大量的请求就击穿了缓存,直接请求数据库,就像是在一道屏障上凿开了一个洞。 32 | 33 | 解决办法: 34 | 35 | 1. 可以将热点数据设置为永远不过期 36 | 2. 基于 redis or zookeeper 实现互斥锁,等待第一个请求构建完缓存之后,再释放锁,进而其它请求才能通过该 key 访问数据。 37 | 38 | ### 如何保证缓存与数据库双写时的数据一致性? 39 | 40 | 在高并发的业务场景下,数据库大多数情况都是用户并发访问最薄弱的环节。所以,就需要使用redis做一个缓冲操作,让请求先访问到redis,而不是直接访问MySQL等数据库。 41 | 42 | 读取缓存一般没有什么问题,但是一旦涉及到数据更新,就容易出现缓存和数据库间的数据一致性问题。 43 | 44 | 不管是先写MySQL数据库,再删除Redis缓存;还是先删除缓存,再写库,都有可能出现数据不一致的情况。举一个例子: 45 | 46 | 1. 如果删除了缓存Redis,还没有来得及写库MySQL,另一个线程就来读取,发现缓存为空,则去数据库中读取数据写入缓存,此时缓存中为脏数据。 47 | 2. 如果先写了库,在删除缓存前,写库的线程宕机了,没有删除掉缓存,则也会出现数据不一致情况。 48 | 49 | 因为写和读是并发的,没法保证顺序,就会出现缓存和数据库的数据不一致的问题。 50 | 51 | **第一种方案:采用延时双删策略** 52 | 53 | 在写库前后都进行redis.del(key)操作,并且设定合理的超时时间。 54 | 55 | ``` java 56 | public void write(String key,Object data) { 57 | redis.delKey(key); 58 | db.updateData(data); 59 | Thread.sleep(500); 60 | redis.delKey(key); 61 | } 62 | ``` 63 | 64 | **具体步骤:** 65 | 66 | 1. 先删除缓存 67 | 68 | 2. 再写数据库 69 | 70 | 3. 休眠500毫秒 71 | 72 | 4. 再次删除缓存 73 | 74 | 具体休眠多久,需要评估自己的项目的读数据业务逻辑的耗时。这么做的目的,就是确保读请求结束,写请求可以删除读请求造成的缓存脏数据。 75 | 76 | 当然这种策略还要考虑redis和数据库主从同步的耗时。最后的的写数据的休眠时间:则在读数据业务逻辑的耗时基础上,加几百ms即可。 77 | 78 | **设置缓存过期时间** 79 | 80 | 从理论上来说,给缓存设置过期时间,是保证最终一致性的解决方案。所有的写操作以数据库为准,只要到达缓存过期时间,则后面的读请求自然会从数据库中读取新值然后回填缓存。 81 | 82 | **该方案的弊端** 83 | 84 | 结合双删策略 + 缓存超时设置,这样最差的情况就是在超时时间内数据存在不一致,而且又增加了写请求的耗时。 85 | 86 | **第二种方案:异步更新缓存** 87 | 88 | **整体思路:** 89 | 90 | MySQL binlog增量订阅消费 + 消息队列 + 增量数据更新到redis 91 | 92 | 1. 读Redis:热数据基本都在Redis 93 | 94 | 2. 写MySQL:增删改都是操作MySQL 95 | 96 | 3. 更新Redis数据:MySQL的数据操作binlog,来更新到Redis 97 | 98 | **Redis更新** 99 | 100 | 数据操作主要分为两大块: 101 | 102 | 全量(将全部数据一次写入到redis)和增量(update、insert、delate变更数据) 103 | 104 | 读取binlog后分析,利用消息队列推送更新各台的redis缓存数据。 105 | 106 | 这样一旦MySQL中产生了新的写入、更新、删除等操作,就可以把binlog相关的消息推送至Redis,Redis再根据binlog中的记录,对Redis进行更新。 107 | 108 | 其实这种机制,很类似MySQL的主从备份机制,因为MySQL的主备也是通过binlog来实现的数据一致性。 109 | 110 | 这里可以结合使用canal,通过该框架可以对MySQL的binlog进行订阅,而canal正是模仿了mysql的slave数据库的备份请求,使得Redis的数据更新达到了相同的效果。 111 | 112 | ### 如何解决 Redis 的并发竞争 Key 问题 113 | 114 | 所谓 Redis 的并发竞争 Key 的问题也就是多个系统同时对一个 key 进行操作,但是最后执行的顺序和我们期望的顺序不同,这样也就导致了结果的不同! 115 | 116 | 推荐一种方案:分布式锁(zookeeper 和 redis 都可以实现)。如果不存在 Redis 的并发竞争 Key 问题,不要使用分布式锁,这样会影响性能。 117 | 118 | 基于zookeeper临时有序节点可以实现的分布式锁。大致思想为:每个客户端对某个方法加锁时,在zookeeper上的与该方法对应的指定节点的目录下,生成一个唯一的瞬时有序节点。 判断是否获取锁的方式很简单,只需要判断有序节点中序号最小的一个。 当释放锁的时候,只需将这个瞬时节点删除即可。同时,其可以避免服务宕机导致的锁无法释放,而产生的死锁问题。完成业务流程后,删除对应的子节点释放锁。 119 | 120 | ### Redis分布式寻址算法 121 | 122 | 常见的分布式寻址算法可分为三大类: 123 | 124 | - hash 算法 125 | - 一致性 hash 算法+ 虚拟节点 126 | - redis cluster 的 hash slot 算法 127 | 128 | #### hash 算法 129 | 130 | 简介:对key计算hash值,然后对节点数取模。然后找到对应的master节点上。 131 | 132 | 存在的问题:一旦某一个master节点宕机,所有请求过来,都会基于最新的剩余 master 节点数去取模,尝试去取数据。这会导致大部分的请求无法得到有效的缓存数据,从而导致大量的流量涌入数据库。 133 | 134 | #### 一致性 hash 算法 135 | 136 | 简介:将整个 hash 值空间组织成一个虚拟的圆环,整个空间按顺时针方向组织,将各个 master 节点进行 hash,这样就能确定每个节点在其哈希环上的位置。对key计算hash值,并确定此数据在环上的位置,从此位置沿环顺时针行走,遇到的第一个 master 节点就是 key 所在位置。 137 | 138 | 在一致性哈希算法中,如果一个节点挂了,受影响的数据仅仅是此节点到环空间前一个节点之间的数据,其它不受影响。增加一个节点也同理。 139 | 140 | 一致性哈希算法在节点太少时,容易因为节点分布不均匀而造成**缓存热点**的问题。为了解决这种热点问题,一致性 hash 算法引入了虚拟节点机制,即对每一个节点计算多个 hash,每个计算结果位置都放置一个虚拟节点。这样就实现了数据的均匀分布,负载均衡。 141 | 142 | ![image-20190730124116313](assets/image-20190730124116313.png) 143 | 144 | 145 | 146 | #### redis cluster 的 hash slot 算法 147 | 148 | redis cluster 有固定的 `16384` 个 hash slot,对每个 `key` 计算 `CRC16` 值,然后对 `16384` 取模,可以获取 key 对应的 hash slot。 149 | 150 | redis cluster 中每个 master 都会持有部分 slot,`hash slot` 让 node 的增加和移除很简单,增加一个 master,就将其他 master 的 `hash slot` 移动部分过去,减少一个 master,就将它的 `hash slot` 移动到其他 master 上去。移动 `hash slot` 的成本是非常低的。任何一台机器宕机,其他节点不受影响,因为 key 找的是 hash slot,不是机器。 151 | 152 | -------------------------------------------------------------------------------- /Redis/数据库与持久化.md: -------------------------------------------------------------------------------- 1 | ### 数据库 2 | 3 | Redis服务器将所有数据库都保存在redisServer结构的db数组中。 4 | 5 | #### redisServer数据结构 6 | 7 | ``` c 8 | struct redisServer { 9 | // ... 10 | redisDb *db; 11 | // 服务器的数据库数量,默认16 12 | int dbnum; 13 | // ... 14 | }; 15 | 16 | struct redisDb { 17 | // ... 18 | // 数据库键空间,保存所有键值对 19 | dict *dict; 20 | // 过期字典,保存着键的过期时间 21 | dict *expires; 22 | // ... 23 | } redisDb; 24 | ``` 25 | 26 | 每个Redis客户端都有自己的目标数据库,默认情况下为0号数据库,可以通过`SELECT`命令切换目标数据库。 27 | 28 | #### redisClient数据结构 29 | 30 | ``` c 31 | typedef struct redisClient { 32 | // ... 33 | // 目标数据库 34 | redisDb *db; 35 | } 36 | ``` 37 | 38 | #### 设置键的生存时间或过期时间 39 | 40 | Redis中有个设置时间过期的功能,即对存储在 redis 数据库中的键值对可以设置一个过期时间。作为一个缓存数据库,这是非常实用的。如我们一般项目中的 token 或者一些登录信息,尤其是短信验证码都是有时间限制的,按照传统的数据库处理方式,一般都是自己判断过期,这样无疑会严重影响项目性能。 41 | 42 | 通过`EXPIRE`或者`PEXPIRE`命令,客户端可以设置数据库中某个键的生存时间,服务器会保存这个键的过期时间,到达指定时间后,服务器就会自动删除生存时间为0的键。 43 | 44 | `redisDb`中`expires`字段保存了键的过期时间,键为指向过期键的指针,值为过期时间。 45 | 46 | #### Redis的键删除策略 47 | 48 | redis中采用了惰性删除+定期删除的策略来删除过期键。 49 | 50 | - 惰性删除:所有读写Redis数据库的命令执行前都会对输入键进行检查 51 | - 已过期:删除 52 | - 未过期:不执行任何操作· 53 | - 定期删除:Redis服务器周期性执行删除操作,在规定时间内,分多次便利各个数据库,从`expires`字典中随机检查一部分键的过期时间,并删除其中的过期键。 54 | 55 | ##### 持久化和复制期间对过期键的处理 56 | 57 | - 生成RDB文件: 58 | - 已过期的键不会被保存到RDB文件 59 | - 载入RDB文件: 60 | - master:过期键会被忽略 61 | - slave: 过期键会被载入,在进行主从同步时,过期键会被删除 62 | - 写入AOF文件: 63 | - 当某个键已过期,但还未被删除时,AOF文件不会因为它过期而改变 64 | - 当某个键已过期,并且被删除后,AOF文件会追加一条DEL命令,来显示标记删除。 65 | - 重写AOF文件: 66 | - 已过期的键不会被保存到AOF文件 67 | - 复制: 68 | - master在删除一个过期键后会向所有slave发生一个DEL命令,告知slave这个键已过期。 69 | - slave在执行客户端的读命令时,即使碰到过期键也不会删除,而是当做未过期键处理。 70 | - slave只有接收到master的DEL命令后才会删除过期键。 71 | 72 | 但是仅仅通过设置过期时间还是有问题的。我们想一下:如果定期删除漏掉了很多过期 key,然后你也没及时去查,也就没走惰性删除,此时会怎么样?如果大量过期key堆积在内存里,导致redis内存块耗尽了。所以引入了 **redis 内存淘汰机制。** 73 | 74 | **redis 提供 6种数据淘汰策略:** 75 | 76 | 1. **volatile-lru**:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰 77 | 2. **volatile-ttl**:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰 78 | 3. **volatile-random**:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰 79 | 4. **allkeys-lru**:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key(这个是最常用的) 80 | 5. **allkeys-random**:从数据集(server.db[i].dict)中任意选择数据淘汰 81 | 6. **no-eviction**:禁止驱逐数据,也就是说当内存不足以容纳新写入数据时,新写入操作会报错。这个应该没人使用吧! 82 | 83 | 4.0版本后增加以下两种: 84 | 85 | 1. **volatile-lfu**:从已设置过期时间的数据集(server.db[i].expires)中挑选最不经常使用的数据淘汰 86 | 2. **allkeys-lfu**:当内存不足以容纳新写入数据时,在键空间中,移除最不经常使用的key 87 | 88 | 89 | 90 | ### RDB持久化 91 | 92 | 因为Redis时内存数据库,所以提供了持久化功能,其中一种就是RDB持久化。RDB持久化可以将某个时间点上数据库的状态保存到一个RDB文件中。RDB文件是一个经过压缩的二进制文件,可以通过它将数据库还原到生成RDB文件时的状态。 93 | 94 | 使用`SAVE`命令或`BGSAVE`命令可以生成RDB文件。 95 | 96 | - SAVE:会阻塞服务器进程,期间不能处理任何命令。 97 | - BGSAVE:会派生出一个子进程,子进程负责创建RDB文件,父进程继续处理命令请求。 98 | 99 | 通过配置`save`选项,可以让服务器隔一段时间自动执行`BGSAVE`命令,Redis默认的`save`选项: 100 | 101 | ```c 102 | // 900秒内对数据库至少修改过1次就会执行BGSAVE 103 | save 900 1 104 | // 300秒内对数据库至少修改过10次就会执行BGSAVE 105 | save 300 10 106 | // 60秒内对数据库至少修改过10000次就会执行BGSAVE 107 | save 60 10000 108 | ``` 109 | 110 | 当满足以上任一条件时,就会执行`BGSAVE`命令。 111 | 112 | 113 | 114 | ### AOF持久化 115 | 116 | 与RDB不同的是,AOF持久化是通过保存Redis服务器所执行的命令来记录数据库状态的。所以AOF文件的更新频率通常比RDB更高。AOF文件还原数据的原理也很简单:即将所有命令执行一遍。 117 | 118 | - 如果服务器开启了AOF持久化,那么服务器会优先通过AOF文件还原数据库。 119 | - 只有在AOF持久化关闭后,才会使用RDB还原数据库。 120 | 121 | #### AOF持久化 122 | 123 | 可分为`命令追加`、`文件写入`、`文件同步`三个步骤。 124 | 125 | - 命令追加:服务器在执行完一个写命令后,会以协议格式将命令追加到`aof_buf`缓冲区末尾。 126 | 127 | - 写入与同步:AOF有三种策略来将`aof_buf`缓冲区中的内容写入AOF文件里面,可以通过修改`appendfsync`选项来配置策略。 128 | 129 | - `always`:服务器在每个时间循环都要将`aof_buf`缓冲区中的写入并同步到AOF文件。 130 | - `everysec`:服务器在每个时间循环都要将`aof_buf`缓冲区中的写入到AOF文件,并且每隔一秒就要在子线程中对AOF文件进行一次同步。 131 | - `no`:服务器在每个时间循环都要将`aof_buf`缓冲区中的写入到AOF文件,由操作系统负责同步。 132 | 133 | 一般采用`everysec`策略,即一秒钟同步一次,这样效率足够高,并且最多只会丢失一秒的数据。 134 | 135 | #### AOF重写 136 | 137 | 随着服务器运行时间的流逝,AOF文件中的内容会越来越多,所以需要进行重写来解决文件体积膨胀的问题。AOF文件重写并不需要对现有AOF文件进行任何操作,而是通过读取当前服务器状态来实现。所以重写后的AOF文件只包含还原当前数据库所必需的命令,不会浪费任何硬盘空间。 138 | 139 | AOF重写是在子进程中进行的,这样有两个好处: 140 | 141 | - 子进程重写AOF期间,父进程可以继续处理命令请求。 142 | - 子进程带有父进程的数据副本,因为子进程不是线程,所以可以在避免使用锁的情况下保证数据安全性。 143 | 144 | 在执行重写过程中,数据库仍然会执行命令,这样可能会造成重写后的AOF文件与当前数据库状态不一致的问题,所以Redis服务器设置了一个AOF重写缓冲区,在重写过程中,Redis执行完一条写命令后,会将这条命令写入AOF缓冲区和AOF重写缓冲区。当AOF重写完成后,子进程会向父进程发送一个信号,父进程接收到信号后,会调用一个信号处理函数,将AOF重写缓冲区中的内容写入到新的AOF文件中,然后原子的覆盖旧的AOF文件。在整个AOF重写过程中,只有执行信号处理函数的时候父进程会被阻塞。 145 | 146 | 147 | 148 | ### 事件 149 | 150 | Redis服务器是一个事件驱动程序,需要处理两类事件: 151 | 152 | - 文件事件:Redis服务器通过套接字与客户端连接,文件事件就是服务器对套接字操作的抽象。 153 | - 时间事件:Redis服务器的一些操作需要在给定时间点执行,时间事件就是服务器对这类操作的抽象。 154 | 155 | #### 文件事件 156 | 157 | Redis基于Reactor模式开发了一套网络事件处理模型,即文件事件处理器。其使用IO多路复用程序同事监听多个套接字,当套接字准备好执行应答、写入、读取、关闭等操作时,会产生一个文件事件,IO多路复用程序将文件事件按顺序放入一个队列中,以有序、同步、每次一个套接字的方式向文件事件分派器传送套接字,当处理完毕后才会继续处理队列中下一个套接字。 158 | 159 | ![image-20190728134118436](assets/image-20190728134118436.png) 160 | 161 | 文件事件处理器以单线程模式运行,通过IO多路复用程序监听多个套接字,实现了高性能的网络通信模型,又可以很好地与其他同样以单线程模式运行的模块对接。 162 | 163 | ![image-20190728134308856](assets/image-20190728134308856.png) 164 | 165 | #### 时间事件 166 | 167 | Redis的时间事件分为两类: 168 | 169 | - 定时事件:让一段程序在指定时间之后执行一次。 170 | - 周期事件:让一段程序每隔一段时间执行一次。 171 | 172 | 所有时间事件都放在一个无序链表中,每当时间事件执行器运行时,就遍历整个链表,查找所有已到达的时间事件,并调用相应的事件处理器。所以时间事件的实际处理事件通常会比设定的到达时间晚一点。 173 | 174 | 文件事件和时间事件是合作关系,服务器会轮流处理这两种事件,并且处理事件过程中不会进行抢占。 175 | 176 | -------------------------------------------------------------------------------- /分布式/assets/1525529091749.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/分布式/assets/1525529091749.png -------------------------------------------------------------------------------- /分布式/assets/1525529671801.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/分布式/assets/1525529671801.png -------------------------------------------------------------------------------- /分布式/assets/1525530657919.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/分布式/assets/1525530657919.png -------------------------------------------------------------------------------- /分布式/assets/1525530804753.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/分布式/assets/1525530804753.png -------------------------------------------------------------------------------- /分布式/assets/1525532344817.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/分布式/assets/1525532344817.png -------------------------------------------------------------------------------- /分布式/assets/1526860071166.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/分布式/assets/1526860071166.png -------------------------------------------------------------------------------- /分布式/assets/image-20190730155048201.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/分布式/assets/image-20190730155048201.png -------------------------------------------------------------------------------- /分布式/assets/image-20190730155052026.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/分布式/assets/image-20190730155052026.png -------------------------------------------------------------------------------- /分布式/assets/image-20190730184938904.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/分布式/assets/image-20190730184938904.png -------------------------------------------------------------------------------- /分布式/assets/image-20190730190533235.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/分布式/assets/image-20190730190533235.png -------------------------------------------------------------------------------- /分布式/assets/image-20190730192913945.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/分布式/assets/image-20190730192913945.png -------------------------------------------------------------------------------- /分布式/assets/image-20190730193221987.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/分布式/assets/image-20190730193221987.png -------------------------------------------------------------------------------- /分布式/assets/image-20190730193408341.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/分布式/assets/image-20190730193408341.png -------------------------------------------------------------------------------- /分布式/assets/image-20190730193458258.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/分布式/assets/image-20190730193458258.png -------------------------------------------------------------------------------- /分布式/assets/image-20190730193504134.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/分布式/assets/image-20190730193504134.png -------------------------------------------------------------------------------- /分布式/assets/image-20190730193530011.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/分布式/assets/image-20190730193530011.png -------------------------------------------------------------------------------- /分布式/一致性协议.md: -------------------------------------------------------------------------------- 1 | 当一个事务跨越多个分布式节点时,为了保持事务处理的ACID特性,需要引入一个协调者组件来统一调度所有分布式节点(参与者)的执行逻辑,协调者负责调度参与者的行为,并最终决定这些参与者是否要真正进行事务提交。为了解决分布式一致性问题,诞生了二阶段提交协议、三阶段提交协议和Paxos算法。 2 | 3 | ### 2PC 4 | 5 | 2PC,即二阶段提交。为了使分布式事务处理过程中能保持原子性和一致性而设计的一种强一致性算法,分为两个阶段: 6 | 7 | #### 阶段一:提交事务请求(投票) 8 | 9 | 1. 事务询问:协调者向所有参与者发送事务内容,询问是否可以执行事务提交操作。 10 | 2. 执行事务:各参与者执行事务操作,并记录`Undo/Redo`日志。 11 | 3. 各参与者向协调者反馈事务询问的响应:如果参与者成功执行了事务操作,那么就返回`Yes`响应,表示事务可以执行;否则返回`No`响应,表示事务不可执行。 12 | 13 | #### 阶段二:执行事务提交(执行) 14 | 15 | 如果所有参与者都返回`Yes`响应,那么就会执行事务提交: 16 | 17 | 1. 协调者向参与者发送提交请求 18 | 2. 参与者接收到后提交事务 19 | 3. 参与者相协调者反馈事务提交结果 20 | 4. 完成事务 21 | 22 | 任意一个参与者返回了`No`响应或者等待超时,那么就会中断事务: 23 | 24 | 1. 协调者向参与者发送回滚请求 25 | 2. 参与者接收到后回滚事务 26 | 3. 参与者相协调者反馈事务回滚结果 27 | 4. 中断事务 28 | 29 | #### 优点 30 | 31 | 原理简单、实现方便。 32 | 33 | #### 缺点 34 | 35 | 同步阻塞、单点问题、数据不一致(可能只有部分参与者接收到了`Commit`请求)、太过保守(没有较完善的容错机制)。 36 | 37 | ### 3PC 38 | 39 | 是2PC的改进版,将2PC的投票阶段一分为二,形成了`CanCommit`、`PreCommit`和`doCpmmit`三个阶段: 40 | 41 | #### 阶段一:CanCommit 42 | 43 | 1. 事务询问:协调者询问参与者时候否可以执行事务提交操作。 44 | 2. 各参与者向协调者反馈事务询问的响应。 45 | 46 | #### 阶段二:PreCommit 47 | 48 | 如果所有参与者都返回`Yes`响应,那么就会执行事务预提交: 49 | 50 | 1. 发送预提交请求:协调者向所有参与者发送preCommit请求 51 | 2. 执行事务:各参与者执行事务操作,并记录`Undo/Redo`日志。 52 | 3. 各参与者向协调者反馈事务询问的响应:如果参与者成功执行了事务操作,那么就返回`ACK`响应,表示事务可以执行。 53 | 54 | 任意一个参与者返回了`No`响应或者等待超时,那么就会中断事务。 55 | 56 | #### 阶段三:doCommit 57 | 58 | 如果协调者发送了preCommit请求,并且接收到了所有参与者的`ACK`响应,那么就会执行事务提交: 59 | 60 | 1. 协调者向参与者发送提交请求 61 | 2. 参与者接收到后提交事务 62 | 3. 参与者相协调者反馈事务提交结果 63 | 4. 完成事务 64 | 65 | 否则: 66 | 67 | 1. 协调者向参与者发送回滚请求 68 | 2. 参与者接收到后回滚事务 69 | 3. 参与者相协调者反馈事务回滚结果 70 | 4. 中断事务 71 | 72 | 值得注意的是,一旦进入阶段三,当协调者与接收者之间无法通信时,参与者会在等待超时之后继续进行事务提交。 73 | 74 | #### 优点 75 | 76 | 相比2PC,降低了参与者的阻塞范围,并且能在在出现单点故障后继续达成一致。 77 | 78 | #### 缺点 79 | 80 | 如果某个参与者预提交事务失败,之后协调者和参与者无法通信,超时后参与者会提交事务,这必然会造成数据不一致。 81 | 82 | ### Paxos算法 83 | 84 | Paxos是一种分布式一致性算法。在多个节点中,每个节点可能都有一个值,并且这个值不一定相同,Paxos的作用就是选出一个值,并让所有节点接受这个值。 85 | 86 | 在Paxos算法中,节点一个有三种角色:`Proposer(提议者)`、`Acceptor(接受者)`、`Learner(告知者)`,并且每台机器可能拥有其中不止一种角色。 87 | 88 | **Paxos算法分为两个阶段:** 89 | 90 | 1. `Proposer`向过半`Acceptor`节点发送提案为`[Mn, Vn]`的`Prepare`请求,其中`Mn`为提案编号,`Vn`为提案值。`Acceptor`接收到`Proposer`的`Prepare`请求,此时可能会有两种情况: 91 | - 该`Acceptor`还未接受过`Prepare`请求,那么此时将会接受该请求,并更新自身状态为`[Mn, Vn]`,并将`[Mn, Vn]`作为`Prepare`请求响应反馈给`Proposer`,并且承诺不会再接受任何编号比`Mn`小的请求。 92 | 93 | - 该`Acceptor`已经接受过`Prepare`请求,此时有会有两种情况: 94 | - `Mn`小于之前接受过最大的请求编号,忽略该请求。 95 | - `Mn`大于等于之前接受过最大的请求编号`Mp`,更新当前状态为`[Mn, Vn]`,并将`[Mp, Vp]`作为`Prepare`请求响应反馈给`Proposer`,并且承诺不会再接受任何编号比`Mn`小的请求。 96 | 97 | 2. 如果`Proposer`接收到半数以上`Acceptor`对其发出的提案`[Mn, Vn]`的`Prepare`请求的响应,那么就会向`Acceptor`发出一个提案为`[Mn, Vx]`的`Accept`请求,其中`Vx`为其接收到的`Prepare`请求响应中编号最大的提案的值(如果响应中不包含任意提案,那么就为任意值)。`Acceptor`接收到的`Accept`请求中,如果提案编号`Mn`不小于其承诺的最小编号,并且当前`Acceptor`没有通过任何编号大于`Mn`的`Accept`请求,那么就会通过这个`Accept`请求。如果有半数以上`Acceptor`通过了某个提案,那么就会告知部分`Learner`,再由这部分`Learner`同步给其他所有`Learner`通过的结果。 98 | 99 | ### Raft算法 100 | 101 | 由于paxos算法过于繁杂,诞生了raft算法,raft是工程上使用较为广泛的强一致性、去中心化、高可用的分布式协议。Raft一致性算法就是比Paxos简单又能实现Paxos所解决的问题的一致性算法。 102 | 103 | #### Raft概述 104 | 105 | ##### 角色 106 | 107 | Raft把集群中的节点分为三种状态:Leader、 Follower 、Candidate,每种状态负责的任务不一样,Raft运行时提供服务的时候只存在Leader与Follower两种状态。 108 | 109 | - Leader(领导者):负责日志的同步管理,处理来自客户端的请求,与Follower保持着`heartBeat`联系。 110 | - Follower(追随者):刚启动时所有节点为Follower状态,响应Leader的日志同步请求,响应Candidate的请求,把请求到Follower的事务转发给Leader。 111 | - Candidate(候选者):负责选举投票,Raft刚启动时由一个节点heartBeat等待超时后,从Follower转为Candidate发起选举,选举出Leader后从Candidate转为Leader状态。 112 | 113 | #### Term 114 | 115 | 在Raft中使用了一个可以理解为纪元的概念,用Term作为一个纪元,每个Term都是一个连续递增的编号,每一轮选举都是一个Term纪元,在一个Term中只能产生一个Leader。Raft开始时所有Follower的Term为1,其中一个Follower逻辑时钟到期后转换为Candidate,Term加1,这时Term为2,然后开始选举,这时候有几种情况会使Term发生改变: 116 | 117 | - 如果当前Term为2的任期内没有选举出Leader或出现异常,则Term递增,开始新一任期选举 118 | - 当这轮Term为2的周期选举出Leader后,过后Leader宕掉了,然后其他Follower转为Candidate,Term递增,开始新一任期选举 119 | - 当Leader或Candidate发现自己的Term比别的Follower小时Leader或Candidate将转为Follower,Term递增 120 | - 当Follower的Term比别的Term小时,Follower也将更新Term保持与其他Follower一致 121 | 122 | 可以说每次Term的递增都将发生新一轮的选举,Raft保证一个Term只有一个Leader,在Raft正常运转中所有的节点的Term都是一致的,如果节点不发生故障一个Term会一直保持下去,当某节点收到的请求中Term比当前Term小时则拒绝该请求。 123 | 124 | #### 选举(Election) 125 | 126 | Raft的选举由定时器来触发,每个节点的选举定时器时间都是不一样的,开始时状态都为Follower。某个节点定时器触发选举后Term递增,状态由Follower转为Candidate,向其他节点发起RequestVote RPC请求,这时候有三种可能的情况发生: 127 | 128 | - 该RequestVote请求接收到过半数个节点的投票,从Candidate转为Leader,向其他节点发送heartBeat以保持Leader的正常运转 129 | - 在此期间如果收到其他节点发送过来的AppendEntries RPC请求,如该节点的Term大则当前节点转为Follower,否则保持Candidate拒绝该请求 130 | - Election timeout发生则Term递增,重新发起选举 131 | 132 | 在一个Term期间每个节点只能投票一次,所以当有多个Candidate存在时就会出现每个Candidate发起的选举都存在接收到的投票数都不过半的问题,这时每个Candidate都将Term递增、重启定时器并重新发起选举,由于每个节点中定时器的时间都是随机的,所以就不会多次存在有多个Candidate同时发起投票的问题。 133 | 有这么几种情况会发起选举: 134 | 135 | 1. Raft初次启动,不存在Leader,发起选举 136 | 2. Leader宕机或Follower没有接收到Leader的heartBeat,发生election timeout从而发起选举; 137 | 138 | #### 日志复制(Log Replication) 139 | 140 | 日志复制主要作用是用于保证节点的一致性,这阶段所做的操作也是为了保证一致性与高可用性;当Leader选举出来后便开始负责客户端的请求,所有事务(更新操作)请求都必须先经过Leader处理,要保证节点的一致性就要保证每个节点都按顺序执行相同的操作序列,日志复制就是为了保证执行相同的操作序列所做的工作;在Raft中当接收到客户端的日志后先把该日志追加到本地的Log中,然后通过heartbeat把该Entry同步给其他Follower,Follower接收到日志后记录日志然后向Leader发送ACK,当Leader收到大多数Follower的ACK信息后将该日志设置为已提交并追加到本地磁盘中,通知客户端并在下个heartbeat中Leader将通知所有的Follower将该日志存储在自己的本地磁盘中。 141 | 142 | #### 安全性(Safety) 143 | 144 | 安全性是用于保证每个节点都执行相同序列的安全机制,如当某个Follower在当前Leader commit Log时变得不可用了,稍后可能该Follower又会倍选举为Leader,这时新Leader可能会用新的Log覆盖先前已committed的Log,这就是导致节点执行不同序列。Safety就是用于保证选举出来的Leader一定包含先前 commited Log的机制。 145 | 146 | 147 | 148 | ### 参考资料 149 | 150 | - 《从Paxos到Zookeeper》 151 | 152 | - [raft动图](http://thesecretlivesofdata.com/raft/) -------------------------------------------------------------------------------- /分布式/分布式架构.md: -------------------------------------------------------------------------------- 1 | 从集中式到分布式 2 | 3 | 大型机虽然在性能和稳定性方面有卓越表现,但是其具有集中式系统的单点问题,并且扩展性非常差。随着小型机性能的不断提升和网络技术的快速发展,越来越多的人改用了小型机来搭建分布式系统。 4 | 5 | #### 分布式系统 6 | 7 | 分布式系统是一个硬件或软件组件分布在不同的网络计算机上,彼此之间通过消息传递进行通信和协调的系统。 8 | 9 | 没有任何业务逻辑约束的分布式系统的特点: 10 | 11 | - 分布性:分布式系统中的多台机器会在空间上随意分布。 12 | - 对等性:各机器没有主从之分。 13 | - 并发性:多个节点可能会进行并发操作。 14 | - 缺乏全局时钟:分布式系统中缺乏一个全局的时钟序列控制。 15 | - 故障总是会发生:一个被大量工程实践所检验过的黄金定理:任何在设计阶段考虑到的异常情况,一定会在系统实际运行中发送,并且实际运行中还会遇到很多未考虑到的异常故障。 16 | 17 | #### 分布式系统的问题 18 | 19 | - 通信异常 20 | 21 | - 网络分区,即脑裂。(由于网络异常导致只有部分节点能够进行正常通信,会出现局部小集群等问题) 22 | 23 | - 三态:分布式系统的每一次请求与响应会存在三种结果:成功、失败、超时。 24 | 25 | - 节点故障:分布式节点可能会出现宕机等故障。 26 | 27 | #### 事务的ACID特性 28 | 29 | 事务是由一系列对系统中数据进行访问与更新操作所组成的一个程序执行逻辑单元。其具有四个特性: 30 | 31 | - 原子性:一个事务中的操作要么全部执行要么全部不执行。 32 | - 一致性:事务执行的结果必须是使数据库从一个一致性状态转变到另一个一致性状态。 33 | - 隔离性:并发的事务是相互隔离的,相互之间不能干扰。 34 | - 持久性:事务一旦被提交,对数据库状态的变更就是永久的。 35 | 36 | #### 分布式事务 37 | 38 | 在单机系统中,很容易实现一套满足ACID特性的事务处理系统。但是在分布式系统中,数据分散在不同的机器上分布式事务中的各个子事务的执行是分布式的,因此分布式的事务处理会碰到很多问题。 39 | 40 | #### CAP定理 41 | 42 | 一个分布式系统不可能同时满足**一致性**、**可用性**、**分区容错性**这三个基本需求,最多只能同时满足其中两种。 43 | 44 | - 一致性 45 | 46 | 一个多副本的系统在数据一致性的状态下执行了更新操作后,应该保证系统的数据仍然处于一致性状态。 47 | 48 | - 可用性 49 | 50 | 系统提供的服务必须一直处于可用状态,即对于用户的每一个操作请求总是在有限时间内返回结果。 51 | 52 | - 分区容错性 53 | 54 | 分布式系统在遇到任何网络分区故障的时候,仍然需要能够保证对外提供满足一致性和可用性的服务,除非是整个网络都发生了故障。 55 | 56 | ![image-20190730155052026](assets/image-20190730155052026.png) 57 | 58 | 59 | 60 | 对于一个分布式系统而言,分区容错性是最基本的要求。因此架构师们往往把精力花在如何根据业务特点在一致性和可用性之间寻求平衡。 61 | 62 | #### BASE理论 63 | 64 | 即使无法做到强一致性,但是每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性。 65 | 66 | BASE理论三要素: 67 | 68 | - 基本可用:分布式系统在出现不可预知故障的时候,允许损失部分可用性。 69 | - 响应时间上的损失:可以慢一点。 70 | - 功能上损失:请求高峰期间可以进行服务降级。 71 | - 弱状态:允许系统在不同的数据副本之间进行数据同步的过程存在延时。 72 | - 最终一致性:系统中所有的数据副本,在经过一段时间的同步后,最终能达到一个一致性状态。 73 | 74 | 最终一致性的五类主要变种: 75 | 76 | - 因果一致性:进程A在更新完某个数据项后通知了进程B,那么之后进程B之后访问该数据项得到的都是A更新后的最新值。 77 | - 读己之所写:进程A更新了一个数据项后,它自己总是能够访问到更新过的最新值。 78 | - 会话一致性:执行完更新操作后,客户始终能够在一个会话中读取到该数据的最新值。 79 | - 单调读一致性:进程A读取到一个数据项的某个值后,都不会再读取到旧值。 80 | - 单调写一致性:系统能够保证来自一个进程的写操作被顺序执行。 81 | 82 | 83 | 84 | ### 参考资料 85 | 86 | - 《从Paxos到Zookeeper》 87 | 88 | -------------------------------------------------------------------------------- /分布式/微服务.md: -------------------------------------------------------------------------------- 1 | ### 系统架构演变 2 | 3 | 随着互联网的发展,网站应用的规模不断扩大。需求的激增,带来的是技术上的压力。系统架构也因此也不断的演进、升级、迭代。从单一应用,到垂直拆分,分布式服务,SOA,再到现在火热的微服务架构。 4 | 5 | #### 集中式架构 6 | 7 | 当系统流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。 8 | 9 | ![img](assets/1525529091749.png) 10 | 11 | 存在的问题: 12 | 13 | - 代码耦合,开发维护困难 14 | - 无法针对不同模块进行针对性优化 15 | - 无法水平扩展 16 | - 单点容错率低,并发能力差 17 | 18 | 19 | 20 | #### 垂直拆分 21 | 22 | 当访问量逐渐增大,单一应用无法满足需求,为了应对高并发和业务需求,需要根据业务功能对系统进行拆分: 23 | 24 | ![img](assets/1525529671801.png) 25 | 26 | 优点: 27 | 28 | - 系统拆分实现了流量分担,解决了并发问题 29 | - 可以针对不同模块进行优化 30 | - 方便水平扩展,负载均衡,容错率提高 31 | 32 | 缺点: 33 | 34 | - 系统间相互独立,会有很多重复开发工作,影响开发效率 35 | 36 | 37 | 38 | #### 分布式服务 39 | 40 | 当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式调用是关键。 41 | 42 | ![img](assets/1525530657919.png) 43 | 44 | 优点: 45 | 46 | - 将基础服务进行了抽取,系统间相互调用,提高了代码复用和开发效率 47 | 48 | 缺点: 49 | 50 | - 系统间耦合度变高,调用关系错综复杂,难以维护 51 | 52 | 53 | 54 | #### 服务治理(SOA) 55 | 56 | 当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键 57 | 58 | ![img](assets/1525530804753.png) 59 | 60 | 以前出现的问题 61 | 62 | - 服务越来越多,需要管理每个服务的地址 63 | - 调用关系错综复杂,难以理清依赖关系 64 | - 服务过多,服务状态难以管理,无法根据服务情况动态管理 65 | 66 | 服务治理的任务 67 | 68 | - 服务注册中心,实现服务自动注册和发现,无需人为记录服务地址 69 | - 服务自动订阅,服务列表自动推送,服务调用透明化,无需关心依赖关系 70 | - 动态监控服务状态监控报告,人为控制服务状态 71 | 72 | 缺点: 73 | 74 | - 服务间会有依赖关系,一旦某个环节出错会影响较大 75 | - 服务关系复杂,运维、测试部署困难,不符合DevOps思想 76 | 77 | ## 1.5.微服务 78 | 79 | 前面说的SOA,英文翻译过来是面向服务。微服务,似乎也是服务,都是对系统进行拆分。因此两者非常容易混淆,但其实缺有一些差别: 80 | 81 | ![img](assets/1525532344817.png) 82 | 83 | 微服务的特点: 84 | 85 | - 单一职责:微服务中每一个服务都对应唯一的业务能力,做到单一职责 86 | - 微:微服务的服务拆分粒度很小。 87 | - 面向服务:面向服务是说每个服务都要对外暴露服务接口API。并不关心服务的技术实现,做到与平台和语言无关,也不限定用什么技术实现,只要提供Rest的接口即可。 88 | - 自治:自治是说服务间互相独立,互不干扰 89 | - 团队独立:每个服务都是一个独立的开发团队,人数不能过多。 90 | - 技术独立:因为是面向服务,提供Rest接口,使用什么技术没有别人干涉 91 | - 前后端分离:采用前后端分离开发,提供统一Rest接口,后端不用再为PC、移动段开发不同接口 92 | - 数据库分离:每个服务都使用自己的数据源 93 | - 部署独立,服务间虽然有调用,但要做到服务重启不影响其它服务。有利于持续集成和持续交付。每个服务都是独立的组件,可复用,可替换,降低耦合,易维护 94 | 95 | 微服务结构图: 96 | 97 | ![img](assets/1526860071166.png) 98 | 99 | ### 谈谈对微服务的理解 100 | 101 | 1. 微服务很小,以业务边界确定系统边界,每个服务专注于做好一件事情。 102 | 2. 微服务具有自治性,服务之间通过暴露API实现网络通信,服务高度内聚可单独部署,互不影响。 103 | 104 | ### 微服务的好处 105 | 106 | 1. 技术的异构性:根据服务需求选择合适的技术实现。 107 | 2. 提升效率:小型代码在小型团队更为高效,接口约束后,可以并行开发。 108 | 3. 弹性:微服务中如果一个服务不可用了,不会导致整个应用都不可用。 109 | 4. 易扩容:可以只对需要扩容的服务进行扩容,降低成本。 110 | 5. 可组合性:可以根据不同的目的,通过不同的方式使用同一个功能。 111 | 6. 简化部署:各服务的部署时独立的,当部分代码发生变更后,只需要重新部署对应的服务。 112 | 7. 降低风险:重写或者移除小规模服务阻碍很小。 113 | 114 | ### 微服务架构的不足 115 | 116 | - 运维要求较高 117 | - 对于单体架构来讲,只需要维护好这一个项目就可以了。但是对于微服务架构来讲,由于项目是由多个微服务构成的,每个模块出现问题都会造成整个项目运行出现异常,这就对运维人员提出了很高的要求。 118 | - 分布式的复杂性 119 | - 对于微服务架构来说,分布式是必需的技术,由于分布式的复杂性,导致微服务架构也变得复杂起来。 120 | 121 | - 接口调整成本高 122 | - 微服务的接口发生大的变动时,所有依赖它的微服务可能都要做相应的调整,由于微服务可能非常多,那么调整接口所造成的成本将会明显提高。 123 | 124 | - 重复劳动 125 | - 对于单体架构来讲,如果某段业务被多个模块所共同使用,我们可以抽象成一个工具类,被所有模块直接调用。但是微服务的工具类是不能被其它微服务所直接调用的,从而我们便不得不在每个微服务上都建这么一个工具类,从而导致代码的重复。 126 | 127 | ### HTTP调用和RPC调用的比较 128 | 129 | 在HTTP和RPC的选择上,有些人是迷惑的。有些RPC框架配置复杂,用HTTP也能完成同样的功能,为什么要选择RPC,而不是更容易上手的HTTP来实现了。 130 | 131 | **比较一下:** 132 | 133 | - 传输协议 134 | - RPC:可以基于TCP协议,也可以基于HTTP协议。 135 | - HTTP:基于HTTP协议。 136 | 137 | - 传输效率 138 | - RPC:使用自定义的TCP协议,可以让请求报文体积更小,或者使用HTTP2协议,也可以很好的减少报文的体积,提高传输效率。 139 | - HTTP:如果是基于HTTP1.1的协议,请求中会包含很多无用的内容,如果是基于HTTP2.0,那么简单的封装以下是可以作为一个RPC来使用的,这时标准RPC框架更多的是服务治理。 140 | - 性能消耗(主要在于序列化和反序列化的耗时) 141 | - RPC:可以基于thrift实现高效的二进制传输 142 | - HTTP:大部分是通过json来实现的,字节大小和序列化耗时都比thrift要更消耗性能 143 | - 灵活性 144 | - HTTP:不关心实现细节,跨平台、跨语言 145 | - RPC:部分不支持跨平台、跨预言 146 | 147 | RPC主要用于公司内部的服务调用,性能消耗低,传输效率高,服务治理方便。 148 | 149 | HTTP主要用于对外的异构环境,浏览器接口调用,APP接口调用,第三方接口调用等。 150 | 151 | ### 微服务部署策略 152 | 153 | 微服务应用程序由数十甚至上百个服务组成。服务以不同的语言和框架编写。每个都是一个迷你的应用程序,具有自己特定的部署、资源、扩展和监视要求。需要根据该服务的需求运行每个服务的一定数量的实例。此外,必须为每个服务实例提供相应的 CPU、内存和 I/O 资源。 154 | 155 | 156 | 157 | ### 参考资料 158 | 159 | - 《微服务设计》 160 | 161 | -------------------------------------------------------------------------------- /掘金Mysql小册精简/01.重新认识Mysql.md: -------------------------------------------------------------------------------- 1 | ### MySQL的使用过程 2 | 3 | 1. 启动`MySQL`服务器程序。 4 | 2. 启动`MySQL`客户端程序并连接到服务器程序。 5 | 3. 在客户端程序中输入一些命令语句作为请求发送到服务器程序,服务器程序收到这些请求后,会根据请求的内容来操作具体的数据并向客户端返回操作结果。 6 | 7 | 我们的`MySQL`服务器程序和客户端程序本质上都算是计算机上的一个`进程`,这个代表着`MySQL`服务器程序的进程也被称为`MySQL数据库实例`,简称`数据库实例`。 8 | 9 | 每个进程都有一个唯一的编号,称为`进程ID`,英文名叫`PID`,这个编号是在我们启动程序的时候由操作系统随机分配的,操作系统会保证在某一时刻同一台机器上的进程号不重复。每个进程都有一个名称,这个名称是编写程序的人自己定义的,比如我们启动的`MySQL`服务器进程的默认名称为`mysqld`, 而我们常用的`MySQL`客户端进程的默认名称为`mysql`。 10 | 11 | ### 服务器处理客户端请求 12 | 13 | 其实不论客户端进程和服务器进程是采用哪种方式进行通信,最后实现的效果都是:客户端进程向服务器进程发送一段文本(MySQL语句),服务器进程处理后再向客户端进程发送一段文本(处理结果)。那服务器进程对客户端进程发送的请求做了什么处理,才能产生最后的处理结果呢?客户端可以向服务器发送增删改查各类请求,我们这里以比较复杂的查询请求为例来画个图展示一下大致的过程: 14 | 15 | ![image-20190710142826837](assets/image-20190710142826837.png) 16 | 17 | 从图中我们可以看出,服务器程序处理来自客户端的查询请求大致需要经过三个部分,分别是`连接管理`、`解析与优化`、`存储引擎`。下边我们来详细看一下这三个部分都干了什么。 18 | 19 | ### 连接管理 20 | 21 | 客户端进程可以采用`TCP/IP`、`命名管道或共享内存`、`Unix域套接字`这几种方式之一来与服务器进程建立连接,每当有一个客户端进程连接到服务器进程时,服务器进程都会创建一个线程来专门处理与这个客户端的交互,当该客户端退出时会与服务器断开连接,服务器并不会立即把与该客户端交互的线程销毁掉,而是把它缓存起来,在另一个新的客户端再进行连接时,把这个缓存的线程分配给该新客户端。这样就起到了不频繁创建和销毁线程的效果,从而节省开销。从这一点大家也能看出,`MySQL`服务器会为每一个连接进来的客户端分配一个线程,但是线程分配的太多了会严重影响系统性能,所以我们也需要限制一下可以同时连接到服务器的客户端数量,至于怎么限制我们后边再说哈~ 22 | 23 | 在客户端程序发起连接的时候,需要携带主机信息、用户名、密码,服务器程序会对客户端程序提供的这些信息进行认证,如果认证失败,服务器程序会拒绝连接。另外,如果客户端程序和服务器程序不运行在一台计算机上,我们还可以采用使用了`SSL`(安全套接字)的网络连接进行通信,来保证数据传输的安全性。 24 | 25 | 当连接建立后,与该客户端关联的服务器线程会一直等待客户端发送过来的请求,`MySQL`服务器接收到的请求只是一个文本消息,该文本消息还要经过各种处理,预知后事如何,继续往下看哈~ 26 | 27 | ### 解析与优化 28 | 29 | 到现在为止,`MySQL`服务器已经获得了文本形式的请求,接着 还要经过九九八十一难的处理,其中的几个比较重要的部分分别是`查询缓存`、`语法解析`和`查询优化`,下边我们详细来看。 30 | 31 | #### 查询缓存 32 | 33 | `MySQL`服务器程序处理查询请求的过程中,会把刚刚处理过的查询请求和结果`缓存`起来,如果下一次有一模一样的请求过来,直接从缓存中查找结果就好了,就不用再傻呵呵的去底层的表中查找了。这个查询缓存可以在不同客户端之间共享,也就是说如果客户端A刚刚查询了一个语句,而客户端B之后发送了同样的查询请求,那么客户端B的这次查询就可以直接使用查询缓存中的数据。 34 | 35 | 当然,`MySQL`服务器并没有人聪明,如果两个查询请求在任何字符上的不同(例如:空格、注释、大小写),都会导致缓存不会命中。另外,如果查询请求中包含某些系统函数、用户自定义变量和函数、一些系统表,如 mysql 、information_schema、 performance_schema 数据库中的表,那这个请求就不会被缓存。 36 | 37 | 不过既然是缓存,那就有它缓存失效的时候。MySQL的缓存系统会监测涉及到的每张表,只要该表的结构或者数据被修改,如对该表使用了`INSERT`、 `UPDATE`、`DELETE`、`TRUNCATE TABLE`、`ALTER TABLE`、`DROP TABLE`或 `DROP DATABASE`语句,那使用该表的所有高速缓存查询都将变为无效并从高速缓存中删除! 38 | 39 | > 小贴士: 虽然查询缓存有时可以提升系统性能,但也不得不因维护这块缓存而造成一些开销,比如每次都要去查询缓存中检索,查询请求处理完需要更新查询缓存,维护该查询缓存对应的内存区域。从MySQL 5.7.20开始,不推荐使用查询缓存,并在MySQL 8.0中删除。 40 | 41 | #### 语法解析 42 | 43 | 如果查询缓存没有命中,接下来就需要进入正式的查询阶段了。因为客户端程序发送过来的请求只是一段文本而已,所以`MySQL`服务器程序首先要对这段文本做分析,判断请求的语法是否正确,然后从文本中将要查询的表、各种查询条件都提取出来放到`MySQL`服务器内部使用的一些数据结构上来。 44 | 45 | #### 查询优化 46 | 47 | 语法解析之后,服务器程序获得到了需要的信息,比如要查询的列是哪些,表是哪个,搜索条件是什么等等,但光有这些是不够的,因为我们写的`MySQL`语句执行起来效率可能并不是很高,`MySQL`的优化程序会对我们的语句做一些优化,如外连接转换为内连接、表达式简化、子查询转为连接吧啦吧啦的一堆东西。优化的结果就是生成一个执行计划,这个执行计划表明了应该使用哪些索引进行查询,表之间的连接顺序是啥样的。我们可以使用`EXPLAIN`语句来查看某个语句的执行计划。 48 | 49 | ### 存储引擎 50 | 51 | `MySQL`服务器把数据的存储和提取操作都封装到了一个叫`存储引擎`的模块里。我们知道`表`是由一行一行的记录组成的,但这只是一个逻辑上的概念,物理上如何表示记录,怎么从表中读取数据,怎么把数据写入具体的物理存储器上,这都是`存储引擎`负责的事情。不同`存储引擎`管理的表具体的存储结构可能不同,采用的存取算法也可能不同。 52 | 53 | 为了管理方便,人们把`连接管理`、`查询缓存`、`语法解析`、`查询优化`这些并不涉及真实数据存储的功能划分为`MySQL server`的功能,把真实存取数据的功能划分为`存储引擎`的功能。各种不同的存储引擎向上边的`MySQL server`层提供统一的调用接口(也就是存储引擎API)。所以在`MySQL server`完成了查询优化后,只需按照生成的执行计划调用底层存储引擎提供的API,获取到数据后返回给客户端就好了。 54 | 55 | ### 常用存储引擎 56 | 57 | `MySQL`支持非常多种存储引擎,我这先列举一些: 58 | 59 | | 存储引擎 | 描述 | 60 | | :---------: | :----------------------------------: | 61 | | `ARCHIVE` | 用于数据存档(行被插入后不能再修改) | 62 | | `BLACKHOLE` | 丢弃写操作,读操作会返回空内容 | 63 | | `CSV` | 在存储数据时,以逗号分隔各个数据项 | 64 | | `FEDERATED` | 用来访问远程表 | 65 | | `InnoDB` | 具备外键支持功能的事务存储引擎 | 66 | | `MEMORY` | 置于内存的表 | 67 | | `MERGE` | 用来管理多个MyISAM表构成的表集合 | 68 | | `MyISAM` | 主要的非事务处理存储引擎 | 69 | | `NDB` | MySQL集群专用存储引擎 | 70 | 71 | -------------------------------------------------------------------------------- /掘金Mysql小册精简/02.字符集与比较规则.md: -------------------------------------------------------------------------------- 1 | ## MySQL中支持的字符集和比较规则 2 | 3 | ### MySQL中的utf8和utf8mb4 4 | 5 | `utf8`字符集表示一个字符需要使用1~4个字节,但是我们常用的一些字符使用1~3个字节就可以表示了。而在`MySQL`中字符集表示一个字符所用最大字节长度在某些方面会影响系统的存储和性能,所以设计`MySQL`的大叔偷偷的定义了两个概念: 6 | 7 | - `utf8mb3`:阉割过的`utf8`字符集,只使用1~3个字节表示字符。 8 | - `utf8mb4`:正宗的`utf8`字符集,使用1~4个字节表示字符。 9 | 10 | 有一点需要大家十分的注意,在`MySQL`中`utf8`是`utf8mb3`的别名,所以之后在`MySQL`中提到`utf8`就意味着使用1~3个字节来表示一个字符,如果大家有使用4字节编码一个字符的情况,比如存储一些emoji表情啥的,那请使用`utf8mb4`。 11 | 12 | ## 字符集和比较规则的应用 13 | 14 | ### 各级别的字符集和比较规则 15 | 16 | `MySQL`有4个级别的字符集和比较规则,分别是: 17 | 18 | - 服务器级别 19 | - 数据库级别 20 | - 表级别 21 | - 列级别 22 | 23 | 这4个级别字符集和比较规则的联系如下: 24 | 25 | - 如果创建或修改列时没有显式的指定字符集和比较规则,则该列默认用表的字符集和比较规则 26 | - 如果创建或修改表时没有显式的指定字符集和比较规则,则该表默认用数据库的字符集和比较规则 27 | - 如果创建或修改数据库时没有显式的指定字符集和比较规则,则该数据库默认用服务器的字符集和比较规则 28 | 29 | #### 仅修改字符集或仅修改比较规则 30 | 31 | 由于字符集和比较规则是互相有联系的,如果我们只修改了字符集,比较规则也会跟着变化,如果只修改了比较规则,字符集也会跟着变化,具体规则如下: 32 | 33 | - 只修改字符集,则比较规则将变为修改后的字符集默认的比较规则。 34 | - 只修改比较规则,则字符集将变为修改后的比较规则对应的字符集。 35 | 36 | ### 客户端和服务器通信中的字符集 37 | 38 | #### 字符集转换的概念 39 | 40 | 如果接收`0xE68891`这个字节串的程序按照`utf8`字符集进行解码,然后又把它按照`gbk`字符集进行编码,最后编码后的字节串就是`0xCED2`,我们把这个过程称为`字符集的转换`,也就是字符串`'我'`从`utf8`字符集转换为`gbk`字符集。 41 | 42 | #### MySQL中字符集的转换 43 | 44 | 我们知道从客户端发往服务器的请求本质上就是一个字符串,服务器向客户端返回的结果本质上也是一个字符串,而字符串其实是使用某种字符集编码的二进制数据。这个字符串可不是使用一种字符集的编码方式一条道走到黑的,从发送请求到返回结果这个过程中伴随着多次字符集的转换,在这个过程中会用到3个系统变量,我们先把它们写出来看一下: 45 | 46 | | 系统变量 | 描述 | 47 | | :------------------------: | :----------------------------------------------------------: | 48 | | `character_set_client` | 服务器解码请求时使用的字符集 | 49 | | `character_set_connection` | 服务器处理请求时会把请求字符串从`character_set_client`转为`character_set_connection` | 50 | | `character_set_results` | 服务器向客户端返回数据时使用的字符集 | 51 | 52 | 53 | 54 | 这几个系统变量的默认值都是`utf8`,为了体现出字符集在请求处理过程中的变化,我们这里特意修改一个系统变量的值: 55 | 56 | ``` 57 | mysql> set character_set_connection = gbk; 58 | Query OK, 0 rows affected (0.00 sec) 59 | ``` 60 | 61 | 所以现在系统变量`character_set_client`和`character_set_results`的值还是`utf8`,而`character_set_connection`的值为`gbk`。现在假设我们客户端发送的请求是下边这个字符串: 62 | 63 | ``` 64 | SELECT * FROM t WHERE s = '我'; 65 | ``` 66 | 67 | 为了方便大家理解这个过程,我们只分析字符`'我'`在这个过程中字符集的转换。 68 | 69 | 现在看一下在请求从发送到结果返回过程中字符集的变化: 70 | 71 | ![image-20190710151542780](assets/image-20190710151542780.png) 72 | 73 | 我们通常都把 ***character_set_client*** 、***character_set_connection***、***character_set_results*** 这三个系统变量设置成和客户端使用的字符集一致的情况,这样减少了很多无谓的字符集转换。 74 | 75 | ## 总结 76 | 77 | 1. `字符集`指的是某个字符范围的编码规则。 78 | 79 | 2. `比较规则`是针对某个字符集中的字符比较大小的一种规则。 80 | 81 | 3. 在`MySQL`中,一个字符集可以有若干种比较规则,其中有一个默认的比较规则,一个比较规则必须对应一个字符集。 82 | 83 | 4. 查看`MySQL`中查看支持的字符集和比较规则的语句如下: 84 | 85 | ``` 86 | SHOW (CHARACTER SET|CHARSET) [LIKE 匹配的模式]; 87 | SHOW COLLATION [LIKE 匹配的模式]; 88 | ``` 89 | 90 | 5. MySQL有四个级别的字符集和比较规则 91 | 92 | - 服务器级别 93 | 94 | `character_set_server`表示服务器级别的字符集,`collation_server`表示服务器级别的比较规则。 95 | 96 | - 数据库级别 97 | 98 | 创建和修改数据库时可以指定字符集和比较规则: 99 | 100 | ``` 101 | CREATE DATABASE 数据库名 102 | [[DEFAULT] CHARACTER SET 字符集名称] 103 | [[DEFAULT] COLLATE 比较规则名称]; 104 | 105 | ALTER DATABASE 数据库名 106 | [[DEFAULT] CHARACTER SET 字符集名称] 107 | [[DEFAULT] COLLATE 比较规则名称]; 108 | ``` 109 | 110 | `character_set_database`表示当前数据库的字符集,`collation_database`表示当前默认数据库的比较规则,这两个系统变量是只读的,不能修改。如果没有指定当前默认数据库,则变量与相应的服务器级系统变量具有相同的值。 111 | 112 | - 表级别 113 | 114 | 创建和修改表的时候指定表的字符集和比较规则: 115 | 116 | ``` 117 | CREATE TABLE 表名 (列的信息) 118 | [[DEFAULT] CHARACTER SET 字符集名称] 119 | [COLLATE 比较规则名称]]; 120 | 121 | ALTER TABLE 表名 122 | [[DEFAULT] CHARACTER SET 字符集名称] 123 | [COLLATE 比较规则名称]; 124 | ``` 125 | 126 | - 列级别 127 | 128 | 创建和修改列定义的时候可以指定该列的字符集和比较规则: 129 | 130 | ``` 131 | CREATE TABLE 表名( 132 | 列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称], 133 | 其他列... 134 | ); 135 | 136 | ALTER TABLE 表名 MODIFY 列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称]; 137 | ``` 138 | 139 | 1. 从发送请求到接收结果过程中发生的字符集转换: 140 | 2. 比较规则的作用通常体现比较字符串大小的表达式以及对某个字符串列进行排序中。 -------------------------------------------------------------------------------- /掘金Mysql小册精简/07.Mysql目录结构.md: -------------------------------------------------------------------------------- 1 | ## MySQL数据目录 2 | 3 | MySQL服务器程序在启动时会到文件系统的某个目录下加载一些文件,之后在运行过程中产生的数据也都会存储到这个目录下的某些文件中,这个目录就称为`数据目录`,我们下边就要详细唠唠这个目录下具体都有哪些重要的东西。 4 | 5 | ### 如何确定MySQL中的数据目录 6 | 7 | `数据目录`对应着一个系统变量`datadir`,我们在使用客户端与服务器建立连接之后查看这个系统变量的值就可以了: 8 | 9 | ```mysql 10 | mysql> SHOW VARIABLES LIKE 'datadir'; 11 | +---------------+-----------------------+ 12 | | Variable_name | Value | 13 | +---------------+-----------------------+ 14 | | datadir | /usr/local/var/mysql/ | 15 | +---------------+-----------------------+ 16 | 1 row in set (0.00 sec) 17 | ``` 18 | 19 | 从结果中可以看出,在我的计算机上`MySQL`的数据目录就是`/usr/local/var/mysql/`、 20 | 21 | ## 数据目录的结构 22 | 23 | `MySQL`在运行过程中除了会产生这些用户数据,为了程序更好的运行,`MySQL`也会创建一些其他的额外数据。 24 | 25 | ### 数据库在文件系统中的表示 26 | 27 | 每个数据库都对应数据目录下的一个子目录,或者说对应一个文件夹,我们每当我们新建一个数据库时,`MySQL`会帮我们做这两件事: 28 | 29 | 1. 在`数据目录`下创建一个和数据库名同名的子目录。 30 | 2. 在该与数据库名同名的子目录下创建一个名为`db.opt`的文件,这个文件中包含了该数据库的各种属性,比方说该数据库的字符集和比较规则。 31 | 32 | 比方说我们查看一下在我的计算机上当前有哪些数据库: 33 | 34 | ```mysql 35 | mysql> SHOW DATABASES; 36 | +--------------------+ 37 | | Database | 38 | +--------------------+ 39 | | information_schema | 40 | | charset_demo_db | 41 | | dahaizi | 42 | | mysql | 43 | | performance_schema | 44 | | sys | 45 | | xiaohaizi | 46 | +--------------------+ 47 | 7 rows in set (0.00 sec) 48 | ``` 49 | 50 | 可以看到在我的计算机上当前有7个数据库,其中`charset_demo_db`、`dahaizi`和`xiaohaizi`数据库是我们自定义的,其余4个数据库是属于MySQL自带的系统数据库。我们再看一下我的计算机上的`数据目录`下的内容: 51 | 52 | ```mysql 53 | . 54 | ├── auto.cnf 55 | ├── ca-key.pem 56 | ├── ca.pem 57 | ├── charset_demo_db 58 | ├── client-cert.pem 59 | ├── client-key.pem 60 | ├── dahaizi 61 | ├── ib_buffer_pool 62 | ├── ib_logfile0 63 | ├── ib_logfile1 64 | ├── ibdata1 65 | ├── ibtmp1 66 | ├── mysql 67 | ├── performance_schema 68 | ├── private_key.pem 69 | ├── public_key.pem 70 | ├── server-cert.pem 71 | ├── server-key.pem 72 | ├── sys 73 | ├── xiaohaizideMacBook-Pro.local.err 74 | ├── xiaohaizideMacBook-Pro.local.pid 75 | └── xiaohaizi 76 | 77 | 6 directories, 16 files 78 | ``` 79 | 80 | 当然这个数据目录下的文件和子目录比较多哈,但是如果仔细看的话,除了`information_schema`这个系统数据库外,其他的数据库在`数据目录`下都有对应的子目录。这个`information_schema`比较特殊,设计MySQL的大叔们对它的实现进行了特殊对待,没有使用相应的数据库目录,我们忽略它的存在就好了哈。 81 | 82 | ### 表在文件系统中的表示 83 | 84 | 我们的数据其实都是以记录的形式插入到表中的,每个表的信息其实可以分为两种: 85 | 86 | 1. 表结构的定义 87 | 2. 表中的数据 88 | 89 | `表结构`就是该表的名称是啥,表里边有多少列,每个列的数据类型是啥,有啥约束条件和索引,用的是啥字符集和比较规则各种信息,为了保存这些信息,`InnoDB`和`MyISAM`这两种存储引擎都在`数据目录`下对应的数据库子目录下创建了一个专门用于描述表结构的文件,文件名是这样: 90 | 91 | ```mysql 92 | 表名.frm 93 | ``` 94 | 95 | 描述表结构的文件我们知道怎么存储了,下边我们分别看一下`InnoDB`是用什么文件来保存表中数据的。 96 | 97 | #### InnoDB是如何存储表数据的 98 | 99 | 我们前边重点唠叨过`InnoDB`的一些实现原理,到现在为止我们应该熟悉下边这些东东: 100 | 101 | - `InnoDB`其实是使用`页`为基本单位来管理存储空间的,默认的`页`大小为`16KB`。 102 | - 对于`InnoDB`存储引擎来说,每个索引都对应着一棵`B+`树,该`B+`树的每个节点都是一个数据页,数据页之间不必要是物理连续的,因为数据页之间有`双向链表`来维护着这些页的顺序。 103 | - `InnoDB`的聚簇索引的叶子节点存储了完整的用户记录,也就是所谓的索引即数据,数据即索引。 104 | 105 | 为了更好的管理这些页,设计`InnoDB`的大叔们提出了一个`表空间`的概念,这个表空间是一个抽象的概念,它可以对应文件系统上一个或多个真实文件。每一个`表空间`可以被划分为很多很多很多个`页`,我们的表数据就存放在某个`表空间`下的某些页里。设计`InnoDB`的大叔将表空间划分为几种不同的类型,我们一个一个看一下。 106 | 107 | ##### 系统表空间(system tablespace) 108 | 109 | 这个所谓的`系统表空间`可以对应文件系统上一个或多个实际的文件,默认情况下,`InnoDB`会在`数据目录`下创建一个名为`ibdata1`、大小为`12M`的文件,这个文件就是对应的`系统表空间`在文件系统上的表示。这个文件是所谓的`自扩展文件`,也就是当不够用的时候它会自己增加文件大小 110 | 111 | 当然,如果你想让系统表空间对应文件系统上多个实际文件,或者仅仅觉得原来的`ibdata1`这个文件名难听,那可以在`MySQL`启动时配置对应的文件路径以及它们的大小,比如我们这样修改一下配置文件: 112 | 113 | ```mysql 114 | [server] 115 | innodb_data_file_path=data1:512M;data2:512M:autoextend 116 | ``` 117 | 118 | 这样在`MySQL`启动之后就会创建这两个512M大小的文件作为`系统表空间`,其中的`autoextend`表明这两个文件如果不够用会自动扩展`data2`文件的大小。 119 | 120 | 我们也可以把`系统表空间`对应的文件路径不配置到`数据目录`下,甚至可以配置到单独的磁盘分区上,涉及到的启动参数就是`innodb_data_file_path`和`innodb_data_home_dir`。 121 | 122 | 需要注意的一点是,在一个MySQL服务器中,系统表空间只有一份。从MySQL5.5.7到MySQL5.6.6之间的各个版本中,我们表中的数据都会被默认存储到这个 ***系统表空间***。 123 | 124 | ##### 独立表空间(file-per-table tablespace) 125 | 126 | 在MySQL5.6.6以及之后的版本中,`InnoDB`并不会默认的把各个表的数据存储到系统表空间中,而是为每一个表建立一个独立表空间。使用`独立表空间`来存储表数据的话,会在该表所属数据库对应的子目录下创建一个表示该`独立表空间`的文件,文件名和表名相同,只不过添加了一个`.ibd`的扩展名而已,所以完整的文件名称长这样: 127 | 128 | ```mysql 129 | 表名.ibd 130 | ``` 131 | 132 | 当然我们也可以自己指定使用`系统表空间`还是`独立表空间`来存储数据,这个功能由启动参数`innodb_file_per_table`控制,比如说我们想刻意将表数据都存储到`系统表空间`时,可以在启动`MySQL`服务器的时候这样配置: 133 | 134 | ```mysql 135 | [server] 136 | innodb_file_per_table=0 137 | ``` 138 | 139 | 当`innodb_file_per_table`的值为`0`时,代表使用系统表空间;当`innodb_file_per_table`的值为`1`时,代表使用独立表空间。 140 | 141 | ### 视图在文件系统中的表示 142 | 143 | `MySQL`中的视图其实是虚拟的表,所以在存储`视图`的时候只需要把它的结构存储起来就行了。和`表`一样,描述视图结构的文件也会被存储到所属数据库对应的子目录下边,只会存储一个`视图名.frm`的文件。 144 | 145 | ### 其他的文件 146 | 147 | 除了我们上边说的这些用户自己存储的数据以外,`数据目录`下还包括为了更好运行程序的一些额外文件,主要包括这几种类型的文件: 148 | 149 | - 服务器进程文件。 150 | 151 | 我们知道每运行一个`MySQL`服务器程序,都意味着启动一个进程。`MySQL`服务器会把自己的进程ID写入到一个文件中。 152 | 153 | - 服务器日志文件。 154 | 155 | 在服务器运行过程中,会产生各种各样的日志,比如常规的查询日志、错误日志、二进制日志、redo日志。 156 | 157 | - 默认/自动生成的SSL和RSA证书和密钥文件。 158 | 159 | 主要是为了客户端和服务器安全通信而创建的一些文件。 160 | 161 | ## MySQL系统数据库简介 162 | 163 | 我们前边提到了MySQL的几个系统数据库,这几个数据库包含了MySQL服务器运行过程中所需的一些信息以及一些运行状态信息,我们现在稍微了解一下。 164 | 165 | - `mysql` 166 | 167 | 这个数据库贼核心,它存储了MySQL的用户账户和权限信息,一些存储过程、事件的定义信息,一些运行过程中产生的日志信息,一些帮助信息以及时区信息等。 168 | 169 | - `information_schema` 170 | 171 | 这个数据库保存着MySQL服务器维护的所有其他数据库的信息,比如有哪些表、哪些视图、哪些触发器、哪些列、哪些索引。这些信息并不是真实的用户数据,而是一些描述性信息,有时候也称之为元数据。 172 | 173 | - `performance_schema` 174 | 175 | 这个数据库里主要保存MySQL服务器运行过程中的一些状态信息,算是对MySQL服务器的一个性能监控。包括统计最近执行了哪些语句,在执行过程的每个阶段都花费了多长时间,内存的使用情况等等信息。 176 | 177 | - `sys` 178 | 179 | 这个数据库主要是通过视图的形式把`information_schema`和`performance_schema`结合起来,让程序员可以更方便的了解MySQL服务器的一些性能信息。 -------------------------------------------------------------------------------- /掘金Mysql小册精简/10.连接的原理.md: -------------------------------------------------------------------------------- 1 | ## 连接简介 2 | 3 | ### 连接的本质 4 | 5 | 为了故事的顺利发展,我们先建立两个简单的表并给它们填充一点数据: 6 | 7 | ```mysql 8 | CREATE TABLE t1 (m1 int, n1 char(1)); 9 | CREATE TABLE t2 (m2 int, n2 char(1)); 10 | INSERT INTO t1 VALUES(1, 'a'), (2, 'b'), (3, 'c'); 11 | INSERT INTO t2 VALUES(2, 'b'), (3, 'c'), (4, 'd'); 12 | ``` 13 | 14 | 我们成功建立了`t1`、`t2`两个表,这两个表都有两个列,一个是`INT`类型的,一个是`CHAR(1)`类型的。 15 | 16 | `连接`的本质就是把各个连接表中的记录都取出来依次匹配的组合加入结果集并返回给用户。所以我们把`t1`和`t2`两个表连接起来的过程如下图所示: 17 | 18 | ![image-20190714220000411](assets/image-20190714220000411.png) 19 | 20 | 这个过程看起来就是把`t1`的记录和`t2`的记录连起来组成新的更大的记录,所以这个查询过程称之为连接查询。连接查询的结果集中包含一个表中的每一条记录与另一个表中的每一条记录相互匹配的组合,像这样的结果集就可以称之为`笛卡尔积`。在`MySQL`中,连接查询的语法也很随意,只要在`FROM`语句后边跟多个表名就好了,比如我们把`t1`表和`t2`表连接起来的查询语句可以写成这样: 21 | 22 | ```mysql 23 | SELECT * FROM t1, t2; 24 | ``` 25 | 26 | ### 连接过程简介 27 | 28 | 我们可以连接任意数量张表,但是如果没有任何限制条件的话,这些表连接起来产生的`笛卡尔积`可能是非常巨大的。所以在连接的时候过滤掉特定记录组合是有必要的,在连接查询中的过滤条件可以分成两种: 29 | 30 | - 涉及单表的条件 31 | 32 | 这种只设计单表的过滤条件我们之前都提到过一万遍了,我们之前也一直称为`搜索条件`。 33 | 34 | - 涉及两表的条件 35 | 36 | 这种过滤条件我们之前没见过,比如`t1.m1 = t2.m2`、`t1.n1 > t2.n2`等,这些条件中涉及到了两个表。 37 | 38 | 下边我们就要看一下携带过滤条件的连接查询的大致执行过程了,比方说下边这个查询语句: 39 | 40 | ```mysql 41 | SELECT * FROM t1, t2 WHERE t1.m1 > 1 AND t1.m1 = t2.m2 AND t2.n2 < 'd'; 42 | ``` 43 | 44 | 这个连接查询的大致执行过程如下: 45 | 46 | 1. 首先确定第一个需要查询的表,这个表称之为`驱动表`。此处假设使用`t1`作为驱动表,那么就需要到`t1`表中找满足`t1.m1 > 1`的记录,因为表中的数据太少,我们也没在表上建立二级索引,所以此处查询`t1`表的访问方法就设定为`all`吧。所以查询过程就如下图所示: 47 | 48 | ![image-20190714220440338](assets/image-20190714220440338.png) 49 | 50 | 我们可以看到,`t1`表中符合`t1.m1 > 1`的记录有两条。 51 | 52 | 2. 上一步骤中从驱动表产生的结果集中的每一条记录,分别需要到`t2`表中查找匹配的记录。所以`t2`表也可以被称之为`被驱动表`。上一步骤从驱动表中得到了2条记录,所以需要查询2次`t2`表。此时涉及两个表的列的过滤条件`t1.m1 = t2.m2`就派上用场了: 53 | 54 | - 当`t1.m1 = 2`时,过滤条件`t1.m1 = t2.m2`就相当于`t2.m2 = 2`,所以此时`t2`表相当于有了`t2.m2 = 2`、`t2.n2 < 'd'`这两个过滤条件,然后到`t2`表中执行单表查询。 55 | - 当`t1.m1 = 3`时,过滤条件`t1.m1 = t2.m2`就相当于`t2.m2 = 3`,所以此时`t2`表相当于有了`t2.m2 = 3`、`t2.n2 < 'd'`这两个过滤条件,然后到`t2`表中执行单表查询。 56 | 57 | 所以整个连接查询的执行过程就如下图所示: 58 | 59 | ![image-20190714220709887](assets/image-20190714220709887.png) 60 | 61 | 从上边两个步骤可以看出来,这个两表连接查询共需要查询1次`t1`表,2次`t2`表。如果我们把`t1.m1 > 1`这个条件去掉,就需要查询3次`t2`表了。在两表连接查询中,驱动表只需要访问一次,被驱动表可能被访问多次。 62 | 63 | ## 连接的原理 64 | 65 | ### 嵌套循环连接(Nested-Loop Join) 66 | 67 | 对于两表连接来说,驱动表只会被访问一遍,但被驱动表却要被访问到好多遍。对于内连接来说,选取哪个表为驱动表都没关系,而外连接的驱动表是固定的: 68 | 69 | - 步骤1:选取驱动表,使用与驱动表相关的过滤条件,选取代价最低的单表访问方法来执行对驱动表的单表查询。 70 | - 步骤2:对上一步骤中查询驱动表得到的结果集中每一条记录,都分别到被驱动表中查找匹配的记录。 71 | 72 | 通用的两表连接过程如下图所示: 73 | 74 | ![image-20190714222215921](assets/image-20190714222215921.png) 75 | 76 | 如果有3个表进行连接的话,那么`步骤2`中得到的结果集就像是新的驱动表,然后第三个表就成为了被驱动表,重复上边过程。这个过程就像是一个嵌套的循环,所以这种驱动表只访问一次,但被驱动表却可能被多次访问,访问次数取决于对驱动表执行单表查询后的结果集中的记录条数的连接执行方式称之为`嵌套循环连接`,这是最简单,也是最笨拙的一种连接查询算法。 77 | 78 | ### 使用索引加快连接速度 79 | 80 | 在`嵌套循环连接`的`步骤2`中可能需要访问多次被驱动表,我们可以利用索引来加快查询速度。 81 | 82 | ### 基于块的嵌套循环连接 83 | 84 | 采用`嵌套循环连接`算法的两表连接过程中,被驱动表可是要被访问好多次的,这个`I/O`代价就非常大了。设计`MySQL`的大叔提出了一个`join buffer`的概念,就是执行连接查询前申请的一块固定大小的内存,先把若干条驱动表结果集中的记录装在这个`join buffer`中,然后开始扫描被驱动表,每一条被驱动表的记录一次性和`join buffer`中的多条驱动表记录做匹配,因为匹配的过程都是在内存中完成的,所以这样可以显著减少被驱动表的`I/O`代价。使用`join buffer`的过程如下图所示: 85 | 86 | ![image-20190714222759171](assets/image-20190714222759171.png) 87 | 88 | 最好的情况是`join buffer`足够大,能容纳驱动表结果集中的所有记录,这样只需要访问一次被驱动表就可以完成连接操作了。设计`MySQL`的大叔把这种加入了`join buffer`的嵌套循环连接算法称之为`基于块的嵌套连接`算法。 89 | 90 | 这个`join buffer`的大小是可以通过启动参数或者系统变量`join_buffer_size`进行配置。对于优化被驱动表的查询来说,最好是为被驱动表加上效率高的索引,如果实在不能使用索引,并且自己的机器的内存也比较大可以尝试调大`join_buffer_size`的值来对连接查询进行优化。 -------------------------------------------------------------------------------- /掘金Mysql小册精简/17.事务.md: -------------------------------------------------------------------------------- 1 | ## 事务的起源 2 | 3 | ### 原子性(Atomicity) 4 | 5 | 现实世界中转账操作是一个不可分割的操作,也就是说要么压根儿就没转,要么转账成功,不能存在中间的状态,也就是转了一半的这种情况。设计数据库的大叔们把这种要么全做,要么全不做的规则称之为`原子性`。 6 | 7 | ### 隔离性(Isolation) 8 | 9 | 现实世界中不仅要保证这些操作以`原子性`的方式执行完成,而且要保证其它的状态转换不会影响到本次状态转换,这个规则被称之为`隔离性`。这时设计数据库的大叔们就需要采取一些措施来让访问相同数据的不同状态转换对应的数据库操作的执行顺序有一定规律,这也是我们后边章节要仔细唠叨的内容。 10 | 11 | ### 一致性(Consistency) 12 | 13 | 如果数据库中的数据全部符合现实世界中的约束,我们说这些数据就是一致的,或者说符合`一致性`的。 14 | 15 | 保证数据库中数据的一致性其实靠两方面的努力: 16 | 17 | - 数据库本身能为我们保证一部分一致性需求(就是数据库自身可以保证一部分现实世界的约束永远有效)。 18 | - 更多的一致性需求需要靠写业务代码的程序员自己保证。 19 | 20 | ### 持久性(Durability) 21 | 22 | 当现实世界的一个状态转换完成后,这个转换的结果将永久的保留,这个规则被设计数据库的大叔们称为`持久性`。 23 | 24 | ## 事务的概念 25 | 26 | 设计数据库的大叔为了方便起见,把需要保证`原子性`、`隔离性`、`一致性`和`持久性`的一个或多个数据库操作称之为一个`事务`。 27 | 28 | 我们现在知道`事务`是一个抽象的概念,它其实对应着一个或多个数据库操作,设计数据库的大叔根据这些操作所执行的不同阶段把`事务`大致上划分成了这么几个状态: 29 | 30 | - 活动的(active) 31 | 32 | 事务对应的数据库操作正在执行过程中 33 | 34 | - 部分提交的(partially committed) 35 | 36 | 当事务中的最后一个操作执行完成,但由于操作都在内存中执行,所造成的影响并没有刷新到磁盘时。 37 | 38 | - 失败的(failed) 39 | 40 | 事务处在`活动的`或者`部分提交的`状态时,可能遇到了某些错误而无法继续执行,或者人为的停止当前事务的执行,我们就说该事务处在`失败的`状态。 41 | 42 | - 中止的(aborted) 43 | 44 | 当`回滚`操作执行完毕时,也就是数据库恢复到了执行事务之前的状态,我们就说该事务处在了`中止的`状态。 45 | 46 | - 提交的(committed) 47 | 48 | 处在`部分提交的`状态的事务将修改过的数据都同步到磁盘上之后,我们就可以说该事务处在了`提交的`状态。 49 | 50 | 随着事务对应的数据库操作执行到不同阶段,事务的状态也在不断变化: 51 | 52 | ![image-20190716220713606](assets/image-20190716220713606.png) 53 | -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710142826837.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710142826837.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710151542780.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710151542780.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710153004692.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710153004692.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710153355829.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710153355829.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710153500452.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710153500452.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710154642358.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710154642358.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710154716274.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710154716274.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710154744227.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710154744227.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710154826244.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710154826244.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710154844202.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710154844202.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710154916604.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710154916604.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710154940478.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710154940478.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710161752427.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710161752427.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710161932337.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710161932337.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710162240894.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710162240894.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710162757194.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710162757194.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710163019075.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710163019075.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710163336969.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710163336969.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710163352925.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710163352925.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710165257045.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710165257045.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710165431539.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710165431539.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710165445272.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710165445272.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710170644606.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710170644606.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710170726206.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710170726206.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710171634768.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710171634768.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710172425288.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710172425288.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710172707152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710172707152.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710172744491.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710172744491.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710172932794.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710172932794.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710173014175.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710173014175.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710173606736.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710173606736.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710173713620.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710173713620.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710173850067.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710173850067.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710173925879.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710173925879.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710174054376.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710174054376.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710175154158.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710175154158.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710175305846.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710175305846.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710175340275.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710175340275.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710175408125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710175408125.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710175512689.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710175512689.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710175514456.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710175514456.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190710175631122.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190710175631122.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190711140712530.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190711140712530.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190711141411056.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190711141411056.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190711141636448.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190711141636448.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190711141741720.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190711141741720.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190711142250628.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190711142250628.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190711142301078.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190711142301078.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190711142422467.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190711142422467.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190711142556685.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190711142556685.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190711142857785.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190711142857785.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190711142935883.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190711142935883.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190712103450970.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190712103450970.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190712103853882.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190712103853882.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190712105752472.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190712105752472.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190712105903377.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190712105903377.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190712110454051.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190712110454051.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190712110834976.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190712110834976.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190712111337355.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190712111337355.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190712111624533.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190712111624533.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190712160851745.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190712160851745.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190712165142921.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190712165142921.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190712165205998.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190712165205998.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190712173028964.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190712173028964.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190712173514433.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190712173514433.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190712173526667.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190712173526667.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190712173559992.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190712173559992.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190712173710859.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190712173710859.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190712175254961.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190712175254961.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190712175359520.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190712175359520.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190714173457099.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190714173457099.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190714174132968.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190714174132968.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190714180355233.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190714180355233.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190714180517760.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190714180517760.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190714182422469.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190714182422469.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190714182709944.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190714182709944.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190714183204766.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190714183204766.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190714183434761.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190714183434761.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190714184036398.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190714184036398.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190714195943414.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190714195943414.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190714200119993.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190714200119993.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190714200702858.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190714200702858.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190714201420265.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190714201420265.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190714201813740.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190714201813740.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190714220000411.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190714220000411.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190714220440338.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190714220440338.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190714220709887.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190714220709887.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190714222215921.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190714222215921.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190714222759171.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190714222759171.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190715140313217.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190715140313217.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190715140648227.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190715140648227.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190715141331782.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190715141331782.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190715145056733.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190715145056733.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190715145126768.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190715145126768.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190715145240949.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190715145240949.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190715154306751.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190715154306751.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190715154308331.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190715154308331.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190715154339793.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190715154339793.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190715155947003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190715155947003.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190715172451857.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190715172451857.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190715172725767.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190715172725767.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190715172730227.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190715172730227.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190715173458697.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190715173458697.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190715174542674.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190715174542674.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190716214518564.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190716214518564.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190716215112184.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190716215112184.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190716220713606.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190716220713606.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190716221846362.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190716221846362.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717100212209.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717100212209.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717100330032.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717100330032.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717100943644.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717100943644.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717101343927.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717101343927.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717103115139.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717103115139.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717103215216.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717103215216.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717103248746.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717103248746.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717103733568.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717103733568.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717103847974.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717103847974.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717104447445.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717104447445.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717104626751.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717104626751.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717104704512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717104704512.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717104726794.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717104726794.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717105240186.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717105240186.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717105436458.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717105436458.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717110010350.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717110010350.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717110059761.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717110059761.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717110335505.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717110335505.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717112349490.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717112349490.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717112428358.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717112428358.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717113314041.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717113314041.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717113738572.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717113738572.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717113851944.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717113851944.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717113923435.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717113923435.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717114026869.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717114026869.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717114217587.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717114217587.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717114342453.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717114342453.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717114527423.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717114527423.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190717114630983.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190717114630983.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718092638632.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718092638632.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718093412360.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718093412360.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718093804019.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718093804019.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718104449930.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718104449930.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718105912168.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718105912168.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718110411591.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718110411591.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718110931736.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718110931736.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718111451894.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718111451894.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718111525394.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718111525394.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718121100412.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718121100412.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718121138252.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718121138252.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718121935383.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718121935383.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718122048287.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718122048287.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718122154061.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718122154061.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718122255895.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718122255895.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718124314985.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718124314985.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718124840202.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718124840202.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718125015663.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718125015663.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718125541742.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718125541742.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718130010210.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718130010210.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718131226945.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718131226945.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718131626550.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718131626550.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718131821660.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718131821660.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718131915391.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718131915391.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718140444119.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718140444119.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718141217625.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718141217625.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718141544295.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718141544295.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718141619824.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718141619824.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718141735266.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718141735266.png -------------------------------------------------------------------------------- /掘金Mysql小册精简/assets/image-20190718141831621.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/掘金Mysql小册精简/assets/image-20190718141831621.png -------------------------------------------------------------------------------- /操作系统/Linux.md: -------------------------------------------------------------------------------- 1 | ### 打包与压缩 2 | 3 | - 早期 `Linux` 的备份介质是磁带,使用命令 `tar` 进行打包。 4 | - 之后可以使用 `gzip` 和 `bzip2` 对打包后的磁带文件进行压缩存储 5 | - 经常使用的扩展名是 `.tar.gz` 、 `.tar.bz2` 、 `tgz` 6 | 7 | #### 打包命令 8 | 9 | - `tar` 10 | - 常用参数 11 | - `c` 打包 12 | - `x` 解包 13 | - `f` 指定操作类型为文件 14 | - `z` 使用 `gzip` 进行解压缩 15 | - `j` 使用 `bzip` 进行解压缩 16 | 17 | #### 举例 18 | 19 | - 打包压缩 20 | - `tar czf /tmp/etc-backup.tar.gz /etc` 21 | - 解压缩 22 | - `tar xzf /tmp/etc-backup.tar.gz -C /root` 23 | 24 | ### VIM 25 | 26 | - 四种模式 27 | - 正常模式 28 | - `u` 撤销 29 | - `ctrl + r` 重做 30 | - `xxxdd` 剪切 `xxx` 行 31 | - `xxxyy` 复制 `xxx` 行 32 | - `x` 删除字符 33 | - `r` 替换字符 34 | - `gg` 跳到行首 35 | - `GG` 跳到行尾 36 | - `xxxgg` 跳到 `xxx` 行 37 | - `^` 跳到行首 38 | - `$` 跳到行尾 39 | - 插入模式(`i、I、o、O、a、A`) 40 | - 命令模式(`:`) 41 | - `set nu` 显示行号 42 | - `set nohlsearch` 关闭高亮显示 43 | - `!command` 临时执行 `command` 命令 44 | - `/xxx` 查找 `xxx` 45 | - `s/old/new` 替换当前行中第一个 `old` 为 `new` 46 | - `%s/old/new` 替换所有文本中第一个 `old` 为 `new` 47 | - `%s/old/new/g` 替换所有文本所有 `old` 为 `new` 48 | - `3,5s/old/new/g` 替换 `3 - 5` 行文本所有 `old` 为 `new` 49 | - 可视模式(`v 、shift + v 、 ctrl + v`) 50 | 51 | ### 用户和用户组 52 | 53 | #### 用户 54 | 55 | - 添加用户 56 | - `useradd xxx` 57 | - 查看用户 58 | - `id xxx` 59 | - 设置密码 60 | - `passwd xxx psw` 61 | - 删除用户 62 | - `userdel -r xxx` 保证家目录被删除 63 | - 修改用户属性 64 | - ` usermod` 65 | - `usermod -d /home/w1 w` 将用户 `w` 家目录修改为 `w1` 66 | 67 | #### 用户组 68 | 69 | - 添加用户组 70 | - `groupadd xxx` 71 | - 添加用户到用户组 72 | - `usermod -g groupxxx userxxx` 73 | - 新建用户加入用户组 74 | - `useradd -g groupxxx userxxx` 75 | 76 | #### 切换用户 77 | 78 | - 将当前用户和运行环境临时切换为userxxx 79 | - `su - userxxx` 80 | 81 | - 为用户添加 `root` 权限 82 | - `visudo` 进入编辑器模式,在最后面添加一行并保存 83 | - `lollipop ALL=(ALL)` 84 | 85 | ### 文件 86 | 87 | - 文件类型 88 | - `-` 普通文件 89 | - `d` 目录文件 90 | - `b` 快特殊文件(设备) 91 | - `c` 字符特殊文件(终端) 92 | - `l` 符号链接 93 | - `f` 命名管道 94 | - `s` 套接字文件 95 | 96 | -------------------------------------------------------------------------------- /算法/cyc题目.md: -------------------------------------------------------------------------------- 1 | ### 双指针 2 | 3 | 167, 633, 345, 680, 88, 141, 524 4 | 5 | ### 排序 6 | 7 | 347, 451, 75 8 | 9 | ### 贪心 10 | 11 | 455, 435, 452, 406, 121, 122, 605, 392, 665, 53, 763 12 | 13 | ### 二分查找 14 | 15 | 69, 744, 540, 278, 153, 34 16 | 17 | ### 分治 18 | 19 | 241, 95 20 | 21 | ###搜索 22 | 23 | 279, 127, 695, 200, 647, 130, 417, 17, 93, 79, 257, 46, 47, 77, 39, 40, 216, 78, 90, 131, 37, 51 24 | 25 | ### 动态规划 26 | 27 | 70, 198, 213, 64, 62, 303, 413, 343, 279, 91, 300, 646, 376, 416, 494, 474, 322, 518, 139, 377, 309, 714, 123, 188, 583, 72, 650 28 | 29 | ### 数学 30 | 31 | 204, 504, 405, 168, 172, 67, 415, 462, 169, 367, 326, 238, 628 32 | 33 | ### 链表 34 | 35 | 160, 206, 21, 83, 19, 24, 445, 234, 725, 328 36 | 37 | ### 树 38 | 39 | 104, 110, 543, 226, 617, 112, 437, 572, 101, 111, 404, 687, 337, 671, 637, 513, 144, 145, 94, 669, 230, 583, 235, 236, 108, 109, 653, 530, 501, 208, 677 40 | 41 | ### 栈和队列 42 | 43 | 232, 225, 155, 20, 739, 503 44 | 45 | ### 哈希表 46 | 47 | 1, 217, 594, 128 48 | 49 | ### 字符串 50 | 51 | 242, 409, 205, 647, 9, 696 52 | 53 | ### 矩阵和数组 54 | 55 | 283, 566, 485, 240, 378, 645, 448, 442, 287, 667, 697, 766, 565, 769 56 | 57 | ### 图 58 | 59 | 785, 207, 210, 684 60 | 61 | ### 位运算 62 | 63 | 461, 136, 268, 260, 190, 231, 342, 693, 476, 371, 318, 338 -------------------------------------------------------------------------------- /系统设计/assets/image-20190730231224593.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190730231224593.png -------------------------------------------------------------------------------- /系统设计/assets/image-20190804213406361.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190804213406361.png -------------------------------------------------------------------------------- /系统设计/assets/image-20190804213447835.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190804213447835.png -------------------------------------------------------------------------------- /系统设计/assets/image-20190804215043251.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190804215043251.png -------------------------------------------------------------------------------- /系统设计/assets/image-20190804230529069.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190804230529069.png -------------------------------------------------------------------------------- /系统设计/assets/image-20190804230613264.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190804230613264.png -------------------------------------------------------------------------------- /系统设计/assets/image-20190804230736540.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190804230736540.png -------------------------------------------------------------------------------- /系统设计/assets/image-20190804231212870.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190804231212870.png -------------------------------------------------------------------------------- /系统设计/assets/image-20190804231421908.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190804231421908.png -------------------------------------------------------------------------------- /系统设计/assets/image-20190806164132345.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190806164132345.png -------------------------------------------------------------------------------- /系统设计/assets/image-20190806164644434.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190806164644434.png -------------------------------------------------------------------------------- /系统设计/assets/image-20190806164840016.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190806164840016.png -------------------------------------------------------------------------------- /系统设计/assets/image-20190806192106918.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190806192106918.png -------------------------------------------------------------------------------- /系统设计/assets/image-20190806195852238.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190806195852238.png -------------------------------------------------------------------------------- /系统设计/assets/image-20190806203124953.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190806203124953.png -------------------------------------------------------------------------------- /系统设计/assets/image-20190806210654541.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190806210654541.png -------------------------------------------------------------------------------- /系统设计/assets/image-20190806213923841.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190806213923841.png -------------------------------------------------------------------------------- /系统设计/assets/image-20190806220658575.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190806220658575.png -------------------------------------------------------------------------------- /系统设计/assets/image-20190806225942551.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190806225942551.png -------------------------------------------------------------------------------- /系统设计/assets/image-20190806232711281.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190806232711281.png -------------------------------------------------------------------------------- /系统设计/assets/image-20190807002318014.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190807002318014.png -------------------------------------------------------------------------------- /系统设计/assets/image-20190807193917981.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190807193917981.png -------------------------------------------------------------------------------- /系统设计/assets/image-20190807205738080.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190807205738080.png -------------------------------------------------------------------------------- /系统设计/assets/image-20190807225638075.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/系统设计/assets/image-20190807225638075.png -------------------------------------------------------------------------------- /系统设计/消息队列.md: -------------------------------------------------------------------------------- 1 | ### 为什么使用消息队列 2 | 3 | 消息队列常见的使用场景有很多,但是比较核心的有 3 个:**解耦**、**异步**、**削峰**。 4 | 5 | #### 解耦 6 | 7 | **场景:** A系统发送数据到B、C、D三个系统,通过接口同步调用发送。如果现在E系统也需要这个数据或者C系统现在不需要了,需要去修改A系统的代码。这里A系统跟其它系统严重耦合,很多系统都需要 A 系统将这个数据发送过来。 8 | 9 | **使用MQ:** A系统产生一条数据,发送到 MQ 里面去,其他系统需要数据就去 MQ 里面消费,如果不需要这条数据了,就取消对 MQ 消息的消费即可。通过一个 MQ,A 系统就跟其它系统彻底解耦了。 10 | 11 | #### 异步 12 | 13 | **场景:** A系统接收一个请求,需要在自己本地写库,还需要在B、C、D三个系统写库,自己本地写库要 3ms,B、C、D三个系统分别写库要 300ms、450ms、200ms。最终请求总延时是 3 + 300 + 450 + 200 = 953ms,接近 1s。用户通过浏览器发起请求等待1s,这几乎是不可接受的。 14 | 15 | **使用MQ:** A系统连续发送3条消息到MQ队列中,假如耗时5ms,A系统从接受一个请求到返回响应给用户,总时长是3 + 5 = 8ms,对于用户而言,其实感觉上就是点个按钮,8ms 以后就直接返回了。 16 | 17 | #### 削峰 18 | 19 | **场景:** 每天晚上,系统A的TPS为50。12:00 ~ 13:00时,TPS暴增到5k+。一般的MySQL,TPS最多也就2k,如果5k的话,mysql就会直接崩溃。但是高峰期一过,TPS就又恢复到了50,整个系统几乎没有任何的压力。 20 | 21 | **使用MQ:** 每秒 5k 个请求写入 MQ,A系统从MQ中慢慢拉取请求,每秒拉取 2k 个请求,这样下来,哪怕是高峰期的时候,A 系统也绝对不会挂掉。而 MQ 每秒钟 5k 个请求进来,就 2k 个请求出去,就导致在中午高峰期,可能有几十万甚至几百万的请求积压在 MQ 中。高峰期过了之后,每秒钟就 50 个请求进 MQ,但是 A 系统依然会按照每秒 2k 个请求的速度在处理。只要高峰期一过,A 系统就会快速将积压的消息给解决掉。 22 | 23 | ### 消息队列有什么优点和缺点 24 | 25 | 好处:**解耦**、**异步**、**削峰**。 26 | 27 | 缺点: 28 | 29 | - 系统可用性降低:MQ一旦挂掉,整套系统崩溃。 30 | - 系统复杂度提高:要保证没有重复消费、没有消息丢失,保证消息传递的顺序性。 31 | - 一致性问题:A 系统处理完了直接返回成功了,但是BCD三个系统中BD写库成功了,C写库失败,导致数据不一致。 32 | 33 | ### RabbitMQ的高可用性 34 | 35 | RabbitMQ 有三种模式:单机模式、普通集群模式、镜像集群模式。 36 | 37 | #### 单机模式 38 | 39 | 玩玩就好。 40 | 41 | #### 普通集群模式(无高可用性) 42 | 43 | 在多台机器上启动多个 RabbitMQ 实例。queue只会放在一个 RabbitMQ 实例上,每个实例都同步 queue 的元数据。你消费的时候,实际上如果连接到了另外一个实例,那么那个实例会从 queue 所在实例上拉取数据过来。 44 | 45 | 如果那个放 queue 的实例宕机了,会导致接下来其他实例就无法从那个实例拉取,如果你**开启了消息持久化**,让 RabbitMQ 落地存储消息的话,**消息不一定会丢**,得等这个实例恢复了,然后才可以继续从这个 queue 拉取数据。 46 | 47 | #### 镜像集群模式(高可用性) 48 | 49 | RabbitMQ 的高可用模式。无论元数据还是 queue 里的消息都会**存在于多个实例上**,每个 RabbitMQ 节点都有这个 queue 的一个**完整镜像**,包含 queue 的全部数据的意思。每次写消息到 queue 的时候,都会自动把**消息同步**到多个实例的 queue 上。由于其不是分布式的,所以不支持线性扩展。 50 | 51 | ### Kafka 的高可用性 52 | 53 | Kafka由多个 broker 组成,每个 broker 是一个节点;你创建一个 topic,这个 topic 可以划分为多个 partition,每个 partition 可以存在于不同的 broker 上,每个 partition 就放一部分数据。这就是**天然的分布式消息队列**,就是说一个 topic 的数据,是**分散放在多个机器上的,每个机器就放一部分数据**。 54 | 55 | ### 如何保证消息不被重复消费? 56 | 57 | 等同于如何保证消息消费的幂等性。 58 | 59 | 得结合业务来思考,这里有几个思路: 60 | 61 | - 如果要写库,先根据主键查一下,如果这数据存在,就直接update 62 | - 如果要写 Redis,set天然幂等性。 63 | - 如果不是上面两个场景,那做的稍微复杂一点,让生产者发送每条数据的时候,里面加一个全局唯一的 id,然后消费到了之后,先根据这个 id 去比如 Redis 里查一下是否消费过。如果没有消费过就处理,然后把这个id写入Redis。如果消费过就忽略。 64 | - 比如基于数据库的唯一键来保证重复数据不会重复插入多条。因为有唯一键约束了,重复数据插入只会报错,不会导致数据库中出现脏数据。 65 | 66 | ### 如何保证消息的可靠性传输? 67 | 68 | #### 生产者弄丢了数据 69 | 70 | 生产者将数据发送到 RabbitMQ 的时候,可能数据就在半路给搞丢了。如果要确保写 RabbitMQ 的消息不丢,可以开启 `confirm` 模式,在生产者那里设置开启 `confirm` 模式之后,你每次写的消息都会分配一个唯一的 id,然后如果写入了 RabbitMQ 中,会回传一个 `ack` 消息。如果 RabbitMQ 没能处理这个消息,会回调你的一个 `nack` 接口,告诉你这个消息接收失败,你可以重试。 71 | 72 | #### RabbitMQ 弄丢了数据 73 | 74 | **开启 RabbitMQ 的持久化** 75 | 76 | 设置持久化有**两个步骤**: 77 | 78 | - 创建 queue 的时候将其设置为持久化 79 | 这样就可以保证 RabbitMQ 持久化 queue 的元数据,但是它是不会持久化 queue 里的数据的。 80 | - 第二个是发送消息的时候将消息的 `deliveryMode` 设置为 2 81 | 就是将消息设置为持久化的,此时 RabbitMQ 就会将消息持久化到磁盘上去。 82 | 83 | 必须要同时设置这两个持久化才行,RabbitMQ 哪怕是挂了,再次重启,也会从磁盘上重启恢复 queue,恢复这个 queue 里的数据。 84 | 85 | 有一种可能,就是这个消息写到了 RabbitMQ 中,但是还没来得及持久化到磁盘上,结果不巧,此时 RabbitMQ 挂了,就会导致内存里的一点点数据丢失。所以,持久化可以和 `confirm` 机制配合起来,只有消息被持久化到磁盘之后,才会通知生产者 `ack` 了,所以哪怕是在持久化到磁盘之前,RabbitMQ 挂了,数据丢了,生产者收不到 `ack`,你也是可以自己重发的。 86 | 87 | #### 消费端弄丢了数据 88 | 89 | 消费的时候,刚消费到,还没处理,结果进程挂了,RabbitMQ 会认为消费过了,这时数据就丢了。这个时候必须关闭 RabbitMQ 的自动 `ack`,可以通过一个 api 来调用就行,然后代码里确保处理完的时候,在程序里 `ack` 一下。这样的话,如果还没处理进程就挂了,RabbitMQ会认为还没处理完,这个时候 RabbitMQ 会把这个消费分配给别的 consumer 去处理,消息是不会丢的。 90 | 91 | ### RabbitMQ如何保证消息的顺序性? 92 | 93 | 拆分多个 queue,每个 queue 一个 consumer,就是多一些 queue 而已,确实是麻烦点;或者就一个 queue 但是对应一个 consumer,然后这个 consumer 内部用内存队列做排队,然后分发给底层不同的 worker 来处理。 94 | 95 | ![image-20190730231224593](assets/image-20190730231224593.png) 96 | 97 | 98 | 99 | ### 参考资料 100 | 101 | - [互联网 Java 工程师进阶知识完全扫盲](https://github.com/doocs/advanced-java) -------------------------------------------------------------------------------- /系统设计/网络攻击与安全算法.md: -------------------------------------------------------------------------------- 1 | ## 网络攻击 2 | 3 | ### CSRF攻击 4 | 5 | 全称是跨站请求伪造(Cross Site Request Forgery)。 6 | 7 | `CSRF`是通过伪装来自受信任的用户的请求来利用受信任的网站。攻击者盗用了用户的身份,以用户的名义向第三方网站发起恶意请求,可能会利用用户的身份进行转账等危险操作。 8 | 9 | **简介:** 用户A登录了网站B,网站B在用户A的浏览器上存了`cookie`信息,这时候用户A没有登出网站B,转换又去访问网站C,网站C中有一个链接点击后会对网站B发起恶意访问请求。用户A点击后,对网站B发起了请求。如果没有跨域访问限制,这时候网站B便执行了用户A的请求,导致恶意转账等结果。 10 | 11 | **解决手段:** 12 | 13 | 1. 将`cookie`设置为`HttpOnly`,这样就不能通过js去获取`cookie`信息了。 14 | 15 | 2. 增加 `token`: 16 | 17 | 在请求中放入攻击者所不能伪造的信息,并且该信息不存在与`cookie`中。例如在请求中以参数形式加入一个随机生成的`token`,并且在服务端进行`token`校验,如果请求中没有有效的`token`,则拒绝该请求。 18 | 19 | 假设请求通过`POST`方式提交,则可以在相应的表单中增加一个隐藏域:``,`token` 的值通过服务端生成,表单提交后`token`的值通过 `POST` 请求与参数一起带到服务端,每次会话可以使用相同的`token`,会话过期 `token` 失效,攻击者无法获取`token`,所以也就无法伪造请求。 20 | 21 | 3. `cros`跨域资源共享: 22 | 23 | > `cros`配置: 24 | > 25 | > 1. 服务器配置可以发起访问的域,以及请求方法,请求头部信息。 26 | > 2. 对于简单请求,用户在发送请求时,浏览器会自动添加 `Origin` 头部信息。 27 | > 3. 对于复杂请求,浏览器先发送一次带有 `Origin` 字段的 `OPTION` 请求,检测是否允许跨域访问,然后再发送真实请求。 28 | > 4. 服务器会判断请求头部的`Origin`信息是否在已配置的 `AllowedOrigin` 中。 29 | > 5. 服务器响应头部信息中包含配置的 `Access-Control-Allow-Origin` 以及是否允许携带cookie等字段。 30 | > 6. 浏览器检测到 `Origin` 字段中的值若存在于 `Access-Control-Allow-Origin` 字段中便会将数据显示给用户。 31 | > 7. 浏览器检测到 `Origin` 字段中的值不存在于 `Access-Control-Allow-Origin` 字段中便会忽略响应,并报错。 32 | 33 | `cors`跨域资源共享可以有效的抵御`csrf`攻击,用户A浏览网站C时发起恶意请求时,由于恶意请求属于非简单请求,浏览器会先发送一次带有 `Origin` 字段的 `OPTION` 请求,检测是否允许跨域访问,这时浏览器响应头部信息的 `Access-Control-Allow-Origin` 字段中没有 `Origin` 字段的值,因此不会发起真正的请求。 34 | 35 | 36 | 37 | ### XSS攻击 38 | 39 | 全称是跨站脚本攻击(Cross Site Scripting)。 40 | 41 | **简介:** 攻击者在网页中嵌入恶意脚本程序,当用户打开该网页时,脚本程序便开始在用户的浏览器上执行,盗取用户的 `cookie` 、用户名密码、下载执行病毒木马程序,甚至是获取客户端admin权限。 42 | 43 | **原理:** 我现在做了个博客系统,然后有一个用户在博客上发布了一篇文章,内容是``,如过我没有对它做处理,直接存到数据库里,当别的用户读取文章后,浏览器会执行这段js脚本,然后发起恶意攻击。 44 | 45 | **解决手段:** 对用户输入的数据进行过滤和转义。 46 | 47 | ### DDos攻击 48 | 49 | 全称是分布式拒绝服务(Distributed Denial of Service)。 50 | 51 | **简介:** 是目前最强大、最难以防御的攻击方式之一。攻击者利用很多设备在同一时间对目标进行大量访问请求,耗尽服务器资源,导致服务器无法正常响应。 52 | 53 | **解决方案:** 54 | 55 | - DDos攻击很难有效防御,可以通过购买更多的带宽 56 | 57 | - 使用多台服务器,并部署在不同的数据中心 58 | - 将静态资源部署到CDN上,利用CDN,就近访问,提高访问速度,同时又避免了服务器被攻击 59 | - 开启路由器反ip欺骗 60 | 61 | ### SQL注入攻击 62 | 63 | SQL注入就是把SQL命令伪装成正常的HTTP请求参数,传递到服务端,欺骗服务器执行恶意的SQL命令。 64 | 65 | **简介:** 我现在做了个网站,用户登录时,调用的后台接口中有一段代码中SQL语句是这么写的:`"SELECT username FROM user WHERE username = " + username + " AND password = (" + password + ")"`,用户如果输入的用户名是 `xxx`,密码是 `password OR 1 = 1`,那么这条SQL语句将会查询出用户的信息,并且可以绕过检查直接登录成功。 66 | 67 | **解决方案:** 68 | 69 | - 使用预编译的语句,预编译语句使用参数占位符来替代需要动态传入的参数,这时程序会将用户输入的 `password OR 1 = 1`当做普通字符串来处理,攻击者便无法概念SQL语句的结构。 70 | - 使用`ORM`框架,流行的`ORM`框架都对相应的关键字进行了转义。 71 | - 避免以明文方式存放密码,这样攻击者便无法通过SQL注入攻击获取用户的密码。 72 | 73 | ## 数字摘要 74 | 75 | 数字摘要也称为消息摘要,它是一个唯一对应于一个消息的固定长度的值,由一个单向`Hash`函数对消息进行计算而产生。接受者对收到的消息采用相同的`Hash`函数重新计算,将新生成的摘要与原摘对比,如果不相同,则说明消息在传递的过程中改变了。 76 | 77 | 消息摘要的特点: 78 | 79 | 1. 长度固定,与消息长度无关。 80 | 2. 一般不同消息生成的摘要不同,相同的消息生成的摘要一定相同。 81 | 3. 不能重摘要中恢复原消息。 82 | 83 | ### MD5 84 | 85 | `MD5`是数字摘要算法的一种实现,它可以从任意长度的明文字符生成128位的hash值。 86 | 87 | MD5算法的过程分为四步:处理原文,设置初始值,循环加工,拼接结果。 88 | 89 | 1. 先计算出原文比特长度,然后对512求余,如果余数不等于448,就填充原文使得原文对512求余的结果等于448。填充的方法是第一位填充1,其余位填充0,填充完后,信息的长度就是 512 * N + 448。用剩余的位置64位记录原文的真正长度,这样处理后的信息长度就是 512 * (N + 1)。 90 | 2. MD5的哈希结果长度为128位,按每32位分成一组共4组。这4组结果是由4个初始值A、B、C、D经过不断演变得到。 91 | 3. 循环加工,每一次循环都会让旧的A、B、C、D产生新的A、B、C、D。假设处理的原文长度是M,主循环次数 = M / 512,每个主循环中包含 512 / 32 * 4 = 64次子循环。所以消息越大,MD5运算越慢。 92 | 4. 拼接结果。 93 | 94 | ### SHA 95 | 96 | `SHA`是安全散列算法,它可以从任意长度的明文字符生成160位的hash值。由于生成的摘要信息更长,运算更加复杂,所以比`MD5`运行速度慢,但是也更安全。 97 | 98 | ### Base64编码 99 | 100 | 由于计算出的摘要需要转换为字符串,可能会产生一些无法显示或者网络传输的控制字符,所以需要对摘要字符串进行编码。 101 | 102 | `Base64`是一种基于64个可打印字符来表示二进制数据的方法,由于 `2 ^ 6 = 64` ,所以每6位字符为1个单元,3个字节刚好对应4个 `Base64` 单元,即3个字节用4个可打印字符表示。 103 | 104 | `Base64` 只是一种编码算法,可以通过固定的方法逆向得到编码之前的信息,所以不能作为一种加密算法使用。 105 | 106 | ## 对称加密算法 107 | 108 | 即加密和解密使用同一个秘钥的加密算法。 109 | 110 | 对称加密算法的特点: 111 | 112 | - 算法公开 113 | - 计算量小 114 | - 加密速度快 115 | - 加密效率高 116 | - 安全性依赖于秘钥,秘钥一旦泄露就失去了安全性 117 | 118 | 常见的对策加密算法有:`DES`算法、`3DES`算法、`AES`算法等。 119 | 120 | ## 非对称加密算法 121 | 122 | 非对称加密算法需要公钥和私钥配对使用。用公钥加密,只有私钥才能解密;使用私钥加密,只有公钥才能解密。 123 | 124 | 非对称加密算法的特点: 125 | 126 | - 只要保证私钥的安全性就能保证加密算法的安全性 127 | - 只需要传递公钥,大大提高了秘钥传输的安全性 128 | - 由于算法的复杂性,其加解密速度远慢于对称加密算法 129 | 130 | 非对称加密算法实现机密信息交换的基本过程: 131 | 132 | 1. 甲生成一对秘钥,并把一把作为公钥,向其他人公开。 133 | 2. 乙得到该公钥后使用它对机密信息进行加密后发生给甲。 134 | 3. 甲使用私钥对加密后的信息进行解密得到原文。 135 | 136 | 为了达到时间和安全的平衡,通常利用对称加密算法加密较长的文件,用非对称加密算法传递加密文件的对称加密算法的秘钥。 137 | 138 | 常见的非对称加密算法:`RSA`算法。 -------------------------------------------------------------------------------- /网络/assets/image-20190803112837126.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/网络/assets/image-20190803112837126.png -------------------------------------------------------------------------------- /网络/assets/image-20190803112849922.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/网络/assets/image-20190803112849922.png -------------------------------------------------------------------------------- /网络/assets/image-20190803112906970.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/网络/assets/image-20190803112906970.png -------------------------------------------------------------------------------- /网络/assets/image-20190803112929377.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/网络/assets/image-20190803112929377.png -------------------------------------------------------------------------------- /网络/assets/image-20190803112942000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/网络/assets/image-20190803112942000.png -------------------------------------------------------------------------------- /网络/assets/image-20190803113115316.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/网络/assets/image-20190803113115316.png -------------------------------------------------------------------------------- /网络/assets/image-20190803113848257.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/网络/assets/image-20190803113848257.png -------------------------------------------------------------------------------- /网络/assets/image-20190803113934388.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/网络/assets/image-20190803113934388.png -------------------------------------------------------------------------------- /网络/assets/image-20190803114155913.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/网络/assets/image-20190803114155913.png -------------------------------------------------------------------------------- /网络/assets/image-20190803114210615.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/网络/assets/image-20190803114210615.png -------------------------------------------------------------------------------- /网络/assets/image-20190803114222157.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/网络/assets/image-20190803114222157.png -------------------------------------------------------------------------------- /网络/assets/image-20190803114234109.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/网络/assets/image-20190803114234109.png -------------------------------------------------------------------------------- /网络/assets/image-20190803120713093.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/网络/assets/image-20190803120713093.png -------------------------------------------------------------------------------- /网络/assets/image-20190803125537154.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/网络/assets/image-20190803125537154.png -------------------------------------------------------------------------------- /网络/assets/image-20190803135321710.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/网络/assets/image-20190803135321710.png -------------------------------------------------------------------------------- /面经/阿里/2.md: -------------------------------------------------------------------------------- 1 | 面经来源:[牛客网](https://www.nowcoder.com/discuss/234601?type=2&order=0&pos=8&page=1) 2 | 3 | 终于面上阿里新零售部门的一面了 4 | 5 | 1. 自我介绍 6 | 7 | 2. linux我了解的指令有哪些,平常遇到过linux性能问题吗,怎么排除的,日志统计文件是哪个命令? 8 | 9 | 帮助:`--help` `man` `info` `doc` 10 | 11 | 文件:`pwd` `cd` `ls` `mkdir` `rm -rf` `touch` `cp` `mv` `chomd` `cat` `more` `less` `tail` 12 | 13 | 搜索:`which` `whereis` `locate` `find / -name xxx` 14 | 15 | 进程:`ps` `pstree` `top -d` `netstat` 16 | 17 | 18 | 19 | 3. 给我讲讲tcp三次握手四次挥手,在什么是三次不是两次,为什么等待2MSL? 20 | 21 | **三次握手:** tcp建立连接需要进行三次握手,客户端向服务端发送 `SYN` 请求进入 `SYN-SENT` 状态,服务端回复 `SYN + ACK` 请求进入`SYN-RECV` 状态,客户端接收到 `SYN + ACK` 请求后进入`ESTABLISHED` 状态,并开始向服务端发送数据,服务端接收到数据后也进入 `ESTABLISHED` 状态,三次握手完成。 22 | 23 | **三次握手的目的:** 防止失效连接请求到达服务器,让服务器错误打开连接。 24 | 25 | **为什么不是两次握手:** 客户端发送的连接请求如果在网络中滞留,那么就会隔很长一段时间才能收到服务器端发回的连接确认。客户端等待一个超时重传时间之后,就会重新请求连接。但是这个滞留的连接请求最后还是会到达服务器,如果不进行三次握手,那么服务器就会打开两个连接。如果有第三次握手,客户端会忽略服务器之后发送的对滞留连接请求的连接确认,不进行第三次握手,因此就不会再次打开连接。 26 | 27 | **四次挥手:** 假设客户端发起关闭。 客户端向服务端发送 `FIN` 请求,进入 `FIN-WAIT1` 状态,服务端接收到后回复 `ACK` 请求,并进入 `CLOSE-WAIT` 状态,客户端接收到后,进入 `FIN-WAIT2` 状态,服务端此时继续发送未发送完毕的数据。数据发送完毕后,服务端发送 `FIN` 请求,并进入 `LAST-ACK` 状态,客户端接收到 `FIN` 请求后,回应 `ACK` 请求并进入 `TIME-WAIT` 状态,等待 `2MSL` 后进入 `CLOSE` 状态。服务端接收到 `ACK` 后进入 `CLOSE` 状态。 28 | 29 | **为什么等待2MSL:** 服务端发送了 `FIN` 请求后,客户端回应 `ACK`请求。由于网络原因,服务端在报文存活时间内未收到 `ACK` 请求,则会重新发送 `FIN` 请求。如果客户端进入了 `CLOSE` 状态,服务端将无法关闭,因此需要等待 `2MSL` 。 30 | 31 | **大量 `TIME_WAIT` 原因:** 在**高并发短连接**的TCP服务器上,当服务器处理完请求后立刻主动正常关闭连接。这个场景下会出现大量 `socket` 处于 `TIME_WAIT` 状态。如果客户端的并发量持续很高,此时部分客户端就会显示连接不上。 32 | 33 | **大量 `TIME_WAIT` 解决方案:** 34 | 35 | 修改 **/etc/sysctl.conf** 文件 36 | 37 | > 表示开启SYN Cookies,当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击 38 | > 39 | > net.ipv4.tcp_syncookies = 1 40 | > 41 | > 表示开启重用,允许将TIME-WAIT sockets重新用于新的TCP连接 42 | > 43 | > net.ipv4.tcp_tw_reuse = 1 44 | > 45 | > 表示开启TCP连接中TIME-WAIT sockets的快速回收 46 | > 47 | > net.ipv4.tcp_tw_recycle = 1 48 | > 49 | > 表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息 50 | > 51 | > net.ipv4.tcp_max_tw_buckets = 5000 52 | > 53 | > 表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数 54 | > 55 | > net.ipv4.tcp_max_syn_backlog = 8192 56 | > 57 | > 表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟 58 | > 59 | > net.ipv4.tcp_keepalive_time = 1200 60 | 61 | 62 | 63 | 4. 跟我说说redis数据类型以及应用场景,面试官看我说的不错,出了一个场景设计题目,怎么在redis中快速定位查找信息,我回答的不太好,说了排序啥的,一开始说了面试官提示说想想二分查找,还有其他复杂度更低的吗? 64 | 65 | | 数据类型 | 可以存储的值 | 操作 | 66 | | -------- | ---------------------- | ------------------------------------------------------------ | 67 | | STRING | 字符串、整数或者浮点数 | 对整个字符串或者字符串的其中一部分执行操作 对整数和浮点数执行自增或者自减操作 | 68 | | LIST | 列表 | 从两端压入或者弹出元素 对单个或者多个元素进行修剪, 只保留一个范围内的元素 | 69 | | SET | 无序集合 | 添加、获取、移除单个元素 检查一个元素是否存在于集合中 计算交集、并集、差集 从集合里面随机获取元素 | 70 | | HASH | 包含键值对的无序散列表 | 添加、获取、移除单个键值对 获取所有键值对 检查某个键是否存在 | 71 | | ZSET | 有序集合 | 添加、获取、删除元素 根据分值范围或者成员来获取元素 计算一个键的排名 | 72 | 73 | 1. 计数器 74 | 75 | 可以对 String 进行自增自减运算,从而实现计数器功能。Redis 这种内存型数据库的读写性能非常高,很适合存储频繁读写的计数量。 76 | 77 | 2. 缓存 78 | 79 | 将热点数据放到内存中,设置内存的最大使用量以及淘汰策略来保证缓存的命中率。 80 | 81 | 3. 查找表 82 | 83 | 例如 DNS 记录就很适合使用 Redis 进行存储。查找表和缓存类似,也是利用了 Redis 快速的查找特性。但是查找表的内容不能失效,而缓存的内容可以失效,因为缓存不作为可靠的数据来源。 84 | 85 | 4. 消息队列 86 | 87 | List 是一个双向链表,可以通过 lpush 和 rpop 写入和读取消息。不过最好使用 Kafka、RabbitMQ 等消息中间件。 88 | 89 | 5. 会话缓存 90 | 91 | 可以使用 Redis 来统一存储多台应用服务器的会话信息。当应用服务器不再存储用户的会话信息,也就不再具有状态,一个用户可以请求任意一个应用服务器,从而更容易实现高可用性以及可伸缩性。 92 | 93 | 6. 分布式锁实现 94 | 95 | 在分布式场景下,无法使用单机环境下的锁来对多个节点上的进程进行同步。可以使用 Redis 自带的 SETNX 命令实现分布式锁,除此之外,还可以使用官方提供的 RedLock 分布式锁实现。 96 | 97 | 7. 其它 98 | 99 | Set 可以实现交集、并集等操作,从而实现共同好友等功能。 100 | 101 | ZSet 可以实现有序性操作,从而实现排行榜等功能。 102 | 103 | 104 | 105 | 5. Mysql,为什么是B树而不是hash等? 106 | 107 | **为什么采用B+树** 108 | 109 | 1. 它是一颗平衡树,并且每一个节点都有很多子节点,使得树很矮,一般在4以内,使得查询效率很高。 110 | 2. B+树的叶子节点按顺序连接成了一个双向链表,使得范围查询效率很高,只用遍历链表即可。 111 | 3. 一个节点的大小等于一个页,这样每个节点只需要一次I/O就可以完全载入。 112 | 113 | **为什么不是Hash** 114 | 115 | 1. hash虽然查询速度快,但是不支持范围查询。 116 | 117 | 2. hash碰撞 118 | 119 | 3. 无法利用索引排序 120 | 121 | 4. 不支持最左匹配 122 | 123 | 124 | 125 | 6. 了解过java的输入流和输出流那些吗? 126 | 127 | ![image-20190827193159404](assets/image-20190827193159404.png) 128 | 129 | 7. 读过redis源码吗,spring源码吗? 130 | 131 | 没有,redis有看过《redis设计与实现》 132 | 133 | 134 | 135 | 8. 说说对spring ioc. 以及控制反转的理解? 136 | 137 | IOC(控制反转)是一种**设计思想**,就是 **将原本在程序中手动创建对象的控制权,交由Spring框架来管理。** IOC 容器是 Spring 用来实现 IOC 的载体, IOC 容器实际上就是个Map,存放的是各种对象。将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC 容器完成对象的注入。这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来。 **IoC 容器就像是一个工厂一样,当我们需要创建一个对象的时候,只需要配置好配置文件/注解即可,完全不用考虑对象是如何被创建出来的。** 138 | 139 | 140 | 141 | 9. 最后反问环节 142 | 143 | 问了面试官平常怎么处理技术难点的,面试官讲的头头是道,然后顺便征求学习建议 144 | 145 | -------------------------------------------------------------------------------- /面经/阿里/3.md: -------------------------------------------------------------------------------- 1 | 面经来源:[牛客网](https://www.nowcoder.com/discuss/234578?type=post&order=create&pos=&page=1) 2 | 3 | 1. HashMap,数据结构,怎么解决冲突? 4 | 5 | 数组+链表和红黑树 6 | 7 | 2. ConcurrentHashMap,性能会比较差吗?Cas是什么 8 | 9 | 3. 类加载过程 10 | 11 | 4. 堆的划分 12 | 13 | 5. 排序算法,讲一下堆排序 14 | 15 | 6. 二叉树遍历,讲一下中序遍历 16 | 17 | 7. TCP和UDP区别 18 | 19 | 8. cookie和session 20 | 21 | 9. 状态码,200,302 22 | 23 | 10. Mysql索引说一下,聚簇索引,非聚簇索引。sql优化 24 | 25 | 11. 实习最有挑战的!? 26 | 27 | 12. 怼分布式锁的设计 28 | 29 | 13. 缓存击穿问题 30 | 31 | 14. 双链表和单链表 32 | 33 | 15. 数组和链表 34 | 35 | 16. Spring Ioc,AOP,初始化流程 36 | 37 | 17. Spring Cloud了解哪些? 38 | 39 | 18. 线程池执行流程,拒绝策略有哪些 40 | 41 | 19. 怼项目 -------------------------------------------------------------------------------- /面经/阿里/README.md: -------------------------------------------------------------------------------- 1 | [1.阿里一面凉经](1.md) 2 | 3 | -------------------------------------------------------------------------------- /面经/阿里/assets/image-20190827193159404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanggegreat/CS-Tree/4072ddd392afa813932381cc9ed0652a03bc5058/面经/阿里/assets/image-20190827193159404.png --------------------------------------------------------------------------------