├── .gitattributes
├── .gitignore
├── .nojekyll
├── LICENSE
├── README.md
├── _coverpage.md
├── _sidebar.md
├── docs
├── Collection.md
├── Drools.md
├── Git.md
├── JUC.md
├── JVM.md
├── Linux.md
├── MySql.md
├── Mybatis.md
├── NetWork.md
├── Redis.md
├── Spring.md
├── SpringBoot.md
└── SpringCloud.md
├── favicon.ico
├── index.html
└── media
├── pictures
├── Collection.assets
│ ├── 031542494733474.png
│ ├── 1586522321227.png
│ ├── 1586530161293.png
│ ├── 1586600321902.png
│ ├── 1586673715667.png
│ ├── 1586678878099.png
│ ├── 1586679535828.png
│ ├── 1591855019306.png
│ ├── 1591855044381.png
│ ├── 1591855058758.png
│ ├── 1591855117657.png
│ ├── 1591855155154.png
│ ├── 620953-20190726223529160-967135077.png
│ ├── 67233764.jpg
│ ├── clipboard-1586947479092.png
│ └── clipboard.png
├── Drools.assets
│ ├── 10.png
│ ├── 11.png
│ ├── 12.png
│ ├── 13.png
│ ├── 14.png
│ ├── 15.png
│ ├── 16.png
│ ├── 17.png
│ ├── 18.png
│ ├── 19.png
│ ├── 20.png
│ ├── 21.png
│ ├── 22.png
│ ├── 23.png
│ ├── 24.png
│ ├── 25.png
│ ├── 26.png
│ ├── 27.png
│ ├── 28.png
│ ├── 29.png
│ ├── 30.png
│ ├── 31.png
│ ├── 32.png
│ ├── 33.png
│ ├── 34.png
│ ├── 35.png
│ ├── 36.png
│ ├── 37.png
│ ├── 38.png
│ ├── 39.png
│ ├── 4.png
│ ├── 40.png
│ ├── 41.png
│ ├── 42.png
│ ├── 43.png
│ ├── 44.png
│ ├── 45.png
│ ├── 5.png
│ ├── 8.png
│ ├── 9.png
│ ├── image-20200113154817582.png
│ ├── image-20200113155136957.png
│ ├── image-20200113155332666.png
│ ├── image-20200113155819517.png
│ ├── image-20200113160102668.png
│ ├── image-20200113160728259.png
│ ├── image-20200113162923877.png
│ ├── image-20200113163005061.png
│ ├── image-20200113163313305.png
│ ├── image-20200113163344174.png
│ ├── image-20200113163539676.png
│ ├── image-20200114163727767.png
│ ├── image-20200214132448956.png
│ ├── image-20200214202525859.png
│ ├── image-20200217160930138.png
│ ├── image-20200218105819932.png
│ └── image-20200218120618384.png
├── JUC.assets
│ ├── 1587439674710.png
│ ├── 1587439715060.png
│ ├── 1591855866847.png
│ ├── 1591855884494.png
│ ├── 1591855933076.png
│ ├── 1591855993252.png
│ ├── 1591856012716.png
│ ├── volatile关键字的可见性.png
│ └── 数据不一致.png
├── Linux.assets
│ ├── 1585882274571-1588243560477.png
│ ├── 1585882387300-1588243560479.png
│ ├── 1588237066015.png
│ ├── 1588240540192.png
│ └── 1588242904651.png
├── MySql.assets
│ ├── 1104082-20170226015714054-85509796.png
│ ├── 1104082-20170226020236195-1260049812.png
│ ├── 1104082-20170226021558210-635714085.png
│ ├── 1104082-20170226021913023-31075463.png
│ ├── 1104082-20170226022145538-205031549.png
│ ├── 1104082-20170226022446179-827444722.png
│ ├── 1104082-20170226022911710-1188849130.png
│ ├── 1104082-20170226023222945-1965432269.png
│ ├── 1216484-20190825002227995-188371311.png
│ ├── 1216484-20190825002311121-524783044.png
│ ├── 1395687-20190514091613619-1312062639.png
│ ├── 1586957379982.png
│ ├── 1586963200056.png
│ ├── 1586963416248.png
│ ├── 1586963579924.png
│ ├── 1587010722777.png
│ ├── 1587010757484.png
│ ├── 1587016917857.png
│ ├── 1587023865165.png
│ ├── 1587024092429.png
│ ├── 1587097704600.png
│ ├── 1587097929883.png
│ ├── 1587105563111.png
│ ├── 1587120003820.png
│ ├── 1587186663559.png
│ ├── 1587186724075.png
│ ├── 1587224210490.png
│ ├── 1587224238456.png
│ ├── 1587224256728.png
│ ├── 1587224297397.png
│ ├── 1644694-20190505155016157-1108127109.png
│ ├── 1644694-20190505155026646-1387513390.png
│ ├── 169fab4ad1e262c7
│ ├── 169fab4ae00ad805
│ ├── 169fab4ae1b1e740
│ ├── 169fab4ae260d343
│ ├── 169fab4ae468dd5f
│ ├── 169fab4aeeea3142
│ ├── 169fab4af64502e8
│ ├── 169fab4affd9796f
│ ├── 169fab4b0047390e
│ ├── 169fab4b06548ad2
│ ├── 169fab4b06d96e59
│ ├── 169fab4b14bfcb89
│ ├── 169fab4b1c978ec4
│ ├── 169fab4b23724f6c
│ ├── 169fab4b25c75f18
│ ├── 169fab4b25c75f18-1587224765941
│ ├── 169fab4b2c6ecb0a
│ ├── 169fab4b3331840f
│ ├── 169fab4b38f8b6a9
│ ├── 169fab4b4082bcd3
│ ├── 169fab4b4450f7a8
│ ├── 169fab4b555acbb1
│ ├── 169fab4b563095df
│ ├── 169fab4b5cd19ef9
│ ├── 169fab4b5f67f5db
│ ├── 169fab4b627a3aa3
│ ├── 169fab4b7a2dd2ac
│ ├── 169fab4b7c297188
│ ├── 169fab4b80770fc3
│ ├── 169fab4b81039ab4
│ ├── 169fab4b97c18e40
│ ├── 169fab4b992d6c22
│ ├── 940884-20190129111427216-1965281810.png
│ ├── 940884-20190129111443667-1089405966.png
│ ├── 940884-20190129111500436-1212656786.png
│ ├── 940884-20190129111702299-1368712722.png
│ ├── 940884-20190129111711788-545661817.png
│ ├── B+树二级索引(辅助索引).png
│ ├── B+树索引.png
│ ├── Mysql索引文件截图.png
│ ├── mysql-engines.png
│ ├── 事务特性.png
│ └── 查看表的存储引擎.png
├── Mybatis.assets
│ ├── 1588578489385_数据库、.png
│ ├── 37d3d539b6003af38427311c555ea05a1138b6ac.jpeg
│ ├── 6d81800a19d8bc3e953df07fe2ffc018a9d345cc.jpeg
│ └── b151f8198618367a5e108e327107edd2b21ce53b.jpeg
├── Redis.assets
│ ├── 1586705737024.png
│ ├── 1586760599707.png
│ ├── 1586760870677.png
│ ├── 1586767247276.png
│ ├── 6078367.jpg
│ ├── image-20210225011159324.png
│ ├── 布隆过滤器-缓存穿透-redis.png
│ ├── 正常缓存处理流程-redis.png
│ └── 缓存穿透处理流程-redis.png
└── SpringCloud.assets
│ ├── clipboard.png
│ ├── image-20201222090455797.png
│ ├── image-20201222090512129.png
│ ├── image-20201222090531185.png
│ └── image-20210223153533186.png
└── xmind
├── Docker.xmind
├── Drools.xmind
├── Git.xmind
├── JUC.xmind
├── JVM.xmind
├── Linux.xmind
├── Mybatis.xmind
├── Mysql.xmind
├── Network.xmind
├── Redis.xmind
├── Spring.xmind
├── SpringCloud2020.xmind
└── 算法.xmind
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 | *.js linguist-language=java
3 | *.css linguist-language=java
4 | *.html linguist-language=java
5 | *.md linguist-language=java
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /**/target/
2 | /**/.settings/
3 | /**/log/
4 | /**/logs/
5 | /**/.idea/
6 | /**/.project
7 | /**/.classpath
8 | /**/.log
9 | /**/*.iml
10 | /**/.DS_Store
11 | /**/.factorypath
12 | *.epoch
13 |
--------------------------------------------------------------------------------
/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/.nojekyll
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # JavaInterview
2 |
3 | - [个人博客](https://happysnail.cn/) 欢迎访问!
4 |
5 | - [Gitee 在线阅读地址](https://happysnailsunshine.gitee.io/javainterview)(速度更快,图片可以快速加载出来)
6 | - [Github 在线阅读地址](https://happysnail.cn/JavaInterview/)(速度相对较慢)
7 | - Github:https://github.com/HappySnailSunshine/JavaInterview.git
8 | - 码云:https://gitee.com/HappySnailSunshine/JavaInterview.git
9 |
10 |
11 |
12 |
13 | ## 作者介绍
14 |
15 | **作者介绍:** 笔者是19年本科毕业,现在在成都这边做后端开发工作,是一名对技术有追求的开发者。希望记录下自己学习和成长的历程,并和大家一起交流学习。
16 |
17 |
18 |
19 | ## 初心
20 |
21 | - 热爱可低岁月漫长,希望可以让分享成为我的一种习惯,也可以让自己在过程中变得更加优秀;
22 | - 当学习完一个知识点以后,自己做笔记,同时事后要总结,如果自己能把一个知识清晰表达出来的时候,自己也是有很大的收获和成长的;
23 | - 赠人玫瑰手留余香。
24 |
25 |
26 |
27 | ## 目录
28 |
29 | ### 学习知识相关
30 |
31 | * Java
32 |
33 | * [JVM虚拟机](./docs/JVM.md)
34 | * [JUC高并发](./docs/JUC.md)
35 | * [集合数据结构](./docs/Collection.md)
36 | * 计算机基础
37 |
38 | * [计算机网络](./docs/NetWork.md)
39 | * 数据库
40 | - [MySql](./docs/MySql.md)
41 | - [Redis](./docs/Redis.md)
42 |
43 | - 规则引擎
44 | - [Drools](./docs/Drools.md)
45 | - 常用框架
46 | - [Spring](./docs/Spring.md)
47 | - [SpringBoot](./docs/SpringBoot.md)
48 | - [SpringCloud](./docs/SpringCloud.md)
49 | - [Mybatis](./docs/Mybatis.md)
50 | - 工具
51 | - [Git](./docs/Git.md)
52 | - [Linux](./docs/Linux.md)
53 |
54 |
55 |
56 | ## 学习方法
57 |
58 | - [费曼学习法](https://baike.baidu.com/item/%E8%B4%B9%E6%9B%BC%E5%AD%A6%E4%B9%A0%E6%B3%95/50895393?fr=aladdin) 认真理解并去实践这个方法。个人认为这个方法有几个好处:
59 |
60 | - 其一、在讲授的过程中,会对要学习的这个概念印象特别深刻;
61 | - 其二、因为我们做开发平时说话较少,讲授知识的过程可以锻炼自己的语言表达能力,语言组织能力,思维能力;
62 | - 其三、前两个优点加起来,在面试的时候,就可以和面试官侃侃而谈;
63 |
64 | 这个方法可以简化为四个单词(这里不是按照顺序排列的):Concept (概念)、Teach (教给别人)、Review (回顾)、Simplify (简化)。具体操作分为下面四步:
65 |
66 | - 第一步:把它教给一个小孩子;
67 | - 第二步:回顾;
68 | - 第三步:将语言条理化,简化;
69 | - 第四步(可选):传授
70 |
71 | - 稍微简单的知识,自己通过书籍、博客、Github上面的开源项目,进行学习,并自己写代码实际操作总结。
72 |
73 | - 稍微复杂一点的知识,可以先看看学习视频(比如B站一些学习视频,然后自己深入学习可以看书或者看文档、GitHub上面开源项目),并进行总结。有一些知识先试着用起来,代到项目中,或者看使用到这个技术的开源项目,然后再深挖底层原理,可能会好理解一些。
74 |
75 | - 每天选择一两篇写的好的博客,进行认真学习,总结。不管关注的公众号多少,或者看的博客多少,只有自己仔细研读过的文章,并进行总结,才可能消化里面的知识。
76 |
77 | - 最后一条,保证效率的情况下,坚持前面几条。
78 |
79 |
80 |
81 | ## 说明
82 |
83 | - 笔者有一部分是在学习过程中参考其他作者的开源项目,如有内容侵权请联系删除。
84 | - 文件夹/media/xmind 下面有一些思维导图,有一些是笔者自己在学习过程中为了梳理知识点,自己画的,还有一些是看到其他作者画的比较好的,我作为参考保存下来的。如果有喜欢的小伙伴,可以作为参考。
85 | - 由于作者水平有限,笔记有很多不完善之处,望谅解。
86 | - 有些知识只有一个提纲,内容没有写完,笔者会在一步一步完善。
87 | - 如果你觉得项目还不错,欢迎Star,满足一下我的虚荣心(^_^)。
--------------------------------------------------------------------------------
/_coverpage.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | JavaInterview
5 |
6 |
7 | [GitHub](https://github.com/HappySnailSunshine/JavaInterview.git)
8 | [开始阅读](#JavaInterview)
--------------------------------------------------------------------------------
/_sidebar.md:
--------------------------------------------------------------------------------
1 | * Java
2 |
3 | * [JVM虚拟机](./docs/JVM.md)
4 | * [JUC高并发](./docs/JUC.md)
5 | * [集合数据结构](./docs/Collection.md)
6 | * 计算机基础
7 |
8 | * [计算机网络](./docs/NetWork.md)
9 | * 数据库
10 | - [MySql](./docs/MySql.md)
11 | - [Redis](./docs/Redis.md)
12 |
13 | - 规则引擎
14 | - [Drools](./docs/Drools.md)
15 | - 常用框架
16 | - [Spring](./docs/Spring.md)
17 | - [SpringBoot](./docs/SpringBoot.md)
18 | - [SpringCloud](./docs/SpringCloud.md)
19 | - [Mybatis](./docs/Mybatis.md)
20 | - 工具
21 | - [Git版本控制工具](./docs/Git.md)
22 | - [Linux](./docs/Linux.md)
--------------------------------------------------------------------------------
/docs/Git.md:
--------------------------------------------------------------------------------
1 | # Git
2 |
3 | # Interview
4 |
5 | 1、Git代码被覆盖了怎么办?
6 |
7 | 2、用户的特征信息?
8 |
9 | 3、你们的git的开发模式是怎样的?是怎么管理不同的功能?
10 |
11 | 4、有两个不同的需求,你们是怎么处理git的?
12 |
13 | 5、你们团队中如果一个人提交错了,你们后面是怎么处理的
14 |
15 | 6、代码管理工具是什么?git用过没?你写了三四天代码然后push,冲突,你把别人代码覆盖了怎么解决?回答:回退,问:那你自己代码不要了?
16 |
17 | 7、删除提交到本地仓库的文件?
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/docs/JVM.md:
--------------------------------------------------------------------------------
1 | # JVM
2 |
3 | # Interview
4 |
5 | ## 1.新生代包含的区域(牛客题)
6 |
7 | **Java** **中的堆是** **JVM** **所管理的最**大的一块内存空间,主要用于存放各种类的实例对象。
8 |
9 | 在 **Java** 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )。新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor。
10 | 这样划分的目的是为了使 **JVM** 能够更好的管理堆内存中的对象,包括内存的分配以及回收。
11 | 堆的内存模型大致为:
12 |
13 | 
14 |
15 |
16 |
17 |
18 |
19 | 从图中可以看出: 堆大小 = 新生代 + 老年代。其中,堆的大小可以通过参数 –Xms、-Xmx 来指定。
20 |
21 | ## 2.JMM(Java内存模型(Java Memory Model)
22 |
23 | JMM就是一种符合内存模型规范的,屏蔽了各种硬件和操作系统的访问差异的,保证了Java程序在各种平台下对内存的访问都能保证效果一致的机制及规范。
24 |
25 |
26 |
27 | Java线程之间的通信由Java内存模型(简称为JMM)控制,JMM决定一个线程对共享变量的写入何时对另一个线程可见。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化
28 |
29 | volatile变量的写-读可以实现线程之间的通信。
30 |
31 | 从内存语义的角度来说,volatile与监视器锁有相同的效果:volatile写和监视器的释放有相同的内存语义;volatile读与监视器的获取有相同的内存语义。
32 |
33 |
34 |
35 | **下面的是博客看到的:**
36 |
37 | 在Java内存模型中,描述了在多线程代码中,哪些行为是正确的、合法的,以及多线程之间如何进行通信,代码中变量的读写行为如何反应到内存、CPU缓存的底层细节。
38 |
39 | 在Java中包含了几个关键字:volatile、final和synchronized,帮助程序员把代码中的并发需求描述给编译器。Java内存模型中定义了它们的行为,确保正确同步的Java代码在所有的处理器架构上都能正确执行。
40 |
41 |
42 |
43 | 参考:https://www.jianshu.com/p/bf158fbb2432
44 |
45 |
46 |
47 | 简答内存模型的时候,最好再答上内存区域。有些面试官也没分清楚。
48 |
49 | ## 3.下面有关java内存模型的描述,说法错误的是?(没搞清 然后看看)
50 |
51 | 正确答案: D 你的答案: B (错误)
52 |
53 | ```
54 | A、JMM通过控制主内存与每个线程的本地内存之间的交互,来为java程序员提供内存可见性保证
55 | B、“synchronized” — 保证在块开始时都同步主内存的值到工作内存,而块结束时将变量同步回主内存
56 | C、“volatile” — 保证修饰后在对变量读写前都会与主内存更新。
57 | D、如果在一个线程构造了一个不可变对象之后(对象仅包含final字段),就可以保证了这个对象被其他线程正确的查看
58 | ```
59 |
60 |
61 |
62 | ## 4.垃圾回收算法
63 |
64 | 
65 |
66 | ### 3.1 标记-清除算法
67 |
68 | 该算法分为“标记”和“清除”阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。它是最基础的收集算法,后续的算法都是对其不足进行改进得到。这种垃圾收集算法会带来两个明显的问题:
69 |
70 | 1. **效率问题**
71 | 2. **空间问题(标记清除后会产生大量不连续的碎片)**
72 | 3. 
73 |
74 | ### 3.2 复制算法
75 |
76 | 为了解决效率问题,“复制”收集算法出现了。它可以将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。这样就使每次的内存回收都是对内存区间的一半进行回收。
77 |
78 | 
79 |
80 | ### 3.3 标记-整理算法
81 |
82 | 根据老年代的特点提出的一种标记算法,标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象回收,而是让所有存活的对象向一端移动,然后直接清理掉端边界以外的内存。
83 |
84 | 
85 |
86 | ### 3.4 分代收集算法
87 |
88 | 当前虚拟机的垃圾收集都采用分代收集算法,这种算法没有什么新的思想,只是根据对象存活周期的不同将内存分为几块。一般将 java 堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。
89 |
90 | **比如在新生代中,每次收集都会有大量对象死去,所以可以选择复制算法,只需要付出少量对象的复制成本就可以完成每次垃圾收集。而老年代的对象存活几率是比较高的,而且没有额外的空间对它进行分配担保,所以我们必须选择“标记-清除”或“标记-整理”算法进行垃圾收集。**
91 |
92 | **延伸面试问题:** HotSpot 为什么要分为新生代和老年代?
93 |
94 | 根据上面的对分代收集算法的介绍回答。
95 |
96 | ## 4 垃圾收集器
97 |
98 | 
99 |
100 | **如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。**
101 |
102 | 虽然我们对各个收集器进行比较,但并非要挑选出一个最好的收集器。因为直到现在为止还没有最好的垃圾收集器出现,更加没有万能的垃圾收集器,**我们能做的就是根据具体应用场景选择适合自己的垃圾收集器**。试想一下:如果有一种四海之内、任何场景下都适用的完美收集器存在,那么我们的 HotSpot 虚拟机就不会实现那么多不同的垃圾收集器了。
103 |
104 |
105 |
106 | #### 4.1 Serial 收集器
107 |
108 | Serial(串行)收集器收集器是最基本、历史最悠久的垃圾收集器了。大家看名字就知道这个收集器是一个单线程收集器了。它的 **“单线程”** 的意义不仅仅意味着它只会使用一条垃圾收集线程去完成垃圾收集工作,更重要的是它在进行垃圾收集工作的时候必须暂停其他所有的工作线程( **"Stop The World"** ),直到它收集结束。
109 |
110 | **新生代采用复制算法,老年代采用标记-整理算法。**
111 | 
112 |
113 | 虚拟机的设计者们当然知道 Stop The World 带来的不良用户体验,所以在后续的垃圾收集器设计中停顿时间在不断缩短(仍然还有停顿,寻找最优秀的垃圾收集器的过程仍然在继续)。
114 |
115 | 但是 Serial 收集器有没有优于其他垃圾收集器的地方呢?当然有,它**简单而高效(与其他收集器的单线程相比)**。Serial 收集器由于没有线程交互的开销,自然可以获得很高的单线程收集效率。Serial 收集器对于运行在 Client 模式下的虚拟机来说是个不错的选择。
116 |
117 | #### 4.2 ParNew 收集器
118 |
119 | **ParNew 收集器其实就是 Serial 收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为(控制参数、收集算法、回收策略等等)和 Serial 收集器完全一样。**
120 |
121 | **新生代采用复制算法,老年代采用标记-整理算法。**
122 | 
123 |
124 | 它是许多运行在 Server 模式下的虚拟机的首要选择,除了 Serial 收集器外,只有它能与 CMS 收集器(真正意义上的并发收集器,后面会介绍到)配合工作。
125 |
126 | **并行和并发概念补充:**
127 |
128 | - **并行(Parallel)** :指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。
129 | - **并发(Concurrent)**:指用户线程与垃圾收集线程同时执行(但不一定是并行,可能会交替执行),用户程序在继续运行,而垃圾收集器运行在另一个 CPU 上。
130 |
131 | #### 4.3 Parallel Scavenge 收集器
132 |
133 | Parallel Scavenge 收集器也是使用复制算法的多线程收集器,它看上去几乎和ParNew都一样。 **那么它有什么特别之处呢?**
134 |
135 | ```
136 | -XX:+UseParallelGC
137 |
138 | 使用 Parallel 收集器+ 老年代串行
139 |
140 | -XX:+UseParallelOldGC
141 |
142 | 使用 Parallel 收集器+ 老年代并行
143 |
144 | ```
145 |
146 | **Parallel Scavenge 收集器关注点是吞吐量(高效率的利用 CPU)。CMS 等垃圾收集器的关注点更多的是用户线程的停顿时间(提高用户体验)。所谓吞吐量就是 CPU 中用于运行用户代码的时间与 CPU 总消耗时间的比值。** Parallel Scavenge 收集器提供了很多参数供用户找到最合适的停顿时间或最大吞吐量,如果对于收集器运作不太了解的话,手工优化存在困难的话可以选择把内存管理优化交给虚拟机去完成也是一个不错的选择。
147 |
148 | **新生代采用复制算法,老年代采用标记-整理算法。**
149 | 
150 |
151 | #### 4.4.Serial Old 收集器
152 |
153 | **Serial 收集器的老年代版本**,它同样是一个单线程收集器。它主要有两大用途:一种用途是在 JDK1.5 以及以前的版本中与 Parallel Scavenge 收集器搭配使用,另一种用途是作为 CMS 收集器的后备方案。
154 |
155 | #### 4.5 Parallel Old 收集器
156 |
157 | **Parallel Scavenge 收集器的老年代版本**。使用多线程和“标记-整理”算法。在注重吞吐量以及 CPU 资源的场合,都可以优先考虑 Parallel Scavenge 收集器和 Parallel Old 收集器。
158 |
159 | #### 4.6 CMS 收集器
160 |
161 | **CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。它非常符合在注重用户体验的应用上使用。**
162 |
163 | **CMS(Concurrent Mark Sweep)收集器是 HotSpot 虚拟机第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作。**
164 |
165 | 从名字中的**Mark Sweep**这两个词可以看出,CMS 收集器是一种 **“标记-清除”算法**实现的,它的运作过程相比于前面几种垃圾收集器来说更加复杂一些。整个过程分为四个步骤:
166 |
167 | - **初始标记:** 暂停所有的其他线程,并记录下直接与 root 相连的对象,速度很快 ;
168 | - **并发标记:** 同时开启 GC 和用户线程,用一个闭包结构去记录可达对象。但在这个阶段结束,这个闭包结构并不能保证包含当前所有的可达对象。因为用户线程可能会不断的更新引用域,所以 GC 线程无法保证可达性分析的实时性。所以这个算法里会跟踪记录这些发生引用更新的地方。
169 | - **重新标记:** 重新标记阶段就是为了修正并发标记期间因为用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段的时间稍长,远远比并发标记阶段时间短
170 | - **并发清除:** 开启用户线程,同时 GC 线程开始对为标记的区域做清扫。
171 |
172 | 
173 |
174 | 从它的名字就可以看出它是一款优秀的垃圾收集器,主要优点:**并发收集、低停顿**。但是它有下面三个明显的缺点:
175 |
176 | - **对 CPU 资源敏感;**
177 | - **无法处理浮动垃圾;**
178 | - **它使用的回收算法-“标记-清除”算法会导致收集结束时会有大量空间碎片产生。**
179 |
180 | #### 4.7 G1 收集器
181 |
182 | **G1 (Garbage-First) 是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器. 以极高概率满足 GC 停顿时间要求的同时,还具备高吞吐量性能特征.**
183 |
184 | 被视为 JDK1.7 中 HotSpot 虚拟机的一个重要进化特征。它具备一下特点:
185 |
186 | - **并行与并发**:G1 能充分利用 CPU、多核环境下的硬件优势,使用多个 CPU(CPU 或者 CPU 核心)来缩短 Stop-The-World 停顿时间。部分其他收集器原本需要停顿 Java 线程执行的 GC 动作,G1 收集器仍然可以通过并发的方式让 java 程序继续执行。
187 | - **分代收集**:虽然 G1 可以不需要其他收集器配合就能独立管理整个 GC 堆,但是还是保留了分代的概念。
188 | - **空间整合**:与 CMS 的“标记--清理”算法不同,G1 从整体来看是基于“标记整理”算法实现的收集器;从局部上来看是基于“复制”算法实现的。
189 | - **可预测的停顿**:这是 G1 相对于 CMS 的另一个大优势,降低停顿时间是 G1 和 CMS 共同的关注点,但 G1 除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为 M 毫秒的时间片段内。
190 |
191 | G1 收集器的运作大致分为以下几个步骤:
192 |
193 | - **初始标记**
194 | - **并发标记**
195 | - **最终标记**
196 | - **筛选回收**
197 |
198 | **G1 收集器在后台维护了一个优先列表,每次根据允许的收集时间,优先选择回收价值最大的 Region(这也就是它的名字 Garbage-First 的由来)**。这种使用 Region 划分内存空间以及有优先级的区域回收方式,保证了 G1 收集器在有限时间内可以尽可能高的收集效率(把内存化整为零)。
199 |
200 |
201 |
202 | ## 5.JVM内存区域
203 |
204 | Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分成若干个不同的数据区域。JDK. 1.8 和之前的版本略有不同,下面会介绍到。
205 |
206 | **JDK 1.8 之前:**
207 |
208 |
209 |
210 |
211 |
212 |
213 | **JDK 1.8 :**
214 |
215 |
216 |
217 |
218 |
219 |
220 | **线程私有的:**
221 |
222 | - 程序计数器
223 | - 虚拟机栈
224 | - 本地方法栈
225 |
226 | **线程共享的:**
227 |
228 | - 堆
229 | - 方法区
230 | - 直接内存 (非运行时数据区的一部分)
231 |
232 |
233 |
234 | #### 2.1 程序计数器
235 |
236 | 程序计数器是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器。**字节码解释器工作时通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等功能都需要依赖这个计数器来完成。**
237 |
238 | 另外,**为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各线程之间计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。**
239 |
240 | **从上面的介绍中我们知道程序计数器主要有两个作用:**
241 |
242 | 1. 字节码解释器通过改变程序计数器来依次读取指令,从而实现代码的流程控制,如:顺序执行、选择、循环、异常处理。
243 | 2. 在多线程的情况下,程序计数器用于记录当前线程执行的位置,从而当线程被切换回来的时候能够知道该线程上次运行到哪儿了。
244 |
245 | **注意:程序计数器是唯一一个不会出现 OutOfMemoryError 的内存区域,它的生命周期随着线程的创建而创建,随着线程的结束而死亡。**
246 |
247 | #### 2.2 Java 虚拟机栈
248 |
249 | **与程序计数器一样,Java 虚拟机栈也是线程私有的,它的生命周期和线程相同,描述的是 Java 方法执行的内存模型,每次方法调用的数据都是通过栈传递的。**
250 |
251 | **Java 内存可以粗糙的区分为堆内存(Heap)和栈内存 (Stack),其中栈就是现在说的虚拟机栈,或者说是虚拟机栈中局部变量表部分。** (实际上,Java 虚拟机栈是由一个个栈帧组成,而每个栈帧中都拥有:局部变量表、操作数栈、动态链接、方法出口信息。)
252 |
253 | **局部变量表主要存放了编译器可知的各种数据类型**(boolean、byte、char、short、int、float、long、double)、**对象引用**(reference 类型,它不同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或其他与此对象相关的位置)。
254 |
255 | **Java 虚拟机栈会出现两种错误:StackOverFlowError 和 OutOfMemoryError。**
256 |
257 | - **StackOverFlowError:** 若 Java 虚拟机栈的内存大小不允许动态扩展,那么当线程请求栈的深度超过当前 Java 虚拟机栈的最大深度的时候,就抛出 StackOverFlowError 错误。
258 | - **OutOfMemoryError:** 若 Java 虚拟机栈的内存大小允许动态扩展,且当线程请求栈时内存用完了,无法再动态扩展了,此时抛出 OutOfMemoryError 错误。
259 |
260 | Java 虚拟机栈也是线程私有的,每个线程都有各自的 Java 虚拟机栈,而且随着线程的创建而创建,随着线程的死亡而死亡。
261 |
262 | **扩展:那么方法/函数如何调用?**
263 |
264 | Java 栈可用类比数据结构中栈,Java 栈中保存的主要内容是栈帧,每一次函数调用都会有一个对应的栈帧被压入 Java 栈,每一个函数调用结束后,都会有一个栈帧被弹出。
265 |
266 | Java 方法有两种返回方式:
267 |
268 | 1. return 语句。
269 | 2. 抛出异常。
270 |
271 | 不管哪种返回方式都会导致栈帧被弹出。
272 |
273 |
274 |
275 | 补充:
276 |
277 | **内存溢出:**(out of memory)通俗理解就是内存不够,通常在运行大型软件或游戏时,软件或游戏所需要的内存远远超出了你主机内安装的内存所承受大小,就叫内存溢出。
278 |
279 | **内存泄漏:**(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果
280 |
281 | 参考:https://blog.csdn.net/weixin_42665577/article/details/81944939
282 |
283 | #### 2.3 本地方法栈
284 |
285 | 和虚拟机栈所发挥的作用非常相似,区别是: **虚拟机栈为虚拟机执行 Java 方法 (也就是字节码)服务,而本地方法栈则为虚拟机使用到的 Native 方法服务。** 在 HotSpot 虚拟机中和 Java 虚拟机栈合二为一。
286 |
287 | 本地方法被执行的时候,在本地方法栈也会创建一个栈帧,用于存放该本地方法的局部变量表、操作数栈、动态链接、出口信息。
288 |
289 | 方法执行完毕后相应的栈帧也会出栈并释放内存空间,也会出现 StackOverFlowError 和 OutOfMemoryError 两种错误。
290 |
291 | #### 2.4 堆
292 |
293 | Java 虚拟机所管理的内存中最大的一块,Java 堆是所有线程共享的一块内存区域,在虚拟机启动时创建。**此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例以及数组都在这里分配内存。**
294 |
295 | Java 堆是垃圾收集器管理的主要区域,因此也被称作**GC 堆(Garbage Collected Heap)**.从垃圾回收的角度,由于现在收集器基本都采用分代垃圾收集算法,所以 Java 堆还可以细分为:新生代和老年代:再细致一点有:Eden 空间、From Survivor、To Survivor 空间等。**进一步划分的目的是更好地回收内存,或者更快地分配内存。**
296 |
297 | 在 JDK 7 版本及JDK 7 版本之前,堆内存被通常被分为下面三部分:
298 |
299 | 1. 新生代内存(Young Generation)
300 |
301 | 2. 老生代(Old Generation)
302 |
303 | 3. 永生代(Permanent Generation
304 |
305 | 
306 |
307 | JDK 8 版本之后方法区(HotSpot 的永久代)被彻底移除了(JDK1.7 就已经开始了),取而代之是元空间,元空间使用的是直接内存。
308 |
309 | 
310 |
311 | **上图所示的 Eden 区、两个 Survivor 区都属于新生代(为了区分,这两个 Survivor 区域按照顺序被命名为 from 和 to),中间一层属于老年代。**
312 |
313 | 大部分情况,对象都会首先在 Eden 区域分配,在一次新生代垃圾回收后,如果对象还存活,则会进入 s0 或者 s1,并且对象的年龄还会加 1(Eden 区->Survivor 区后对象的初始年龄变为 1),当它的年龄增加到一定程度(默认为 15 岁),就会被晋升到老年代中。对象晋升到老年代的年龄阈值,可以通过参数 `-XX:MaxTenuringThreshold` 来设置。
314 |
315 | > 修正([issue552](https://github.com/Snailclimb/JavaGuide/issues/552)):“Hotspot遍历所有对象时,按照年龄从小到大对其所占用的大小进行累积,当累积的某个年龄大小超过了survivor区的一半时,取这个年龄和MaxTenuringThreshold中更小的一个值,作为新的晋升年龄阈值”。
316 | >
317 | > **动态年龄计算的代码如下**
318 | >
319 | > ```c++
320 | > uint ageTable::compute_tenuring_threshold(size_t survivor_capacity) {
321 | > //survivor_capacity是survivor空间的大小
322 | > size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100);
323 | > size_t total = 0;
324 | > uint age = 1;
325 | > while (age < table_size) {
326 | > total += sizes[age];//sizes数组是每个年龄段对象大小
327 | > if (total > desired_survivor_size) break;
328 | > age++;
329 | > }
330 | > uint result = age < MaxTenuringThreshold ? age : MaxTenuringThreshold;
331 | > ...
332 | > }
333 | >
334 | > ```
335 | >
336 | >
337 |
338 | 堆这里最容易出现的就是 OutOfMemoryError 错误,并且出现这种错误之后的表现形式还会有几种,比如:
339 |
340 | 1. **`OutOfMemoryError: GC Overhead Limit Exceeded`** : 当JVM花太多时间执行垃圾回收并且只能回收很少的堆空间时,就会发生此错误。
341 | 2. **`java.lang.OutOfMemoryError: Java heap space`** :假如在创建新的对象时, 堆内存中的空间不足以存放新创建的对象, 就会引发`java.lang.OutOfMemoryError: Java heap space` 错误。(和本机物理内存无关,和你配置的内存大小有关!)
342 | 3. ......
343 |
344 | #### 2.5 方法区
345 |
346 | 方法区与 Java 堆一样,是各个线程共享的内存区域,它用于**存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据**。虽然 **Java 虚拟机规范把方法区描述为堆的一个逻辑部分**,但是它却有一个别名叫做 **Non-Heap(非堆)**,目的应该是与 Java 堆区分开来。
347 |
348 | 方法区也被称为永久代。很多人都会分不清方法区和永久代的关系,为此我也查阅了文献。
349 |
350 | ##### 2.5.1 方法区和永久代的关系
351 |
352 | > 《Java 虚拟机规范》只是规定了有方法区这么个概念和它的作用,并没有规定如何去实现它。那么,在不同的 JVM 上方法区的实现肯定是不同的了。 **方法区和永久代的关系很像 Java 中接口和类的关系,类实现了接口,而永久代就是 HotSpot 虚拟机对虚拟机规范中方法区的一种实现方式。** 也就是说,永久代是 HotSpot 的概念,方法区是 Java 虚拟机规范中的定义,是一种规范,而永久代是一种实现,一个是标准一个是实现,其他的虚拟机实现并没有永久代这一说法。
353 |
354 | ##### 2.5.2 常用参数
355 |
356 | JDK 1.8 之前永久代还没被彻底移除的时候通常通过下面这些参数来调节方法区大小
357 |
358 | ```java
359 | -XX:PermSize=N //方法区 (永久代) 初始大小
360 | -XX:MaxPermSize=N //方法区 (永久代) 最大大小,超过这个值将会抛出 OutOfMemoryError 异常:java.lang.OutOfMemoryError: PermGen
361 | ```
362 |
363 | 相对而言,垃圾收集行为在这个区域是比较少出现的,但并非数据进入方法区后就“永久存在”了。
364 |
365 | JDK 1.8 的时候,方法区(HotSpot 的永久代)被彻底移除了(JDK1.7 就已经开始了),取而代之是元空间,元空间使用的是直接内存。
366 |
367 | 下面是一些常用参数:
368 |
369 | ```java
370 | -XX:MetaspaceSize=N //设置 Metaspace 的初始(和最小大小)
371 | -XX:MaxMetaspaceSize=N //设置 Metaspace 的最大大小
372 | ```
373 |
374 | 与永久代很大的不同就是,如果不指定大小的话,随着更多类的创建,虚拟机会耗尽所有可用的系统内存。
375 |
376 | ##### 2.5.3 为什么要将永久代 (PermGen) 替换为元空间 (MetaSpace) 呢?
377 |
378 | 1. 整个永久代有一个 JVM 本身设置固定大小上限,无法进行调整,而元空间使用的是直接内存,受本机可用内存的限制,虽然元空间仍旧可能溢出,但是比原来出现的几率会更小。
379 |
380 | > 当你元空间溢出时会得到如下错误: `java.lang.OutOfMemoryError: MetaSpace`
381 |
382 | 你可以使用 `-XX:MaxMetaspaceSize` 标志设置最大元空间大小,默认值为 unlimited,这意味着它只受系统内存的限制。`-XX:MetaspaceSize` 调整标志定义元空间的初始大小如果未指定此标志,则 Metaspace 将根据运行时的应用程序需求动态地重新调整大小。
383 |
384 | 2. 元空间里面存放的是类的元数据,这样加载多少类的元数据就不由 `MaxPermSize` 控制了, 而由系统的实际可用空间来控制,这样能加载的类就更多了。
385 | 3. 在 JDK8,合并 HotSpot 和 JRockit 的代码时, JRockit 从来没有一个叫永久代的东西, 合并之后就没有必要额外的设置这么一个永久代的地方了。
386 |
387 | #### 2.6 运行时常量池
388 |
389 | 运行时常量池是方法区的一部分。Class 文件中除了有类的版本、字段、方法、接口等描述信息外,还有常量池信息(用于存放编译期生成的各种字面量和符号引用)
390 |
391 | 既然运行时常量池是方法区的一部分,自然受到方法区内存的限制,当常量池无法再申请到内存时会抛出 OutOfMemoryError 错误。
392 |
393 | **JDK1.7 及之后版本的 JVM 已经将运行时常量池从方法区中移了出来,在 Java 堆(Heap)中开辟了一块区域存放运行时常量池。**
394 |
395 | 
396 | ——图片来源:https://blog.csdn.net/wangbiao007/article/details/78545189
397 |
398 | #### 2.7 直接内存
399 |
400 |
401 |
402 | **直接内存并不是虚拟机运行时数据区的一部分,也不是虚拟机规范中定义的内存区域,但是这部分内存也被频繁地使用。而且也可能导致 OutOfMemoryError 错误出现。**
403 |
404 | JDK1.4 中新加入的 **NIO(New Input/Output) 类**,引入了一种基于**通道(Channel)** 与**缓存区(Buffer)** 的 I/O 方式,它可以直接使用 Native 函数库直接分配堆外内存,然后通过一个存储在 Java 堆中的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样就能在一些场景中显著提高性能,因为**避免了在 Java 堆和 Native 堆之间来回复制数据**。
405 |
406 | 本机直接内存的分配不会受到 Java 堆的限制,但是,既然是内存就会受到本机总内存大小以及处理器寻址空间的限制。
407 |
408 |
409 |
410 | ## 6、JVM调优(GC调优)
411 |
412 | 首先列举常见参数:
413 |
414 | | 参数名称 | 含义 | 默认值 | 说明 |
415 | | -------------------------- | ---------------------------------------------------------- | -------------------- | ------------------------------------------------------------ |
416 | | -Xms | 初始堆大小 | 物理内存的1/64(<1GB) | 默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制. |
417 | | -Xmx | 最大堆大小 | 物理内存的1/4(<1GB) | 默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制 |
418 | | -Xmn | 年轻代大小(1.4or lator) | | 注意:此处的大小是(eden+ 2 survivor space).与jmap -heap中显示的New gen是不同的。整个堆大小=年轻代大小 + 老年代大小 + 持久代(永久代)大小.增大年轻代后,将会减小年老代大小.此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8 |
419 | | -XX:NewSize | 设置年轻代大小(for 1.3/1.4) | | |
420 | | -XX:MaxNewSize | 年轻代最大值(for 1.3/1.4) | | |
421 | | -XX:PermSize | 设置持久代(perm gen)初始值 | 物理内存的1/64 | |
422 | | -XX:MaxPermSize | 设置持久代最大值 | 物理内存的1/4 | |
423 | | -Xss | 每个线程的堆栈大小 | | JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K.更具应用的线程所需内存大小进行 调整.在相同物理内存下,减小这个值能生成更多的线程.但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右一般小的应用, 如果栈不是很深, 应该是128k够用的 大的应用建议使用256k。这个选项对性能影响比较大,需要严格的测试。(校长)和threadstacksize选项解释很类似,官方文档似乎没有解释,在论坛中有这样一句话:-Xss is translated in a VM flag named ThreadStackSize”一般设置这个值就可以了 |
424 | | -XX:NewRatio | 年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代) | | -XX:NewRatio=4表示年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5Xms=Xmx并且设置了Xmn的情况下,该参数不需要进行设置。 |
425 | | -XX:SurvivorRatio | Eden区与Survivor区的大小比值 | | 设置为8,则两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10 |
426 | | -XX:+DisableExplicitGC | 关闭System.gc() | | 这个参数需要严格的测试 |
427 | | -XX:PretenureSizeThreshold | 对象超过多大是直接在旧生代分配 | 0 | 单位字节 新生代采用Parallel ScavengeGC时无效另一种直接在旧生代分配的情况是大的数组对象,且数组中无外部引用对象. |
428 | | -XX:ParallelGCThreads | 并行收集器的线程数 | | 此值最好配置与处理器数目相等 同样适用于CMS |
429 | | -XX:MaxGCPauseMillis | 每次年轻代垃圾回收的最长时间(最大暂停时间) | | 如果无法满足此时间,JVM会自动调整年轻代大小,以满足此值. |
430 |
431 | 其实还有一些打印及CMS方面的参数,这里就不以一一列举了
432 |
433 | 作者:说出你的愿望吧链接:https://juejin.im/post/5e1505d0f265da5d5d744050来源:掘金著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
434 |
435 | 参考JavaGuide大白话带你认识JVM,讲的比较实际。
436 |
437 | #### (1)调整最大堆内存和最小堆内存
438 |
439 | -Xmx –Xms:指定java堆最大值(默认值是物理内存的1/4(<1GB))和初始java堆最小值(默认值是物理内存的1/64(<1GB))
440 |
441 | 默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制.,默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制。简单点来说,你不停地往堆内存里面丢数据,等它剩余大小小于40%了,JVM就会动态申请内存空间不过会小于-Xmx,如果剩余大小大于70%,又会动态缩小不过不会小于–Xms。就这么简单
442 |
443 | 开发过程中,**通常会将 -Xms 与 -Xmx两个参数的配置相同的值**,其目的是为了能够在java垃圾回收机制清理完堆区后不需要重新分隔计算堆区的大小而浪费资源。
444 |
445 | #### (2)调整Survivor区和Eden区的比值
446 |
447 | 最优解当然就是官方的Eden和Survivor的占比为8:1:1
448 |
449 | #### (3)设置新生代,老年代大小
450 |
451 | 堆,有新生代和老年代组成,新生代有Eden,from,to区组成。
452 |
453 | 根据实际事情调整新生代和幸存代的大小,官方推荐**新生代占java堆的3/8**,**幸存代占新生代的1/10**。
454 |
455 | #### (4)永久区的设置
456 |
457 | ```
458 | -XX:PermSize -XX:MaxPermSize
459 | ```
460 |
461 | 初始空间(默认为物理内存的1/64)和最大空间(默认为物理内存的1/4)。也就是说,jvm启动时,永久区一开始就占用了PermSize大小的空间,如果空间还不够,可以继续扩展,但是不能超过MaxPermSize,否则会OOM。
462 |
463 | tips:如果堆空间没有用完也抛出了OOM,有可能是永久区导致的。堆空间实际占用非常少,但是永久区溢出 一样抛出OOM。
464 |
465 | #### (5)JVM的栈参数调优
466 |
467 | ##### 4.7.1 调整每个线程栈空间的大小
468 |
469 | 可以通过-Xss:调整每个线程栈空间的大小
470 |
471 | JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右
472 |
473 | ##### 4.7.2 设置线程栈的大小
474 |
475 | ```
476 | -XXThreadStackSize:
477 | 设置线程栈的大小(0 means use default stack size)
478 | ```
479 |
480 |
481 |
482 | 下面这个也是JavaGuide里面的:
483 |
484 | #### GC 调优策略
485 |
486 | **策略 1:**将新对象预留在新生代,由于 Full GC 的成本远高于 Minor GC,因此尽可能将对象分配在新生代是明智的做法,实际项目中根据 GC 日志分析新生代空间大小分配是否合理,适当通过“-Xmn”命令调节新生代大小,最大限度降低新对象直接进入老年代的情况。
487 |
488 | **策略 2:**大对象进入老年代,虽然大部分情况下,将对象分配在新生代是合理的。但是对于大对象这种做法却值得商榷,大对象如果首次在新生代分配可能会出现空间不足导致很多年龄不够的小对象被分配的老年代,破坏新生代的对象结构,可能会出现频繁的 full gc。因此,对于大对象,可以设置直接进入老年代(当然短命的大对象对于垃圾回收来说简直就是噩梦)。`-XX:PretenureSizeThreshold` 可以设置直接进入老年代的对象大小。
489 |
490 | **策略 3:**合理设置进入老年代对象的年龄,`-XX:MaxTenuringThreshold` 设置对象进入老年代的年龄大小,减少老年代的内存占用,降低 full gc 发生的频率。
491 |
492 | **策略 4:**设置稳定的堆大小,堆大小设置有两个参数:`-Xms` 初始化堆大小,`-Xmx` 最大堆大小。
493 |
494 | **策略5:**注意: 如果满足下面的指标,**则一般不需要进行 GC 优化:**
495 |
496 | > MinorGC 执行时间不到50ms; Minor GC 执行不频繁,约10秒一次; Full GC 执行时间不到1s; Full GC 执行频率不算频繁,不低于10分钟1次。
497 |
498 |
499 |
500 | 参考:JavaGuide
501 |
502 | 参考:https://blog.csdn.net/weixin_42447959/article/details/81637909?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1(感觉这篇文章写得很好,但是好多不懂)
503 |
504 | https://blog.csdn.net/Javazhoumou/article/details/99298624
505 |
506 |
507 |
508 |
509 |
510 | ## 7.新生代怎么变成年轻代
511 |
512 | 也叫新生代,顾名思义,主要是用来存放新生的对象。新生代又细分为 Eden区、SurvivorFrom区、SurvivorTo区。
513 |
514 | 新创建的对象都会被分配到Eden区(如果该对象占用内存非常大,则直接分配到老年代区), 当Eden区内存不够的时候就会触发MinorGC(Survivor满不会引发MinorGC,而是将对象移动到老年代中),
515 |
516 | 在Minor GC开始的时候,对象只会存在于Eden区和Survivor from区,Survivor to区是空的。
517 |
518 | Minor GC操作后,Eden区如果仍然存活(判断的标准是被引用了,通过GC root进行可达性判断)的对象,将会被移到Survivor To区。而From区中,**对象在Survivor区中每熬过一次Minor GC,年龄就会+1岁,当年龄达到一定值(年龄阈值,可以通过-XX:MaxTenuringThreshold来设置,默认是15)的对象会被移动到年老代中**,否则对象会被复制到“To”区。经过这次GC后,Eden区和From区已经被清空。
519 |
520 | “From”区和“To”区互换角色,原Survivor To成为下一次GC时的Survivor From区, 总之,GC后,都会保证Survivor To区是空的。
521 |
522 | 奇怪为什么有 From和To,2块区域?
523 | 这就要说到新生代Minor GC的算法了:复制算法
524 |
525 | 把内存区域分为两块,每次使用一块,GC的时候把一块中的内容移动到另一块中,原始内存中的对象就可以被回收了,
526 |
527 | 优点是避免内存碎片。
528 |
529 | 参考:https://blog.csdn.net/yujianping_123/article/details/99545138 (感觉写的挺好)
530 |
531 |
532 |
533 | ## 8.Java会出现内存泄漏吗,什么情况下会出现?
534 |
535 | 当然会出现内存泄露。
536 |
537 | **内存溢出:**(out of memory)通俗理解就是内存不够,通常在运行大型软件或游戏时,软件或游戏所需要的内存远远超出了你主机内安装的内存所承受大小,就叫内存溢出。
538 |
539 | **内存泄漏:**(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果
540 |
541 |
542 |
543 | 内存泄露的根本原因:
544 |
545 | Java内存泄漏的根本原因是什么呢?长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄漏,尽管短生命周期对象已经不再需要,但是因为长生命周期持有它的引用而导致不能被回收,这就是Java中内存泄漏的发生场景。
546 |
547 | 
548 |
549 | 总结起来就比如上图,A的生命周期很长,而B的生命周期很短,而A一直没有释放,导致B也一直没有被回收。
550 |
551 |
552 |
553 | **以下情况会出现内存泄露**:
554 |
555 | **1、静态集合类引起内存泄漏:** (如果static 修饰一个很大的对象,也可能会发生内存泄露)
556 |
557 | 像HashMap、Vector等的使用最容易出现内存泄露,这些静态变量的生命周期和应用程序一致,他们所引用的所有的对象Object也不能被释放,因为他们也将一直被Vector等引用着。
558 |
559 | 例如:
560 |
561 | ```java
562 | Static Vector v = new Vector(10);
563 | for (int i = 1; i<100; i++)
564 | {
565 | Object o = new Object();
566 | v.add(o);
567 | o = null;
568 | }
569 | ```
570 |
571 | 在这个例子中,循环申请Object 对象,并将所申请的对象放入一个Vector 中,如果仅仅释放引用本身(o=null),那么Vector 仍然引用该对象,所以这个对象对GC 来说是不可回收的。因此,如果对象加入到Vector 后,还必须从Vector 中删除,最简单的方法就是将Vector对象设置为null。
572 |
573 | **2、当集合里面的对象属性被修改后,再调用remove()方法时不起作用。**
574 |
575 | 例如:
576 |
577 | ```java
578 | public static void main(String[] args){Set set = new HashSet();Person p1 = new Person("唐僧","pwd1",25);Person p2 = new Person("孙悟空","pwd2",26);Person p3 = new Person("猪八戒","pwd3",27);set.add(p1);set.add(p2);set.add(p3);System.out.println("总共有:"+set.size()+" 个元素!"); //结果:总共有:3 个元素!p3.setAge(2); //修改p3的年龄,此时p3元素对应的hashcode值发生改变set.remove(p3); //此时remove不掉,造成内存泄漏set.add(p3); //重新添加,居然添加成功System.out.println("总共有:"+set.size()+" 个元素!"); //结果:总共有:4 个元素!for (Person person : set){System.out.println(person);}}
579 | ```
580 |
581 | **3、监听器**
582 |
583 | 在java 编程中,我们都需要和监听器打交道,通常一个应用当中会用到很多监听器,我们会调用一个控件的诸如addXXXListener()等方法来增加监听器,但往往在释放对象的时候却没有记住去删除这些监听器,从而增加了内存泄漏的机会。
584 |
585 | **4、各种连接**
586 |
587 | 比如数据库连接(dataSourse.getConnection()),网络连接(socket)和io连接,除非其显式的调用了其close()方法将其连接关闭,否则是不会自动被GC 回收的。对于Resultset 和Statement 对象可以不进行显式回收,但Connection 一定要显式回收,因为Connection 在任何时候都无法自动回收,而Connection一旦回收,Resultset 和Statement 对象就会立即为NULL。但是如果使用连接池,情况就不一样了,除了要显式地关闭连接,还必须显式地关闭Resultset Statement 对象(关闭其中一个,另外一个也会关闭),否则就会造成大量的Statement 对象无法释放,从而引起内存泄漏。这种情况下一般都会在try里面去的连接,在finally里面释放连接。
588 |
589 | **5、内部类和外部模块的引用**
590 |
591 | 内部类的引用是比较容易遗忘的一种,而且一旦没释放可能导致一系列的后继类对象没有释放。此外程序员还要小心外部模块不经意的引用,例如程序员A 负责A 模块,调用了B 模块的一个方法如:
592 |
593 | public void registerMsg(Object b);
594 |
595 | 这种调用就要非常小心了,传入了一个对象,很可能模块B就保持了对该对象的引用,这时候就需要注意模块B 是否提供相应的操作去除引用。
596 |
597 | **6、单例模式**
598 |
599 | 不正确使用单例模式是引起内存泄漏的一个常见问题,单例对象在初始化后将在JVM的整个生命周期中存在(以静态变量的方式),如果单例对象持有外部的引用,那么这个对象将不能被JVM正常回收,导致内存泄漏,考虑下面的例子:
600 |
601 | ```java
602 | class A{public A(){B.getInstance().setA(this);}....}//B类采用单例模式class B{private A a;private static B instance=new B();public B(){}public static B getInstance(){return instance;}public void setA(A a){this.a=a;}//getter...}
603 | ```
604 |
605 | 显然B采用singleton模式,它持有一个A对象的引用,而这个A类的对象将不能被回收。想象下如果A是个比较复杂的对象或者集合类型会发生什么情况
606 |
607 |
608 |
609 | 参考:https://blog.csdn.net/u012516166/article/details/77014910
610 |
611 |
612 |
613 | ## 9.GC如何搜索到需要回收的对象?如何判断哪些对象需要回收?
614 |
615 | 
616 |
617 | #### 引用计数法:
618 |
619 | 给对象中添加一个引用计数器,每当有一个地方引用它,计数器就加 1;当引用失效,计数器就减 1;任何时候计数器为 0 的对象就是不可能再被使用的。
620 |
621 | **这个方法实现简单,效率高,但是目前主流的虚拟机中并没有选择这个算法来管理内存,其最主要的原因是它很难解决对象之间相互循环引用的问题。**
622 |
623 | #### 可达性分析算法:(有些地方叫根搜索算法?)
624 |
625 | 这个算法的基本思想就是通过一系列的称为 **“GC Roots”** 的对象作为起点,从这些节点开始向下搜索,节点所走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链相连的话,则证明此对象是不可用的。
626 |
627 | 
628 |
629 |
630 |
631 | 当然还有:参考JavaGuide JVM垃圾回收 对象已经死亡
632 |
633 |
634 |
635 | ## 10.JAVA内存区域 堆和栈上存储什么
636 |
637 | 堆内存是用来存放由new创建的对象实例和数组。**此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例以及数组都在这里分配内存。**
638 |
639 | 栈内存中保存的是堆内存空间的访问地址,或者说栈中的变量指向堆内存中的变量(java中的“指针”)
640 |
641 |
642 |
643 | **堆和栈队列定义和差别**
644 |
645 | 堆与栈的区别:
646 |
647 | 1.栈内存存储的是局部变量而堆内存存储的是实体;
648 |
649 | 2.栈内存的更新速度要快于堆内存,因为局部变量的生命周期很短;
650 |
651 | 3.栈内存存放的变量生命周期一旦结束就会被释放,而堆内存存放的实体会被垃圾回收机制不定时的回收。
652 |
653 | 堆和栈区别,参考:https://www.cnblogs.com/cchHers/p/10010275.html
654 |
655 |
656 |
657 | ## 11.GC Roots可以是哪些对象?
658 |
659 | (能够直接从外部访问的对象)可以和Java内存区域合起来记忆。
660 |
661 | 虚拟机栈中的引用对象
662 |
663 | 方法区中的静态属性引用的对象
664 |
665 | 方法区中的常量引用的对象
666 |
667 | 本地方法栈中native方法的引用对象
668 |
669 |
670 |
671 | ## 12.JVM内存区域,哪些是线程私有?
672 |
673 | 虚拟机栈,本地方法栈,程序计数器。
674 |
675 |
676 |
677 | ## 13.Java 对象的创建过程(五步,建议能默写出来并且要知道每一步虚拟机做了什么)
678 |
679 | 下图便是 Java 对象的创建过程,我建议最好是能默写出来,并且要掌握每一步在做什么。
680 |
681 | 
682 |
683 | #### Step1:类加载检查
684 |
685 | 虚拟机遇到一条 new 指令时,首先将去检查这个指令的参数是否能在常量池中定位到这个类的符号引用,并且检查这个符号引用代表的类是否已被加载过、解析和初始化过。如果没有,那必须先执行相应的类加载过程。
686 |
687 | #### Step2:分配内存
688 |
689 | 在**类加载检查**通过后,接下来虚拟机将为新生对象**分配内存**。对象所需的内存大小在类加载完成后便可确定,为对象分配空间的任务等同于把一块确定大小的内存从 Java 堆中划分出来。**分配方式**有 **“指针碰撞”** 和 **“空闲列表”** 两种,**选择那种分配方式由 Java 堆是否规整决定,而 Java 堆是否规整又由所采用的垃圾收集器是否带有压缩整理功能决定**。
690 |
691 | **内存分配的两种方式:(补充内容,需要掌握)**
692 |
693 | 选择以上两种方式中的哪一种,取决于 Java 堆内存是否规整。而 Java 堆内存是否规整,取决于 GC 收集器的算法是"标记-清除",还是"标记-整理"(也称作"标记-压缩"),值得注意的是,复制算法内存也是规整的
694 |
695 | 
696 |
697 | **内存分配并发问题(补充内容,需要掌握)**
698 |
699 | 在创建对象的时候有一个很重要的问题,就是线程安全,因为在实际开发过程中,创建对象是很频繁的事情,作为虚拟机来说,必须要保证线程是安全的,通常来讲,虚拟机采用两种方式来保证线程安全:
700 |
701 | - **CAS+失败重试:** CAS 是乐观锁的一种实现方式。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。**虚拟机采用 CAS 配上失败重试的方式保证更新操作的原子性。**
702 | - **TLAB:** 为每一个线程预先在 Eden 区分配一块儿内存,JVM 在给线程中的对象分配内存时,首先在 TLAB 分配,当对象大于 TLAB 中的剩余内存或 TLAB 的内存已用尽时,再采用上述的 CAS 进行内存分配
703 |
704 | #### Step3:初始化零值
705 |
706 | 内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值(不包括对象头),这一步操作保证了对象的实例字段在 Java 代码中可以不赋初始值就直接使用,程序能访问到这些字段的数据类型所对应的零值。
707 |
708 | #### Step4:设置对象头
709 |
710 | 初始化零值完成之后,**虚拟机要对对象进行必要的设置**,例如这个对象是那个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的 GC 分代年龄等信息。 **这些信息存放在对象头中。** 另外,根据虚拟机当前运行状态的不同,如是否启用偏向锁等,对象头会有不同的设置方式。
711 |
712 | #### Step5:执行 init 方法
713 |
714 | 在上面工作都完成之后,从虚拟机的视角来看,一个新的对象已经产生了,但从 Java 程序的视角来看,对象创建才刚开始,`` 方法还没有执行,所有的字段都还为零。所以一般来说,执行 new 指令之后会接着执行 `` 方法,把对象按照程序员的意愿进行初始化,这样一个真正可用的对象才算完全产生出来。
715 |
716 |
717 |
718 | ## 14.对象的访问定位:
719 |
720 | 句柄,直接指针。
721 |
722 |
723 |
724 | ## 15.String类和常量池
725 |
726 | **String 对象的两种创建方式:**
727 |
728 | ```java
729 | String str1 = "abcd";//先检查字符串常量池中有没有"abcd",如果字符串常量池中没有,则创建一个,然后 str1 指向字符串常量池中的对象,如果有,则直接将 str1 指向"abcd"";String str2 = new String("abcd");//堆中创建一个新的对象String str3 = new String("abcd");//堆中创建一个新的对象System.out.println(str1==str2);//falseSystem.out.println(str2==str3);//false
730 | ```
731 |
732 | 这两种不同的创建方法是有差别的。
733 |
734 | - 第一种方式是在常量池中拿对象;
735 | - 第二种方式是直接在堆内存空间创建一个新的对象。
736 |
737 | 记住一点:**只要使用 new 方法,便需要创建新的对象。**
738 |
739 | 再给大家一个图应该更容易理解,图片来源::
740 |
741 | 
742 |
743 | **String 类型的常量池比较特殊。它的主要使用方法有两种:**
744 |
745 | - 直接使用双引号声明出来的 String 对象会直接存储在常量池中。
746 | - 如果不是用双引号声明的 String 对象,可以使用 String 提供的 intern 方法。String.intern() 是一个 Native 方法,它的作用是:如果运行时常量池中已经包含一个等于此 String 对象内容的字符串,则返回常量池中该字符串的引用;如果没有,JDK1.7之前(不包含1.7)的处理方式是在常量池中创建与此 String 内容相同的字符串,并返回常量池中创建的字符串的引用,JDK1.7以及之后的处理方式是在常量池中记录此字符串的引用,并返回该引用。
747 |
748 | ```java
749 | String s1 = new String("计算机"); String s2 = s1.intern(); String s3 = "计算机"; System.out.println(s2);//计算机 System.out.println(s1 == s2);//false,因为一个是堆内存中的 String 对象一个是常量池中的 String 对象, System.out.println(s3 == s2);//true,因为两个都是常量池中的 String 对象
750 | ```
751 |
752 | **字符串拼接:**
753 |
754 | ```java
755 | String str1 = "str"; String str2 = "ing"; String str3 = "str" + "ing";//常量池中的对象 String str4 = str1 + str2; //在堆上创建的新的对象 String str5 = "string";//常量池中的对象 System.out.println(str3 == str4);//false System.out.println(str3 == str5);//true System.out.println(str4 == str5);//false
756 | ```
757 |
758 | 
759 |
760 | 尽量避免多个字符串拼接,因为这样会重新创建对象。如果需要改变字符串的话,可以使用 StringBuilder 或者 StringBuffer。
761 |
762 | #### String s1 = new String("abc");这句话创建了几个字符串对象?
763 |
764 | **将创建 1 或 2 个字符串。如果池中已存在字符串常量“abc”,则只会在堆空间创建一个字符串常量“abc”。如果池中没有字符串常量“abc”,那么它将首先在池中创建,然后在堆空间中创建,因此将创建总共 2 个字符串对象。**
765 |
766 | **验证:**
767 |
768 | ```java
769 | String s1 = new String("abc");// 堆内存的地址值 String s2 = "abc"; System.out.println(s1 == s2);// 输出 false,因为一个是堆内存,一个是常量池的内存,故两者是不同的。 System.out.println(s1.equals(s2));// 输出 true
770 | ```
771 |
772 | **结果:**
773 |
774 | ```
775 | falsetrue
776 | ```
777 |
778 |
779 |
780 | ## 16.如何实现小内存,排序大文件?只用2GB内存在20亿个整数中找到出现次数最多的数?
781 |
782 | 用哈希函数分小,再找。
783 |
784 | 参考:https://blog.csdn.net/u010456903/article/details/48805985?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-3&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-3
785 |
786 | 分成多个满足内存限制的小文件,再操作。
787 |
788 |
789 |
790 | ## 17.如何设置jvm创建的堆内存的大小?
791 |
792 | -Xmx:最大堆大小
793 |
794 | -Xms:初始堆大小(有的地方也叫最小堆内存)
795 |
796 |
797 |
798 | ## 18.八种基本类型包装类
799 |
800 | **Java 基本类型的包装类的大部分都实现了常量池技术,即 Byte,Short,Integer,Long,Character,Boolean;前面 4 种包装类默认创建了数值[-128,127] 的相应类型的缓存数据,Character创建了数值在[0,127]范围的缓存数据,Boolean 直接返回True Or False。如果超出对应范围仍然会去创建新的对象。** 为啥把缓存设置为[-128,127]区间?([参见issue/461](https://github.com/Snailclimb/JavaGuide/issues/461))性能和资源之间的权衡。
801 |
802 | ```java
803 | public static Boolean valueOf(boolean b) { return (b ? TRUE : FALSE);}
804 | ```
805 |
806 | ```java
807 | private static class CharacterCache { private CharacterCache(){} static final Character cache[] = new Character[127 + 1]; static { for (int i = 0; i < cache.length; i++) cache[i] = new Character((char)i); } }
808 | ```
809 |
810 | 两种浮点数类型的包装类 Float,Double 并没有实现常量池技术。**
811 |
812 | ```java
813 | Integer i1 = 33; Integer i2 = 33; System.out.println(i1 == i2);// 输出 true Integer i11 = 333; Integer i22 = 333; System.out.println(i11 == i22);// 输出 false Double i3 = 1.2; Double i4 = 1.2; System.out.println(i3 == i4);// 输出 false
814 | ```
815 |
816 | **Integer 缓存源代码:**
817 |
818 | ```java
819 | /***此方法将始终缓存-128 到 127(包括端点)范围内的值,并可以缓存此范围之外的其他值。*/ public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
820 | ```
821 |
822 | **应用场景:**
823 |
824 | 1. Integer i1=40;Java 在编译的时候会直接将代码封装成 Integer i1=Integer.valueOf(40);,从而使用常量池中的对象。
825 | 2. Integer i1 = new Integer(40);这种情况下会创建新的对象。
826 |
827 | ```java
828 | Integer i1 = 40; Integer i2 = new Integer(40); System.out.println(i1==i2);//输出 false
829 | ```
830 |
831 | **Integer 比较更丰富的一个例子:**
832 |
833 | ```java
834 | Integer i1 = 40; Integer i2 = 40; Integer i3 = 0; Integer i4 = new Integer(40); Integer i5 = new Integer(40); Integer i6 = new Integer(0); System.out.println("i1=i2 " + (i1 == i2)); System.out.println("i1=i2+i3 " + (i1 == i2 + i3)); System.out.println("i1=i4 " + (i1 == i4)); System.out.println("i4=i5 " + (i4 == i5)); System.out.println("i4=i5+i6 " + (i4 == i5 + i6)); System.out.println("40=i5+i6 " + (40 == i5 + i6));
835 | ```
836 |
837 | 结果:
838 |
839 | ```
840 | i1=i2 truei1=i2+i3 truei1=i4 falsei4=i5 falsei4=i5+i6 true40=i5+i6 true
841 | ```
842 |
843 | 解释:
844 |
845 | 语句 i4 == i5 + i6,因为+这个操作符不适用于 Integer 对象,首先 i5 和 i6 进行自动拆箱操作,进行数值相加,即 i4 == 40。然后 Integer 对象无法与数值进行直接比较,所以 i4 自动拆箱转为 int 值 40,最终这条语句转为 40 == 40 进行数值比较。
846 |
847 |
848 |
849 | ## 19.堆 (垃圾回收器管理的主要区域)
850 |
851 | Java 虚拟机所管理的内存中最大的一块,Java 堆是所有线程共享的一块内存区域,在虚拟机启动时创建。**此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例以及数组都在这里分配内存。**
852 |
853 | Java 堆是垃圾收集器管理的主要区域,因此也被称作**GC 堆(Garbage Collected Heap)**.从垃圾回收的角度,由于现在收集器基本都采用分代垃圾收集算法,所以 Java 堆还可以细分为:新生代和老年代:再细致一点有:Eden 空间、From Survivor、To Survivor 空间等。**进一步划分的目的是更好地回收内存,或者更快地分配内存。**
854 |
855 | 在 JDK 7 版本及JDK 7 版本之前,堆内存被通常被分为下面三部分:
856 |
857 | 1. 新生代内存(Young Generation)
858 | 2. 老生代(Old Generation)
859 | 3. 永生代(Permanent Generation)
860 |
861 | 
862 |
863 | JDK 8 版本之后方法区(HotSpot 的永久代)被彻底移除了(JDK1.7 就已经开始了),取而代之是元空间,元空间使用的是直接内存。
864 |
865 | 
866 |
867 | **上图所示的 Eden 区、两个 Survivor 区都属于新生代(为了区分,这两个 Survivor 区域按照顺序被命名为 from 和 to),中间一层属于老年代。**
868 |
869 |
870 |
871 | ## 19.商用垃圾回收算法中的分代收集算法中如何确定一个对象属于新生代还是老年代?
872 |
873 | #### 对象优先在 eden 区分配
874 |
875 | 目前主流的垃圾收集器都会采用分代回收算法,因此需要将堆内存分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。
876 |
877 | 大多数情况下,对象在新生代中 eden 区分配。当 eden 区没有足够空间进行分配时,虚拟机将发起一次 Minor GC.下面我们来进行实际测试以下。
878 |
879 | 在测试之前我们先来看看 **Minor GC 和 Full GC 有什么不同呢?**
880 |
881 | - **新生代 GC(Minor GC)**:指发生新生代的的垃圾收集动作,Minor GC 非常频繁,回收速度一般也比较快。
882 | - **老年代 GC(Major GC/Full GC)**:指发生在老年代的 GC,出现了 Major GC 经常会伴随至少一次的 Minor GC(并非绝对),Major GC 的速度一般会比 Minor GC 的慢 10 倍以上。
883 |
884 | #### 大对象直接进入老年代
885 |
886 | 大对象就是需要大量连续内存空间的对象(比如:字符串、数组)。
887 |
888 | **为什么要这样呢?**
889 |
890 | 为了避免为大对象分配内存时由于分配担保机制带来的复制而降低效率。
891 |
892 | #### 长期存活的对象将进入老年代
893 |
894 | 既然虚拟机采用了分代收集的思想来管理内存,那么内存回收时就必须能识别哪些对象应放在新生代,哪些对象应放在老年代中。为了做到这一点,虚拟机给每个对象一个对象年龄(Age)计数器。
895 |
896 | 如果对象在 Eden 出生并经过第一次 Minor GC 后仍然能够存活,并且能被 Survivor 容纳的话,将被移动到 Survivor 空间中,并将对象年龄设为 1.对象在 Survivor 中每熬过一次 MinorGC,年龄就增加 1 岁,当它的年龄增加到一定程度(默认为 15 岁),就会被晋升到老年代中。对象晋升到老年代的年龄阈值,可以通过参数 `-XX:MaxTenuringThreshold` 来设置。
897 |
898 | #### 动态对象年龄判定
899 |
900 | 大部分情况,对象都会首先在 Eden 区域分配,在一次新生代垃圾回收后,如果对象还存活,则会进入 s0 或者 s1,并且对象的年龄还会加 1(Eden 区->Survivor 区后对象的初始年龄变为 1),当它的年龄增加到一定程度(默认为 15 岁),就会被晋升到老年代中。对象晋升到老年代的年龄阈值,可以通过参数 `-XX:MaxTenuringThreshold` 来设置。
901 |
902 |
903 |
904 | 个人博客写过这个。(是参考一篇博客写的)
905 |
906 |
907 |
908 | ## 20.描述一下JVM加载class文件的原理机制
909 |
910 |
911 |
912 | ## 21.String对象可以改变吗,为什么?
913 |
914 |
915 |
916 | 牛客20201221选择题
917 |
918 | 错误的是(C)
919 |
920 | ```java
921 | A 程序计数器是一个比较小的内存区域,用于指示当前线程所执行的字节码执行到了第几行,是线程隔离的B 虚拟机栈描述的是Java方法执行的内存模型,用于存储局部变量,操作数栈,动态链接,方法出口等信息,是线程隔离的C 方法区用于存储JVM加载的类信息、常量、静态变量、以及编译器编译后的代码等数据,是线程隔离的D 原则上讲,所有的对象都在堆区上分配内存,是线程之间共享的
922 | ```
923 |
924 | 解释:方法区和堆,都是线程共享的。
925 |
926 | 大多数 JVM 将内存区域划分为 **Method Area(Non-Heap)(方法区)** ,**Heap(堆)** , **Program Counter Register(程序计数器)** , **VM Stack(虚拟机栈,也有翻译成JAVA 方法栈的),Native Method Stack** ( **本地方法栈** ),其中**Method Area** 和 **Heap** 是线程共享的 **VM Stack,Native Method Stack 和\*\*Program Counter Register** 是非线程共享的。为什么分为 线程共享和非线程共享的呢?请继续往下看。
927 |
928 | 首先我们熟悉一下一个一般性的 Java 程序的工作过程。一个 Java 源程序文件,会被编译为字节码文件(以 class 为扩展名),每个java程序都需要运行在自己的JVM上,然后告知 JVM 程序的运行入口,再被 JVM 通过字节码解释器加载运行。那么程序开始运行后,都是如何涉及到各内存区域的呢?
929 |
930 | 概括地说来,JVM初始运行的时候都会分配好 **Method Area(方法区)** 和**Heap(堆)** ,而JVM 每遇到一个线程,就为其分配一个 **Program Counter Register(程序计数器)** , **VM Stack(虚拟机栈)和Native Method Stack (本地方法栈),** 当线程终止时,三者(虚拟机栈,本地方法栈和程序计数器)所占用的内存空间也会被释放掉。这也是为什么我把内存区域分为线程共享和非线程共享的原因,非线程共享的那三个区域的生命周期与所属线程相同,而线程共享的区域与JAVA程序运行的生命周期相同,所以这也是系统垃圾回收的场所只发生在线程共享的区域(实际上对大部分虚拟机来说知发生在Heap上)的原因。
931 |
932 |
933 |
934 | ## 22.类加载相关
935 |
936 | ### **类加载的过程**
937 |
938 | 类从被加载到JVM中开始,到卸载为止,整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段。其中**类加载过程包括加载、验证、准备、解析和初始化五个阶段**。
939 |
940 | 
941 |
942 | \4. 从类加载到方法执行的执行顺序?
943 |
944 | \5. 为什么类对象能避免重复加载?(双亲委派)加载类对象是先从自己的类中进行加载,还是从父类中进行加载?(父类)
945 |
946 | 解释java内存中栈(stack),堆(heap)及方法区(method area)的用法?
947 |
948 |
949 |
950 | # 网上面试题
951 |
952 | 参考:https://www.jianshu.com/p/573b5c6b8e89
953 |
954 | https://blog.csdn.net/qq_41701956/article/details/100074023
955 |
956 |
--------------------------------------------------------------------------------
/docs/Linux.md:
--------------------------------------------------------------------------------
1 | # Linux
2 |
3 |
4 |
5 | # Interview
6 |
7 | ### 1.Linux下如何启动springboot的包?
8 |
9 | ```html
10 | nohup java -jar blog.jar > system.log 2>&1 &
11 |
12 | ```
13 |
14 | 下面我们对这条命令进行分析
15 |
16 | nohub一般形式为如下:
17 |
18 | nohub command &
19 |
20 | 但是当你退出账户时,仍然会停止对应的进程。
21 |
22 | 所以这就需要你在后面添加 2>&1 &(相当于正常退出,仍保持命令在后台运行)
23 |
24 | 上面这个command正好对上java -jar blog.jar > system.log
25 |
26 | “>” 输出重定向,通常用于输出日志
27 |
28 |
29 |
30 | ### 2.linux命令(怎么查看linux中当前各个进程占用的系统资源)
31 |
32 | ```shell
33 | ps -aux
34 |
35 | ```
36 |
37 |
38 |
39 | ### 3.说几个常用的linux命令 ,五个以上,用途
40 |
41 | 1.目录切换
42 |
43 | ```java
44 | cd 文件夹 //进入某一个文件夹
45 | cd .. //返回上一级目录
46 |
47 | ```
48 |
49 | 2.目录操作
50 |
51 | ```shell
52 | mkdir //增加目录
53 | ll/ls //查看目录下文件
54 | rmdir //删除文件
55 |
56 | ```
57 |
58 | 3.文件操作
59 |
60 | ```shell
61 | 1. touch 文件名称 //文件的创建(增)
62 | 2. cat/more/less/tail 文件名称 //文件的查看(查)
63 |
64 | ```
65 |
66 | 4.压缩和解压
67 |
68 | (1)压缩
69 |
70 | Linux中的打包文件一般是以.tar结尾的,压缩的命令一般是以.gz结尾的。
71 |
72 | 而一般情况下打包和压缩是一起进行的,打包并压缩后的文件的后缀名一般.tar.gz。
73 | 命令:**`tar -zcvf 打包压缩后的文件名 要打包压缩的文件`**
74 | 其中:
75 |
76 | z:调用gzip压缩命令进行压缩
77 |
78 | c:打包文件
79 |
80 | v:显示运行过程
81 |
82 | f:指定文件名
83 |
84 | 比如:假如test目录下有三个文件分别是:aaa.txt bbb.txt ccc.txt,如果我们要打包test目录并指定压缩后的压缩包名称为test.tar.gz可以使用命令:**`tar -zcvf test.tar.gz aaa.txt bbb.txt ccc.txt`或:`tar -zcvf test.tar.gz /test/`**
85 |
86 | (2)解压
87 |
88 | 命令:tar [-xvf] 压缩文件
89 |
90 | 其中:x:代表解压
91 |
92 | 示例:
93 |
94 | 1 将/test下的test.tar.gz解压到当前目录下可以使用命令:**`tar -xvf test.tar.gz`**
95 |
96 | 2 将/test下的test.tar.gz解压到根目录/usr下:**`tar -xvf test.tar.gz -C /usr`**(- C代表指定解压的位置)
97 |
98 | 5.网络管理
99 |
100 | ```shell
101 | ifconfig 查看ip地址
102 | ping 地址 查看连接情况
103 |
104 | ```
105 |
106 |
107 |
108 | ### 4.linux命令查看服务器性能
109 |
110 | **(1)查看CPU使用**
111 |
112 | ```shell
113 | top
114 | ```
115 |
116 | 
117 |
118 | **(2)查看内存**
119 |
120 | ```shell
121 | free -m
122 |
123 | ```
124 |
125 | 
126 |
127 |
128 |
129 | 参考:https://blog.csdn.net/guoxiaojie_415/article/details/80526667?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-4&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-4 (写的算好的一篇 有参考其他)
130 |
131 | https://netflixtechblog.com/linux-performance-analysis-in-60-000-milliseconds-accc10403c55 (国外的一个,需要梯子)
132 |
133 | **(3)uptime 查看负载**
134 |
135 | 
136 |
137 | 几个负载分别是1min,5min,15min的平均负载
138 |
139 |
140 |
141 | ### 5.Linux改变文件所属组的命令,生成文件的命令
142 |
143 | https://www.cnblogs.com/klb561/p/9170616.html
144 |
145 | [root@localhost ~]# chgrp group1 install.log
146 |
147 | \#修改install.log文件的所属组为group1
148 |
149 |
150 |
151 | [root@localhost user]# touch test
152 |
153 | \#由root用户新建文件test
154 |
155 |
156 |
157 | ### 6.熟悉Linux什么指令? 说一下如何把文件中的abc替换为def;说一下如何找出某文件夹下所有包含“abc”的文件?
158 |
159 | 参考:https://blog.csdn.net/Olivia_Vang/article/details/104091358?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1
160 |
161 |
162 |
163 | ### 7.Linux系统是32位还是64位查询命令
164 |
165 | 
166 |
167 | 参考:https://www.cnblogs.com/nucdy/p/5658488.html
168 |
169 | ### 8.Linux 方面,查日志:cat 命令,如果根据日期查怎么查,日志文件很大,快速定位错误日志(只给一个模糊时间),我又说了 grep 和 管道符,面试官说这不是最好的。
170 |
171 | 下面这个是查询错误:
172 |
173 | ```shell
174 | cat -n system.log | grep "error" //grep是搜索的意思 -n的意思是显示行号(大日志显示行号 很有必要)
175 | ```
176 |
177 | 
178 |
179 | 查出来是这样的。
180 |
181 | 参考:https://www.cnblogs.com/woshixiangshang/p/11585306.html (博客园上面的,写的还行)
182 |
183 |
184 |
185 | **其实还有好多种查日志的方法:** (也很重要)
186 |
187 | 上面的cat命令显示全部,不太好,
188 |
189 | 还有more和less操作,都表示一页一页翻页,但是less操作起来好一点。
190 |
191 | less空格和Pgdown向下翻页,pageup向上翻页
--------------------------------------------------------------------------------
/docs/Mybatis.md:
--------------------------------------------------------------------------------
1 | # Mybatis
2 |
3 |
4 |
5 | # Interviewe
6 |
7 | ## 1.Mybatis有什么关键作用?
8 |
9 | MyBatis是持久层框架,支持JDBC,简化了持久层开发。
10 |
11 | 使用MyBatis时,只需要通过接口指定数据操作的抽象方法,然后配置与之关联的SQL语句,即可。
12 |
13 |
14 |
15 | 持久化存储:在程序运行过程中,数据都是在内存(RAM,即内存条)中的,内存中的数据不是永久存储的,例如程序可以对这些数据进行销毁,或者由于断电也会导致内存中所有数据丢失!而把数据存储到硬盘中的某个文件中,会使得这些数据永久的存储下来,常见做法是存储到数据库中,当然,也可以使用其他技术把数据存储到文本文件、XML文件等其他文件中。
16 |
17 |
18 |
19 | ## 2.Mybatis和Herbanate的区别
20 |
21 | MyBatis(前身是iBatis)是一个支持普通SQL查询、存储过程以及高级映射的持久层框架,它消除了几乎所有的JDBC代码和参数的手动设置以及对结果集的检索,并使用简单的XML或注解进行配置和原始映射,用以将接口和Java的POJO(Plain Old Java Object,普通Java对象)映射成数据库中的记录,使得Java开发人员可以使用面向对象的编程思想来操作数据库。
22 |
23 | MyBatis 框架也被称之为 ORM(Object/Relational Mapping,即对象关系映射)框架。所谓的 ORM 就是一种为了解决面向对象与关系型数据库中数据类型不匹配的技术,它通过描述Java对象与数据库表之间的映射关系,自动将Java应用程序中的对象持久化到关系型数据库的表中。ORM框架的工作原理如下图所示。
24 |
25 | 
26 |
27 |
28 | 从上图可以看出,使用ORM框架后,应用程序不再直接访问底层数据库,而是以面向对象的方式来操作持久化对象(Persisent Object,PO),而ORM框架则会通过映射关系将这些面向对象的操作转换成底层的SQL操作。
29 |
30 | 当前的ORM框架产品有很多,常见的ORM框架有Hibernate和MyBatis。这两个框架的主要区别如下。
31 |
32 | - **Hibernate:**是一个全表映射的框架。通常开发者只需定义好持久化对象到数据库表的映射关系,就可以通过 Hibernate 提供的方法完成持久层操作。开发者并不需要熟练地掌握 SQL语句的编写,Hibernate会根据制定的存储逻辑,自动的生成对应的SQL,并调用JDBC接口来执行,所以其开发效率会高于MyBatis。然而Hibernate自身也存在着一些缺点,例如它在多表关联时,对 SQL 查询的支持较差;更新数据时,需要发送所有字段;不支持存储过程;不能通过优化 SQL 来优化性能等。这些问题导致其只适合在场景不太复杂且对性能要求不高的项目中使用。
33 |
34 | - **MyBatis:**是一个半自动映射的框架。这里所谓的“半自动”是相对于Hibernate全表映射而言的,MyBatis 需要手动匹配提供 POJO、SQL和映射关系,而Hibernate只需提供POJO 和映射关系即可。与Hibernate相比,虽然使用MyBatis手动编写 SQL 要比使用Hibernate的工作量大,但MyBatis可以配置动态SQL并优化SQL,可以通过配置决定SQL的映射规则,它还支持存储过程等。对于一些复杂的和需要优化性能的项目来说,显然使用MyBatis更加合适。推荐了解传智播客[java](http://java.itcast.cn/)中级程序员课程。
35 |
36 |
37 |
38 | ## 3.Mybatis如何实现批量插入?
39 |
40 | **之所以要批量插入是为了避免数据库和程序之间建立多次连接,增加服务器的负荷。**
41 |
42 |
43 |
44 | ### 正常的插入多条数据是这样子的:
45 |
46 | ```sql
47 | insert into user
48 | (username, `password`, age, gender)
49 | VALUES
50 | ('杨豆豆','123456',11,'male'),
51 | ('杨豆豆1','123456',11,'male')
52 | ```
53 |
54 |
55 |
56 | ### 动态sql foreach:
57 |
58 | ```xml
59 |
60 | insert into user
61 | ( )
62 | values
63 |
64 | (#{item.username},#{item.password},#{item.age},#{item.gender})
65 |
66 |
67 | ```
68 |
69 | 参考:https://www.jianshu.com/p/97e484b55d04
70 |
71 |
72 |
73 | ## 4.Mybatis里插入一条数据,如何返回这条记录的主键?
74 |
75 | 统一都用selectKey, 只是在Oracle里面用的话,这里是返回序列号
76 |
77 | Oracle:
78 |
79 | ```xml
80 |
81 | SELECT SEQUENCE_1.nextval AS id FROM dual
82 |
83 | ```
84 |
85 | Mysql:
86 |
87 | ```xml
88 |
89 | SELECT LAST_INSERT_ID()
90 |
91 | ```
92 |
93 |
94 |
95 | ## 5.Mybatis 十万条 数据 五万条数据更新,五万条新增 怎么去实(DUPLICATE)
96 |
97 | 在 mysql 中,当存在主键冲突或唯一键冲突的情况下,根据插入策略不同,一般有以下三种避免方法:
98 |
99 | - `insert ignore into`:若没有则插入,若存在则忽略
100 |
101 | - `replace into`:若没有则正常插入,若存在则先删除后插入
102 |
103 | - `insert into ... on duplicate key update`:若没有则正常插入,若存在则更新
104 |
105 | ```sql
106 | #数据库原来2中有数据,4中没有数据。
107 | insert into ljtest
108 | (id, emp_no, title, from_date)
109 | values
110 | (2, 20002, 'insert test 2', '0000-00-00'),
111 | (4, 40004, 'insert test 4', '0000-00-00')
112 | on duplicate key update emp_no=values(emp_no), title=values(title);
113 |
114 | #结果
115 | Query OK, 3 rows affected (0.00 sec)
116 | Records: 2 Duplicates: 1 Warnings: 0
117 | ```
118 |
119 |
120 |
121 | 参考:https://blog.csdn.net/lijing742180/article/details/90243470?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.channel_param
122 |
123 |
124 |
125 | ## 6.Mybatis #{} 和 ${}的区别是什么? 具体#的底层是怎么样做的?为什么#{}可以防止SQL注入?Mybatis如何防注入的? PrepareStatement底层原理是怎么样的,预编译做了什么?
126 |
127 | - `${}`是 Properties 文件中的变量占位符,它可以用于标签属性值和 sql 内部,属于静态文本替换,比如\${driver}会被静态替换为`com.mysql.jdbc.Driver`。
128 | - `#{}`是 sql 的参数占位符,Mybatis 会将 sql 中的`#{}`替换为?号,在 sql 执行前会使用 PreparedStatement 的参数设置方法,按序给 sql 的?号占位符设置参数值,比如 ps.setInt(0, parameterValue),`#{item.name}` 的取值方式为使用反射从参数对象中获取 item 对象的 name 属性值,相当于 `param.getItem().getName()`。
129 |
130 |
131 |
132 | 参考:JavaGuide和下面这篇文章 写的很好。
133 |
134 | https://blog.csdn.net/yizhenn/article/details/52384601
135 |
136 |
137 |
138 | ## 7.Mybatis里Left join inner join有什么区别?他们使用之后分别是什么结果?
139 |
140 | 参考Mysql。
141 |
142 |
143 |
144 | ## 8.Mybatis中,xml和mapper接口是如何映射的?
145 |
146 |
147 |
148 | 你知道如何批量插入吗?用Mybatis-plus
149 |
150 | Mybatis的缓存原理?
151 |
152 | mybatis用的反射(关于mybatis的细节)
153 |
154 | 介绍逆向工程:Generator和Mybatis-Plus
155 |
156 | 项目mybatis怎么使用?用mapper映射文件还是注解?
157 |
158 | mybatis的xml文件中有什么标签?
159 |
160 | mybatis 逆向工程,mybatis 的批量操作,比如大批量数据更新(这个问题卡住了):在应用里面用 mybatis 实现大批量数据(上万条)的更新,常规做法:Java 的 for 循环,慢,然后他说你可以去了解一下。
161 |
162 |
163 |
164 | mybatis的实现过程?怎么配置的?
165 |
166 | mybait-start,了解过他什么时候生效的吗?
167 |
168 | JPA了解吗?知道Hibernate吗?为何选择Mybatis,它和Hibernate的区别是什么
169 |
170 |
171 |
172 | ## 9.Mybatis的常用标签
173 |
174 | Mybatis的常用标签有哪些,如果DAO层的集合对象和<#foreache>标签名字不一样怎么解决的?(当时一时半会儿想不起来,面试官已经提示用@Param注解了,然而我听成了@Parable……)
175 |
176 |
177 |
178 |
179 |
180 | 10.Hibernate用过吗,JDBCTemplate用过吗?介绍一下里面具体的方法
181 |
182 | 11.where和where标签的区别
183 |
184 | 12.${}和#{}有什么区别
185 |
186 |
187 |
188 |
189 |
190 | > 参考自:https://github.com/Snailclimb/JavaGuide.git
191 |
192 | ## JavaGuide
193 |
194 | ### 1、#{}和\${}的区别是什么?
195 |
196 | 注:这道题是面试官面试我同事的。
197 |
198 | 答:
199 |
200 | - `${}`是 Properties 文件中的变量占位符,它可以用于标签属性值和 sql 内部,属于静态文本替换,比如\${driver}会被静态替换为`com.mysql.jdbc.Driver`。
201 | - `#{}`是 sql 的参数占位符,Mybatis 会将 sql 中的`#{}`替换为?号,在 sql 执行前会使用 PreparedStatement 的参数设置方法,按序给 sql 的?号占位符设置参数值,比如 ps.setInt(0, parameterValue),`#{item.name}` 的取值方式为使用反射从参数对象中获取 item 对象的 name 属性值,相当于 `param.getItem().getName()`。
202 |
203 | ### 2、Xml 映射文件中,除了常见的 select|insert|updae|delete 标签之外,还有哪些标签?
204 |
205 | 注:这道题是京东面试官面试我时问的。
206 |
207 | 答:还有很多其他的标签,``、``、``、``、``,加上动态 sql 的 9 个标签,`trim|where|set|foreach|if|choose|when|otherwise|bind`等,其中为 sql 片段标签,通过``标签引入 sql 片段,``为不支持自增的主键生成策略标签。
208 |
209 | ### 3、最佳实践中,通常一个 Xml 映射文件,都会写一个 Dao 接口与之对应,请问,这个 Dao 接口的工作原理是什么?Dao 接口里的方法,参数不同时,方法能重载吗?
210 |
211 | 注:这道题也是京东面试官面试我时问的。
212 |
213 | 答:Dao 接口,就是人们常说的 `Mapper`接口,接口的全限名,就是映射文件中的 namespace 的值,接口的方法名,就是映射文件中`MappedStatement`的 id 值,接口方法内的参数,就是传递给 sql 的参数。`Mapper`接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为 key 值,可唯一定位一个`MappedStatement`,举例:`com.mybatis3.mappers.StudentDao.findStudentById`,可以唯一找到 namespace 为`com.mybatis3.mappers.StudentDao`下面`id = findStudentById`的`MappedStatement`。在 Mybatis 中,每一个``、``、``、``标签,都会被解析为一个`MappedStatement`对象。
214 |
215 | Dao 接口里的方法,是不能重载的,因为是全限名+方法名的保存和寻找策略。
216 |
217 | Dao 接口的工作原理是 JDK 动态代理,Mybatis 运行时会使用 JDK 动态代理为 Dao 接口生成代理 proxy 对象,代理对象 proxy 会拦截接口方法,转而执行`MappedStatement`所代表的 sql,然后将 sql 执行结果返回。
218 |
219 | ### 4、Mybatis 是如何进行分页的?分页插件的原理是什么?
220 |
221 | 注:我出的。
222 |
223 | 答:Mybatis 使用 RowBounds 对象进行分页,它是针对 ResultSet 结果集执行的内存分页,而非物理分页,可以在 sql 内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
224 |
225 | 分页插件的基本原理是使用 Mybatis 提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的 sql,然后重写 sql,根据 dialect 方言,添加对应的物理分页语句和物理分页参数。
226 |
227 | 举例:`select _ from student`,拦截 sql 后重写为:`select t._ from (select \* from student)t limit 0,10`
228 |
229 | ### 5、简述 Mybatis 的插件运行原理,以及如何编写一个插件。
230 |
231 | 注:我出的。
232 |
233 | 答:Mybatis 仅可以编写针对 `ParameterHandler`、`ResultSetHandler`、`StatementHandler`、`Executor` 这 4 种接口的插件,Mybatis 使用 JDK 的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这 4 种接口对象的方法时,就会进入拦截方法,具体就是 `InvocationHandler` 的 `invoke()`方法,当然,只会拦截那些你指定需要拦截的方法。
234 |
235 | 实现 Mybatis 的 Interceptor 接口并复写` intercept()`方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,记住,别忘了在配置文件中配置你编写的插件。
236 |
237 | ### 6、Mybatis 执行批量插入,能返回数据库主键列表吗?
238 |
239 | 注:我出的。
240 |
241 | 答:能,JDBC 都能,Mybatis 当然也能。
242 |
243 | ### 7、Mybatis 动态 sql 是做什么的?都有哪些动态 sql?能简述一下动态 sql 的执行原理不?
244 |
245 | 注:我出的。
246 |
247 | 答:Mybatis 动态 sql 可以让我们在 Xml 映射文件内,以标签的形式编写动态 sql,完成逻辑判断和动态拼接 sql 的功能,Mybatis 提供了 9 种动态 sql 标签 `trim|where|set|foreach|if|choose|when|otherwise|bind`。
248 |
249 | 其执行原理为,使用 OGNL 从 sql 参数对象中计算表达式的值,根据表达式的值动态拼接 sql,以此来完成动态 sql 的功能。
250 |
251 | ### 8、Mybatis 是如何将 sql 执行结果封装为目标对象并返回的?都有哪些映射形式?
252 |
253 | 注:我出的。
254 |
255 | 答:第一种是使用``标签,逐一定义列名和对象属性名之间的映射关系。第二种是使用 sql 列的别名功能,将列别名书写为对象属性名,比如 T_NAME AS NAME,对象属性名一般是 name,小写,但是列名不区分大小写,Mybatis 会忽略列名大小写,智能找到与之对应对象属性名,你甚至可以写成 T_NAME AS NaMe,Mybatis 一样可以正常工作。
256 |
257 | 有了列名与属性名的映射关系后,Mybatis 通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。
258 |
259 | ### 9、Mybatis 能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别。
260 |
261 | 注:我出的。
262 |
263 | 答:能,Mybatis 不仅可以执行一对一、一对多的关联查询,还可以执行多对一,多对多的关联查询,多对一查询,其实就是一对一查询,只需要把 `selectOne()`修改为 `selectList()`即可;多对多查询,其实就是一对多查询,只需要把 `selectOne()`修改为 `selectList()`即可。
264 |
265 | 关联对象查询,有两种实现方式,一种是单独发送一个 sql 去查询关联对象,赋给主对象,然后返回主对象。另一种是使用嵌套查询,嵌套查询的含义为使用 join 查询,一部分列是 A 对象的属性值,另外一部分列是关联对象 B 的属性值,好处是只发一个 sql 查询,就可以把主对象和其关联对象查出来。
266 |
267 | 那么问题来了,join 查询出来 100 条记录,如何确定主对象是 5 个,而不是 100 个?其去重复的原理是``标签内的``子标签,指定了唯一确定一条记录的 id 列,Mybatis 根据列值来完成 100 条记录的去重复功能,``可以有多个,代表了联合主键的语意。
268 |
269 | 同样主对象的关联对象,也是根据这个原理去重复的,尽管一般情况下,只有主对象会有重复记录,关联对象一般不会重复。
270 |
271 | 举例:下面 join 查询出来 6 条记录,一、二列是 Teacher 对象列,第三列为 Student 对象列,Mybatis 去重复处理后,结果为 1 个老师 6 个学生,而不是 6 个老师 6 个学生。
272 |
273 | t_id t_name s_id
274 |
275 | | 1 | teacher | 38 |
276 | | 1 | teacher | 39 |
277 | | 1 | teacher | 40 |
278 | | 1 | teacher | 41 |
279 | | 1 | teacher | 42 |
280 | | 1 | teacher | 43 |
281 |
282 | ### 10、Mybatis 是否支持延迟加载?如果支持,它的实现原理是什么?
283 |
284 | 注:我出的。
285 |
286 | 答:Mybatis 仅支持 association 关联对象和 collection 关联集合对象的延迟加载,association 指的就是一对一,collection 指的就是一对多查询。在 Mybatis 配置文件中,可以配置是否启用延迟加载 `lazyLoadingEnabled=true|false。`
287 |
288 | 它的原理是,使用` CGLIB` 创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用 `a.getB().getName()`,拦截器 `invoke()`方法发现 `a.getB()`是 null 值,那么就会单独发送事先保存好的查询关联 B 对象的 sql,把 B 查询上来,然后调用 a.setB(b),于是 a 的对象 b 属性就有值了,接着完成 `a.getB().getName()`方法的调用。这就是延迟加载的基本原理。
289 |
290 | 当然了,不光是 Mybatis,几乎所有的包括 Hibernate,支持延迟加载的原理都是一样的。
291 |
292 | ### 11、Mybatis 的 Xml 映射文件中,不同的 Xml 映射文件,id 是否可以重复?
293 |
294 | 注:我出的。
295 |
296 | 答:不同的 Xml 映射文件,如果配置了 namespace,那么 id 可以重复;如果没有配置 namespace,那么 id 不能重复;毕竟 namespace 不是必须的,只是最佳实践而已。
297 |
298 | 原因就是 namespace+id 是作为 `Map`的 key 使用的,如果没有 namespace,就剩下 id,那么,id 重复会导致数据互相覆盖。有了 namespace,自然 id 就可以重复,namespace 不同,namespace+id 自然也就不同。
299 |
300 | ### 12、Mybatis 中如何执行批处理?
301 |
302 | 注:我出的。
303 |
304 | 答:使用 BatchExecutor 完成批处理。
305 |
306 | ### 13、Mybatis 都有哪些 Executor 执行器?它们之间的区别是什么?
307 |
308 | 注:我出的
309 |
310 | 答:Mybatis 有三种基本的 Executor 执行器,**`SimpleExecutor`、`ReuseExecutor`、`BatchExecutor`。**
311 |
312 | **`SimpleExecutor`:**每执行一次 update 或 select,就开启一个 Statement 对象,用完立刻关闭 Statement 对象。
313 |
314 | **``ReuseExecutor`:**执行 update 或 select,以 sql 作为 key 查找 Statement 对象,存在就使用,不存在就创建,用完后,不关闭 Statement 对象,而是放置于 Map内,供下一次使用。简言之,就是重复使用 Statement 对象。
315 |
316 | **`BatchExecutor`:**执行 update(没有 select,JDBC 批处理不支持 select),将所有 sql 都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个 Statement 对象,每个 Statement 对象都是 addBatch()完毕后,等待逐一执行 executeBatch()批处理。与 JDBC 批处理相同。
317 |
318 | 作用范围:Executor 的这些特点,都严格限制在 SqlSession 生命周期范围内。
319 |
320 | ### 14、Mybatis 中如何指定使用哪一种 Executor 执行器?
321 |
322 | 注:我出的
323 |
324 | 答:在 Mybatis 配置文件中,可以指定默认的 ExecutorType 执行器类型,也可以手动给 `DefaultSqlSessionFactory` 的创建 SqlSession 的方法传递 ExecutorType 类型参数。
325 |
326 | ### 15、Mybatis 是否可以映射 Enum 枚举类?
327 |
328 | 注:我出的
329 |
330 | 答:Mybatis 可以映射枚举类,不单可以映射枚举类,Mybatis 可以映射任何对象到表的一列上。映射方式为自定义一个 `TypeHandler`,实现 `TypeHandler` 的 `setParameter()`和 `getResult()`接口方法。`TypeHandler` 有两个作用,一是完成从 javaType 至 jdbcType 的转换,二是完成 jdbcType 至 javaType 的转换,体现为 `setParameter()`和 `getResult()`两个方法,分别代表设置 sql 问号占位符参数和获取列查询结果。
331 |
332 | ### 16、Mybatis 映射文件中,如果 A 标签通过 include 引用了 B 标签的内容,请问,B 标签能否定义在 A 标签的后面,还是说必须定义在 A 标签的前面?
333 |
334 | 注:我出的
335 |
336 | 答:虽然 Mybatis 解析 Xml 映射文件是按照顺序解析的,但是,被引用的 B 标签依然可以定义在任何地方,Mybatis 都可以正确识别。
337 |
338 | 原理是,Mybatis 解析 A 标签,发现 A 标签引用了 B 标签,但是 B 标签尚未解析到,尚不存在,此时,Mybatis 会将 A 标签标记为未解析状态,然后继续解析余下的标签,包含 B 标签,待所有标签解析完毕,Mybatis 会重新解析那些被标记为未解析的标签,此时再解析 A 标签时,B 标签已经存在,A 标签也就可以正常解析完成了。
339 |
340 | ### 17、简述 Mybatis 的 Xml 映射文件和 Mybatis 内部数据结构之间的映射关系?
341 |
342 | 注:我出的
343 |
344 | 答:Mybatis 将所有 Xml 配置信息都封装到 All-In-One 重量级对象 Configuration 内部。在 Xml 映射文件中,``标签会被解析为 `ParameterMap` 对象,其每个子元素会被解析为 ParameterMapping 对象。``标签会被解析为 `ResultMap` 对象,其每个子元素会被解析为 `ResultMapping` 对象。每一个`、、、`标签均会被解析为 `MappedStatement` 对象,标签内的 sql 会被解析为 BoundSql 对象。
345 |
346 | ### 18、为什么说 Mybatis 是半自动 ORM 映射工具?它与全自动的区别在哪里?
347 |
348 | 注:我出的
349 |
350 | 答:Hibernate 属于全自动 ORM 映射工具,使用 Hibernate 查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而 Mybatis 在查询关联对象或关联集合对象时,需要手动编写 sql 来完成,所以,称之为半自动 ORM 映射工具。
351 |
352 | 面试题看似都很简单,但是想要能正确回答上来,必定是研究过源码且深入的人,而不是仅会使用的人或者用的很熟的人,以上所有面试题及其答案所涉及的内容,在我的 Mybatis 系列博客中都有详细讲解和原理分析。
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 | ## 附加:一文了解JPA、Hibernate、Spring Data JPA之间的爱恨情仇
361 |
362 | **前言**
363 |
364 | 我们都知道Java 持久层框架访问数据库的方式大致分为两种。一种以 SQL 核心,封装一定程度的 JDBC 操作,比如: MyBatis。另一种是以 Java 实体类为核心,将实体类的和数据库表之间建立映射关系,也就是我们说的ORM框架,如:Hibernate、Spring Data JPA。今天咱们就先来了解一下什么是Spring Data JPA?
365 |
366 | **JPA是啥**
367 |
368 | 在开始学习Spring Data JPA之前我们首先还是要先了解下什么是JPA,因为Spring Data JPA是建立的JPA的基础之上的,那到底什么是JPA呢?
369 |
370 | 我们都知道不同的数据库厂商都有自己的实现类,后来统一规范也就有了数据库驱动,Java在操作数据库的时候,底层使用的其实是JDBC,而JDBC是一组操作不同数据库的规范。我们的Java应用程序,只需要调用JDBC提供的API就可以访问数据库了,而JPA也是类似的道理。
371 |
372 | 
373 |
374 | JPA全称为Java Persistence API(Java持久层API),它是Sun公司在JavaEE 5中提出的Java持久化规范。它为Java开发人员提供了一种对象/关联映射工具,来管理Java应用中的关系数据,JPA吸取了目前Java持久化技术的优点,旨在规范、简化Java对象的持久化工作。很多ORM框架都是实现了JPA的规范,如:Hibernate、EclipseLink。
375 |
376 | 需要注意的是JPA统一了Java应用程序访问ORM框架的规范
377 |
378 | **JPA为我们提供了以下规范:**
379 |
380 | - ORM映射元数据:JPA支持XML和注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中
381 | - JPA 的API:用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发人员不用再写SQL了
382 | - JPQL查询语言:通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。
383 |
384 | **Hibernate是啥**
385 |
386 | Hibernate是Java中的对象关系映射解决方案。对象关系映射或ORM框架是将应用程序数据模型对象映射到关系数据库表的技术。Hibernate 不仅关注于从 Java 类到数据库表的映射,也有 Java 数据类型到 SQL 数据类型的映射。
387 |
388 | 
389 |
390 | **Hibernate 和 JPA是什么关系呢**
391 |
392 | 上面我们介绍到JPA是Java EE 5规范中提出的Java持久化接口,而Hibernate是一个ORM框架
393 |
394 | JPA和Hibernate的关系:
395 |
396 | JPA是一个规范,而不是框架
397 |
398 | Hibernate是JPA的一种实现,是一个框架
399 |
400 | **Spring Data是啥**
401 |
402 | Spring Data是Spring 社区的一个子项目,主要用于简化数据(关系型&非关系型)访问,其主要目标是使得数据库的访问变得方便快捷。
403 |
404 | 它提供很多模板操作
405 |
406 | – Spring Data Elasticsearch
407 |
408 | – Spring Data MongoDB
409 |
410 | – Spring Data Redis
411 |
412 | – Spring Data Solr
413 |
414 | 强大的 Repository 和定制的数据储存对象的抽象映射
415 |
416 | 对数据访问对象的支持
417 |
418 | **Spring Data JPA又是啥**
419 |
420 | Spring Data JPA是在实现了JPA规范的基础上封装的一套 JPA 应用框架,虽然ORM框架都实现了JPA规范,但是在不同的ORM框架之间切换仍然需要编写不同的代码,而使用Spring Data JPA能够方便大家在不同的ORM框架之间进行切换而不需要更改代码。Spring Data JPA旨在通过将统一ORM框架的访问持久层的操作,来提高开发人的效率。
421 |
422 | 
423 |
424 | **Spring Data JPA给我们提供的主要的类和接口**
425 |
426 | Repository 接口:
427 |
428 | Repository
429 |
430 | CrudRepository
431 |
432 | JpaRepository
433 |
434 | Repository 实现类:
435 |
436 | SimpleJpaRepository
437 |
438 | QueryDslJpaRepository
439 |
440 | 以上这些类和接口就是我们以后在使用Spring Data JPA的时候需要掌握的。
441 |
442 | **Spring Data JPA和Hibernate的关系**
443 |
444 | Hibernate其实是JPA的一种实现,而Spring Data JPA是一个JPA数据访问抽象。也就是说Spring Data JPA不是一个实现或JPA提供的程序,它只是一个抽象层,主要用于减少为各种持久层存储实现数据访问层所需的样板代码量。但是它还是需要JPA提供实现程序,其实Spring Data JPA底层就是使用的 Hibernate实现。
445 |
446 | **小结:**
447 |
448 | Hibernate是JPA的一种实现,是一个框架
449 |
450 | Spring Data JPA是一种JPA的抽象层,底层依赖Hibernate
451 |
452 | **总结:**
453 |
454 | 这里主要给介绍了JPA、Hibernate、以及Spring Data JPA的概念以及三者的关系,让我们对这些常用的持久层规范和框架有一个清晰的认识。这样以后我们再接触到其他的同类ORM框架或者其他持久层框架的时候就能更加的游刃有余。
455 |
456 |
457 |
458 | ·
459 |
460 |
461 |
462 | ·
--------------------------------------------------------------------------------
/docs/NetWork.md:
--------------------------------------------------------------------------------
1 | # NetWork
2 |
3 | 计算机网络
4 |
5 |
6 |
7 | > 在408四门课中,计算机网络这一部分知识问的挺多,平时工作也跟这一部分打交道比较多。
8 |
9 | # Interview
10 |
11 | ## 1.三次握手、四次挥手相关
12 |
13 | TCP的三次握手有听说过吗?
14 |
15 | 具体都有哪些?
16 |
17 | 为什么要握手需要三次,而挥手需要四次?
18 |
19 | 有哪些参数,为什么要三次握手?
20 |
21 | 画图描述?
22 |
23 |
24 |
25 | ## 2.HTTP相关
26 |
27 | ### 1.HTTP状态码相关
28 |
29 | Http协议状态码 错误码?
30 |
31 | HTTP协议的状态码有哪些?403是什么?
32 |
33 | 说一下除了200/302/404/500之外的常见状态码?
34 |
35 | 错误码401,301分别代表什么?
36 |
37 | 30x状态码的重定向功能在底层具体是怎么样实现的?
38 |
39 | socekt跟http它门之间有什么关系吗?各个状态码分别代表什么不同的含义?
40 |
41 |
42 |
43 | ### 2.HTTP请求方式、请求头、请求行相关
44 |
45 | 说一下HTTP请求有哪些?
46 |
47 | Http怎么封装header?
48 |
49 | 你们除了用GET和POST,还用过哪些请求方式?
50 |
51 | HTTP请求头中的Connection参数是干什么用的?
52 |
53 | HTTP请求头跟缓存有关的参数是哪些?
54 |
55 | HTTP报文的请求行,请求头都有哪些参数?
56 |
57 | 详细说下HTTP协议的请求报文中,请求头有哪些请求参数,响应头有哪些参数?
58 |
59 |
60 |
61 | ### 3.HTTP概念相关
62 |
63 | HTTP请求是什么?
64 |
65 | 前后端交互是通过http请求,http请求一般会包括哪些部分?
66 |
67 |
68 |
69 | ### 4.HTTP和HTTPS对比
70 |
71 | 相比Http,Https为什么是安全的?
72 |
73 | HTTP1.1和1.0有什么区别?
74 |
75 | http和https之间的区别?
76 |
77 | 区别是HTTPS是HTTP+SSL,有一个安全验证机制(CA证书)
78 |
79 |
80 |
81 | ### 5.HTTP协议相关
82 |
83 | http是哪层协议?应用层协议
84 |
85 | Http协议的组成?
86 |
87 |
88 |
89 | ### 6.HTTP缓存
90 |
91 | http缓存有哪几种,了解过吗?
92 |
93 |
94 |
95 | ## 3.POST请求和GET请求的区别
96 |
97 | GET和POST有什么区别?
98 |
99 | 了解过其他的比如put,delete吗?
100 |
101 | GET方式的特点:在URL地址后附带的参数是有限制的,其数据容量通常不能超过1K
102 |
103 | POST方式,则可以在请求的正文内容中向服务器发送数据,Post方式的特点:传送的数据量无限制
104 |
105 |
106 |
107 | GET请求的URL长度之前有4KB大小的限制,现在已经没有限制了?
108 |
109 |
110 |
111 | ## 4.OSI模型和TCP/IP模型的区别
112 |
113 |
114 |
115 | ## 5.TCP、UDP、TCP/IP、HTTP,TCP,IP,UDP,RPC协议
116 |
117 | ### 1.TCP相关
118 |
119 | TCP/IP说一下?
120 |
121 | TCP/IP:是利用 IP 进行通信时所必须用到的协议群的统称。互联网进行通信时,需要相应的网络协议,TCP/IP 原本就是为使用互联网而开发制定的协议族。因此,互联网的协议就是 TCP/IP,TCP/IP 就是互联网的协议。
122 |
123 |
124 |
125 | TCP断开的时候存在TimeWait的状态,还记得吗?
126 |
127 | TCP的流量控制还记得吗?(滑动窗口) ?
128 |
129 | TCP/IP协议族总共分了几层?
130 |
131 | 一个tcp连接可以发送多少个http请求?
132 |
133 | tcp属于哪层协议?写过TCP有关的程序吗?
134 |
135 | 一个tcp连接可以发送多少个http请求?
136 |
137 | 讲一下TCP?面向连接,可靠性传输,还有什么?
138 |
139 | 有没有在项目中用到TCP?
140 |
141 | HTTP协议和dubbo这些协议基于TCP,可能强答了。微信发信息用的是TCP还是UDP, 微信电话呢?(微信电话我答UDP,实时性要求较高,可靠性可以有一定程度的容忍,面试官点了点头)
142 |
143 |
144 |
145 | ### 2.UDP相关
146 |
147 |
148 |
149 | ### 3.协议之间对比
150 |
151 | TCP,UDP区别?
152 |
153 | HTTP,TCP,IP,UDP,RPC协议分别有什么区别?
154 |
155 |
156 |
157 | ## 6.计算机网络一共有几层?ARP协议是7层哪一层?TCP IP HTTP分别在哪层?
158 |
159 | 给出一堆协议,选出哪些是应用层协议?(主要区别于传输层协议)
160 |
161 |
162 |
163 | ## 7.Tomcat相关
164 |
165 | Tomcat启动后,第一次访问时间很长,之后就很快了,为什么?
166 |
167 | Tomcat的最大连接数是多少?
168 |
169 | Tomcat配置文件中可以修改哪些内容,提升Tomcat性能?
170 |
171 | Tomcat服务器,我们如果需要修改一些参数,一般会修改哪些?
172 |
173 | 对Tomcat的配置(connector支持哪些协议)?
174 |
175 | Tomcat内部怎么处理请求?
176 |
177 | 什么是并发,tomcat的controller方法是并发的吗?
178 |
179 | 描述下Tomcat的工作原理?
180 |
181 |
182 |
183 | ## 8.系统之间通信的方式有哪些? 它们之间有什么区别?
184 |
185 |
186 |
187 | ## 9.用户从打开浏览器输入网址到展现出结果,整个流程是怎样的?
188 |
189 |
190 |
191 | ## 10.接收到的数据是一个json,那页面的元素,比如样式、图片是怎样展现出来的?
192 |
193 |
194 |
195 | ## 11.为什么客户端只发送了一个请求,但是却能接收到图片和样式这些东西
196 |
197 |
198 |
199 |
200 |
201 | ## 12.解释一下TCP的滑动窗口机制和拥塞控制?
202 |
203 |
204 |
205 | ## 13.什么是网络传输中的粘包问题?
206 |
207 |
208 |
209 | ## 14.RPC通信原理 ,如何实现
210 |
211 |
212 |
213 | ## 15.Java网络编程中同步、异步、阻塞、非阻塞的概念分别都是什么?
214 |
215 |
216 |
217 | ## 16.Socket连接谷歌官网,并且下载
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
--------------------------------------------------------------------------------
/docs/Redis.md:
--------------------------------------------------------------------------------
1 | # Redis
2 |
3 |
4 |
5 | # Interview
6 |
7 | 简单来说 redis 就是一个数据库,不过与传统数据库不同的是 **redis 的数据是存在内存中的**,所以读写速度非常快,因此 redis 被广泛应用于**缓存方向**。另外,redis 也经常用来做**分布式锁**。redis 提供了多种数据类型来支持不同的业务场景。除此之外,redis 支持事务 、持久化、LUA脚本、LRU驱动事件、多种集群方案。
8 |
9 |
10 |
11 | ### 1.Redis数据类型,及其底层原理?zset底层是怎么样对数据进行排序的?
12 |
13 | Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)
14 |
15 | #### 1)、**字符串string**
16 |
17 | string字符串是一种**动态的字符串**,使用者可以动态修改,类似于Java中的ArrayList
18 |
19 | 你会发现同样一组结构 Redis 使用泛型定义了好多次,**为什么不直接使用 int 类型呢?**
20 |
21 | 因为当字符串比较短的时候,len 和 alloc 可以使用 byte 和 short 来表示,**Redis 为了对内存做极致的优化,不同长度的字符串使用不同的结构体来表示。**(亮点)
22 |
23 | ##### 对字符串的基本操作
24 |
25 | 安装好 Redis,我们可以使用 `redis-cli` 来对 Redis 进行命令行的操作,当然 Redis 官方也提供了在线的调试器,你也可以在里面敲入命令进行操作:[http://try.redis.io/#run](http://try.redis.io/#run)
26 |
27 | ###### 设置和获取键值对
28 |
29 | ```console
30 | > SET key value
31 | OK
32 | > GET key
33 | "value"
34 | ```
35 |
36 | 正如你看到的,我们通常使用 `SET` 和 `GET` 来设置和获取字符串值。
37 |
38 | 值可以是任何种类的字符串(包括二进制数据),例如你可以在一个键下保存一张 `.jpeg` 图片,只需要注意不要超过 512 MB 的最大限度就好了。
39 |
40 | 当 key 存在时,`SET` 命令会覆盖掉你上一次设置的值:
41 |
42 | ```console
43 | > SET key newValue
44 | OK
45 | > GET key
46 | "newValue"
47 | ```
48 |
49 | 另外你还可以使用 `EXISTS` 和 `DEL` 关键字来查询是否存在和删除键值对:
50 |
51 | ```console
52 | > EXISTS key
53 | (integer) 1
54 | > DEL key
55 | (integer) 1
56 | > GET key
57 | (nil)
58 | ```
59 |
60 | ###### 批量设置键值对
61 |
62 | ```console
63 | > SET key1 value1
64 | OK
65 | > SET key2 value2
66 | OK
67 | > MGET key1 key2 key3 # 返回一个列表
68 | 1) "value1"
69 | 2) "value2"
70 | 3) (nil)
71 | > MSET key1 value1 key2 value2
72 | > MGET key1 key2
73 | 1) "value1"
74 | 2) "value2"
75 | ```
76 |
77 | ###### 过期和 SET 命令扩展
78 |
79 | 可以对 key 设置过期时间,到时间会被自动删除,这个功能常用来控制缓存的失效时间。*(过期可以是任意数据结构)*
80 |
81 | ```console
82 | > SET key value1
83 | > GET key
84 | "value1"
85 | > EXPIRE name 5 # 5s 后过期
86 | ... # 等待 5s
87 | > GET key
88 | (nil)
89 | ```
90 |
91 | 等价于 `SET` + `EXPIRE` 的 `SETNX` 命令:
92 |
93 | ```console
94 | > SETNX key value1
95 | ... # 等待 5s 后获取
96 | > GET key
97 | (nil)
98 |
99 | > SETNX key value1 # 如果 key 不存在则 SET 成功
100 | (integer) 1
101 | > SETNX key value1 # 如果 key 存在则 SET 失败
102 | (integer) 0
103 | > GET key
104 | "value" # 没有改变
105 | ```
106 |
107 | ###### 计数
108 |
109 | 如果 value 是一个整数,还可以对它使用 `INCR` 命令进行 **原子性** 的自增操作,这意味着及时多个客户端对同一个 key 进行操作,也决不会导致竞争的情况:
110 |
111 | ```console
112 | > SET counter 100
113 | > INCR count
114 | (interger) 101
115 | > INCRBY counter 50
116 | (integer) 151
117 | ```
118 |
119 | ###### 返回原值的 GETSET 命令
120 |
121 | 对字符串,还有一个 `GETSET` 比较让人觉得有意思,它的功能跟它名字一样:为 key 设置一个值并返回原值:
122 |
123 | ```console
124 | > SET key value
125 | > GETSET key value1
126 | "value"
127 | ```
128 |
129 | 这可以对于某一些需要隔一段时间就统计的 key 很方便的设置和查看,例如:系统每当由用户进入的时候你就是用 `INCR` 命令操作一个 key,当需要统计时候你就把这个 key 使用 `GETSET` 命令重新赋值为 0,这样就达到了统计的目的。
130 |
131 | #### 2)、**列表list**
132 |
133 | 列表list相当于java中的LinkedList,插入和删除非常快,时间复杂度O(1),索引定位很慢O(n)
134 |
135 | ##### 链表的基本操作
136 |
137 | - `LPUSH` 和 `RPUSH` 分别可以向 list 的左边(头部)和右边(尾部)添加一个新元素;
138 | - `LRANGE` 命令可以从 list 中取出一定范围的元素;
139 | - `LINDEX` 命令可以从 list 中取出指定下表的元素,相当于 Java 链表操作中的 `get(int index)` 操作;
140 |
141 | 示范:
142 |
143 | ```console
144 | > rpush mylist A(integer) 1> rpush mylist B(integer) 2> lpush mylist first(integer) 3> lrange mylist 0 -1 # -1 表示倒数第一个元素, 这里表示从第一个元素到最后一个元素,即所有1) "first"2) "A"3) "B"
145 | ```
146 |
147 | ####
148 |
149 | #### 3)、**字典hash**
150 |
151 | 字典hash类似于java中的HashMap,内部实现也类似,是通过“数组+列表”的实现来解决部分哈希冲突。
152 |
153 | 正常情况下,当元素数量达到第一个数组的长度,就会扩容,扩容为原来的两倍,(和HashMap一样)
154 |
155 | ##### 字典的基本操作
156 |
157 | hash 也有缺点,hash 结构的存储消耗要高于单个字符串,所以到底该使用 hash 还是字符串,需要根据实际情况再三权衡:
158 |
159 | ```shell
160 | > HSET books java "think in java" # 命令行的字符串如果包含空格则需要使用引号包裹(integer) 1> HSET books python "python cookbook"(integer) 1> HGETALL books # key 和 value 间隔出现1) "java"2) "think in java"3) "python"4) "python cookbook"> HGET books java"think in java"> HSET books java "head first java" (integer) 0 # 因为是更新操作,所以返回 0> HMSET books java "effetive java" python "learning python" # 批量操作OK
161 | ```
162 |
163 | ##
164 |
165 | #### 4)、**集合set**
166 |
167 | 集合相当于java中的HashSet,他内部的键值对是无序的惟一的,他的内部实现相当于一个字典,字典中所有的value都是一个value
168 |
169 | ##### 集合 set 的基本使用
170 |
171 | 由于该结构比较简单,我们直接来看看是如何使用的:
172 |
173 | ```shell
174 | > SADD books java(integer) 1> SADD books java # 重复(integer) 0> SADD books python golang(integer) 2> SMEMBERS books # 注意顺序,set 是无序的 1) "java"2) "python"3) "golang"> SISMEMBER books java # 查询某个 value 是否存在,相当于 contains(integer) 1> SCARD books # 获取长度(integer) 3> SPOP books # 弹出一个"java"
175 | ```
176 |
177 | ##
178 |
179 | #### 5)、**有序列表zset**
180 |
181 | 这可能是redis最具特色的一个结构,它类似于 Java 中 **SortedSet** 和 **HashMap** 的结合体,一方面它是一个 set,保证了内部 value 的唯一性,另一方面它可以为每个 value 赋予一个 score 值,用来代表排序的权重。
182 |
183 |
184 |
185 | 底层实现是一个**跳跃表**:
186 |
187 | 跳跃表就类似于这样的机制,最下面一层所有的元素都会串起来,都是员工,然后每隔几个元素就会挑选出一个代表,再把这几个代表使用另外一级指针串起来。然后再在这些代表里面挑出二级代表,再串起来。**最终形成了一个金字塔的结构。**
188 |
189 | 想一下你目前所在的地理位置:亚洲 > 中国 > 某省 > 某市 > ....,**就是这样一个结构!**
190 |
191 |
192 |
193 | ##### 有序列表 zset 基础操作
194 |
195 | ```console
196 | > ZADD books 9.0 "think in java"> ZADD books 8.9 "java concurrency"> ZADD books 8.6 "java cookbook"> ZRANGE books 0 -1 # 按 score 排序列出,参数区间为排名范围1) "java cookbook"2) "java concurrency"3) "think in java"> ZREVRANGE books 0 -1 # 按 score 逆序列出,参数区间为排名范围1) "think in java"2) "java concurrency"3) "java cookbook"> ZCARD books # 相当于 count()(integer) 3> ZSCORE books "java concurrency" # 获取指定 value 的 score"8.9000000000000004" # 内部 score 使用 double 类型进行存储,所以存在小数点精度问题> ZRANK books "java concurrency" # 排名(integer) 1> ZRANGEBYSCORE books 0 8.91 # 根据分值区间遍历 zset1) "java cookbook"2) "java concurrency"> ZRANGEBYSCORE books -inf 8.91 withscores # 根据分值区间 (-∞, 8.91] 遍历 zset,同时返回分值。inf 代表 infinite,无穷大的意思。1) "java cookbook"2) "8.5999999999999996"3) "java concurrency"4) "8.9000000000000004"> ZREM books "java concurrency" # 删除 value(integer) 1> ZRANGE books 0 -11) "java cookbook"2) "think in java"
197 | ```
198 |
199 |
200 |
201 | ### 2.Redis 持久化策略(存储策略)
202 |
203 | (怎么保证 redis 挂掉之后再重启数据可以进行恢复)
204 |
205 | 很多时候我们需要持久化数据也就是将内存中的数据写入到硬盘里面,大部分原因是为了之后重用数据(比如重启机器、机器故障之后恢复数据),或者是为了防止系统故障而将数据备份到一个远程位置。
206 |
207 |
208 |
209 | **持久化通用的两种方式**:
210 |
211 | **1)、快照(snapshotting,RDB)**(某一时刻对数据的备份)
212 |
213 | 类似拍照片把那瞬间的数据保存在了**dump.rdb**文件中(打开看到这个文件其实是二进制文件)
214 |
215 | 这种是redis默认采用的一种持久化方式。在redis.conf配置文件中默认有此下配置:
216 |
217 | ```j
218 | save 900 1 #在900秒(15分钟)之后,如果至少有1个key发生变化,Redis就会自动触发BGSAVE命令创建快照。save 300 10 #在300秒(5分钟)之后,如果至少有10个key发生变化,Redis就会自动触发BGSAVE命令创建快照。save 60 10000 #在60秒(1分钟)之后,如果至少有10000个key发生变化,Redis就会自动触发BGSAVE命令创建快照。
219 | ```
220 |
221 |
222 |
223 | **2)、追加文件(append-only file,AOF**)
224 |
225 | 与快照持久化相比,AOF持久化 的实时性更好,因此已成为主流的持久化方案。
226 |
227 | 追加文件这种持久化方式,默认是没有开启的,如果要开启,需要在config里面设置
228 |
229 | ```conf
230 | appendonly yes
231 | ```
232 |
233 | 在Redis的配置文件中存在三种不同的 AOF 持久化方式,它们分别是:
234 |
235 | ```conf
236 | appendfsync always #每次有数据修改发生时都会写入AOF文件,这样会严重降低Redis的速度appendfsync everysec #每秒钟同步一次,显示地将多个写命令同步到硬盘appendfsync no #让操作系统决定何时进行同步
237 | ```
238 |
239 | 为了兼顾数据和写入性能,用户可以考虑 appendfsync everysec选项 ,让Redis每秒同步一次AOF文件,Redis性能几乎没受到任何影响。而且这样即使出现系统崩溃,用户最多只会丢失一秒之内产生的数据。
240 |
241 |
242 |
243 | 参考:https://www.jianshu.com/p/ae47d69f92eb
244 |
245 |
246 |
247 | ### 3. Redis的存储策略(持久化策略),你们项目中用的是哪一种
248 |
249 | RDB和AOF两个都用
250 |
251 | - **RDB**
252 |
253 | 优点:数据全,并且数据存放整齐
254 |
255 | 缺点:每次都能保存所有数据,短时间比较消耗性能
256 |
257 |
258 |
259 | - **AOF**
260 |
261 | 缺点:消耗性能(因为每次改变都要执行日志),磁盘存储零散
262 |
263 | 优点:实时性,不容易丢失数据
264 |
265 |
266 |
267 | ### 4. Redis的使用场景,那些地方用到Redis?
268 |
269 | 1)、第一做缓存,因为用户第一次访问数据库的时候,是比较慢的,所以第一次访问完以后,会将数据查出来放到缓存中,以后查的时候就会非常快。 (高性能)
270 |
271 | 2)、直接操作缓存能够承受的请求是远远大于直接访问数据库的,所以我们可以考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用经过数据库。(高并发)
272 |
273 |
274 |
275 | 上面两个是比较笼统的对redis的概括。
276 |
277 | 
278 |
279 | 具体的使用:
280 |
281 | 1、注册,修改密码等,短信放redis中
282 |
283 | 2、登录上去以后,当前登录用户的信息,钱包等 信息,都放到redis中,啥时候用的时候再取出来
284 |
285 | 3、系统的一些配置,在项目启动的时候,放到redis中
286 |
287 | 4、交易的各种币种的汇率等
288 |
289 | 5、交易历史
290 |
291 | 6、交易对信息(谁和谁交易)
292 |
293 | 7、通知等
294 |
295 | 8、商户信息
296 |
297 |
298 |
299 | ### 5.缓存雪崩和缓存穿透问题解决方案
300 |
301 | #### **缓存雪崩**
302 |
303 | 上次看敖丙画这个图,然后自己画一个
304 |
305 |
306 |
307 |
308 |
309 | **什么是缓存雪崩?**
310 |
311 | 简介:缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。
312 |
313 | **有哪些解决办法?**(三太子敖丙 过期时间设置不一样,随机值,就不会同一时间同时雪崩)
314 |
315 | (中华石杉老师在他的视频中提到过,视频地址在最后一个问题中有提到):
316 |
317 | - 事前:尽量保证整个 redis 集群的高可用性,发现机器宕机尽快补上。选择合适的内存淘汰策略。
318 | - 事中:本地ehcache缓存 + hystrix限流&降级,避免MySQL崩掉
319 | - 事后:利用 redis 持久化机制保存的数据尽快恢复缓存
320 |
321 | 
322 |
323 | #### **缓存穿透**
324 |
325 | **什么是缓存穿透?**
326 |
327 | 缓存穿透说简单点就是大量请求的 key 根本不存在于缓存中,导致请求直接到了数据库上,根本没有经过缓存这一层。举个例子:某个黑客故意制造我们缓存中不存在的 key 发起大量请求,导致大量请求落到数据库。下面用图片展示一下(这两张图片不是我画的,为了省事直接在网上找的,这里说明一下):
328 |
329 | **正常缓存处理流程:**
330 |
331 |
332 |
333 | **缓存穿透情况处理流程:**
334 |
335 |
336 |
337 | ------
338 |
339 | **有哪些解决办法?**
340 |
341 | 最基本的就是首先做好参数校验,一些不合法的参数请求直接抛出异常信息返回给客户端。比如查询的数据库 id 不能小于 0、传入的邮箱格式不对的时候直接返回错误消息给客户端等等。
342 |
343 | **1)缓存无效 key** : 如果缓存和数据库都查不到某个 key 的数据就写一个到 redis 中去并设置过期时间,具体命令如下:`SET key value EX 10086`。这种方式可以解决请求的 key 变化不频繁的情况,如果黑客恶意攻击,每次构建不同的请求key,会导致 redis 中缓存大量无效的 key 。很明显,这种方案并不能从根本上解决此问题。如果非要用这种方式来解决穿透问题的话,尽量将无效的 key 的过期时间设置短一点比如 1 分钟。
344 |
345 | 另外,这里多说一嘴,一般情况下我们是这样设计 key 的: `表名:列名:主键名:主键值`。
346 |
347 | 如果用 Java 代码展示的话,差不多是下面这样的:
348 |
349 | ```java
350 | public Object getObjectInclNullById(Integer id) { // 从缓存中获取数据 Object cacheValue = cache.get(id); // 缓存为空 if (cacheValue == null) { // 从数据库中获取 Object storageValue = storage.get(key); // 缓存空对象 cache.set(key, storageValue); // 如果存储数据为空,需要设置一个过期时间(300秒) if (storageValue == null) { // 必须设置过期时间,否则有被攻击的风险 cache.expire(key, 60 * 5); } return storageValue; } return cacheValue;}
351 | ```
352 |
353 | **2)布隆过滤器:**布隆过滤器是一个非常神奇的数据结构,通过它我们可以非常方便地判断一个给定数据是否存在与海量数据中。我们需要的就是判断 key 是否合法,有没有感觉布隆过滤器就是我们想要找的那个“人”。具体是这样做的:**把所有可能存在的请求的值都存放在布隆过滤器中**,当用户请求过来,我会先判断用户发来的请求的值是否存在于布隆过滤器中。不存在的话,直接返回请求参数错误信息给客户端,存在的话才会走下面的流程。总结一下就是下面这张图(这张图片不是我画的,为了省事直接在网上找的):
354 |
355 |
356 |
357 | 更多关于布隆过滤器的内容可以看我的这篇原创:[《不了解布隆过滤器?一文给你整的明明白白!》](https://github.com/Snailclimb/JavaGuide/blob/master/docs/dataStructures-algorithms/data-structure/bloom-filter.md) ,强烈推荐,个人感觉网上应该找不到总结的这么明明白白的文章了。
358 |
359 |
360 |
361 |
362 |
363 | ### 6.redis是如何配置的? 你们的redis有集群吗? 有主从关系吗?
364 |
365 |
366 |
367 | redis配置,现在还没有搞集群。准备等用户量大的时候搞集群。
368 |
369 | redis集群参考:https://www.cnblogs.com/silent2012/p/10697896.html(写的很好)
370 |
371 | 这个里面三主三从。也可以设置四主四从。
372 |
373 |
374 |
375 | ### 7.redis内存淘汰策略(内存淘汰机制)
376 |
377 |
378 |
379 | 如果redis的内存占用过多的时候,此时会进行内存淘汰,有如下一些策略:
380 |
381 |
382 |
383 | noeviction:当内存不足以容纳新写入数据时,新写入操作会报错,这个一般没人用吧
384 |
385 | allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key(这个是最常用的)
386 |
387 | allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key,这个一般没人用吧
388 |
389 | volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key(这个一般不太合适)
390 |
391 | volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key
392 |
393 | volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除
394 |
395 |
396 |
397 | 参考:https://www.cnblogs.com/mengchunchen/p/10039467.html (说是中华石杉的)
398 |
399 |
400 |
401 | ### 8.上面提到的Hystrix限流,降级
402 |
403 | 限流,降级,熔断
404 |
405 | 参考:https://www.jianshu.com/p/857d90a0afba(这个是转载自阿里的大牛)
406 |
407 | https://blog.csdn.net/qq_17522211/article/details/84559987
408 |
409 |
410 |
411 | ### 9.MangoDB和Redis的区别?
412 |
413 | 项目中用的是MongoDB,但是为什么用其实当时选型的时候也没有太多考虑,只是认为**数据量比较大**,所以采用MongoDB。
414 |
415 | 最近又想起为什么用MongoDB,就查阅一下,汇总汇总:
416 |
417 | 之前也用过redis,当时是用来存储一些热数据,量也不大,但是操作很频繁。现在项目中用的是MongoDB,目前是百万级的数据,将来会有千万级、亿级。
418 |
419 | 就Redis和MongoDB来说,大家一般称之为**Redis缓存、MongoDB数据库**。这也是有道有理有根据的,
420 |
421 | Redis主要把数据存储在内存中,其“缓存”的性质远大于其“数据存储“的性质,其中数据的增删改查也只是像变量操作一样简单;
422 |
423 | MongoDB却是一个“存储数据”的系统,增删改查可以添加很多条件,就像SQL数据库一样灵活,这一点在面试的时候很受用。
424 |
425 | 点击查看:[MongoDB语法与现有关系型数据库SQL语法比较](https://www.cnblogs.com/java-spring/p/9488200.html)
426 |
427 |
428 |
429 | **Mongodb与Redis应用指标对比**
430 |
431 | **MongoDB和Redis都是NoSQL**,采用结构型数据存储。二者在使用场景中,存在一定的区别,这也主要由于
432 | 二者在内存映射的处理过程,持久化的处理方法不同。MongoDB建议集群部署,更多的考虑到集群方案,Redis
433 | 更偏重于进程顺序写入,虽然支持集群,也仅限于主-从模式。
434 |
435 |
436 |
437 | | 指标 | MongoDB(v2.4.9) | Redis(v2.4.17) | 比较说明 |
438 | | :--------: | :----------------------------------------------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: |
439 | | 实现语言 | C++ | C/C++ | - |
440 | | 协议 | BSON、自定义二进制 | 类Telnet | - |
441 | | 性能 | 依赖内存,TPS较高 | 依赖内存,TPS非常高 | Redis优于MongoDB |
442 | | 可操作性 | 丰富的数据表达、索引;最类似于关系数据库,支持丰富的查询语言 | 数据丰富,较少的IO | MongoDB优于Redis |
443 | | 内存及存储 | 适合大数据量存储,依赖系统虚拟内存管理,采用镜像文件存储;内存占有率比较高,官方建议独立部署在64位系统(32位有最大2.5G文件限制,64位没有改限制) | Redis2.0后增加虚拟内存特性,突破物理内存限制;数据可以设置时效性,类似于memcache | 不同的应用角度看,各有优势 |
444 | | 可用性 | 支持master-slave,replicaset(内部采用paxos选举算法,自动故障恢复),auto sharding机制,对客户端屏蔽了故障转移和切分机制 | 依赖客户端来实现分布式读写;主从复制时,每次从节点重新连接主节点都要依赖整个快照,无增量复制;不支持自动sharding,需要依赖程序设定一致hash机制 | MongoDB优于Redis;单点问题上,MongoDB应用简单,相对用户透明,Redis比较复杂,需要客户端主动解决。(MongoDB 一般会使用replica sets和sharding功能结合,replica sets侧重高可用性及高可靠性,而sharding侧重于性能、易扩展) |
445 | | 可靠性 | 从1.8版本后,采用binlog方式(MySQL同样采用该方式)支持持久化,增加可靠性 | 依赖快照进行持久化;AOF增强可靠性;增强可靠性的同时,影响访问性能 | MongoDB优于Redis |
446 | | 一致性 | 不支持事物,靠客户端自身保证 | 支持事物,比较弱,仅能保证事物中的操作按顺序执行 | Redis优于MongoDB |
447 | | 数据分析 | 内置数据分析功能(mapreduce) | 不支持 | MongoDB优于Redis |
448 | | 应用场景 | 海量数据的访问效率提升 | 较小数据量的性能及运算 | MongoDB优于Redis |
449 |
450 |
451 |
452 | 参考自:https://www.cnblogs.com/java-spring/p/9488227.html
453 |
454 |
455 |
456 | **上面的表数据太多啦,简单来说:**
457 |
458 | 1.首先开发语言,MangoDB和redis都是用c++开发的。
459 |
460 | 2.性能方面,他俩都是依赖内存,但是Redis的TPS(系统的吞吐量)更高。
461 |
462 | 3.可操作性性,MangoDB有最丰富的数据表达,最类似于关系型数据库,支持丰富的查询语句,
463 |
464 | 而Redis数据丰富,但是较少的IO,这一点MangDB要好于Redis
465 |
466 | 4.使用场景,MangoDB用于海量数据访问效率提升,Redis较小数据量,MangoDB要好
467 |
468 | 5.一致性,Redis支持事务,MangoDB不支持事务
469 |
470 |
471 |
472 | ### 10.Redis里有哪些命令? 主要看上面第一个
473 |
474 | 1)、对字符串操作:
475 |
476 | #### 设置和获取键值对
477 |
478 | ```console
479 | > SET key valueOK> GET key"value"
480 | ```
481 |
482 | 另外你还可以使用 `EXISTS` 和 `DEL` 关键字来查询是否存在和删除键值对:
483 |
484 | ```console
485 | > EXISTS key(integer) 1> DEL key(integer) 1> GET key(nil)
486 | ```
487 |
488 | #### 批量设置键值对
489 |
490 | ```console
491 | > SET key1 value1OK> SET key2 value2OK> MGET key1 key2 key3 # 返回一个列表1) "value1"2) "value2"3) (nil)> MSET key1 value1 key2 value2> MGET key1 key21) "value1"2) "value2"
492 | ```
493 |
494 | #### 过期和 SET 命令扩展
495 |
496 | 可以对 key 设置过期时间,到时间会被自动删除,这个功能常用来控制缓存的失效时间。*(过期可以是任意数据结构)*
497 |
498 | ```console
499 | > SET key value1> GET key"value1"> EXPIRE name 5 # 5s 后过期... # 等待 5s> GET key(nil)
500 | ```
501 |
502 | #### 链表的基本操作
503 |
504 | - `LPUSH` 和 `RPUSH` 分别可以向 list 的左边(头部)和右边(尾部)添加一个新元素;
505 | - `LRANGE` 命令可以从 list 中取出一定范围的元素;
506 | - `LINDEX` 命令可以从 list 中取出指定下表的元素,相当于 Java 链表操作中的 `get(int index)` 操作;
507 |
508 | 示范:
509 |
510 | ```console
511 | > rpush mylist A(integer) 1> rpush mylist B(integer) 2> lpush mylist first(integer) 3> lrange mylist 0 -1 # -1 表示倒数第一个元素, 这里表示从第一个元素到最后一个元素,即所有1) "first"2) "A"3) "B"
512 | ```
513 |
514 |
515 |
516 | ### 11.Redis怎么实现分布式锁?Redis的分布式锁是哪个命令?
517 |
518 | **为什么要用分布式锁?**
519 |
520 | 在Java中,关于锁我想大家都很熟悉。在并发编程中,我们通过锁,来避免由于竞争而造成的数据不一致问题。通
521 |
522 | 常,我们以`synchronized 、Lock`来使用它。
523 |
524 | 但是Java中的锁,只能保证在同一个JVM进程内中执行。如果在分布式集群环境下呢?
525 |
526 |
527 |
528 | **实现分布式锁的命令:**
529 |
530 | SETNX 关键字,设置参数如果存在返回 0,如果不存在返回 value 和 1
531 |
532 | expire 关键字,为 key 设置过期时间,解决死锁。
533 |
534 | delete 关键字,删除 key,释放锁
535 |
536 |
537 |
538 | **实现思想**
539 |
540 | (1)获取锁的时候,使用 setnx 加锁,并使用 expire 命令为锁添加一个超时时间,超过该
541 |
542 | 时间则自动释放锁,锁的 value 值为一个随机生成的 UUID,通过此在释放锁的时候进行判
543 |
544 | 断。
545 |
546 | (2)获取锁的时候还设置一个获取的超时时间,若超过这个时间则放弃获取锁。
547 |
548 | (3)释放锁的时候,通过 UUID 判断是不是该锁,若是该锁,则执行 delete 进行锁释放。
549 |
550 |
551 |
552 | 参考:帅老师发的文档
553 |
554 | https://www.jianshu.com/p/47fd7f86c848(简书 开始讲的简单易懂)
555 |
556 | https://www.cnblogs.com/williamjie/p/9395659.html (可以实现一下)
557 |
558 |
559 |
560 | ### 12.Redis只是用来当作缓存吗?当然不是
561 |
562 | redis应用场景总结redis平时我们用到的地方蛮多的,下面就了解的应用场景做个总结:
563 |
564 | #### 1、热点数据的缓存
565 |
566 | 由于redis访问速度块、支持的数据类型比较丰富,所以redis很适合用来存储热点数据,另外结合expire,我们可以设置过期时间然后再进行缓存更新操作,这个功能最为常见,我们几乎所有的项目都有所运用。
567 |
568 | #### 2、限时业务的运用
569 |
570 | redis中可以使用expire命令设置一个键的生存时间,到时间后redis会删除它。利用这一特性可以运用在限时的优惠活动信息、手机验证码等业务场景。
571 |
572 | #### 3、计数器相关问题
573 |
574 | redis由于incrby命令可以实现原子性的递增,所以可以运用于高并发的秒杀活动、分布式序列号的生成、具体业务还体现在比如限制一个手机号发多少条短信、一个接口一分钟限制多少请求、一个接口一天限制调用多少次等等。
575 |
576 | #### 4、排行榜相关问题
577 |
578 | 关系型数据库在排行榜方面查询速度普遍偏慢,所以可以借助redis的SortedSet进行热点数据的排序。
579 |
580 | 在奶茶活动中,我们需要展示各个部门的点赞排行榜, 所以我针对每个部门做了一个SortedSet,然后以用户的openid作为上面的username,以用户的点赞数作为上面的score, 然后针对每个用户做一个hash,通过zrangebyscore就可以按照点赞数获取排行榜,然后再根据username获取用户的hash信息,这个当时在实际运用中性能体验也蛮不错的。
581 |
582 | #### 5、分布式锁
583 |
584 | 这个主要利用redis的setnx命令进行,setnx:"set if not exists"就是如果不存在则成功设置缓存同时返回1,否则返回0 ,这个特性在俞你奔远方的后台中有所运用,因为我们服务器是集群的,定时任务可能在两台机器上都会运行,所以在定时任务中首先 通过setnx设置一个lock,如果成功设置则执行,如果没有成功设置,则表明该定时任务已执行。 当然结合具体业务,我们可以给这个lock加一个过期时间,比如说30分钟执行一次的定时任务,那么这个过期时间设置为小于30分钟的一个时间 就可以,这个与定时任务的周期以及定时任务执行消耗时间相关。
585 |
586 | 当然我们可以将这个特性运用于其他需要分布式锁的场景中,结合过期时间主要是防止死锁的出现。
587 |
588 | #### 6、延时操作
589 |
590 | 这个目前我做过相关测试,但是还没有运用到我们的实际项目中,下面我举个该特性的应用场景。 比如在订单生产后我们占用了库存,10分钟后去检验用户是够真正购买,如果没有购买将该单据设置无效,同时还原库存。 由于redis自2.8.0之后版本提供Keyspace Notifications功能,允许客户订阅Pub/Sub频道,以便以某种方式接收影响Redis数据集的事件。 所以我们对于上面的需求就可以用以下解决方案,我们在订单生产时,设置一个key,同时设置10分钟后过期, 我们在后台实现一个监听器,监听key的实效,监听到key失效时将后续逻辑加上。 当然我们也可以利用rabbitmq、activemq等消息中间件的延迟队列服务实现该需求。
591 |
592 | #### 7、分页、模糊搜索
593 |
594 | redis的set集合中提供了一个zrangebylex方法,语法如下:
595 |
596 | ZRANGEBYLEX key min max [LIMIT offset count]
597 |
598 | 通过ZRANGEBYLEX zset - + LIMIT 0 10 可以进行分页数据查询,其中- +表示获取全部数据
599 |
600 | zrangebylex key min max 这个就可以返回字典区间的数据,利用这个特性可以进行模糊查询功能,这个也是目前我在redis中发现的唯一一个支持对存储内容进行模糊查询的特性。
601 |
602 | 前几天我通过这个特性,对学校数据进行了模拟测试,学校数据60万左右,响应时间在700ms左右,比mysql的like查询稍微快一点,但是由于它可以避免大量的数据库io操作,所以总体还是比直接mysql查询更利于系统的性能保障。
603 |
604 | #### 8、点赞、好友等相互关系的存储
605 |
606 | Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。 又或者在微博应用中,每个用户关注的人存在一个集合中,就很容易实现求两个人的共同好友功能。
607 |
608 | 这个在奶茶活动中有运用,就是利用set存储用户之间的点赞关联的,另外在点赞前判断是否点赞过就利用了sismember方法,当时这个接口的响应时间控制在10毫秒内,十分高效。
609 |
610 | #### 9、队列
611 |
612 | 由于redis有list push和list pop这样的命令,所以能够很方便的执行队列操作。
613 |
614 |
615 |
616 | 参考:https://www.jianshu.com/p/40dbc78711c8(感觉写的很好)
617 |
618 |
619 |
620 | ### 13 Redis 是如何配置的?说一下 redis 的集群模式、哨兵模式
621 |
622 | #### 常见和比较重要的配置
623 |
624 | 1, port:6379 指定访问 redis 服务的端口
625 | 2, bind: 0.0.0.0 指定 redis 绑定的主机地址,配置为 0.0.0.0 表示为外网也可以访问
626 | 3, timeout:指定客户端连接 redis 服务器时,当闲置的时间为多少时关闭连接
627 | 4, loglevel:指定 redis 数据库的日志级别,常用的日志级别有 debug、 verbose、 notice、
628 | warning,不进行修改的情况下默认的是 notice
629 | 5, save : 指定 redis 数据库多少时间内(s)就有多少次更新操作(insert、
630 | update 和 delete)时就把缓存中的数据同步到本地库,比如 save 600 2,指的是 10 分
631 | 钟内有 2 次更新操作,就同步到本地库,也就是持久化到本地磁盘。
632 | 6, dir 指本地数据文件存放的目录
633 | 7, requirepass:指定 redis 的访问密码
634 | 8, maxmemory:指定 redis 的最大内存。 Redis 在启动时会把数据加载到内存中,当到达
635 | 最大内存时, redis 会自动清除已经到期和即将到期的 key 值
636 | 9, appendonly:指定 redis 是否开启日志记录功能。由于 redis 时利用 save 命令异步的方
637 | 式更新数据到本地库,所以不开启日志记录功能,可能会导致在出现生产事故时,导致
638 | 部分数据未更新到本地库。
639 | 10, vm-enabled: 指定 redis 是否启用虚拟内存机制
640 |
641 | #### redis 的集群模式
642 |
643 | **1, 主从复制模式:**
644 | Slave 从节点服务启动并连接到 Master 之后,它将主动发送一个 SYNC 命令。Master
645 | 服务主节点收到同步命令后将启动后台存盘进程,同时收集所有接收到的用于修改
646 | 数据集的命令,在后台进程执行完毕后, Master 将传送整个数据库文件到 Slave,
647 | 以完成一次完全同步。而 Slave 从节点服务在接收到数据库文件数据之后将其存盘
648 | 并加载到内存中。此后, Master 主节点继续将所有已经收集到的修改命令,和新的
649 | 修改命令依次传送给 Slaves, Slave 将在本次执行这些数据修改命令,从而达到最
650 | 终的数据同步。
651 |
652 | **2, 哨兵模式:**
653 | 
654 | 哨兵(sentinel) 是一个分布式系统,你可以在一个架构中运行多个哨兵(sentinel) 进
655 | 程,这些进程使用流言协议(gossipprotocols)来接收关于 Master 是否下线的信息,并使用
656 | 投票协议(agreement protocols)来决定是否执行自动故障迁移,以及选择哪个 Slave 作为
657 | 新的 Master。
658 | 每个哨兵(sentinel) 会向其它哨兵(sentinel)、 master、 slave 定时发送消息,以确认对
659 | 方是否” 活” 着,如果发现对方在指定时间(可配置)内未回应,则暂时认为对方已挂(所谓
660 | 的” 主观认为宕机” Subjective Down,简称 sdown).
661 | 若“哨兵群” 中的多数 sentinel,都报告某一 master 没响应,系统才认为该 master"彻
662 | 底死亡"(即:客观上的真正 down 机,Objective Down,简称 odown),通过一定的 vote 算法,
663 | 从剩下的 slave 节点中,选一台提升为 master,然后自动修改相关配置。
664 | 虽然哨兵(sentinel) 释出为一个单独的可执行文件 redis-sentinel ,但实际上它只是
665 | 一个运行在特殊模式下的 Redis 服务器,你可以在启动一个普通 Redis 服务器时通过
666 | 给定 --sentinel 选项来启动哨兵(sentinel)。
667 |
668 | **3, Cluster 集群模式:**
669 |
670 | 
671 |
672 | 自动将数据进行分片,每个节点上放一部分数据,如何放的呢?
673 | Redis-Cluster 采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他
674 | 所有节点连接,其结构图如如下:
675 |
676 | 结构特点:
677 | 1, 所有的 redis 节点彼此互联(PING-PONG 机制),内部使用二进制协议优化传输速
678 | 度和带宽。
679 | 2, 节点的 fail 是通过集群中超过半数的节点检测失效时才失效。
680 | 3, 客户端与 redis 节点直连,中间不需要 proxy 层,客户端不需要连接所有集群的所有
681 | 节点,连接集群中任意一个可用节点即可。
682 | 4, Redis-cluster 把所有的物理节点映射到 16384 个哈希槽(hash slot)上,不一定是
683 | 平均分配, cluster 负责维护 node<->slot<->value。
684 | 5, 当有数据需要存储的时候, redis 通过 CRC16 算法计算出 key 的值,然后把这个值
685 | 对 16384 取余,得到的结果在哪个节点负责的范围内就会把值存入哪个节点。
686 | 6, 如上图,每个 master 都是一个节点,而 slave 是该 master 的备份,当 redis 的一个
687 | master 节点挂了, slave 会顶替掉 master,如何一个节点的 master 和 slave 都挂了,
688 | 那么则认为该 redis 集群挂了,因为有一部分数据丢失了,也有一部分数据永远也存
689 | 取不了了。
690 |
691 |
692 |
693 | ### 14.Redis是单线程的,为什么能够抗住高并发?为什么单线程还那么快?
694 |
695 | Redis高并发快总结:
696 |
697 | 1.Redis是**纯内存数据库**,一般都是简单的存取操作,线程占用的时间很多,时间的花费主要集中在IO上,所以读取速度快。
698 |
699 | 2.再说一下IO,Redis使用的是**非阻塞IO,IO多路复用**,使用了单线程来轮询描述符,将数据库的开、关、读、写都转换成了事件,减少了线程切换时上下文的切换和竞争。
700 |
701 | 3.Redis采用了单线程的模型,保证了每个操作的原子性,也**减少了线程的上下文切换和竞争**。
702 |
703 | 4.另外,**数据结构**也帮了不少忙,Redis全程使用hash结构,读取速度快,还有一些特殊的数据结构,对数据存储进行了优化,如压缩表,对短数据进行压缩存储,再如,跳表,使用有序的数据结构加快读取的速度。
704 |
705 | 5.还有一点,Redis采用自己实现的事件分离器,效率比较高,内部采用非阻塞的执行方式,吞吐能力比较大。
706 |
707 |
708 |
709 | 参考:https://blog.csdn.net/u011663149/article/details/85307615
710 |
711 |
712 |
713 | ### 15.如果有两台Redis,怎么样把其中一台Redis里的数据备份到另一台上?
714 |
715 | #### 1、aof 导入方式。
716 |
717 | 因为这种方式比较简单,所以我就先介绍它。
718 |
719 | 分两步来实现,第一步先让源 Redis 生成 AOF 数据文件。
720 |
721 | ```shell
722 |
723 | ```
724 |
725 | dir 目录,可以通过 config get dir 目录获得。
726 |
727 | ```shell
728 |
729 | ```
730 |
731 |
732 |
733 | 通过上面的命令,我们可以看到我本地的 dir 目录是:/usr/local/var/db/redis。
734 |
735 | 现在我们来做第二步操作,让目标 Redis 实例导入 aof 数据。
736 |
737 | ```shell
738 |
739 | ```
740 |
741 | 上面的第一个命令,执行后,如果出现以下内容,则表示导入 aof 数据成功。
742 |
743 | ```shell
744 |
745 | ```
746 |
747 |
748 |
749 | 我这里是测试,数据比较少,所以提示有 5 个导入成功了。
750 |
751 | AOF 的缺点也很明显,就是速度慢,并且如果内容多的话,文件也比较大。而且开启 AOF 后,QPS 会比 RDB 模式写的 QPS 低。还有就是 AOF 是一个定时任务,可能会出现数据丢失的情况。
752 |
753 | #### 2、通过我的 xttblog_redis_mv.sh 脚本来实现。
754 |
755 | 我的脚本内容如下:
756 |
757 | ```shell
758 |
759 | ```
760 |
761 | 大家在使用的时候,只需要替换 IP 即可。
762 |
763 | 这个脚本同样有一个问题就是使用了 keys *,然后一个一个遍历,如果是生产环境,不建议这样使用!当然我的脚本也是可以再进行优化的!
764 |
765 | #### 3、使用 redis-dump 工具。
766 |
767 | Redis-Dump 是一个用于 Redis 数据导入 / 导出的工具,是基于 Ruby 实现的,可以方便的进行 redis 的数据备份。这个工具需要先安装,以我的 Mac 为例,安装教程如下:
768 |
769 | ```shell
770 |
771 | ```
772 |
773 | 目前我发现,淘宝的镜像已经出现 bad response Not Found 404 了,被告知镜像维护站点已迁往 Ruby China 镜像。
774 |
775 | ```shell
776 |
777 | ```
778 |
779 | 安装完成后,就可以使用 redis-dump 工具进行数据的导入导出了!
780 |
781 | ```shell
782 |
783 | ```
784 |
785 | cat 源Redis数据文件.json | redis-load -u :password@目标RedisIp:6379
786 |
787 | Linux 系统或者 Window 系统也都类似,安装 redis-dump 工具完成后直接使用 redis-dump 导出,redis-load 导入即可完成数据的备份与迁移。
788 |
789 | redis-dump 工具很强大,建议大家到官网上多看看它的官方文档。
790 |
791 | #### 4、rdb 文件迁移
792 |
793 | redis-dump 麻烦就麻烦在需要进行安装,如果我的 Redis 已经有备份机制,比如有 rdb 文件,那么我们直接迁移 rdb 文件就可以达到同样的目的。
794 |
795 | 首先,我们可以先关闭源 Redis 实例的 aof 功能。如果不关闭 aof,Redis 默认用 aof 文件来恢复数据。
796 |
797 | ```shell
798 |
799 | ```
800 |
801 | 然后使用 save 命令把数据固化到 rdb 文件中。
802 |
803 | ```shell
804 |
805 | ```
806 |
807 | save 完成后,还是通过 config get dir 命令获得保存的 RDB 数据文件位置。
808 |
809 | 接下来,我们需要杀死 redis 进程。杀掉当前 redis 的进程,否则下一步的复制 rdb 文件,rdb 处于打开的状态,复制的文件,会占用同样的句柄。
810 |
811 | ```shell
812 |
813 | ```
814 |
815 | 然后复制源 redis 的 rdb 文件到目标 Redis 的 dir 数据目录,名字为你要迁移的 redis 的 rdb 文件名。
816 |
817 | 复制完成后,重启目标 Redis 实例,数据就迁移完成了。 重启完成后可以验证一下数据是否成功的复制了。
818 |
819 |
820 |
821 | 参考:https://www.jb51.net/article/179745.htm
822 |
823 |
824 |
825 | ### 16.Redis存的key是什么?如果是username,那可以查到其他人的订单,怎么防止这种情况?
826 |
827 | 我的理解是在Redis的key后面拼接一段无规则符号,即使是知道username,其他人也查不出你的订单。(个人理解,不知道有没有更好地办法)
828 |
829 |
830 |
831 | ### 17.redis,如果来了无效数据(存下来),如果无效数据非常多怎么处理
832 |
833 | 首先设置过期时间:(但是是随机删除。为什么要随机删除?因为下面定期删除里面说啦)
834 |
835 | 如果假设你设置了一批 key 只能存活1个小时,那么接下来1小时后,redis是怎么对这批key进行删除的?
836 |
837 | **定期删除+惰性删除。**
838 |
839 | 通过名字大概就能猜出这两个删除方式的意思了。
840 |
841 | - **定期删除**:redis默认是每隔 100ms 就**随机抽取**一些设置了过期时间的key,检查其是否过期,如果过期就删除。注意这里是随机抽取的。为什么要随机呢?你想一想假如 redis 存了几十万个 key ,每隔100ms就遍历所有的设置过期时间的 key 的话,就会给 CPU 带来很大的负载!
842 | - **惰性删除** :定期删除可能会导致很多过期 key 到了时间并没有被删除掉。所以就有了惰性删除。假如你的过期 key,靠定期删除没有被删除掉,还停留在内存里,除非你的系统去查一下那个 key,才会被redis给删除掉。这就是所谓的惰性删除,也是够懒的哈!
843 |
844 | 但是仅仅通过设置过期时间还是有问题的。我们想一下:如果定期删除漏掉了很多过期 key,然后你也没及时去查,也就没走惰性删除,此时会怎么样?如果大量过期key堆积在内存里,导致redis内存块耗尽了。怎么解决这个问题呢? **redis 内存淘汰机制。**
845 |
846 |
847 |
848 | **淘汰机制:**
849 |
850 | **redis 提供 6种数据淘汰策略:**
851 |
852 | 1. **volatile-lru**:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
853 | 2. **volatile-ttl**:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
854 | 3. **volatile-random**:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
855 | 4. **allkeys-lru**:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key(这个是最常用的)
856 | 5. **allkeys-random**:从数据集(server.db[i].dict)中任意选择数据淘汰
857 | 6. **no-eviction**:禁止驱逐数据,也就是说当内存不足以容纳新写入数据时,新写入操作会报错。这个应该没人使用吧!
858 |
859 | 4.0版本后增加以下两种:
860 |
861 | 7. **volatile-lfu**:从已设置过期时间的数据集(server.db[i].expires)中挑选最不经常使用的数据淘汰
862 | 8. **allkeys-lfu**:当内存不足以容纳新写入数据时,在键空间中,移除最不经常使用的key
863 |
864 |
865 |
866 | ### 18.Redis和memcache的比较:
867 |
868 | **一 性能对比:**
869 |
870 | 由于 redis 只使用单核,而 memcached 可以使用多核,所以平均每一个核上 redis 在存储小数据时比memcached 性能更高。而在 100k 以上的数据中,memcached 性能要高于 redis,虽然 redis 最近也在存储大数据的性能上进行优化,但是比起 memcached,还是稍有逊色。
871 |
872 | **二 为啥 redis 单线程模型也能效率这么高?**
873 |
874 | 纯内存操作
875 | 核心是基于非阻塞的 IO 多路复用机制
876 | 单线程反而避免了多线程的频繁上下文切换问题
877 |
878 | **三 其他不同**
879 |
880 | 数据类型不同,redis有五种(list set string hash zset),memcached只有一种string
881 | Redis支持数据的备份,即master-slave模式的数据备份。
882 | Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
883 | 内存的使用率上memcached数据结构简单 只有一种string ,不用记录数据的类型
884 |
885 | ### 19.Redis实现序列化:
886 |
887 | **什么是序列化:**
888 |
889 | 序列化:把对象转化为可传输的字节序列过程称为序列化。
890 |
891 | 反序列化:把字节序列还原为对象的过程称为反序列化。
892 |
893 | **为什么要序列化:**
894 |
895 | 序列化最终的目的是为了对象可以跨平台存储,和进行网络传输。而我们进行跨平台存储和网络传输的方式就是IO,而我们的IO支持的数据格式就是字节数组。
896 |
897 | 因为我们单方面的只把对象转成字节数组还不行,因为没有规则的字节数组我们是没办法把对象的本来面目还原回来的,所以我们必须在把对象转成字节数组的时候就制定一种规则(序列化),那么我们从IO流里面读出数据的时候再以这种规则把对象还原回来(反序列化)。
898 |
899 | 如果我们要把一栋房子从一个地方运输到另一个地方去,序列化就是我把房子拆成一个个的砖块放到车子里,然后留下一张房子原来结构的图纸,反序列化就是我们把房子运输到了目的地以后,根据图纸把一块块砖头还原成房子原来面目的过程
900 |
901 | **什么情况下需要序列化:**
902 |
903 | 通过上面我想你已经知道了凡是需要进行“跨平台存储”和”网络传输”的数据,都需要进行序列化。
904 |
905 | 本质上存储和网络传输 都需要经过 把一个对象状态保存成一种跨平台识别的字节格式,然后其他的平台才可以通过字节信息解析还原对象信息。
906 |
907 | **序列化的方式:**
908 |
909 | 序列化只是一种拆装组装对象的规则,那么这种规则肯定也可能有多种多样,比如现在常见的序列化方式有:
910 |
911 | JDK(不支持跨语言)、JSON、XML、Hessian、Kryo(不支持跨语言)、Thrift、Protostuff、FST(不支持跨语言)
912 |
913 | **Java序列化**
914 |
915 | java 实现序列化很简单,只需要实现Serializable 接口即可。
916 |
917 | ```java
918 | public class User implements Serializable{ //年龄 private int age; //名字 private String name ; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; }}
919 | ```
920 |
921 | 注意: JAVA序列化中常见的问题
922 |
923 | - 问题一:static 属性不能被序列化
924 |
925 | 原因:序列化保存的是对象的状态,静态变量属于类的状态,因此 序列化并不保存静态变量。
926 |
927 | - 问题二:Transient 属性不会被序列化
928 | - 问题三:序列化版本号serialVersionUID
929 |
930 | 所有实现序列化的对象都必须要有个版本号,这个版本号可以由我们自己定义,当我们没定义的时候JDK工具会按照我们对象的属性生成一个对应的版本号。使用JDK生成的serialVersionUID,只要对象有一丁点改变serialVersionUID就会随着变更。因此建议自己手动定义该版本号。
931 |
932 | **Redis序列化**
933 |
934 | 当你用Redis的key和value时,value对于redis来讲就是个byte array。你要自己负责把你的数据结构转换成byte array,等读取时再读出来。
935 |
936 | > 一个特例是字符串,因为字符串自己几乎就已经是byte array了,所以不需要自己处理。
937 |
938 | Spring的redisTemplate默认会使用java serialization做序列化。你也可以用StringRedisTemplate,那么你set的所有数据都会被toString一下再存到redis里。但这个toString不一定能反解析的回来。如果使用 java原生序列化方式,可能会有远程代码执行问题,因此建议使用其他序列化方式代替。
939 |
940 |
941 |
942 | 参考:https://www.cnblogs.com/lemos/p/11081448.html (写的很好)
943 |
944 |
945 |
946 | ### 20.Redis的核心功能
947 |
948 | 做缓存,解决高并发问题等。
949 |
950 |
951 |
952 | ### 21.Redis三级缓存
953 |
954 | 没有找到三级缓存,找到了二级缓存。
955 |
956 |
957 |
958 | 1,了解数据存储的位置的不同
959 |
960 | 数据库:存储在磁盘上
961 |
962 | redis:存储在内存上
963 |
964 | ehcache:应用内缓存
965 |
966 |
967 |
968 | 缓存的目的:是为了将数据从一个较慢的介质上读取出来,放到一个较快的介质上,为了下次读取的时候更加的快。
969 |
970 | 数据存入在书库库中,每次获取数据都有IO交互,所以放入到Redis中。Redis 存放数据在内存中。
971 |
972 | Redis 也还不够快,网络IO 传输,连接池等,所以放到ehcache 这样的应用内缓存中。
973 |
974 | 2,一级缓存:ehcache 二级缓存:redis
975 |
976 |
977 |
978 | 
979 |
980 | ### 22.Redis 如何模糊查询?
981 |
982 | ```
983 | scan
984 | ```
985 |
986 |
987 |
988 | 参考:https://blog.csdn.net/fly910905/article/details/78942357
989 |
990 |
991 |
992 | ### 23.优化项目中的redis代码,使用Hash和List结构·····
993 |
994 |
995 |
996 | ### 24.用户修改用户信息,该怎么保证redis缓存和数据库中数据一致?
997 |
998 | ### 25.Java中用到缓存的主要是哪些场合?
999 |
1000 |
1001 |
1002 | # Redis 实际应用
1003 |
1004 | 将大对象放入缓存中,有两种方式,第一种转换成json串,第二种
1005 |
1006 | 参考:https://www.jianshu.com/p/c22954a9c37d
1007 |
1008 |
1009 |
1010 |
1011 |
1012 |
1013 |
1014 |
1015 |
1016 |
1017 |
1018 |
1019 |
1020 |
1021 |
1022 |
1023 |
1024 |
--------------------------------------------------------------------------------
/docs/Spring.md:
--------------------------------------------------------------------------------
1 | # Spring
2 |
3 | # Interview
4 |
5 | ## Spring相关
6 |
7 | ### 1.什么叫面向对象编程,什么叫面向切面编程?(被三次问到什么叫面向对象)
8 |
9 | #### 面向对象:
10 |
11 | 很早很早以前的编程是面向过程的,比如实现一个算术运算1+1 = 2,通过这个简单的算法就可以解决问题。但是随着时代的进步,人们不满足现有的算法了,因为问题越来越复杂,不是1+1那么单纯了,比如一个班级的学生的数据分析,这样就有了对象这个概念,一切事物皆对象。将现实的事物抽象出来,注意抽象这个词是重点啊,把现实生活的事物以及关系,抽象成类,通过继承,实现,组合的方式把万事万物都给容纳了。实现了对现实世界的抽象和数学建模。这是一次飞跃性的进步。
12 |
13 | 举个最简单点的例子来区分 面向过程和面向对象
14 |
15 | 有一天你想吃鱼香肉丝了,怎么办呢?你有两个选择
16 |
17 | 1、自己买材料,肉,鱼香肉丝调料,蒜苔,胡萝卜等等然后切菜切肉,开炒,盛到盘子里。
18 |
19 | 2、去饭店,张开嘴:老板!来一份鱼香肉丝!
20 |
21 | ##### 优缺点:
22 |
23 | 面向过程:
24 |
25 | 优点:性能比面向对象好,因为类调用时需要实例化,开销比较大,比较消耗资源。
26 | 缺点:不易维护、不易复用、不易扩展.
27 |
28 | 面向对象:
29 |
30 | 优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护 .
31 | 缺点:性能比面向过程差
32 |
33 |
34 |
35 | ##### 面向对象的三大特性:
36 |
37 | 1、封装
38 | 隐藏对象的属性和实现细节,仅对外提供公共访问方式,将变化隔离,便于使用,提高复用性和安全性。
39 | 2、继承
40 | 提高代码复用性;继承是多态的前提。
41 | 3、多态
42 | 父类或接口定义的引用变量可以指向子类或具体实现类的实例对象。提高了程序的拓展性。
43 |
44 |
45 |
46 | ##### 五大基本原则:
47 |
48 | 1、单一职责原则SRP(Single Responsibility Principle)
49 | 类的功能要单一,不能包罗万象,跟杂货铺似的。
50 | 2、开放封闭原则OCP(Open-Close Principle)
51 | 一个模块对于拓展是开放的,对于修改是封闭的,想要增加功能热烈欢迎,想要修改,哼,一万个不乐意。
52 | 3、里式替换原则LSP(the Liskov Substitution Principle LSP)
53 | 子类可以替换父类出现在父类能够出现的任何地方。比如你能代表你爸去你姥姥家干活。哈哈~~
54 | 4、依赖倒置原则DIP(the Dependency Inversion Principle DIP)
55 | 高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。抽象不应该依赖于具体实现,具体实现应该依赖于抽象。就是你出国要说你是中国人,而不能说你是哪个村子的。比如说中国人是抽象的,下面有具体的xx省,xx市,xx县。你要依赖的是抽象的中国人,而不是你是xx村的。
56 | 5、接口分离原则ISP(the Interface Segregation Principle ISP)
57 | 设计时采用多个与特定客户类有关的接口比采用一个通用的接口要好。就比如一个手机拥有打电话,看视频,玩游戏等功能,把这几个功能拆分成不同的接口,比在一个接口里要好的多
58 |
59 | 面向对象参考:https://www.jianshu.com/p/7a5b0043b035
60 |
61 |
62 |
63 | ### 2.IOC相关
64 |
65 | #### 1.IOC是什么?它的使用场景是什么?
66 |
67 | AOP它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP代表的是一个横向的关系,如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向方面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。
68 |
69 | 使用“横切”技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比**如权限认证、日志、事务处理**。Aop 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。AOP的核心思想就是“将应用程序中的商业逻辑同对其提供支持的通用服务进行分离。”
70 |
71 | 实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。
72 |
73 |
74 |
75 | #### Spring的IOC是为了解决什么问题?对IOC的理解。
76 |
77 | https://www.cnblogs.com/superjt/p/4311577.html
78 |
79 | 对IOC的和依赖注入理解,参考知乎 https://www.zhihu.com/question/23277575/answer/169698662
80 |
81 |
82 |
83 | #### Spring IOC用了什么技术?
84 |
85 | 反射 https://www.cnblogs.com/superjt/p/4311577.html
86 |
87 |
88 |
89 | #### Spring IOC里面怎样使用bean?
90 |
91 | https://www.cnblogs.com/xiaoma000deblog/p/10288371.html
92 |
93 | 参考:https://www.cnblogs.com/micrari/p/7354650.html
94 |
95 |
96 |
97 | #### Spring的IOC和DI的区别?
98 |
99 | IOC控制反转 DI依赖注入
100 |
101 |
102 |
103 | #### 如果让你实现一个IOC,需要怎么实现?
104 |
105 | https://juejin.cn/post/6844903585830944782
106 |
107 | 代码在 JavaHub/Spring/simpleioc
108 |
109 | #### IOC容器的顶层接口是什么?怎么启用一个IOC容器?
110 |
111 | Spring 源码分析 :https://github.com/seaswalker/spring-analysis
112 |
113 |
114 |
115 |
116 |
117 | https://happysnail.cn/#/
118 |
119 | http://happysnail.cn/#/?id=javainterview
120 |
121 | ### 3.AOP相关
122 |
123 | #### 1.AOP是什么 它的使用场景是什么?
124 |
125 | #### 2.说一下AOP的面向切面?为什么AOP里有切点,为什么叫面向切面不叫面向切点?
126 |
127 | #### 3.Aop 怎么使用 什么使用场景 日志?
128 |
129 | #### 4..AOP用来封装横切关注点,具体可以在下面的场景中使用
130 |
131 | - Authentication 权限
132 |
133 | - Caching 缓存
134 |
135 | - Context passing 内容传递
136 |
137 | - Error handling 错误处理
138 |
139 | - Debugging 调试
140 |
141 | - logging, tracing, profiling and monitoring 记录跟踪 优化 校准
142 |
143 | - Performance optimization 性能优化
144 |
145 | - Persistence 持久化
146 |
147 | - Resource pooling 资源池
148 |
149 | - Synchronization 同步
150 |
151 | - Transactions 事务
152 |
153 | #### 5.设计一个代码,通过AOP实现禁止一个用户在60秒内搜索相同的内容
154 |
155 | #### Aop是啥?是怎样实现的?实现原理?
156 |
157 | #### 介绍一下Spring AOP?AOP是怎样做到的?
158 |
159 | #### 说一下AOP底层是如何实现的 ?
160 |
161 | #### 具体在你的这个项目(影院)中是如何使用AOP的?
162 |
163 |
164 |
165 | ### 4.说一下自己对IOC和AOP的理解?
166 |
167 |
168 |
169 | ### 5.Spring的IOC,DI和AOP的原理了解吗?原理?
170 |
171 |
172 |
173 | ### 7.注解相关 (重点)
174 |
175 | #### 除了用@Autowerid注入实例还可以用什么注解? 看一下注解驱动,总结一下其他常用的注解
176 |
177 | #### @autowired的用法?--回答放在成员变量上,但好像说这样子是会报错
178 |
179 | #### Spring常用注解的异同?
180 |
181 |
182 |
183 | ### 8.Spring都有哪些模块
184 |
185 |
186 |
187 | ### 9.事务相关
188 |
189 | #### 事务的传播形式?
190 |
191 |
192 |
193 | #### 平常spring的事务是怎么控制的?如果外层事务和内层事务 内存事务回滚 外层事务怎么回滚 或者说不回滚 ?这个事务性消息是怎么操作的?
194 |
195 |
196 |
197 | #### Spring里A方法调用B方法有用到事务吗?为什么(假设A方法开了事务,B方法上也有事务注解)
198 |
199 |
200 |
201 | #### Spring的事务你是怎么样理解的,Spring的事务是怎样传播的,默认的传播行为是哪一个?
202 |
203 | #### Spring事务传播机制?
204 |
205 | #### 写出spring事务隔离级别与传播行为?
206 |
207 | #### 对事务了解多吗?能不能介绍一下你们项目中哪里用到了事务?怎么开启事务?事务隔离级别还记得吗?
208 |
209 | #### Spring事务的注解都有哪些
210 |
211 | #### Spring中事务的隔离级别
212 |
213 |
214 |
215 | ### 10.Spring思想相关、整体情况
216 |
217 | #### Spring的核心思想是什么?
218 |
219 | #### 说一下你对Spring的理解?
220 |
221 | #### Spring原理(我答的控制反转,依赖注入 问还有呢? 回答AOP?
222 |
223 | #### Spring全家桶的实现过程?
224 |
225 |
226 |
227 |
228 |
229 | ### 11.Spring容器
230 |
231 | (bean factory)
232 |
233 | #### spring 容器创建的过程中做了几件事
234 |
235 |
236 |
237 |
238 |
239 | ### 12.SpringBean相关
240 |
241 | #### Spring Bean的生命周期,默认的scope是什么,为什么?
242 |
243 | #### spring的scope 以及是否创建
244 |
245 | #### Spring Bean的scope(单例 多例)?
246 |
247 | #### @Bean的使用场景一般在哪?
248 |
249 | #### spring的scope 以及是否创建
250 |
251 | #### Spring的bean不用注解 如何取出bean
252 |
253 |
254 |
255 | ### 13.拦截器过滤器
256 |
257 | #### 说一下Filter和Interceptor的区别?JDK动态代理和Cglib动态代理的区别?
258 |
259 | #### Spring的filter和interceptor,interceptor里有哪些方法
260 |
261 |
262 |
263 | ### 14.Spring日志
264 |
265 | #### 你常用的日志框架是什么,Spring自带的日志框架是哪个?
266 |
267 |
268 |
269 | ### 15.Spring代理(归属IOC)
270 |
271 | #### Java的动态代理和Spring的CGLIB动态代理底层有什么区别,Spring框架用的是哪一种,为什么?
272 |
273 | #### 动态代理有什么局限性,什么时候动态代理会失效?
274 |
275 | #### private的方法可以使用Spring的动态代理吗?
276 |
277 |
278 |
279 | ### 16.Spring 设计模式
280 |
281 | #### 单例是在容器初始化的时候创建 而多例是在getBean()的时候创建?
282 |
283 | #### singleton单例:每一次取出来是同一个,并且只在加载的时候实例化一次
284 |
285 | #### prototype:加载appllicationContext时没有实例化,在每一次getBean的时候都实例化一个新的bean
286 |
287 |
288 |
289 | ### 17.Spring 定时任务
290 |
291 | #### Spring的定时任务用过吗?(@Schedule注解)?
292 |
293 |
294 |
295 | ### 18.HandleAdapter的作用
296 |
297 |
298 |
299 | ### 19.开放性问题
300 |
301 | #### pagehelp这类似的插件,如果叫你写一个这个插件知道怎们写吗
302 |
303 |
304 |
305 | ### 20.逆向工程是用的插件还是自己写的?
306 |
307 | ### 21.BeanFactory 和factoryBean的差别
308 |
309 |
310 |
311 | ## SpringMVC相关
312 |
313 | 这里可以参考 3y电子书
314 |
315 | ### SpringMVC中如何返回一个JSON对象?
316 |
317 | ### SpringMvc 的架构图?
318 |
319 | ### SpringMvc 的大概工作流程?具体工作流程?
320 |
321 | ### SpringMvc的底层原理?
322 |
323 | ### 说一说你对SpringMVC的理解?
324 |
325 | ### 以及SpringMVC的运行过程?
326 |
327 | ### 上次面试碰到一个dispatchServlet 什么的?看看
328 |
329 | ### SpringMVC常用获取传递参数的方法?
330 |
331 | ### SpringMVC常用的注解有哪些?
332 |
333 | ### SpringMVC的架构
334 |
335 | ### springmvc的设计模式
336 |
337 |
338 |
339 | ### 你们的项目MVC层是怎么分的?Dao层?事务你们是在哪层做的?(报装项目好像在service层做)
340 |
341 | ### SpringMVC的核心是什么?请求的流程?控制反转怎么实现?
342 |
343 | ### Spring MVC和Struts的区别
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 | ## Spring SpringBoot SpringCloud SpringMVC 之间的关系和区别相关
360 |
361 |
362 |
363 | ### 1.Spring和SpringBoot的区别,有能力的可以看看SpringBoot的一键启动的源码,到时候也可以吹吹
364 |
365 | 1) Spring Boot可以建立独立的Spring应用程序;
366 | 2) 内嵌了如Tomcat,Jetty和Undertow这样的容器,也就是说可以直接跑起来,用不着再做部署工作了。
367 | 3) 无需再像Spring那样搞一堆繁琐的xml文件的配置;
368 | 4) 可以自动配置Spring;
369 | 5) 提供了一些现有的功能,如量度工具,表单数据验证以及一些外部配置这样的一些第三方功能;
370 | 6) 提供的POM可以简化Maven的配置;
371 |
372 | 本篇,讲述了Spring boot和Spring之间的区别。用一句话概况就是:**Spring Boot只是Spring本身的扩展,使开发,测试和部署更加方便。**
373 |
374 |
375 |
376 | 比较详细的参考:https://mp.weixin.qq.com/s/0qk2kaCKLdAViVzsw401sg
377 |
378 |
379 |
380 | ### 2.spring 与 springmvc的区别
381 |
382 | ### 3.springMVC和springboot有什么区别,springboot和springmvc相比最大的优点是什么?
383 |
384 | ### 4.spring和springboot的区别?
385 |
386 | ### 5.spring,springmvc,springboot区别?
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
--------------------------------------------------------------------------------
/docs/SpringBoot.md:
--------------------------------------------------------------------------------
1 | # SpringBoot
2 |
3 |
4 |
5 | > 参考Guide哥文章:https://snailclimb.gitee.io/springboot-guide
6 |
7 | # Interview
8 |
9 |
10 |
11 | ## SpringBoot相关
12 |
13 | ### 1.介绍一下SpringBoot,为什么会有它的出现?解决了什么问题?他的出现有什么优点或者缺点?
14 |
15 |
16 |
17 | ### 1.SpringBoot注解相关
18 |
19 | #### SpringBoot的常用注解有哪些?
20 |
21 | 虽然在平时开发中用到的注解有很多,但是这里问的是SpringBoot中的注解,范围相对来说很小:
22 |
23 | 参考知乎(SpringBoot中的注解):https://zhuanlan.zhihu.com/p/57689422
24 |
25 | 其他Spring常用的注解(参考JavaGuide注解文章):https://snailclimb.gitee.io/javaguide/#/
26 |
27 |
28 |
29 | #### Spring boot controller 层的常用注解
30 |
31 | @RequsMapping (@GetMapping @PostMapping) @Responsebody @RestController @Reference @RequestBody
32 |
33 |
34 |
35 | #### SpringBoot最核心,最特性的注解是什么(启动项中的)?
36 |
37 | **@SpringBootApplication** 最主要的一个注解
38 |
39 | 这是 Spring Boot 最最最核心的注解,用在 Spring Boot 主类上,标识这是一个 Spring Boot 应用,用来开启 Spring Boot 的各项能力。
40 |
41 | 其实这个注解就是 `@SpringBootConfiguration`、`@EnableAutoConfiguration`、`@ComponentScan` 这三个注解的组合,也可以用这三个注解来代替 `@SpringBootApplication` 注解。
42 |
43 |
44 |
45 | **2、@EnableAutoConfiguration**
46 |
47 | 允许 Spring Boot 自动配置注解,开启这个注解之后,Spring Boot 就能根据当前类路径下的包或者类来配置 Spring Bean。
48 |
49 | 如:当前类路径下有 Mybatis 这个 JAR 包,`MybatisAutoConfiguration` 注解就能根据相关参数来配置 Mybatis 的各个 Spring Bean。
50 |
51 |
52 |
53 | **4、@SpringBootConfiguration**
54 |
55 | 这个注解就是 @Configuration 注解的变体,只是用来修饰是 Spring Boot 配置而已,或者可利于 Spring Boot 后续的扩展。
56 |
57 |
58 |
59 | **5、@ComponentScan**
60 |
61 | 这是 Spring 3.1 添加的一个注解,用来代替配置文件中的 component-scan 配置,开启组件扫描,即自动扫描包路径下的 @Component 注解进行注册 bean 实例到 context 中。
62 |
63 | 参考知乎:https://zhuanlan.zhihu.com/p/57689422
64 |
65 |
66 |
67 | ### 2.SpringBoot启动相关
68 |
69 | #### Springboot的启动流程?
70 |
71 | 下面这是常见的SpringBoot启动的主函数:
72 |
73 | ```java
74 | @SpringBootApplication
75 | public class SpringBootWebApplication {
76 | public static void main(String[] args) {
77 | SpringApplication application = new SpringApplication(SpringBootWebApplication.class);
78 | application.run(args);
79 | }
80 | }
81 | ```
82 |
83 | 要回答SpringBoot启动流程主要从两个方面来回答:
84 |
85 | - @SpringBootApplication注解
86 | - application.run()
87 |
88 | 这两部分分别是SpringBoot**加载配置**和**启动**。
89 |
90 |
91 |
92 | 1、首先介绍@SpringBootApplication 背后是三个注解,每个注解的意义,干了什么事情,参考上面的内容。
93 |
94 | 2、然后介绍application.run() ,这个实例化过程干了三件事:
95 |
96 | - 根据classpath下是否存在(ConfigurableWebApplicationContext)判断是否要启动一个web applicationContext。
97 | - SpringFactoriesInstances加载classpath下所有可用的ApplicationContextInitializer
98 | - SpringFactoriesInstances加载classpath下所有可用的ApplicationListener
99 |
100 |
101 |
102 | 然后还有一些后续收尾工作。
103 |
104 | 参考思否:https://segmentfault.com/a/1190000014525138
105 |
106 |
107 |
108 | ### 3.SpringBoot对微服务的支持
109 |
110 | SpringCloud是一套微服务的解决方案,SpringCloud底层是SpringBoot。
111 |
112 | 而SpringCloud是一套微服务解决方案,里面包含大多数微服务用到的各个组件。
113 |
114 |
115 |
116 | ### 4.SpringBoot框架的优势、特点
117 |
118 | #### 特点
119 |
120 | 首先要知道什么是SpringBoot,先要知道Spring,Spring在做Java EE开发需要写大量的XML,代码非常多,非常繁杂。
121 |
122 | SpringBoot有一句话叫约定大于配置,好多都是不需要自己配置(人家提前配置好了)。
123 |
124 | Spring Boot 并不是用来替代 Spring 的解决方案,而是和 Spring 框架紧密结合用于提升 Spring 开发者体验的工具。同时它集成了大量常用的第三方库配置,Spring Boot应用中这些第三方库几乎可以是零配置的开箱即用(out-of-the-box),大部分的 Spring Boot 应用都只需要非常少量的配置代码(基于 Java 的配置),开发者能够更加专注于业务逻辑。
125 |
126 |
127 |
128 | #### 优点
129 |
130 | - **有良好的基因** 基于Spring 4.0
131 | - **简化编码** 引入的依赖少了很多(本质上是对配置依赖包进行了合并)
132 | - **简化配置** 不需要像Spring一样,使用前配置各种xml,SpringBoot更多的是Java Config类型的配置方式,使用@Configuration 和@Bean两个注解即可
133 | - **简化部署** 以前Spring发布,需要将war包放在Tomcat中,然后启动Tomcat才可以访问项目,现在SpringBoot内部有Tomcat,只需要将项目打包成jar包,然后java -jar **.jar 就可以运行项目。
134 | - **简化监控** 我们可以引入 spring-boot-start-actuator 依赖,直接使用 REST 方式来获取进程的运行期性能参数,从而达到监控的目的,比较方便。但是 Spring Boot 只是个微框架,没有提供相应的服务发现与注册的配套功能,没有外围监控集成方案,没有外围安全管理方案,所以在微服务架构中,还需要 Spring Cloud 来配合一起使用。
135 |
136 |
137 |
138 | 参考:https://blog.csdn.net/qq_32595453/article/details/81141643
139 |
140 |
141 |
142 | #### 修改SpringBoot内置Tomcat的配置
143 |
144 | 常用几种方式:
145 |
146 | - 改配置
147 |
148 | ```yml
149 | #Tomcat
150 | server:
151 | tomcat:
152 | uri-encoding: UTF-8
153 | #最小线程数
154 | min-spare-threads: 500
155 | #最大线程数
156 | max-threads: 2500
157 | #最大链接数
158 | max-connections: 6500
159 | #最大等待队列长度
160 | accept-count: 1000
161 | #请求头最大长度kb
162 | max-http-header-size: 1048576
163 | #请请求体最大长度kb
164 | #max-http-post-size: 2097152
165 | #服务http端口
166 | port: 8080
167 | #链接建立超时时间
168 | connection-timeout: 12000
169 | servlet:
170 | #访问根路径
171 | context-path: /song
172 | ```
173 |
174 |
175 |
176 | - 自定义类修改
177 |
178 | - 参考下面CSDN文章。
179 |
180 |
181 |
182 | 参考博客园:https://www.cnblogs.com/lys_013/p/13185940.html
183 |
184 | 参考CSDN:https://blog.csdn.net/keitho00/article/details/85003430?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&dist_request_id=11289e51-22e1-48fb-ac44-4d80664dcc46&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control
185 |
186 | ### 5.SpringBoot和其他的对比
187 |
188 | #### Springboot和SSM的最大区别是什么?
189 |
190 | 简而言之就是:
191 |
192 | SSM (Spring + Spring MVC + Mybatis)里面包含的三种是固定的,而SpringBoot,他没有和这些框架集成,不一定非要使用这三种框架,你可以使用其他的框架,相当于你需要自己去组装里面的东西。
193 |
194 |
195 |
196 | 参考知乎:https://www.zhihu.com/question/284488830
197 |
198 |
199 |
200 | #### SpringBoot如何实现自动化配置
201 |
202 | 参考博客园:https://www.cnblogs.com/bluemilk/p/10569720.html (这个没有细看,没有看懂)
203 |
204 |
205 |
206 | #### Spring和springboot区别
207 |
208 |
209 |
210 |
211 |
212 | ### 6.SpringBoot处理事务、连接池
213 |
214 | Springboot处理事务工作原理,连接池工作原理
215 |
216 |
217 |
218 | ### Springboot的核心是什么?
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 | ### Springboot中如何导入springMVC自己构建的模块,就是用什么注解可以一键导入?
229 |
230 | ### springboot的pom文件看过吗,里面有什么东西?
231 |
232 | ### 创建一个新的springboot应用要做哪些事情?框架已经搭建好了
233 |
234 | ### springboot里一个service接口,如何将只要是他的实现类都注册到容器里去
235 |
236 |
237 |
238 | ### SpringBoot自动装配原理(重点看一下)
239 |
240 |
241 |
242 | 参考Guide哥收录的篇文章:https://www.cnblogs.com/javaguide/p/springboot-auto-config.html
243 |
244 |
245 |
246 | ##
247 |
248 |
249 |
250 | ##
--------------------------------------------------------------------------------
/docs/SpringCloud.md:
--------------------------------------------------------------------------------
1 | # SpringCloud
2 |
3 |
4 |
5 | # Interview
6 |
7 | ## 分布式
8 |
9 | ### 1.集群,分布式,微服务区别:
10 |
11 | **集群是个物理形态,分布式是个工作方式。**
12 |
13 | - 分布式:一个业务分拆多个子业务,部署在不同的服务器上
14 | - 集群:同一个业务,部署在多个服务器上
15 |
16 | 1:**分布式是指将不同的业务分布在不同的地方。而集群指的是将几台服务器集中在一起,实现同一业务。**
17 |
18 | 分布式中的每一个节点,都可以做集群。而集群并不一定就是分布式的。
19 |
20 | 举例:就比如新浪网,访问的人多了,他可以做一个群集,前面放一个响应服务器,后面几台服务器完成同一业务,如果有业务访问的时候,响应服务器看哪台服务器的负载不是很重,就将给哪一台去完成。
21 |
22 | 而分布式,从窄意上理解,也跟集群差不多,但是它的组织比较松散,不像集群,有一个组织性,**一台服务器垮了,其它的服务器可以顶上来。**
23 |
24 | **分布式的每一个节点,都完成不同的业务,一个节点垮了,那这个业务就不可访问了。**
25 |
26 | 2:简单说,**分布式是以缩短单个任务的执行时间来提升效率的,而集群则是通过提高单位时间内执行的任务数来提升效率。**
27 |
28 | 例如:如果一个任务由 10 个子任务组成,每个子任务单独执行需 1 小时,则在一台服务器上执行该任务需 10 小时。
29 |
30 | 采用分布式方案,提供 10 台服务器,每台服务器只负责处理一个子任务,不考虑子任务间的依赖关系,执行完这个任务只需一个小时。(这种工作模式的一个典型代表就是 Hadoop 的 Map/Reduce 分布式计算模型)
31 |
32 | 而采用集群方案,同样提供 10 台服务器,每台服务器都能独立处理这个任务。假设有 10 个任务同时到达,10 个服务器将同时工作,1 小时后,10 个任务同时完成,这样,整身来看,还是 1 小时内完成一个任务!
33 |
34 | ------
35 |
36 | 好的设计应该是分布式和集群的结合,先分布式再集群,具体实现就是业务拆分成很多子业务,然后针对每个子业务进行集群部署,这样每个子业务如果出了问题,整个系统完全不会受影响。
37 |
38 | 另外,还有一个概念和分布式比较相似,那就是**微服务。**
39 |
40 | **微服务是一种架构风格,一个大型复杂软件应用由一个或多个微服务组成。系统中的各个微服务可被独立部署,各个微服务之间是松耦合的。每个微服务仅关注于完成一件任务并很好地完成该任务。在所有情况下,每个任务代表着一个小的业务能力。**
41 |
42 |
43 |
44 | 区别:
45 |
46 | #### 1.分布式:
47 |
48 | 
49 |
50 | 将一个大的系统划分为多个业务模块,业务模块分别部署到不同的机器上,各个业务模块之间通过接口进行数据交互。区别分布式的方式是根据不同机器不同业务。
51 |
52 | **上面:service A、B、C、D 分别是业务组件,通过API Geteway进行业务访问。**
53 |
54 | 注:分布式需要做好事务管理。
55 |
56 | 分布式事务可参考:[微服务架构的分布式事务解决方案](https://my.oschina.net/838398/blog/761261)
57 |
58 | #### **2.集群模式**
59 |
60 | 
61 |
62 | 集群模式是不同服务器部署同一套服务对外访问,实现服务的负载均衡。区别集群的方式是根据部署多台服务器业务是否相同。
63 |
64 | 注:集群模式需要做好session共享,确保在不同服务器切换的过程中不会因为没有获取到session而中止退出服务。
65 |
66 | 一般配置Nginx*的负载容器实现:静态资源缓存、Session共享可以附带实现,Nginx支持5000个并发量。
67 |
68 | #### 3.分布式是否属于微服务?
69 |
70 | 答案是肯定的。[微服务](http://lib.csdn.net/base/microservice)的意思也就是将模块拆分成一个独立的服务单元通过接口来实现数据的交互。
71 |
72 | #### 4.微服务架构
73 |
74 | 微服务的设计是为了不因为某个模块的升级和BUG影响现有的系统业务。微服务与分布式的细微差别是,微服务的应用不一定是分散在多个服务器上,他也可以是同一个服务器。
75 |
76 | 
77 |
78 | 通俗理解为:
79 |
80 | 去饭店吃饭就是一个完整的业务,饭店的厨师、配菜师、传菜员、服务员就是分布式;厨师、配菜师、传菜员和服务员都不止一个人,这就是集群;分布式就是微服务的一种表现形式,分布式是部署层面,微服务是设计层面。
81 |
82 | 参考:https://blog.csdn.net/qq_37788067/article/details/79250623?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase
83 |
84 |
85 |
86 |
87 |
88 | ### 2.说一说分布式的结构或者实现原理
89 |
90 |
91 |
92 | ### 3.分布式事务相关
93 |
94 | 报装系统使用的是: https://www.jianshu.com/p/86b4ab4f2d18 这个分布式事务
95 |
96 |
97 |
98 | #### 1.为什么要使用分布式事务?
99 |
100 | 答:当单个数据库的性能产生瓶颈的时候,我们需要对数据库分库或者是分区,那么这个时候数据库就处于不同的服务器上了,因此基于单个数据库所控制的传统型事务已经不能在适应这种情况了,故我们需要使用分布式事务来管理这种情况。
101 |
102 | 或者还有一些情况,需要在一次事务中操作两个不同的数据库。如果要用事务,那也算是分布式事务。
103 |
104 |
105 |
106 | #### 2.什么叫分布式事务?
107 |
108 | 答:事务的资源分别位于不同的分布式系统的不同节点之上的事务,简单地说就是一个大的操作由两个或者更多的小的操作共同完成。而这些小的操作又分布在不同的网络主机上。这些操作,要么全部成功执行,要么全部不执行。
109 |
110 |
111 |
112 | #### 3.分布式事务的原理?
113 |
114 |
115 |
116 | #### 4.分布式事务可以分为哪些?
117 |
118 | 答:两阶段提交(2PC),三阶段提交(3PC),补偿事务(TCC),本地消息表即消息队列(核心思想是将分布式事务拆分成本地事务进行处理)
119 |
120 | 分布式事务
121 |
122 | 参考:https://blog.csdn.net/weixin_40533111/article/details/85069536
123 |
124 | 参考:https://zhuanlan.zhihu.com/p/183753774
125 |
126 | 程序员小灰:https://blog.csdn.net/bjweimengshu/article/details/79607522
127 |
128 |
129 |
130 | #### 5.熟悉分布式事务,那你说一下有哪几种使用方法?(二段式、三段式、TCC、MQ)?介绍一下二段式分布式事务的过程
131 |
132 | #### 6.分布式事务中,幂等性问题?举个例子
133 |
134 | 参考:https://www.cnblogs.com/jajian/p/10926681.html
135 |
136 |
137 |
138 | #### 7.钢性事务 柔性事务
139 |
140 | 1. 刚性事务:遵循ACID原则,强一致性。
141 | 2. 柔性事务:遵循BASE理论,最终一致性;与刚性事务不同,柔性事务允许一定时间内,不同节点的数据不一致,但要求最终一致。
142 |
143 | 参考:https://www.jianshu.com/p/d70df89665b9
144 |
145 |
146 |
147 | #### 8.分布式事务是怎么处理的?你们项目如何实现分布式事务?
148 |
149 | 使用rocketMQ
150 |
151 | 
152 |
153 | **如何处理重复消费的问题**
154 |
155 | 让生产者发送每条数据的时候,里面加一个全局唯一的id,类似订单id之类的东西,然后你这里消费到了之后,先根据这个id去比如redis里查一下,之前消费过吗?如果没有消费过,你就处理,然后这个id写redis。如果消费过了,那你就别处理了,保证别重复处理相同的消息即可。
156 |
157 |
158 |
159 | #### 9.介绍常见的分布式锁?介绍一下几种分布式锁?
160 |
161 | 单机环境下,我们用 Synchronized 关键字来修饰方法或者是修饰代码块,以此来保证方法内或者是代码块内的代码在同一时间只能被一个线程执行。但是如果到了分布式环境中,Synchronized 就不好使了,因为他是 JVM 提供的关键字,只能在一台 JVM 中保证同一时间
162 | 只有一个线程执行,那么假如现在有多台 JVM 了(项目有多个节点了),那么就需要分布式锁来保证同一时间,在多个节点内,只有一个线程在执行该代码。
163 |
164 | 基于数据库实现分布式锁 基于缓存(redis,memcached,tair)实现分布式锁 基于Zookeeper实现分布式锁(每个客户端对某个方法加锁时,在zookeeper上的与该方法对应的指定节点的目录下,生成一个唯一的瞬时有序节点。 判断是否获取锁的方式很简单,只需要判断有序节点中序号最小的一个。 当释放锁的时候,只需将这个瞬时节点删除即可。同时,其可以避免服务宕机导致的锁无法释放,而产生的死锁问题。)
165 |
166 |
167 |
168 | ##### 三种实现方式:
169 |
170 | ##### 1 基于数据库:
171 |
172 | 数据库自带的通过唯一性索引或者主键索引,通过它的唯一性,当某个节点来使用某个方法时就在数据库中添加固定的值,这样别的节点来使用这个方法就会因为不能添加这个唯一字段而失败。这样就实现了锁。一个节点执行完毕后就删除这一行数据,别的节点就又能访问这个方法了,这就是释放锁。但是一方面,数据库本身性能就低,而且这种形式非常容易死锁,虽然可以各种优化,但还是不推荐使用。数据库的乐观锁也是一个道理,一般不用
173 |
174 | ##### 2 Redis 分布式锁
175 |
176 | SETNX 关键字,设置参数如果存在返回 0,如果不存在返回 value 和 1 expire 关键字,为 key 设置过期时间,解决死锁。delete 关键字,删除 key,释放锁
177 |
178 | 实现思想:
179 | (1)获取锁的时候,使用 setnx 加锁,并使用 expire 命令为锁添加一个超时时间,超过该
180 | 时间则自动释放锁,锁的 value 值为一个随机生成的 UUID,通过此在释放锁的时候进行判
181 | 断。
182 | (2)获取锁的时候还设置一个获取的超时时间,若超过这个时间则放弃获取锁。
183 | (3)释放锁的时候,通过 UUID 判断是不是该锁,若是该锁,则执行 delete 进行锁释放。
184 |
185 | ##### 3 zookeeper 实现分布式锁
186 |
187 | ZooKeeper 是一个为分布式应用提供一致性服务的开源组件,它内部是一个分层的文件系统
188 | 目录树结构,规定同一个目录下只能有一个唯一文件名。基于 ZooKeeper 实现分布式锁的
189 | 步骤如下:
190 | (1)创建一个目录 mylock;
191 | (2)线程 A 想获取锁就在 mylock 目录下创建临时顺序节点;
192 | (3)获取 mylock 目录下所有的子节点,然后获取比自己小的兄弟节点,如果不存在,则说
193 | 明当前线程顺序号最小,获得锁;
194 | (4)线程 B 获取所有节点,判断自己不是最小节点,设置监听比自己次小的节点;
195 | (5)线程 A 处理完,删除自己的节点,线程 B 监听到变更事件,判断自己是不是最小的节
196 | 点,如果是则获得锁。
197 | 速度没有 redis 快,但是能够解决死锁问题,可用性高于 redis
198 |
199 |
200 |
201 | #### 10.TCC相关 分布式事务
202 |
203 | TCC的原理?如果进行分布式事务的时候,try阶段完成了,但是confirm阶段有一台服务器宕机了怎么办?进行事务的时候,如果TCC服务器宕机了,重新启动之后未完成的事务怎么办?
204 |
205 | 说一下对TCC(分布式事务)的理解?TCC的原理?你们用的TCC框架是什么?
206 |
207 | 参考:https://www.cnblogs.com/jajian/p/10014145.html
208 |
209 |
210 |
211 | 开局tcc ,了解分布式事务吗,如果a事务使用gcc的注解,里面调用b事务,如何保证事务的一致性
212 |
213 | 说一下你对分布式的了解?(说了dubbo)
214 |
215 |
216 |
217 | #### 11.分布式事务的实现方式有哪些,两阶段提交的模式,即TCC会有什么问题
218 |
219 |
220 |
221 | #### 12.分布式事务的ACP有了解吗?(原子性,一致性,可用性)
222 |
223 | 参考一篇很好的文章 公众号里面的https://mp.weixin.qq.com/s/EU1u6scpiPkTuoMbly-WSg
224 |
225 | #### 14.你对分布式和微服务的理解?
226 |
227 |
228 |
229 | #### 15.分布式和集群有什么区别,分布式有什么问题,TCC具体是怎么操作的?
230 |
231 |
232 |
233 | #### 16.分布式并发产生的脏数据是怎么样处理的,有没有了解过分布式锁?
234 |
235 |
236 |
237 | #### 17.分布式CAP理论
238 |
239 | 分布式系统不可能同时满足一致性 可用性 分区容忍性
240 |
241 |
242 |
243 | #### 18.事务以及分布式事务
244 |
245 |
246 |
247 | #### 19.分布式如何携带信息?
248 |
249 |
250 |
251 | ## 微服务
252 |
253 | 1.为什么有微服务架构以及与单体架构的区别,为什么要这样做,可以提前准备一些背景知识
254 |
255 | 2.为什么要采用微服务的架构?和传统的架构相比有哪些好处和缺点?
256 |
257 | 3.微服务的注册中心 熔断器用的是什么
258 |
259 | 4.微服务各个模块之间怎么样实现消息同步?
260 |
261 | 你对微服务有什么看法?
262 |
263 | 13微服务项目是前后端分离的吗?怎么解决跨域,那跨域的时候有需要在请求头里生成些什么东西吗?需要加什么请求头前端才能跨域访问后端
264 |
265 |
266 |
267 | ## SpringCloud相关
268 |
269 | ### 1.Springcloud介绍
270 |
271 | 家族介绍介绍
272 |
273 |
274 |
275 | ### 2.SpringCloud 和Dubbo比较
276 |
277 | 从下面几个方面来说:
278 |
279 | 社区活跃度,开发公司,未来发展,使用上手难易程度,性能,周边完善程度
280 |
281 |
282 |
283 | **Spring相当于整机,而Dubbo需要自己去组装,整机的性能有保证,组装的机子更自由。**
284 |
285 | #### 社区活跃度
286 |
287 | SpringCloud社区活跃度高,也有专业团队在维护,常年很活跃。Dubbo阿里开发,中间停止更新过一段时间,2017年重新又更新,未来会不会持续更新,说不准,但是SpringCloud会应该一直更新。
288 |
289 |
290 |
291 | #### 开发公司、未来发展
292 |
293 | 阿里和Spring团队还是有区别,阿里是商业公司,Spring团队致力于打造全球使用的开源框架,未来SpringCloud作为Spring的一个很重要的项目,Spring团队会好好去维护。Dubbo团队不一定。
294 |
295 |
296 |
297 | #### 上手难度
298 |
299 | SpringCloud上手容易,他里面包含的好多组件,需要什么,自己可以去使用。在我自己的公司,我们使用的是SpringCloud,只是将Dubbo是作为一个服务调用组件来使用的(Dubbo最开始的定位之一)而Dubbo上手难度大,需要公司有专业的中间件团队来修改和维护Dubbo,或者集成其他组件等,上手难度大。
300 |
301 |
302 |
303 | #### 速度、性能方面
304 |
305 | Dubbo由于是二进制的传输,占用带宽会更少
306 |
307 | SpringCloud是HTTP协议传输,带宽会比较多,同时使用HTTP协议一般会使用JSON报文,消耗会更大
308 |
309 |
310 |
311 | 参考(这几篇文章写的比较全,从各个方面介绍):
312 |
313 | https://www.cnblogs.com/hmy-1365/p/11050265.html
314 |
315 | https://www.cnblogs.com/just-for-beyond/p/9790227.html
316 |
317 | 知乎:https://www.zhihu.com/question/45413135/answer/128315403
318 |
319 |
320 |
321 |
322 |
323 | ### 3.简述Springcloud核心组件及用途
324 |
325 | 
326 |
327 | - 服务发现(服务注册中心)——Netflix Eureka、后来用Nacos
328 | - 服务调用 —— Ribbon、LoadBalancer,公司用的是Dubbo调用
329 | - 客服端负载均衡—— Netflix Ribbon
330 | - 断路器(服务降级)—— Netflix Hystrix,高级部分有sentienl
331 | - 服务网关——Netflix Zuul(停更)、gateway(常用)
332 | - 分布式配置——Spring Cloud Config 、后来用的Nacos
333 |
334 |
335 |
336 |
337 |
338 | ## SpringCloud常见问题汇总
339 |
340 | https://blog.csdn.net/hjq_ku/article/details/89504229
341 |
342 | https://blog.csdn.net/qq_40117549/article/details/84944840
343 |
344 | https://www.cnblogs.com/aishangJava/p/11927311.html 这个也很好
345 |
346 | https://baijiahao.baidu.com/s?id=1654336657640346337&wfr=spider&for=pc
347 |
348 | https://www.cnblogs.com/lingboweifu/p/11797840.html
349 |
350 |
--------------------------------------------------------------------------------
/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/favicon.ico
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | JavaInterview
7 |
8 |
9 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/media/pictures/Collection.assets/031542494733474.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Collection.assets/031542494733474.png
--------------------------------------------------------------------------------
/media/pictures/Collection.assets/1586522321227.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Collection.assets/1586522321227.png
--------------------------------------------------------------------------------
/media/pictures/Collection.assets/1586530161293.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Collection.assets/1586530161293.png
--------------------------------------------------------------------------------
/media/pictures/Collection.assets/1586600321902.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Collection.assets/1586600321902.png
--------------------------------------------------------------------------------
/media/pictures/Collection.assets/1586673715667.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Collection.assets/1586673715667.png
--------------------------------------------------------------------------------
/media/pictures/Collection.assets/1586678878099.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Collection.assets/1586678878099.png
--------------------------------------------------------------------------------
/media/pictures/Collection.assets/1586679535828.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Collection.assets/1586679535828.png
--------------------------------------------------------------------------------
/media/pictures/Collection.assets/1591855019306.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Collection.assets/1591855019306.png
--------------------------------------------------------------------------------
/media/pictures/Collection.assets/1591855044381.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Collection.assets/1591855044381.png
--------------------------------------------------------------------------------
/media/pictures/Collection.assets/1591855058758.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Collection.assets/1591855058758.png
--------------------------------------------------------------------------------
/media/pictures/Collection.assets/1591855117657.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Collection.assets/1591855117657.png
--------------------------------------------------------------------------------
/media/pictures/Collection.assets/1591855155154.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Collection.assets/1591855155154.png
--------------------------------------------------------------------------------
/media/pictures/Collection.assets/620953-20190726223529160-967135077.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Collection.assets/620953-20190726223529160-967135077.png
--------------------------------------------------------------------------------
/media/pictures/Collection.assets/67233764.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Collection.assets/67233764.jpg
--------------------------------------------------------------------------------
/media/pictures/Collection.assets/clipboard-1586947479092.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Collection.assets/clipboard-1586947479092.png
--------------------------------------------------------------------------------
/media/pictures/Collection.assets/clipboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Collection.assets/clipboard.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/10.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/11.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/12.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/13.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/14.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/15.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/16.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/17.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/18.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/19.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/20.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/21.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/21.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/22.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/22.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/23.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/23.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/24.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/25.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/26.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/26.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/27.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/27.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/28.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/29.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/30.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/30.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/31.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/31.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/32.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/33.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/33.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/34.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/34.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/35.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/35.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/36.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/37.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/37.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/38.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/38.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/39.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/39.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/4.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/40.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/41.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/41.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/42.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/42.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/43.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/43.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/44.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/44.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/45.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/45.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/5.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/8.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/9.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/image-20200113154817582.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/image-20200113154817582.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/image-20200113155136957.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/image-20200113155136957.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/image-20200113155332666.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/image-20200113155332666.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/image-20200113155819517.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/image-20200113155819517.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/image-20200113160102668.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/image-20200113160102668.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/image-20200113160728259.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/image-20200113160728259.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/image-20200113162923877.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/image-20200113162923877.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/image-20200113163005061.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/image-20200113163005061.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/image-20200113163313305.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/image-20200113163313305.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/image-20200113163344174.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/image-20200113163344174.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/image-20200113163539676.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/image-20200113163539676.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/image-20200114163727767.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/image-20200114163727767.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/image-20200214132448956.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/image-20200214132448956.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/image-20200214202525859.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/image-20200214202525859.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/image-20200217160930138.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/image-20200217160930138.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/image-20200218105819932.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/image-20200218105819932.png
--------------------------------------------------------------------------------
/media/pictures/Drools.assets/image-20200218120618384.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Drools.assets/image-20200218120618384.png
--------------------------------------------------------------------------------
/media/pictures/JUC.assets/1587439674710.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/JUC.assets/1587439674710.png
--------------------------------------------------------------------------------
/media/pictures/JUC.assets/1587439715060.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/JUC.assets/1587439715060.png
--------------------------------------------------------------------------------
/media/pictures/JUC.assets/1591855866847.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/JUC.assets/1591855866847.png
--------------------------------------------------------------------------------
/media/pictures/JUC.assets/1591855884494.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/JUC.assets/1591855884494.png
--------------------------------------------------------------------------------
/media/pictures/JUC.assets/1591855933076.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/JUC.assets/1591855933076.png
--------------------------------------------------------------------------------
/media/pictures/JUC.assets/1591855993252.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/JUC.assets/1591855993252.png
--------------------------------------------------------------------------------
/media/pictures/JUC.assets/1591856012716.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/JUC.assets/1591856012716.png
--------------------------------------------------------------------------------
/media/pictures/JUC.assets/volatile关键字的可见性.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/JUC.assets/volatile关键字的可见性.png
--------------------------------------------------------------------------------
/media/pictures/JUC.assets/数据不一致.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/JUC.assets/数据不一致.png
--------------------------------------------------------------------------------
/media/pictures/Linux.assets/1585882274571-1588243560477.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Linux.assets/1585882274571-1588243560477.png
--------------------------------------------------------------------------------
/media/pictures/Linux.assets/1585882387300-1588243560479.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Linux.assets/1585882387300-1588243560479.png
--------------------------------------------------------------------------------
/media/pictures/Linux.assets/1588237066015.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Linux.assets/1588237066015.png
--------------------------------------------------------------------------------
/media/pictures/Linux.assets/1588240540192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Linux.assets/1588240540192.png
--------------------------------------------------------------------------------
/media/pictures/Linux.assets/1588242904651.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Linux.assets/1588242904651.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1104082-20170226015714054-85509796.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1104082-20170226015714054-85509796.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1104082-20170226020236195-1260049812.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1104082-20170226020236195-1260049812.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1104082-20170226021558210-635714085.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1104082-20170226021558210-635714085.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1104082-20170226021913023-31075463.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1104082-20170226021913023-31075463.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1104082-20170226022145538-205031549.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1104082-20170226022145538-205031549.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1104082-20170226022446179-827444722.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1104082-20170226022446179-827444722.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1104082-20170226022911710-1188849130.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1104082-20170226022911710-1188849130.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1104082-20170226023222945-1965432269.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1104082-20170226023222945-1965432269.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1216484-20190825002227995-188371311.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1216484-20190825002227995-188371311.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1216484-20190825002311121-524783044.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1216484-20190825002311121-524783044.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1395687-20190514091613619-1312062639.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1395687-20190514091613619-1312062639.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1586957379982.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1586957379982.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1586963200056.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1586963200056.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1586963416248.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1586963416248.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1586963579924.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1586963579924.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1587010722777.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1587010722777.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1587010757484.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1587010757484.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1587016917857.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1587016917857.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1587023865165.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1587023865165.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1587024092429.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1587024092429.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1587097704600.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1587097704600.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1587097929883.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1587097929883.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1587105563111.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1587105563111.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1587120003820.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1587120003820.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1587186663559.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1587186663559.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1587186724075.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1587186724075.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1587224210490.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1587224210490.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1587224238456.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1587224238456.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1587224256728.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1587224256728.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1587224297397.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1587224297397.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1644694-20190505155016157-1108127109.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1644694-20190505155016157-1108127109.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/1644694-20190505155026646-1387513390.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/1644694-20190505155026646-1387513390.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4ad1e262c7:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4ad1e262c7
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4ae00ad805:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4ae00ad805
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4ae1b1e740:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4ae1b1e740
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4ae260d343:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4ae260d343
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4ae468dd5f:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4ae468dd5f
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4aeeea3142:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4aeeea3142
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4af64502e8:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4af64502e8
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4affd9796f:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4affd9796f
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b0047390e:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b0047390e
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b06548ad2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b06548ad2
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b06d96e59:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b06d96e59
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b14bfcb89:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b14bfcb89
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b1c978ec4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b1c978ec4
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b23724f6c:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b23724f6c
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b25c75f18:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b25c75f18
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b25c75f18-1587224765941:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b25c75f18-1587224765941
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b2c6ecb0a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b2c6ecb0a
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b3331840f:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b3331840f
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b38f8b6a9:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b38f8b6a9
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b4082bcd3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b4082bcd3
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b4450f7a8:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b4450f7a8
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b555acbb1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b555acbb1
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b563095df:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b563095df
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b5cd19ef9:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b5cd19ef9
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b5f67f5db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b5f67f5db
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b627a3aa3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b627a3aa3
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b7a2dd2ac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b7a2dd2ac
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b7c297188:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b7c297188
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b80770fc3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b80770fc3
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b81039ab4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b81039ab4
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b97c18e40:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b97c18e40
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/169fab4b992d6c22:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/169fab4b992d6c22
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/940884-20190129111427216-1965281810.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/940884-20190129111427216-1965281810.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/940884-20190129111443667-1089405966.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/940884-20190129111443667-1089405966.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/940884-20190129111500436-1212656786.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/940884-20190129111500436-1212656786.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/940884-20190129111702299-1368712722.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/940884-20190129111702299-1368712722.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/940884-20190129111711788-545661817.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/940884-20190129111711788-545661817.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/B+树二级索引(辅助索引).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/B+树二级索引(辅助索引).png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/B+树索引.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/B+树索引.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/Mysql索引文件截图.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/Mysql索引文件截图.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/mysql-engines.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/mysql-engines.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/事务特性.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/事务特性.png
--------------------------------------------------------------------------------
/media/pictures/MySql.assets/查看表的存储引擎.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/MySql.assets/查看表的存储引擎.png
--------------------------------------------------------------------------------
/media/pictures/Mybatis.assets/1588578489385_数据库、.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Mybatis.assets/1588578489385_数据库、.png
--------------------------------------------------------------------------------
/media/pictures/Mybatis.assets/37d3d539b6003af38427311c555ea05a1138b6ac.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Mybatis.assets/37d3d539b6003af38427311c555ea05a1138b6ac.jpeg
--------------------------------------------------------------------------------
/media/pictures/Mybatis.assets/6d81800a19d8bc3e953df07fe2ffc018a9d345cc.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Mybatis.assets/6d81800a19d8bc3e953df07fe2ffc018a9d345cc.jpeg
--------------------------------------------------------------------------------
/media/pictures/Mybatis.assets/b151f8198618367a5e108e327107edd2b21ce53b.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Mybatis.assets/b151f8198618367a5e108e327107edd2b21ce53b.jpeg
--------------------------------------------------------------------------------
/media/pictures/Redis.assets/1586705737024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Redis.assets/1586705737024.png
--------------------------------------------------------------------------------
/media/pictures/Redis.assets/1586760599707.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Redis.assets/1586760599707.png
--------------------------------------------------------------------------------
/media/pictures/Redis.assets/1586760870677.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Redis.assets/1586760870677.png
--------------------------------------------------------------------------------
/media/pictures/Redis.assets/1586767247276.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Redis.assets/1586767247276.png
--------------------------------------------------------------------------------
/media/pictures/Redis.assets/6078367.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Redis.assets/6078367.jpg
--------------------------------------------------------------------------------
/media/pictures/Redis.assets/image-20210225011159324.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Redis.assets/image-20210225011159324.png
--------------------------------------------------------------------------------
/media/pictures/Redis.assets/布隆过滤器-缓存穿透-redis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Redis.assets/布隆过滤器-缓存穿透-redis.png
--------------------------------------------------------------------------------
/media/pictures/Redis.assets/正常缓存处理流程-redis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Redis.assets/正常缓存处理流程-redis.png
--------------------------------------------------------------------------------
/media/pictures/Redis.assets/缓存穿透处理流程-redis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/Redis.assets/缓存穿透处理流程-redis.png
--------------------------------------------------------------------------------
/media/pictures/SpringCloud.assets/clipboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/SpringCloud.assets/clipboard.png
--------------------------------------------------------------------------------
/media/pictures/SpringCloud.assets/image-20201222090455797.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/SpringCloud.assets/image-20201222090455797.png
--------------------------------------------------------------------------------
/media/pictures/SpringCloud.assets/image-20201222090512129.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/SpringCloud.assets/image-20201222090512129.png
--------------------------------------------------------------------------------
/media/pictures/SpringCloud.assets/image-20201222090531185.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/SpringCloud.assets/image-20201222090531185.png
--------------------------------------------------------------------------------
/media/pictures/SpringCloud.assets/image-20210223153533186.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/pictures/SpringCloud.assets/image-20210223153533186.png
--------------------------------------------------------------------------------
/media/xmind/Docker.xmind:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/xmind/Docker.xmind
--------------------------------------------------------------------------------
/media/xmind/Drools.xmind:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/xmind/Drools.xmind
--------------------------------------------------------------------------------
/media/xmind/Git.xmind:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/xmind/Git.xmind
--------------------------------------------------------------------------------
/media/xmind/JUC.xmind:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/xmind/JUC.xmind
--------------------------------------------------------------------------------
/media/xmind/JVM.xmind:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/xmind/JVM.xmind
--------------------------------------------------------------------------------
/media/xmind/Linux.xmind:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/xmind/Linux.xmind
--------------------------------------------------------------------------------
/media/xmind/Mybatis.xmind:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/xmind/Mybatis.xmind
--------------------------------------------------------------------------------
/media/xmind/Mysql.xmind:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/xmind/Mysql.xmind
--------------------------------------------------------------------------------
/media/xmind/Network.xmind:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/xmind/Network.xmind
--------------------------------------------------------------------------------
/media/xmind/Redis.xmind:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/xmind/Redis.xmind
--------------------------------------------------------------------------------
/media/xmind/Spring.xmind:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/xmind/Spring.xmind
--------------------------------------------------------------------------------
/media/xmind/SpringCloud2020.xmind:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/xmind/SpringCloud2020.xmind
--------------------------------------------------------------------------------
/media/xmind/算法.xmind:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/HappySnailSunshine/JavaInterview/c75503683043cd3026c8037d9accbeb21b9f9ef9/media/xmind/算法.xmind
--------------------------------------------------------------------------------