diff --git a/.editorconfig b/.editorconfig index 63bacb1b02..2bd4e639bb 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,33 +1,28 @@ -#------------------------------------------------------------------------- -# EditorConfig helps developers define and maintain consistent -# coding styles between different editors and IDEs -# http://editorconfig.org -# 所有文件换行使用 Unix like 风格(LF),bat 文件使用 win 风格(CRLF) -# 缩进 java 4 个空格,其他所有文件 2 个空格 -#------------------------------------------------------------------------- +# EditorConfig 用于在 IDE 中检查代码的基本 Code Style +# @see: https://editorconfig.org/ + +# 配置说明: +# 所有文件换行使用 Unix 风格(LF),*.bat 文件使用 Windows 风格(CRLF) +# java / sh 文件缩进 4 个空格,其他所有文件缩进 2 个空格 root = true [*] -# Unix-style newlines with a newline ending every file end_of_line = lf - -# Change these settings to your own preference indent_size = 2 indent_style = space max_line_length = 120 - -# We recommend you to keep these unchanged charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true -[*.bat] +[*.{bat, cmd}] end_of_line = crlf -[*.java] +[*.{java, gradle, groovy, kt, sh, xml}] indent_size = 4 [*.md] max_line_length = 0 trim_trailing_whitespace = false +end_of_line = lf diff --git a/.gitattributes b/.gitattributes index e2a6e5e034..eaae227f16 100644 --- a/.gitattributes +++ b/.gitattributes @@ -22,6 +22,7 @@ *.less text *.sql text *.properties text +*.md text # unix style *.sh text eol=lf @@ -50,26 +51,28 @@ *.bin binary *.exe binary -# 图片 +# images *.png binary *.jpg binary *.ico binary *.gif binary -# 音视频 +# medias *.mp3 binary *.swf binary -# 字体 +# fonts *.eot binary *.svg binary *.ttf binary *.woff binary -# other doc +# others *.pdf binary *.doc binary *.docx binary +*.ppt binary +*.pptx binary *.xls binary *.xlsx binary *.xmind binary diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000000..36b705cbe0 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,36 @@ +name: CI + +# 在master分支发生push事件时触发。 +on: + push: + branches: + - master + +env: # 设置环境变量 + TZ: Asia/Shanghai # 时区(设置时区可使页面中的`最近更新时间`使用时区时间) + +jobs: + build: # 自定义名称 + runs-on: ubuntu-latest # 运行在虚拟机环境ubuntu-latest + + strategy: + matrix: + node-version: [14.x] + + steps: + # 使用的动作。格式:userName/repoName。作用:检出仓库,获取源码。 官方actions库:https://github.com/actions + - name: Checkout + uses: actions/checkout@master + + # 指定 nodejs 版本 + - name: Use Nodejs ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + + # 部署 + - name: Deploy + env: # 设置环境变量 + GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }} + GITEE_TOKEN: ${{ secrets.GITEE_TOKEN }} + run: npm install && npm run deploy diff --git a/.gitignore b/.gitignore index 782f2ba214..7d98dac9d2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,66 @@ -# intellij +# --------------------------------------------------------------------- +# more gitignore templates see https://github.com/github/gitignore +# --------------------------------------------------------------------- + +# ------------------------------- java ------------------------------- +# compiled folders +classes +target +logs +.mtj.tmp/ + +# compiled files +*.class + +# bluej files +*.ctxt + +# package files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs +hs_err_pid* + +# maven plugin temp files +.flattened-pom.xml + + +# ------------------------------- javascript ------------------------------- +# dependencies +node_modules + +# temp folders +build +dist +_book +_jsdoc +.temp +.deploy*/ + +# temp files +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +bundle*.js +.DS_Store +Thumbs.db +db.json +book.pdf +package-lock.json + + +# ------------------------------- intellij ------------------------------- .idea *.iml + + +# ------------------------------- eclipse ------------------------------- +.classpath +.project diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..9eb9b2e6d6 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,24 @@ +# 持续集成 CI +# @see https://docs.travis-ci.com/user/tutorial/ + +language: node_js + +sudo: required + +node_js: '16.13.0' + +branches: + only: + - master + +before_install: + - export TZ=Asia/Shanghai + +script: bash ./deploy.sh + +notifications: + email: + recipients: + - forbreak@163.com + on_success: change + on_failure: always diff --git a/LICENSE b/LICENSE index 261eeb9e9f..3b7b82d0da 100644 --- a/LICENSE +++ b/LICENSE @@ -1,201 +1,427 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. +Attribution-ShareAlike 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More_considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution-ShareAlike 4.0 International Public +License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-ShareAlike 4.0 International Public License ("Public +License"). To the extent this Public License may be interpreted as a +contract, You are granted the Licensed Rights in consideration of Your +acceptance of these terms and conditions, and the Licensor grants You +such rights in consideration of benefits the Licensor receives from +making the Licensed Material available under these terms and +conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. BY-SA Compatible License means a license listed at + creativecommons.org/compatiblelicenses, approved by Creative + Commons as essentially the equivalent of this Public License. + + d. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + e. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + f. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + g. License Elements means the license attributes listed in the name + of a Creative Commons Public License. The License Elements of this + Public License are Attribution and ShareAlike. + + h. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + i. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + j. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + k. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + l. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + m. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part; and + + b. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. Additional offer from the Licensor -- Adapted Material. + Every recipient of Adapted Material from You + automatically receives an offer from the Licensor to + exercise the Licensed Rights in the Adapted Material + under the conditions of the Adapter's License You apply. + + c. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + b. ShareAlike. + + In addition to the conditions in Section 3(a), if You Share + Adapted Material You produce, the following conditions also apply. + + 1. The Adapter's License You apply must be a Creative Commons + license with the same License Elements, this version or + later, or a BY-SA Compatible License. + + 2. You must include the text of, or the URI or hyperlink to, the + Adapter's License You apply. You may satisfy this condition + in any reasonable manner based on the medium, means, and + context in which You Share Adapted Material. + + 3. You may not offer or impose any additional or different terms + or conditions on, or apply any Effective Technological + Measures to, Adapted Material that restrict exercise of the + rights granted under the Adapter's License You apply. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material, + + including for purposes of Section 3(b); and + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/README.md b/README.md index 8505b6acab..cfcee6cdb1 100644 --- a/README.md +++ b/README.md @@ -1,55 +1,711 @@ -# Notes +

+ + logo + +

-> 本项目用于归档本人的各种笔记。 +

-| :coffee: | :slot_machine: | :package: | :spider_web: | :computer: | :globe_with_meridians: | :art: | :cloud: | :bulb: | :building_construction: | -| :-------------------: | :------------: | :---------------: | :-----------: | :-------------------: | :--------------------: | :-----------: | :---------------: | :-----------: | :---------------------: | -| [编程语言](#编程语言) | [算法](#算法) | [数据库](#数据库) | [网络](#网络) | [操作系统](#操作系统) | [Web](#web) | [前端](#前端) | [大数据](#大数据) | [设计](#设计) | [软件工程](#软件工程) | + + star + -## 编程语言 + + fork + -- [Java](programming/java) -- [Python](programming/python.md) -- [Shell](programming/shell) + + build + -## 算法 + + code style + -- [数据结构](algorithm/data-structure) -- 算法(:construction: 待整理补充) +

+ +

blog

+ +> 💧 [Blog](https://github.com/dunwu/blog/) 是一个十年 Java 程序员的博客。 +> +> - 🔁 项目同步维护:[Github](https://github.com/dunwu/blog/) | [Gitee](https://gitee.com/turnon/blog/) +> - 📖 电子书阅读:[Github Pages](https://dunwu.github.io/blog/) | [Gitee Pages](https://turnon.gitee.io/blog/) + +## Java + +### JavaCore + +#### [Java 基础特性](source/_posts/01.Java/01.JavaCore/01.基础特性) + +- [Java 基础语法特性](source/_posts/01.Java/01.JavaCore/01.基础特性/Java_基础语法.md) +- [Java 基本数据类型](source/_posts/01.Java/01.JavaCore/01.基础特性/Java_数据类型.md) +- [Java 面向对象](source/_posts/01.Java/01.JavaCore/01.基础特性/Java_面向对象.md) +- [Java 方法](source/_posts/01.Java/01.JavaCore/01.基础特性/Java_方法.md) +- [Java 数组](source/_posts/01.Java/01.JavaCore/01.基础特性/Java_数组.md) +- [Java 枚举](source/_posts/01.Java/01.JavaCore/01.基础特性/Java_枚举.md) +- [Java 控制语句](source/_posts/01.Java/01.JavaCore/01.基础特性/Java_控制语句.md) +- [Java 异常](source/_posts/01.Java/01.JavaCore/01.基础特性/Java_异常.md) +- [Java 泛型](source/_posts/01.Java/01.JavaCore/01.基础特性/Java_泛型.md) +- [Java 反射](source/_posts/01.Java/01.JavaCore/01.基础特性/Java_反射.md) +- [Java 注解](source/_posts/01.Java/01.JavaCore/01.基础特性/Java_注解.md) +- [Java String 类型](source/_posts/01.Java/01.JavaCore/01.基础特性/Java_String.md) + +#### [Java 高级特性](source/_posts/01.Java/01.JavaCore/02.高级特性) + +- [Java 正则](source/_posts/01.Java/01.JavaCore/02.高级特性/Java_正则.md) - 关键词:Pattern、Matcher、捕获与非捕获、反向引用、零宽断言、贪婪与懒惰、元字符、DFA、NFA +- [Java 编码和加密](source/_posts/01.Java/01.JavaCore/02.高级特性/Java_编码和加密.md) - 关键词:Base64、消息摘要、数字签名、对称加密、非对称加密、MD5、SHA、HMAC、AES、DES、DESede、RSA +- [Java 国际化](source/_posts/01.Java/01.JavaCore/02.高级特性/Java_国际化.md) - 关键词:Locale、ResourceBundle、NumberFormat、DateFormat、MessageFormat +- [Java JDK8](source/_posts/01.Java/01.JavaCore/02.高级特性/Java_JDK8.md) - 关键词:Stream、lambda、Optional、@FunctionalInterface +- [Java SPI](source/_posts/01.Java/01.JavaCore/02.高级特性/Java_SPI.md) - 关键词:SPI、ClassLoader +- [JavaAgent](source/_posts/01.Java/01.JavaCore/02.高级特性/Java_Agent.md) + +#### [Java 容器](source/_posts/01.Java/01.JavaCore/03.容器) + +- [Java 容器简介](source/_posts/01.Java/01.JavaCore/03.容器/Java_容器_简介.md) - 关键词:泛型、Iterable、Iterator、Comparable、Comparator、Cloneable、fail-fast +- [Java 容器之 List](source/_posts/01.Java/01.JavaCore/03.容器/Java_容器_List.md) - 关键词:List、ArrayList、LinkedList +- [Java 容器之 Map](source/_posts/01.Java/01.JavaCore/03.容器/Java_容器_Map.md) - 关键词:Map、HashMap、TreeMap、LinkedHashMap、WeakHashMap +- [Java 容器之 Set](source/_posts/01.Java/01.JavaCore/03.容器/Java_容器_Set.md) - 关键词:Set、HashSet、TreeSet、LinkedHashSet、EnumSet +- [Java 容器之 Queue](source/_posts/01.Java/01.JavaCore/03.容器/Java_容器_Queue.md) - 关键词:Queue、Deque、ArrayDeque、LinkedList、PriorityQueue +- [Java 容器之 Stream](source/_posts/01.Java/01.JavaCore/03.容器/Java_容器_Stream.md) + +#### [Java IO](source/_posts/01.Java/01.JavaCore/04.IO) + +- [Java I/O 之 简介](source/_posts/01.Java/01.JavaCore/04.IO/Java_IO_简介.md) - 关键词:BIO、NIO、AIO +- [Java I/O 之 BIO](source/_posts/01.Java/01.JavaCore/04.IO/Java_IO_BIO.md) - 关键词:BIO、InputStream、OutputStream、Reader、Writer、File、Socket、ServerSocket +- [Java I/O 之 NIO](source/_posts/01.Java/01.JavaCore/04.IO/Java_IO_NIO.md) - 关键词:NIO、Channel、Buffer、Selector、多路复用 +- [Java I/O 之序列化](source/_posts/01.Java/01.JavaCore/04.IO/Java_IO_序列化.md) - 关键词:Serializable、serialVersionUID、transient、Externalizable + +#### [Java 并发](source/_posts/01.Java/01.JavaCore/05.并发) + +- [Java 并发简介](source/_posts/01.Java/01.JavaCore/05.并发/Java_并发_简介.md) - 关键词:并发、线程、安全性、活跃性、性能、死锁、活锁 +- [Java 并发之内存模型](source/_posts/01.Java/01.JavaCore/05.并发/Java_并发_内存模型.md) - 关键词:JMM、Happens-Before、内存屏障、volatile、synchronized、final、指令重排序 +- [Java 并发之线程](source/_posts/01.Java/01.JavaCore/05.并发/Java_并发_线程.md) - 关键词:Thread、Runnable、Callable、Future、FutureTask、线程生命周期 +- [Java 并发之锁](source/_posts/01.Java/01.JavaCore/05.并发/Java_并发_锁.md) - 关键词:锁、Lock、Condition、ReentrantLock、ReentrantReadWriteLock、StampedLock +- [Java 并发之无锁](source/_posts/01.Java/01.JavaCore/05.并发/Java_并发_无锁.md) - 关键词:CAS、ThreadLocal、Immutability、Copy-on-Write +- [Java 并发之 AQS](source/_posts/01.Java/01.JavaCore/05.并发/Java_并发_AQS.md) - 关键词:AQS、独占锁、共享锁 +- [Java 并发之容器](source/_posts/01.Java/01.JavaCore/05.并发/Java_并发_容器.md) - 关键词:ConcurrentHashMap、CopyOnWriteArrayList +- [Java 并发之线程池](source/_posts/01.Java/01.JavaCore/05.并发/Java_并发_线程池.md) - 关键词:Executor、ExecutorService、ThreadPoolExecutor、Executors +- [Java 并发之同步工具](source/_posts/01.Java/01.JavaCore/05.并发/Java_并发_同步工具.md) - 关键词:Semaphore、CountDownLatch、CyclicBarrier +- [Java 并发之分工工具](source/_posts/01.Java/01.JavaCore/05.并发/Java_并发_分工工具.md) - 关键词:CompletableFuture、CompletionStage、ForkJoinPool + +#### [Java 虚拟机](source/_posts/01.Java/01.JavaCore/06.JVM) + +- [Java 虚拟机简介](source/_posts/01.Java/01.JavaCore/06.JVM/Java_虚拟机_简介.md) +- [Java 虚拟机之内存区域](source/_posts/01.Java/01.JavaCore/06.JVM/Java_虚拟机_内存区域.md) - 关键词:`程序计数器`、`虚拟机栈`、`本地方法栈`、`堆`、`方法区`、`运行时常量池`、`直接内存`、`OutOfMemoryError`、`StackOverflowError` +- [Java 虚拟机之垃圾收集](source/_posts/01.Java/01.JavaCore/06.JVM/Java_虚拟机_垃圾收集.md) - 关键词:`GC Roots`、`Serial`、`Parallel`、`CMS`、`G1`、`Minor GC`、`Full GC` +- [Java 虚拟机之字节码](source/_posts/01.Java/01.JavaCore/06.JVM/Java_虚拟机_字节码.md) - 关键词:`bytecode`、`asm`、`javassist` +- [Java 虚拟机之类加载](source/_posts/01.Java/01.JavaCore/06.JVM/Java_虚拟机_类加载.md) - 关键词:`ClassLoader`、`双亲委派` +- [Java 虚拟机之工具](source/_posts/01.Java/01.JavaCore/06.JVM/Java_虚拟机_工具.md) - 关键词:`jps`、`jstat`、`jmap` 、`jstack`、`jhat`、`jinfo`、`jconsole`、`jvisualvm`、`MAT`、`JProfile`、`Arthas` +- [Java 虚拟机之故障处理](source/_posts/01.Java/01.JavaCore/06.JVM/Java_虚拟机_故障处理.md) - 关键词:`CPU`、`内存`、`磁盘`、`网络`、`GC` +- [Java 虚拟机之调优](source/_posts/01.Java/01.JavaCore/06.JVM/Java_虚拟机_调优.md) - 关键词:`配置`、`调优` + +### JavaEE + +#### JavaWeb + +- [JavaWeb 面经](source/_posts/01.Java/02.JavaEE/01.JavaWeb/99.JavaWeb面经.md) +- [JavaWeb 之 Servlet 指南](source/_posts/01.Java/02.JavaEE/01.JavaWeb/01.JavaWeb之Servlet指南.md) +- [JavaWeb 之 Jsp 指南](source/_posts/01.Java/02.JavaEE/01.JavaWeb/02.JavaWeb之Jsp指南.md) +- [JavaWeb 之 Filter 和 Listener](source/_posts/01.Java/02.JavaEE/01.JavaWeb/03.JavaWeb之Filter和Listener.md) +- [JavaWeb 之 Cookie 和 Session](source/_posts/01.Java/02.JavaEE/01.JavaWeb/04.JavaWeb之Cookie和Session.md) + +#### Java 服务器 + +> Tomcat 和 Jetty 都是 Java 比较流行的轻量级服务器。 +> +> Nginx 是目前最流行的反向代理服务器,也常用于负载均衡。 + +- [Tomcat 快速入门](source/_posts/01.Java/02.JavaEE/02.服务器/01.Tomcat/01.Tomcat快速入门.md) +- [Tomcat 连接器](source/_posts/01.Java/02.JavaEE/02.服务器/01.Tomcat/02.Tomcat连接器.md) +- [Tomcat 容器](source/_posts/01.Java/02.JavaEE/02.服务器/01.Tomcat/03.Tomcat容器.md) +- [Tomcat 优化](source/_posts/01.Java/02.JavaEE/02.服务器/01.Tomcat/04.Tomcat优化.md) +- [Tomcat 和 Jetty](source/_posts/01.Java/02.JavaEE/02.服务器/01.Tomcat/05.Tomcat和Jetty.md) +- [Jetty](source/_posts/01.Java/02.JavaEE/02.服务器/02.Jetty.md) + +### Java 软件 + +#### Java 构建 + +> Java 项目需要通过 [**构建工具**](source/_posts/01.Java/11.软件/01.构建) 来管理项目依赖,完成编译、打包、发布、生成 JavaDoc 等任务。 +> +> - 目前最主流的构建工具是 Maven,它的功能非常强大。 +> - Gradle 号称是要替代 Maven 等构件工具,它的版本管理确实简洁,但是需要学习 Groovy,学习成本比 Maven 高。 +> - Ant 功能比 Maven 和 Gradle 要弱,现代 Java 项目基本不用了,但也有一些传统的 Java 项目还在使用。 + +- [Maven](source/_posts/01.Java/11.软件/01.构建/01.Maven) 📚 + - [Maven 快速入门](source/_posts/01.Java/11.软件/01.构建/01.Maven/01.Maven快速入门.md) + - [Maven 教程之 pom.xml 详解](source/_posts/01.Java/11.软件/01.构建/01.Maven/02.Maven教程之pom.xml详解.md) + - [Maven 教程之 settings.xml 详解](source/_posts/01.Java/11.软件/01.构建/01.Maven/03.Maven教程之settings.xml详解.md) + - [Maven 实战问题和最佳实践](source/_posts/01.Java/11.软件/01.构建/01.Maven/04.Maven实战问题和最佳实践.md) + - [Maven 教程之发布 jar 到私服或中央仓库](source/_posts/01.Java/11.软件/01.构建/01.Maven/05.Maven教程之发布jar到私服或中央仓库.md) + - [Maven 插件之代码检查](source/_posts/01.Java/11.软件/01.构建/01.Maven/06.Maven插件之代码检查.md) +- [Ant 简易教程](source/_posts/01.Java/11.软件/01.构建/02.Ant.md) + +#### Java IDE + +> 自从有了 [**IDE**](source/_posts/01.Java/11.软件/02.IDE),写代码从此就告别了刀耕火种的蛮荒时代。 +> +> - [Eclipse](source/_posts/01.Java/11.软件/02.IDE/02.Eclipse.md) 是久负盛名的开源 Java IDE,我的学生时代一直使用它写 Java。 +> - 曾经抗拒从转 [Intellij Idea](source/_posts/01.Java/11.软件/02.IDE/01.Intellij.md) ,但后来发现真香,不得不说,确实是目前最优秀的 Java IDE。 +> - 你可以在 [vscode](source/_posts/01.Java/11.软件/02.IDE/03.VsCode.md) 中写各种语言,只要安装相应插件即可。如果你的项目中使用了很多种编程语言,又懒得在多个 IDE 之间切换,那么就用 vscode 来一网打尽吧。 + +- [Intellij Idea](source/_posts/01.Java/11.软件/02.IDE/01.Intellij.md) +- [Eclipse](source/_posts/01.Java/11.软件/02.IDE/02.Eclipse.md) +- [vscode](source/_posts/01.Java/11.软件/02.IDE/03.VsCode.md) + +#### Java 监控诊断 + +> [监控/诊断](source/_posts/01.Java/11.软件/03.监控诊断) 工具主要用于 Java 应用的运维。通过采集、分析、存储、可视化应用的有效数据,帮助开发者、使用者快速定位问题,找到性能瓶颈。 + +- [监控工具对比](source/_posts/01.Java/11.软件/03.监控诊断/01.监控工具对比.md) +- [CAT](source/_posts/01.Java/11.软件/03.监控诊断/02.CAT.md) +- [Zipkin](source/_posts/01.Java/11.软件/03.监控诊断/03.Zipkin.md) +- [SkyWalking](source/_posts/01.Java/11.软件/03.监控诊断/04.Skywalking.md) +- [Arthas](source/_posts/01.Java/11.软件/03.监控诊断/05.Arthas.md) + +### Java 工具 + +#### Java IO + +- [JSON 序列化](source/_posts/01.Java/12.工具/01.IO/01.JSON序列化.md) - [fastjson](https://github.com/alibaba/fastjson)、[Jackson](https://github.com/FasterXML/jackson)、[Gson](https://github.com/google/gson) +- [二进制序列化](source/_posts/01.Java/12.工具/01.IO/02.二进制序列化.md) - [Protobuf](https://developers.google.com/protocol-buffers)、[Thrift](https://thrift.apache.org/)、[Hessian](http://hessian.caucho.com/)、[Kryo](https://github.com/EsotericSoftware/kryo)、[FST](https://github.com/RuedigerMoeller/fast-serialization) + +#### JavaBean 工具 + +- [Lombok](source/_posts/01.Java/12.工具/02.JavaBean/01.Lombok.md) +- [Dozer](source/_posts/01.Java/12.工具/02.JavaBean/02.Dozer.md) + +#### Java 模板引擎 + +- [Freemark](source/_posts/01.Java/12.工具/03.模板引擎/01.Freemark.md) +- [Velocity](source/_posts/01.Java/12.工具/03.模板引擎/02.Thymeleaf.md) +- [Thymeleaf](source/_posts/01.Java/12.工具/03.模板引擎/03.Velocity.md) + +#### Java 测试工具 + +- [Junit](source/_posts/01.Java/12.工具/04.测试/01.Junit.md) +- [Mockito](source/_posts/01.Java/12.工具/04.测试/02.Mockito.md) +- [Jmeter](source/_posts/01.Java/12.工具/04.测试/03.Jmeter.md) +- [JMH](source/_posts/01.Java/12.工具/04.测试/04.JMH.md) + +#### 其他 + +- [Java 日志](source/_posts/01.Java/12.工具/99.其他/01.Java日志.md) +- [Java 工具包](source/_posts/01.Java/12.工具/99.其他/02.Java工具包.md) +- [Reflections](source/_posts/01.Java/12.工具/99.其他/03.Reflections.md) +- [JavaMail](source/_posts/01.Java/12.工具/99.其他/04.JavaMail.md) +- [Jsoup](source/_posts/01.Java/12.工具/99.其他/05.Jsoup.md) +- [Thumbnailator](source/_posts/01.Java/12.工具/99.其他/06.Thumbnailator.md) +- [Zxing](source/_posts/01.Java/12.工具/99.其他/07.Zxing.md) + +### Java 框架 + +#### Spring + +##### 综合 + +- [Spring 概述](source/_posts/01.Java/13.框架/01.Spring/00.Spring综合/01.Spring概述.md) +- [SpringBoot 知识图谱](source/_posts/01.Java/13.框架/01.Spring/00.Spring综合/21.SpringBoot知识图谱.md) +- [SpringBoot 基本原理](source/_posts/01.Java/13.框架/01.Spring/00.Spring综合/22.SpringBoot基本原理.md) +- [Spring 面试](source/_posts/01.Java/13.框架/01.Spring/00.Spring综合/99.Spring面试.md) + +##### 核心 + +- [Spring Bean](source/_posts/01.Java/13.框架/01.Spring/01.Spring核心/01.SpringBean.md) +- [Spring IoC](source/_posts/01.Java/13.框架/01.Spring/01.Spring核心/02.SpringIoC.md) +- [Spring 依赖查找](source/_posts/01.Java/13.框架/01.Spring/01.Spring核心/03.Spring依赖查找.md) +- [Spring 依赖注入](source/_posts/01.Java/13.框架/01.Spring/01.Spring核心/04.Spring依赖注入.md) +- [Spring IoC 依赖来源](source/_posts/01.Java/13.框架/01.Spring/01.Spring核心/05.SpringIoC依赖来源.md) +- [Spring Bean 作用域](source/_posts/01.Java/13.框架/01.Spring/01.Spring核心/06.SpringBean作用域.md) +- [Spring Bean 生命周期](source/_posts/01.Java/13.框架/01.Spring/01.Spring核心/07.SpringBean生命周期.md) +- [Spring 配置元数据](source/_posts/01.Java/13.框架/01.Spring/01.Spring核心/08.Spring配置元数据.md) +- [Spring AOP](source/_posts/01.Java/13.框架/01.Spring/01.Spring核心/10.SpringAop.md) +- [Spring 资源管理](source/_posts/01.Java/13.框架/01.Spring/01.Spring核心/20.Spring资源管理.md) +- [Spring 校验](source/_posts/01.Java/13.框架/01.Spring/01.Spring核心/21.Spring校验.md) +- [Spring 数据绑定](source/_posts/01.Java/13.框架/01.Spring/01.Spring核心/22.Spring数据绑定.md) +- [Spring 类型转换](source/_posts/01.Java/13.框架/01.Spring/01.Spring核心/23.Spring类型转换.md) +- [Spring EL 表达式](source/_posts/01.Java/13.框架/01.Spring/01.Spring核心/24.SpringEL.md) +- [Spring 事件](source/_posts/01.Java/13.框架/01.Spring/01.Spring核心/25.Spring事件.md) +- [Spring 国际化](source/_posts/01.Java/13.框架/01.Spring/01.Spring核心/26.Spring国际化.md) +- [Spring 泛型处理](source/_posts/01.Java/13.框架/01.Spring/01.Spring核心/27.Spring泛型处理.md) +- [Spring 注解](source/_posts/01.Java/13.框架/01.Spring/01.Spring核心/28.Spring注解.md) +- [Spring Environment 抽象](source/_posts/01.Java/13.框架/01.Spring/01.Spring核心/29.SpringEnvironment抽象.md) +- [SpringBoot 教程之快速入门](source/_posts/01.Java/13.框架/01.Spring/01.Spring核心/31.SpringBoot之快速入门.md) +- [SpringBoot 之属性加载](source/_posts/01.Java/13.框架/01.Spring/01.Spring核心/32.SpringBoot之属性加载.md) +- [SpringBoot 之 Profile](source/_posts/01.Java/13.框架/01.Spring/01.Spring核心/33.SpringBoot之Profile.md) + +##### 数据 + +- [Spring 之数据源](source/_posts/01.Java/13.框架/01.Spring/02.Spring数据/01.Spring之数据源.md) +- [Spring 之 JDBC](source/_posts/01.Java/13.框架/01.Spring/02.Spring数据/02.Spring之JDBC.md) +- [Spring 之事务](source/_posts/01.Java/13.框架/01.Spring/02.Spring数据/03.Spring之事务.md) +- [Spring 之 JPA](source/_posts/01.Java/13.框架/01.Spring/02.Spring数据/04.Spring之JPA.md) +- [Spring 集成 Mybatis](source/_posts/01.Java/13.框架/01.Spring/02.Spring数据/10.Spring集成Mybatis.md) +- [Spring 访问 Redis](source/_posts/01.Java/13.框架/01.Spring/02.Spring数据/21.Spring访问Redis.md) +- [Spring 访问 MongoDB](source/_posts/01.Java/13.框架/01.Spring/02.Spring数据/22.Spring访问MongoDB.md) +- [Spring 访问 Elasticsearch](source/_posts/01.Java/13.框架/01.Spring/02.Spring数据/23.Spring访问Elasticsearch.md) + +##### Web + +- [SpringWeb 综述](source/_posts/01.Java/13.框架/01.Spring/03.SpringWeb/01.SpringWeb综述.md) +- [SpringWeb 应用](source/_posts/01.Java/13.框架/01.Spring/03.SpringWeb/02.SpringWeb应用.md) +- [DispatcherServlet](source/_posts/01.Java/13.框架/01.Spring/03.SpringWeb/03.DispatcherServlet.md) +- [Spring 过滤器](source/_posts/01.Java/13.框架/01.Spring/03.SpringWeb/04.Spring过滤器.md) +- [Spring 跨域](source/_posts/01.Java/13.框架/01.Spring/03.SpringWeb/05.Spring跨域.md) +- [Spring 视图](source/_posts/01.Java/13.框架/01.Spring/03.SpringWeb/06.Spring视图.md) +- [SpringBoot 之应用 EasyUI](source/_posts/01.Java/13.框架/01.Spring/03.SpringWeb/21.SpringBoot之应用EasyUI.md) + +##### IO + +- [SpringBoot 之异步请求](source/_posts/01.Java/13.框架/01.Spring/04.SpringIO/01.SpringBoot之异步请求.md) +- [SpringBoot 之 Json](source/_posts/01.Java/13.框架/01.Spring/04.SpringIO/02.SpringBoot之Json.md) +- [SpringBoot 之邮件](source/_posts/01.Java/13.框架/01.Spring/04.SpringIO/03.SpringBoot之邮件.md) + +##### 集成 + +- [Spring 集成缓存中间件](source/_posts/01.Java/13.框架/01.Spring/05.Spring集成/01.Spring集成缓存.md) +- [Spring 集成定时任务中间件](source/_posts/01.Java/13.框架/01.Spring/05.Spring集成/02.Spring集成调度器.md) +- [Spring 集成 Dubbo](source/_posts/01.Java/13.框架/01.Spring/05.Spring集成/03.Spring集成Dubbo.md) + +##### 其他 + +- [Spring4 升级](source/_posts/01.Java/13.框架/01.Spring/99.Spring其他/01.Spring4升级.md) +- [SpringBoot 之 banner](source/_posts/01.Java/13.框架/01.Spring/99.Spring其他/21.SpringBoot之banner.md) +- [SpringBoot 之 Actuator](source/_posts/01.Java/13.框架/01.Spring/99.Spring其他/22.SpringBoot之Actuator.md) + +#### ORM + +- [MyBatis 快速入门](source/_posts/01.Java/13.框架/11.ORM/MyBatis快速入门.md) +- [MyBatis 原理](source/_posts/01.Java/13.框架/11.ORM/MyBatis原理.md) +- [MyBatis 原理](source/_posts/01.Java/13.框架/11.ORM/MyBatis面试.md) + +#### 安全 + +> Java 领域比较流行的安全框架就是 shiro 和 spring-security。 +> +> shiro 更为简单、轻便,容易理解,能满足大多数基本安全场景下的需要。 +> +> spring-security 功能更丰富,也比 shiro 更复杂。值得一提的是由于 spring-security 是 spring 团队开发,所以集成 spring 和 spring-boot 框架更容易。 + +- [Shiro](source/_posts/01.Java/13.框架/12.安全/Shiro.md) +- [SpringSecurity](source/_posts/01.Java/13.框架/12.安全/SpringSecurity.md) + +#### IO + +- [Netty](source/_posts/01.Java/13.框架/13.IO/Netty.md) + +### Java 中间件 + +#### 缓存 + +> 缓存可以说是优化系统性能的第一手段,在各种技术中都会有缓存的应用。 +> +> 如果想深入学习缓存,建议先了解一下 [缓存基本原理](https://dunwu.github.io/design/distributed/分布式缓存.html),有助于理解缓存的特性、原理,使用缓存常见的问题及解决方案。 + +- [Java 缓存中间件](source/_posts/01.Java/14.中间件/02.缓存/02.Java缓存中间件.md) +- [Ehcache 快速入门](source/_posts/01.Java/14.中间件/02.缓存/04.Ehcache.md) +- [Java 进程内缓存](source/_posts/01.Java/14.中间件/02.缓存/05.Java进程内缓存.md) +- [Http 缓存](source/_posts/01.Java/14.中间件/02.缓存/06.Http缓存.md) + +#### 流量控制 + +- [Hystrix](source/_posts/01.Java/14.中间件/03.流量控制/01.Hystrix.md) + +## 数据结构和算法 + +- [数据结构和算法指南](source/_posts/11.算法/数据结构和算法指南.md) +- [复杂度分析](source/_posts/11.算法/复杂度分析.md) - 关键词:**`时间复杂度`**、**`空间复杂度`**、**`大 O 表示法`**、**`复杂度量级`** +- [数组和链表](source/_posts/11.算法/数组和链表.md) - 关键词:**`线性表`**、**`一维数组`**、**`多维数组`**、**`随机访问`**、**`单链表`**、**`双链表`**、**`循环链表`** +- [栈和队列](source/_posts/11.算法/栈和队列.md) - 关键词:**`先进后出`**、**`后进先出`**、**`循环队列`** +- [线性表的查找](source/_posts/11.算法/线性表的查找.md) +- [线性表的排序](source/_posts/11.算法/线性表的排序.md) +- [树和二叉树](source/_posts/11.算法/树和二叉树.md) +- [堆](source/_posts/11.算法/堆.md) +- [B+树](source/_posts/11.算法/B+树.md) +- [LSM 树](source/_posts/11.算法/LSM树.md) +- [字典树](source/_posts/11.算法/字典树.md) +- [红黑树](source/_posts/11.算法/红黑树.md) +- [哈希表](source/_posts/11.算法/哈希表.md) - 关键词:**`哈希函数`**、**`装载因子`**、**`哈希冲突`**、**`开放寻址法`**、**`拉链法`** +- [跳表](source/_posts/11.算法/跳表.md) - 关键词:**`多级索引`** +- [图](source/_posts/11.算法/图.md) ## 数据库 -- [关系型数据库](database/sql) -- [非关系型数据库](database/nosql) +### 数据库综合 + +- [Nosql 技术选型](source/_posts/12.数据库/01.数据库综合/Nosql技术选型.md) +- [数据结构与数据库索引](source/_posts/12.数据库/01.数据库综合/数据结构与数据库索引.md) + +### 数据库中间件 + +- [ShardingSphere](source/_posts/12.数据库/02.数据库中间件/ShardingSphere.md) +- [Flyway](source/_posts/12.数据库/02.数据库中间件/Flyway.md) + +### 关系型数据库 + +> [关系型数据库](source/_posts/12.数据库/03.关系型数据库) 整理主流关系型数据库知识点。 + +- [关系数据库简介](source/_posts/12.数据库/03.关系型数据库/关系数据库简介.md) +- [SQL](source/_posts/12.数据库/03.关系型数据库/SQL.md) +- [PostgreSQL](source/_posts/12.数据库/03.关系型数据库/PostgreSQL.md) +- [H2](source/_posts/12.数据库/03.关系型数据库/H2.md) +- [SqLite](source/_posts/12.数据库/03.关系型数据库/SqLite.md) + +#### [MySQL](source/_posts/12.数据库/03.关系型数据库/mysql) + +- [MySQL 架构](source/_posts/12.数据库/03.关系型数据库/mysql/MySQL_架构.md) +- [MySQL 存储引擎](source/_posts/12.数据库/03.关系型数据库/mysql/MySQL_存储引擎.md) +- [MySQL 索引](source/_posts/12.数据库/03.关系型数据库/mysql/MySQL_索引.md) +- [MySQL 事务](source/_posts/12.数据库/03.关系型数据库/mysql/MySQL_事务.md) +- [MySQL 锁](source/_posts/12.数据库/03.关系型数据库/mysql/MySQL_锁.md) +- [MySQL 复制](source/_posts/12.数据库/03.关系型数据库/mysql/MySQL_复制.md) +- [MySQL 优化](source/_posts/12.数据库/03.关系型数据库/mysql/MySQL_优化.md) +- [MySQL 运维](source/_posts/12.数据库/03.关系型数据库/mysql/MySQL_运维.md) +- [MySQL 面试](source/_posts/12.数据库/03.关系型数据库/mysql/MySQL_面试.md) 💯 +- [MySQL 面试之索引篇](source/_posts/12.数据库/03.关系型数据库/mysql/MySQL_面试_索引.md) 💯 +- [MySQL 面试之事务和锁篇](source/_posts/12.数据库/03.关系型数据库/mysql/MySQL_面试_事务和锁.md) 💯 + +### 文档数据库 + +#### MongoDB + +> MongoDB 是一个基于文档的分布式数据库,由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。 +> +> MongoDB 是一个介于关系型数据库和非关系型数据库之间的产品。它是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似 json 的 bson 格式,因此可以存储比较复杂的数据类型。 +> +> MongoDB 最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。 + +- [MongoDB 简介](source/_posts/12.数据库/04.文档数据库/mongodb/MongoDB_简介.md) +- [MongoDB CRUD](source/_posts/12.数据库/04.文档数据库/mongodb/MongoDB_CRUD.md) +- [MongoDB 聚合](source/_posts/12.数据库/04.文档数据库/mongodb/MongoDB_聚合.md) +- [MongoDB 索引](source/_posts/12.数据库/04.文档数据库/mongodb/MongoDB_索引.md) +- [MongoDB 事务](source/_posts/12.数据库/04.文档数据库/mongodb/MongoDB_事务.md) +- [MongoDB 建模](source/_posts/12.数据库/04.文档数据库/mongodb/MongoDB_建模.md) +- [MongoDB 复制](source/_posts/12.数据库/04.文档数据库/mongodb/MongoDB_复制.md) +- [MongoDB 分片](source/_posts/12.数据库/04.文档数据库/mongodb/MongoDB_分片.md) +- [MongoDB 运维](source/_posts/12.数据库/04.文档数据库/mongodb/MongoDB_运维.md) +- [MongoDB 面试](source/_posts/12.数据库/04.文档数据库/mongodb/MongoDB_面试.md) 💯 + +### KV 数据库 + +#### [Redis](source/_posts/12.数据库/05.KV数据库/redis) + +- [Redis 基本数据类型](source/_posts/12.数据库/05.KV数据库/redis/Redis_数据类型.md) - 关键词:`String`、`Hash`、`List`、`Set`、`Zset` +- [Redis 高级数据类型](source/_posts/12.数据库/05.KV数据库/redis/Redis_数据类型二.md) - 关键词:`BitMap`、`HyperLogLog`、`Geo`、`Stream` +- [Redis 数据结构](source/_posts/12.数据库/05.KV数据库/redis/Redis_数据结构.md) - 关键词:`对象`、`SDS`、`链表`、`字典`、`跳表`、`整数集合`、`压缩列表` +- [Redis 内存管理](source/_posts/12.数据库/05.KV数据库/redis/Redis_内存管理.md) - 关键词:`定时删除`、`惰性删除`、`定期删除`、`LRU`、`LFU` +- [Redis 持久化](source/_posts/12.数据库/05.KV数据库/redis/Redis_持久化.md) - 关键词:`RDB`、`AOF`、`SAVE`、`BGSAVE`、`appendfsync` +- [Redis 事件](source/_posts/12.数据库/05.KV数据库/redis/Redis_事件.md) - 关键词:`文件事件`、`时间事件` +- [Redis 复制](source/_posts/12.数据库/05.KV数据库/redis/Redis_复制.md) - 关键词:`SLAVEOF`、`SYNC`、`PSYNC`、`命令传播`、`心跳` +- [Redis 哨兵](source/_posts/12.数据库/05.KV数据库/redis/Redis_哨兵.md) - 关键词:`高可用`、`监控`、`选主`、`故障转移`、`Raft` +- [Redis 集群](source/_posts/12.数据库/05.KV数据库/redis/Redis_集群.md) - 关键词:`高可用`、`监控`、`选主`、`故障转移`、`分区`、`Raft`、`Gossip` +- [Redis 订阅](source/_posts/12.数据库/05.KV数据库/redis/Redis_订阅.md) - 关键词:`订阅`、`SUBSCRIBE`、`PSUBSCRIBE`、`PUBLISH`、`观察者模式` +- [Redis 独立功能](source/_posts/12.数据库/05.KV数据库/redis/Redis_事务.md) - 关键词:`事务`、`ACID`、`MULTI`、`EXEC`、`DISCARD`、`WATCH` +- [Redis 管道](source/_posts/12.数据库/05.KV数据库/redis/Redis_管道.md) - 关键词:`Pipeline` +- [Redis 脚本](source/_posts/12.数据库/05.KV数据库/redis/Redis_脚本.md) - 关键词:`Lua` +- [Redis 运维](source/_posts/12.数据库/05.KV数据库/redis/Redis_运维.md) - 关键词:`安装`、`配置`、`命令`、`集群`、`客户端` +- [Redis 实战](source/_posts/12.数据库/05.KV数据库/redis/Redis_实战.md) - 关键词:`缓存`、`分布式锁`、`布隆过滤器` +- [Redis 面试](source/_posts/12.数据库/05.KV数据库/redis/Redis_面试.md) - 关键词:`面试` +- [Redis 面试之数据类型篇](source/_posts/12.数据库/05.KV数据库/redis/Redis_面试_数据类型.md) - 关键词:`面试` +- [Redis 面试之应用篇](source/_posts/12.数据库/05.KV数据库/redis/Redis_面试_应用.md) - 关键词:`面试` + +#### [Memcached](source/_posts/12.数据库/05.KV数据库/Memcached.md) + +### 列式数据库 + +#### HBase + +- [HBase 快速入门](source/_posts/12.数据库/06.列式数据库/hbase/HBase_快速入门.md) +- [HBase 数据模型](source/_posts/12.数据库/06.列式数据库/hbase/HBase_数据模型.md) +- [HBase Schema 设计](source/_posts/12.数据库/06.列式数据库/hbase/HBase_Schema.md) +- [HBase 架构](source/_posts/12.数据库/06.列式数据库/hbase/HBase_架构.md) +- [HBase Java API 基础特性](source/_posts/12.数据库/06.列式数据库/hbase/HBase_API_基础特性.md) +- [HBase Java API 高级特性](source/_posts/12.数据库/06.列式数据库/hbase/HBase_API_高级特性.md) +- [HBase Java API 高级特性之过滤器](source/_posts/12.数据库/06.列式数据库/hbase/HBase_API_高级特性_过滤器.md) +- [HBase Java API 高级特性之协处理器](source/_posts/12.数据库/06.列式数据库/hbase/HBase_API_高级特性_协处理器.md) +- [HBase 运维](source/_posts/12.数据库/06.列式数据库/hbase/HBase_运维.md) +- [HBase 命令](source/_posts/12.数据库/06.列式数据库/hbase/HBase_命令.md) +- [HBase 面试](source/_posts/12.数据库/06.列式数据库/hbase/HBase_面试.md) 💯 + +### 搜索引擎数据库 + +#### Elasticsearch + +> Elasticsearch 是一个基于 Lucene 的搜索和数据分析工具,它提供了一个分布式服务。Elasticsearch 是遵从 Apache 开源条款的一款开源产品,是当前主流的企业级搜索引擎。 + +- [Elasticsearch 简介](source/_posts/12.数据库/07.搜索引擎数据库/elasticsearch/Elasticsearch_简介.md) +- [Elasticsearch 存储](source/_posts/12.数据库/07.搜索引擎数据库/elasticsearch/Elasticsearch_存储.md) +- [Elasticsearch 搜索(上)](source/_posts/12.数据库/07.搜索引擎数据库/elasticsearch/Elasticsearch_搜索上.md) +- [Elasticsearch 搜索(下)](source/_posts/12.数据库/07.搜索引擎数据库/elasticsearch/Elasticsearch_搜索下.md) +- [Elasticsearch 聚合](source/_posts/12.数据库/07.搜索引擎数据库/elasticsearch/Elasticsearch_聚合.md) +- [Elasticsearch 分析](source/_posts/12.数据库/07.搜索引擎数据库/elasticsearch/Elasticsearch_分析.md) +- [Elasticsearch 集群](source/_posts/12.数据库/07.搜索引擎数据库/elasticsearch/Elasticsearch_集群.md) +- [Elasticsearch 优化](source/_posts/12.数据库/07.搜索引擎数据库/elasticsearch/Elasticsearch_优化.md) +- [Elasticsearch 运维](source/_posts/12.数据库/07.搜索引擎数据库/elasticsearch/Elasticsearch_运维.md) +- [Elasticsearch API](source/_posts/12.数据库/07.搜索引擎数据库/elasticsearch/Elasticsearch_API.md) +- [ElasticSearch API 之 High Level REST Client](source/_posts/12.数据库/07.搜索引擎数据库/elasticsearch/Elasticsearch_API_HighLevelRest.md) +- [Elasticsearch 面试](source/_posts/12.数据库/07.搜索引擎数据库/elasticsearch/Elasticsearch_面试.md) 💯 + +#### Elastic + +- [Elastic](source/_posts/12.数据库/07.搜索引擎数据库/elastic/Elastic.md) +- [Kibana](source/_posts/12.数据库/07.搜索引擎数据库/elastic/Kibana.md) +- [Logstash](source/_posts/12.数据库/07.搜索引擎数据库/elastic/Logstash.md) +- [Filebeat](source/_posts/12.数据库/07.搜索引擎数据库/elastic/Filebeat.md) ## 网络 -(:construction: 待整理补充) +> 如果你是做通信领域的开发,或者是 Web 应用的开发,那就或多或少需要了解一些计算机网络的知识 。 + +### 网络综合 + +> 理解计算机网络,首先需要从宏观层面了解计算机网络通信的分层结构。最有代表性的是 OSI 七层结构模型,但现实中更流行的是五层结构模型。 +> +> 了解网络分层结构,需要了解每个网络层级在网络通信中的定位,以及这个层级主要的通信设备、通信协议。 + +- [计算机网络面试总结](source/_posts/13.网络/01.网络综合/01.计算机网络面试.md) +- [计算机网络指南](source/_posts/13.网络/01.网络综合/02.计算机网络指南.md) - 关键词:核心概念、拓扑结构、作用范围、性能指标、体系结构 +- **网络分层** + - [计算机网络之物理层](source/_posts/13.网络/01.网络综合/11.物理层.md) - 关键词:调制、解调、数字信号、模拟信号、通信媒介、信道复用 + - [计算机网络之数据链路层](source/_posts/13.网络/01.网络综合/12.数据链路层.md) - 关键词:点对点信道、广播信道、`PPP`、`CSMA/CD`、局域网、以太网、`MAC`、适配器、集线器、网桥、交换机 + - [计算机网络之网络层](source/_posts/13.网络/01.网络综合/13.网络层.md) - 关键词:`IP`、`ICMP`、`ARP`、路由 + - [计算机网络之传输层](source/_posts/13.网络/01.网络综合/14.传输层.md) - 关键词:`UDP`、`TCP`、滑动窗口、拥塞控制、三次握手 + - [计算机网络之应用层](source/_posts/13.网络/01.网络综合/15.应用层.md) - 关键词:`HTTP`、`DNS`、`FTP`、`TELNET`、`DHCP` + +### 网络协议 + +- [超文本传输协议 HTTP](source/_posts/13.网络/02.网络协议/01.HTTP.md) +- [域名系统协议 DNS](source/_posts/13.网络/02.网络协议/02.DNS) +- [传输控制协议 TCP](source/_posts/13.网络/02.网络协议/03.TCP.md) +- [用户数据报协议 UDP](source/_posts/13.网络/02.网络协议/04.UDP.md) +- [ICMP](source/_posts/13.网络/02.网络协议/05.ICMP.md) + +### 网络技术 + +- [WebSocket](source/_posts/13.网络/03.网络技术/01.WebSocket.md) +- [CDN](source/_posts/13.网络/03.网络技术/02.CDN.md) +- [VPN](source/_posts/13.网络/03.网络技术/03.VPN.md) + +## 分布式 + +### [分布式综合](source/_posts/15.分布式/00.分布式综合) + +- [逻辑时钟](source/_posts/15.分布式/00.分布式综合/逻辑时钟.md) - 关键词:`逻辑时钟`、`向量时钟`、`版本时钟`、`全序`、`偏序` +- [CAP 和 BASE](source/_posts/15.分布式/00.分布式综合/CAP&BASE.md) - 关键词:`ACID`、`CAP`、`BASE`、`一致性` +- [拜占庭将军问题](source/_posts/15.分布式/00.分布式综合/拜占庭将军问题.md) - 关键词:`共识` +- [分布式算法 Paxos](source/_posts/15.分布式/00.分布式综合/Paxos.md) - 关键词:`共识`、`Paxos` +- [分布式算法 Raft](source/_posts/15.分布式/00.分布式综合/Raft.md) - 关键词:`共识`、`Raft` +- [分布式算法 Gossip](source/_posts/15.分布式/00.分布式综合/Gossip.md) - 关键词:`Gossip` +- [ZAB 协议](source/_posts/15.分布式/00.分布式综合/Zab.md) - 关键词:`共识`、`ZAB`、`ZooKeeper` +- [分布式综合面试](source/_posts/15.分布式/00.分布式综合/分布式综合面试.md) + +### [分布式协同](source/_posts/15.分布式/11.分布式协同) + +- **分布式协同综合** + - [分布式复制](source/_posts/15.分布式/11.分布式协同/01.分布式协同综合/分布式复制.md) - 关键词:`主从`、`多主`、`无主` + - [分布式分区](source/_posts/15.分布式/11.分布式协同/01.分布式协同综合/分布式分区.md) - 关键词:`分区再均衡`、`路由` + - [分布式共识](source/_posts/15.分布式/11.分布式协同/01.分布式协同综合/分布式共识.md) - 关键词:`共识`、`广播`、`epoch`、`quorum` + - [分布式事务](source/_posts/15.分布式/11.分布式协同/01.分布式协同综合/分布式事务.md) - 关键词:`2PC`、`3PC`、`TCC`、`本地消息表`、`消息事务`、`SAGA` + - [分布式锁](source/_posts/15.分布式/11.分布式协同/01.分布式协同综合/分布式锁.md) - 关键词:`互斥`、`可重入`、`死锁`、`容错`、`自旋尝试`、`公平性` + - [分布式 ID](source/_posts/15.分布式/11.分布式协同/01.分布式协同综合/分布式ID.md) - 关键词:`UUID`、`自增序列`、`雪花算法`、`Leaf` +- **ZooKeeper** + - [ZooKeeper 原理](source/_posts/15.分布式/11.分布式协同/02.ZooKeeper/ZooKeeper原理.md) + - [ZooKeeper Java Api](source/_posts/15.分布式/11.分布式协同/02.ZooKeeper/ZooKeeperJavaApi.md) + - [ZooKeeper 命令](source/_posts/15.分布式/11.分布式协同/02.ZooKeeper/ZooKeeper命令.md) + - [ZooKeeper 运维](source/_posts/15.分布式/11.分布式协同/02.ZooKeeper/ZooKeeper运维.md) + - [ZooKeeper Acl](source/_posts/15.分布式/11.分布式协同/02.ZooKeeper/ZooKeeperAcl.md) + +### [分布式调度](source/_posts/15.分布式/12.分布式调度) + +- [服务注册和发现](source/_posts/15.分布式/12.分布式调度/服务注册和发现.md) - 关键词:`服务注册`、`服务发现`、`元数据` +- [负载均衡](source/_posts/15.分布式/12.分布式调度/负载均衡.md) - 关键词:`轮询`、`随机`、`最少连接`、`源地址哈希`、`一致性哈希`、`虚拟 hash 槽` +- [流量控制](source/_posts/15.分布式/12.分布式调度/流量控制.md) - 关键词:`限流`、`熔断`、`降级`、`计数器法`、`时间窗口法`、`令牌桶法`、`漏桶法` +- [路由和网关](source/_posts/15.分布式/12.分布式调度/网关路由.md) - 关键词:`路由`、`条件路由`、`脚本路由`、`标签路由` + +### 分布式高可用 + +- [服务容错](source/_posts/15.分布式/11.分布式协同/01.分布式协同综合/服务容错.md) + +### [分布式通信](source/_posts/15.分布式/21.分布式通信) + +#### [RPC](source/_posts/15.分布式/21.分布式通信/01.RPC) + +- [Dubbo 面试之服务治理](source/_posts/15.分布式/21.分布式通信/01.RPC/Dubbo_面试_服务治理.md) +- [Dubbo 面试之架构](source/_posts/15.分布式/21.分布式通信/01.RPC/Dubbo_面试_架构.md) +- [Dubbo 面试之应用](source/_posts/15.分布式/21.分布式通信/01.RPC/Dubbo_面试_应用.md) +- [RPC 面试](source/_posts/15.分布式/21.分布式通信/01.RPC/RPC面试.md) + +#### [MQ](source/_posts/15.分布式/21.分布式通信/02.MQ) + +##### [MQ 综合](source/_posts/15.分布式/21.分布式通信/02.MQ/00.MQ综合) + +- [MQ 面试](source/_posts/15.分布式/21.分布式通信/02.MQ/00.MQ综合/MQ面试.md) -## 操作系统 +##### [Kafka](source/_posts/15.分布式/21.分布式通信/02.MQ/01.Kafka) -- [linux](os/linux) -- [windows](os/windows) -- [docker](os/docker) +- [Kafka 快速入门](source/_posts/15.分布式/21.分布式通信/02.MQ/01.Kafka/Kafka快速入门.md) +- [Kafka 生产](source/_posts/15.分布式/21.分布式通信/02.MQ/01.Kafka/Kafka生产.md) +- [Kafka 消费](source/_posts/15.分布式/21.分布式通信/02.MQ/01.Kafka/Kafka消费.md) +- [Kafka 集群](source/_posts/15.分布式/21.分布式通信/02.MQ/01.Kafka/Kafka集群.md) +- [Kafka 可靠传输](source/_posts/15.分布式/21.分布式通信/02.MQ/01.Kafka/Kafka可靠传输.md) +- [Kafka 存储](source/_posts/15.分布式/21.分布式通信/02.MQ/01.Kafka/Kafka存储.md) +- [Kafka 流式处理](source/_posts/15.分布式/21.分布式通信/02.MQ/01.Kafka/Kafka流式处理.md) +- [Kafka 运维](source/_posts/15.分布式/21.分布式通信/02.MQ/01.Kafka/Kafka运维.md) -## Web +##### [RocketMQ](source/_posts/15.分布式/21.分布式通信/02.MQ/02.RocketMQ) -- [nginx](web/nginx) +- [RocketMQ 快速入门](source/_posts/15.分布式/21.分布式通信/02.MQ/02.RocketMQ/RocketMQ快速入门.md) +- [RocketMQ 基本原理](source/_posts/15.分布式/21.分布式通信/02.MQ/02.RocketMQ/RocketMQ基本原理.md) +- [RocketMQ Faq](source/_posts/15.分布式/21.分布式通信/02.MQ/02.RocketMQ/RocketMQFaq.md) -## 前端 +##### 其他 MQ -(:construction: 待整理补充) +- [ActiveMQ](source/_posts/15.分布式/21.分布式通信/02.MQ/99.其他MQ/ActiveMQ.md) -## 大数据 +### [分布式存储](source/_posts/15.分布式/22.分布式存储) -(:construction: 待整理补充) +- [分布式缓存](source/_posts/15.分布式/22.分布式存储/分布式缓存.md) - 关键词:`进程内缓存`、`分布式缓存`、`缓存雪崩`、`缓存穿透`、`缓存击穿`、`缓存更新`、`缓存预热`、`缓存降级` +- [读写分离](source/_posts/15.分布式/22.分布式存储/读写分离.md) +- [分库分表](source/_posts/15.分布式/22.分布式存储/分库分表.md) - 关键词:`分片`、`路由`、`迁移`、`扩容`、`双写`、`聚合` + +## 编程 + +### 编程范式 + +- [如何学习编程语言](source/_posts/02.编程/01.编程范式/01.如何学习编程语言.md) + +### 编程语言 + +- [python](source/_posts/02.编程/02.编程语言/01.python.md) +- [shell](source/_posts/02.编程/02.编程语言/02.shell.md) +- [scala](source/_posts/02.编程/02.编程语言/03.scala.md) ## 设计 -- [UML](design/uml) -- [设计模式](design/design-patterns) -- [重构](design/refactor) +### 架构 + +#### 综合 + +- [如何设计系统](source/_posts/03.设计/01.架构/00.综合/00.如何设计系统.md) +- [系统架构面试总结](source/_posts/03.设计/01.架构/00.综合/01.系统架构面试.md) +- [系统架构概述](source/_posts/03.设计/01.架构/00.综合/02.系统架构概述.md) +- [系统高性能架构](source/_posts/03.设计/01.架构/00.综合/03.系统高性能架构.md) +- [系统高可用架构](source/_posts/03.设计/01.架构/00.综合/04.系统高可用架构.md) +- [系统伸缩性架构](source/_posts/03.设计/01.架构/00.综合/05.系统伸缩性架构.md) +- [系统扩展性架构](source/_posts/03.设计/01.架构/00.综合/06.系统扩展性架构.md) +- [系统安全性架构](source/_posts/03.设计/01.架构/00.综合/07.系统安全性架构.md) +- [大型系统核心技术](source/_posts/03.设计/01.架构/00.综合/08.大型系统核心技术.md) +- [系统测试架构](source/_posts/03.设计/01.架构/00.综合/09.系统测试架构.md) + +#### 微服务 + +- [微服务简介](source/_posts/03.设计/01.架构/01.微服务/01.微服务简介.md) - 关键词:`定义`、`演进`、`利弊`、`如何拆分`、`容量规划`、`核心组件` +- [微服务之注册和发现](source/_posts/03.设计/01.架构/01.微服务/02.微服务之注册和发现.md) - 关键词:`服务定义`、`注册中心`、`元数据`、`健康检查`、`服务订阅`、`一致性` +- [微服务之服务调用](source/_posts/03.设计/01.架构/01.微服务/03.微服务之服务调用.md) - 关键词:`RPC`、`通信协议`、`传输方式`、`序列化` +- [微服务基本原理](source/_posts/03.设计/01.架构/01.微服务/10.微服务基本原理.md) - 关键词:`微服务`、`序列化`、`动态代理`、`通信`、`服务注册发现`、`健康检查`、`路由`、`负载均衡`、`容错处理`、`优雅上线下线`、`限流`、`熔断`、`业务分组` + +#### 安全 + +- [权限认证综述](source/_posts/03.设计/01.架构/02.安全/01.综述.md) +- [认证设计](source/_posts/03.设计/01.架构/02.安全/02.认证.md) +- [授权设计](source/_posts/03.设计/01.架构/02.安全/03.授权.md) +- [安全漏洞](source/_posts/03.设计/01.架构/02.安全/05.安全漏洞.md) +- [编码和加密](source/_posts/03.设计/01.架构/02.安全/06.编码和加密.md) + +### 设计模式 + +[面向对象原则](source/_posts/03.设计/02.设计模式/25.面向对象原则.md) + +#### 创建型模式 + +> 创建型模式提供了创建对象的机制, 能够提升已有代码的灵活性和可复用性。 + +- [简单工厂模式 (Simple Factory)](source/_posts/03.设计/02.设计模式/01.简单工厂模式.md) +- [工厂方法模式 (Factory Method)](source/_posts/03.设计/02.设计模式/02.工厂方法模式.md) +- [抽象工厂模式 (Abstract Factory)](source/_posts/03.设计/02.设计模式/03.抽象工厂模式.md) +- [建造者模式 (Builder)](source/_posts/03.设计/02.设计模式/04.建造者模式.md) +- [原型模式 (Prototype)](source/_posts/03.设计/02.设计模式/05.原型模式.md) +- [单例模式 (Singleton)](source/_posts/03.设计/02.设计模式/06.单例模式.md) + +#### 结构型模式 + +> 结构型模式介绍如何将对象和类组装成较大的结构, 并同时保持结构的灵活和高效。 + +- [适配器模式 (Adapter)](source/_posts/03.设计/02.设计模式/07.适配器模式.md) +- [桥接模式 (Bridge)](source/_posts/03.设计/02.设计模式/08.桥接模式.md) +- [组合模式 (Composite)](source/_posts/03.设计/02.设计模式/09.组合模式.md) +- [装饰模式 (Decorator)](source/_posts/03.设计/02.设计模式/10.装饰模式.md) +- [外观模式 (Facade)](source/_posts/03.设计/02.设计模式/11.外观模式.md) +- [享元模式 (Flyweight)](source/_posts/03.设计/02.设计模式/12.享元模式.md) +- [代理模式 (Proxy)](source/_posts/03.设计/02.设计模式/13.代理模式.md) + +#### 行为型模式 + +> 行为模式负责对象间的高效沟通和职责委派。 + +- [模板方法模式 (Template Method)](source/_posts/03.设计/02.设计模式/14.模板方法模式.md) +- [命令模式 (Command)](source/_posts/03.设计/02.设计模式/15.命令模式.md) +- [迭代器模式 (Iterator)](source/_posts/03.设计/02.设计模式/16.迭代器模式.md) +- [观察者模式 (Observer)](source/_posts/03.设计/02.设计模式/17.观察者模式.md) +- [解释器模式 (Interpreter)](source/_posts/03.设计/02.设计模式/18.解释器模式.md) +- [中介者模式 (Mediator)](source/_posts/03.设计/02.设计模式/19.中介者模式.md) +- [职责链模式 (Chain of Responsibility)](source/_posts/03.设计/02.设计模式/20.职责链模式.md) +- [备忘录模式 (Memento)](source/_posts/03.设计/02.设计模式/21.备忘录模式.md) +- [策略模式 (Strategy)](source/_posts/03.设计/02.设计模式/22.策略模式.md) +- [访问者模式 (Visitor)](source/_posts/03.设计/02.设计模式/23.访问者模式.md) +- [状态模式 (State)](source/_posts/03.设计/02.设计模式/24.状态模式.md) + +### 重构 + +- [代码的坏味道和重构](source/_posts/03.设计/03.重构/01.代码的坏味道和重构.md) +- [代码坏味道之代码臃肿](source/_posts/03.设计/03.重构/02.代码坏味道之代码臃肿.md) +- [代码坏味道之滥用面向对象](source/_posts/03.设计/03.重构/03.代码坏味道之滥用面向对象.md) +- [代码坏味道之变革的障碍](source/_posts/03.设计/03.重构/04.代码坏味道之变革的障碍.md) +- [代码坏味道之非必要的](source/_posts/03.设计/03.重构/05.代码坏味道之非必要的.md) +- [代码坏味道之耦合](source/_posts/03.设计/03.重构/06.代码坏味道之耦合.md) + +### UML + +- [UML 快速入门](source/_posts/03.设计/05.UML/01.UML快速入门.md) +- [UML 结构建模图](source/_posts/03.设计/05.UML/02.UML结构建模图.md) +- [UML 行为建模图](source/_posts/03.设计/05.UML/03.UML行为建模图.md) + +## DevOps + +### CI + +### CD + +### 监控 + +- [监控体系](source/_posts/04.DevOps/03.监控/01.监控体系.md) +- [链路监控](source/_posts/04.DevOps/03.监控/02.链路追踪.md) + +### 工具 + +- Git + - [如何优雅的玩转 Git](source/_posts/04.DevOps/99.工具/01.Git/01.如何优雅的玩转Git.md) + - [Git 帮助手册](source/_posts/04.DevOps/99.工具/01.Git/02.Git帮助手册.md) +- 其他 + - [正则表达式极简教程](source/_posts/04.DevOps/99.工具/99.其他/01.正则表达式.md) + +## 工作 + +### 方法论 + +- [效率提升方法论](source/_posts/96.工作/01.效能/01.方法论/01.效率提升方法论.md) +- [话术](source/_posts/96.工作/01.效能/01.方法论/03.话术.md) + +### 规范 + +- [技术文档规范](source/_posts/96.工作/01.效能/02.规范/01.技术文档规范.md) +- [目录管理规范](source/_posts/96.工作/01.效能/02.规范/02.目录管理规范.md) +- [代码工程规范](source/_posts/96.工作/01.效能/02.规范/03.代码工程规范.md) + +### 工具 + +- [Markdown 极简教程](source/_posts/96.工作/01.效能/99.工具/01.Markdown.md) -## 软件工程 +## 🚪 传送 -(:construction: 待整理补充) +◾ 💧 [钝悟的 IT 知识图谱](https://dunwu.github.io/waterdrop/) ◾ 🎯 [钝悟的博客](https://dunwu.github.io/blog/) ◾ diff --git a/_config.next.yml b/_config.next.yml new file mode 100644 index 0000000000..59ba48fe7c --- /dev/null +++ b/_config.next.yml @@ -0,0 +1,898 @@ +# =============================================================== +# It's recommended to use Alternate Theme Config to configure NexT +# Modifying this file may result in merge conflict +# See: https://theme-next.js.org/docs/getting-started/configuration +# =============================================================== + +# --------------------------------------------------------------- +# Theme Core Configuration Settings +# See: https://theme-next.js.org/docs/theme-settings/ +# --------------------------------------------------------------- + +# Allow to cache content generation. +cache: + enable: true + +# Remove unnecessary files after hexo generate. +minify: true + +# Define custom file paths. +# Create your custom files in site directory `source/_data` and uncomment needed files below. +custom_file_path: + #head: source/_data/head.njk + #header: source/_data/header.njk + #sidebar: source/_data/sidebar.njk + #postMeta: source/_data/post-meta.njk + #postBodyEnd: source/_data/post-body-end.njk + #footer: source/_data/footer.njk + #bodyEnd: source/_data/body-end.njk + #variable: source/_data/variables.styl + #mixin: source/_data/mixins.styl + #style: source/_data/styles.styl + +# --------------------------------------------------------------- +# Scheme Settings +# --------------------------------------------------------------- + +# Schemes +#scheme: Muse +#scheme: Mist +scheme: Pisces +#scheme: Gemini + +# Dark Mode +darkmode: true +# Darkmode JS +# For more information: https://github.com/rqh656418510/hexo-next-darkmode, https://github.com/sandoche/Darkmode.js +darkmode_js: + enable: true + bottom: '64px' # default: '32px' + right: 'unset' # default: '32px' + left: '32px' # default: 'unset' + time: '0.5s' # default: '0.3s' + mixColor: 'transparent' # default: '#fff' + backgroundColor: 'transparent' # default: '#fff' + buttonColorDark: '#100f2c' # default: '#100f2c' + buttonColorLight: '#fff' # default: '#fff' + isActivated: true # default false + saveInCookies: true # default: true + label: '🌓' # default: '' + autoMatchOsTheme: true # default: true + libUrl: # Set custom library cdn url for Darkmode.js + +# --------------------------------------------------------------- +# Site Information Settings +# --------------------------------------------------------------- + +favicon: + small: /uploads/favicon.ico + medium: /uploads/favicon.ico + apple_touch_icon: /images/apple-touch-icon-next.png + safari_pinned_tab: /images/logo.svg + #android_manifest: /manifest.json + +# Custom Logo (Warning: Do not support scheme Mist) +custom_logo: #/uploads/dunwu-logo.png + +# Creative Commons 4.0 International License. +# See: https://creativecommons.org/about/cclicenses/ +creative_commons: + # Available values: by | by-nc | by-nc-nd | by-nc-sa | by-nd | by-sa | cc-zero + license: by-nc-sa + # Available values: big | small + size: small + sidebar: true + post: true + # You can set a language value if you prefer a translated version of CC license, e.g. deed.zh + # CC licenses are available in 39 languages, you can find the specific and correct abbreviation you need on https://creativecommons.org + language: deed.zh + +# Open graph settings +# See: https://hexo.io/docs/helpers#open-graph +open_graph: + enable: true + options: + #twitter_card: + #twitter_id: + #twitter_site: + #twitter_image: + #google_plus: + #fb_admins: + #fb_app_id: + +# --------------------------------------------------------------- +# Menu Settings +# --------------------------------------------------------------- + +# Usage: `Key: /link/ || icon` +# Key is the name of menu item. If the translation for this item is available, the translated text will be loaded, otherwise the Key name will be used. Key is case-sensitive. +# Value before `||` delimiter is the target link, value after `||` delimiter is the name of Font Awesome icon. +# External url should start with http:// or https:// +menu: + home: / || fa fa-home + about: /about/ || fa fa-user + tags: /tags/ || fa fa-tags + categories: /categories/ || fa fa-th + archives: /archives/ || fa fa-archive + #schedule: /schedule/ || fa fa-calendar + #sitemap: /sitemap.xml || fa fa-sitemap + #commonweal: /404/ || fa fa-heartbeat + +# Enable / Disable menu icons / item badges. +menu_settings: + icons: true + badges: true + +# --------------------------------------------------------------- +# Sidebar Settings +# See: https://theme-next.js.org/docs/theme-settings/sidebar +# --------------------------------------------------------------- + +sidebar: + # Sidebar Position. + position: left + #position: right + + # Manual define the sidebar width. If commented, will be default for: + # Muse | Mist: 320 + # Pisces | Gemini: 240 + #width: 300 + + # Sidebar Display (only for Muse | Mist), available values: + # - post expand on posts automatically. Default. + # - always expand for all pages automatically. + # - hide expand only when click on the sidebar toggle icon. + # - remove totally remove sidebar including sidebar toggle. + display: post + + # Sidebar padding in pixels. + padding: 18 + # Sidebar offset from top menubar in pixels (only for Pisces | Gemini). + offset: 12 + +# Sidebar Avatar +avatar: + # Replace the default image and set the url here. + url: /uploads/avatar.gif + # If true, the avatar will be displayed in circle. + rounded: true + # If true, the avatar will be rotated with the cursor. + rotated: true + +# Posts / Categories / Tags in sidebar. +site_state: true + +# Social Links +# Usage: `Key: permalink || icon` +# Key is the link label showing to end users. +# Value before `||` delimiter is the target permalink, value after `||` delimiter is the name of Font Awesome icon. +social: + GitHub: https://github.com/dunwu || fab fa-github + E-Mail: mailto:forbreak@163.com || fa fa-envelope + #Weibo: https://weibo.com/yourname || fab fa-weibo + #Google: https://plus.google.com/yourname || fab fa-google + #Twitter: https://twitter.com/yourname || fab fa-twitter + #FB Page: https://www.facebook.com/yourname || fab fa-facebook + #StackOverflow: https://stackoverflow.com/yourname || fab fa-stack-overflow + #YouTube: https://youtube.com/yourname || fab fa-youtube + #Instagram: https://instagram.com/yourname || fab fa-instagram + #Skype: skype:yourname?call|chat || fab fa-skype + +social_icons: + enable: true + icons_only: false + transition: false + +# Blog rolls +links_settings: + icon: fa fa-globe + title: Links + # Available values: block | inline + layout: block + +links: + #Title: https://example.com + +# Table of Contents in the Sidebar +# Front-matter variable (nonsupport wrap expand_all). +toc: + enable: true + # Automatically add list number to toc. + number: true + # If true, all words will placed on next lines if header width longer then sidebar width. + wrap: false + # If true, all level of TOC in a post will be displayed, rather than the activated part of it. + expand_all: false + # Maximum heading depth of generated toc. + max_depth: 6 + +# --------------------------------------------------------------- +# Footer Settings +# See: https://theme-next.js.org/docs/theme-settings/footer +# --------------------------------------------------------------- + +# Show multilingual switcher in footer. +language_switcher: false + +footer: + # Specify the year when the site was setup. If not defined, current year will be used. + since: 2015 + + # Icon between year and copyright info. + icon: + # Icon name in Font Awesome. See: https://fontawesome.com/icons + name: fa fa-heart + # If you want to animate the icon, set it to true. + animated: true + # Change the color of icon, using Hex Code. + color: '#A34950' + + # If not defined, `author` from Hexo `_config.yml` will be used. + copyright: + + # Powered by Hexo & NexT + powered: false + + # Beian ICP and gongan information for Chinese users. See: https://beian.miit.gov.cn, http://www.beian.gov.cn + beian: + enable: false + icp: + # The digit in the num of gongan beian. + gongan_id: + # The full num of gongan beian. + gongan_num: + # The icon for gongan beian. See: http://www.beian.gov.cn/portal/download + gongan_icon_url: + +# --------------------------------------------------------------- +# Post Settings +# See: https://theme-next.js.org/docs/theme-settings/posts +# --------------------------------------------------------------- + +# Automatically excerpt description in homepage as preamble text. +excerpt_description: true + +# Read more button +# If true, the read more button will be displayed in excerpt section. +read_more_btn: true + +# Post meta display settings +post_meta: + item_text: true + created_at: true + updated_at: + enable: true + another_day: true + categories: true + +# Post wordcount display settings +# Dependencies: https://github.com/next-theme/hexo-word-counter +symbols_count_time: + separated_meta: true + item_text_total: true + +# Use icon instead of the symbol # to indicate the tag at the bottom of the post +tag_icon: false + +# Donate (Sponsor) settings +# Front-matter variable (nonsupport animation). +reward_settings: + # If true, a donate button will be displayed in every article by default. + enable: false + animation: false + #comment: Buy me a coffee + +reward: + #wechatpay: /images/wechatpay.png + #alipay: /images/alipay.png + #paypal: /images/paypal.png + #bitcoin: /images/bitcoin.png + +# Subscribe through Telegram Channel, Twitter, etc. +# Usage: `Key: permalink || icon` (Font Awesome) +follow_me: + #Twitter: https://twitter.com/username || fab fa-twitter + #Telegram: https://t.me/channel_name || fab fa-telegram + #WeChat: /images/wechat_channel.jpg || fab fa-weixin + #RSS: /atom.xml || fa fa-rss + +# Related popular posts +# Dependencies: https://github.com/sergeyzwezdin/hexo-related-posts +related_posts: + enable: false + title: # Custom header, leave empty to use the default one + display_in_home: false + +# Post edit +# Easily browse and edit blog source code online. +post_edit: + enable: true + url: https://github.com/dunwu/blog/blob/master/source/ # Link for view source + #url: https://github.com/user-name/repo-name/edit/branch-name/subdirectory-name # Link for fork & edit + +# Show previous post and next post in post footer if exists +# Available values: left | right | false +post_navigation: left + +# --------------------------------------------------------------- +# Custom Page Settings +# See: https://theme-next.js.org/docs/theme-settings/custom-pages +# --------------------------------------------------------------- + +# TagCloud settings for tags page. +tagcloud: + min: 12 # Minimum font size in px + max: 30 # Maximum font size in px + amount: 200 # Total amount of tags + orderby: name # Order of tags + order: 1 # Sort order + +# Google Calendar +# Share your recent schedule to others via calendar page. +calendar: + calendar_id: # Your Google account E-Mail + api_key: + orderBy: startTime + showLocation: false + offsetMax: 72 # Time Range + offsetMin: 4 # Time Range + showDeleted: false + singleEvents: true + maxResults: 250 + +# --------------------------------------------------------------- +# Misc Theme Settings +# See: https://theme-next.js.org/docs/theme-settings/miscellaneous +# --------------------------------------------------------------- + +# Preconnect CDN for fonts and plugins. +# For more information: https://www.w3.org/TR/resource-hints/#preconnect +preconnect: false + +# Set the text alignment in posts / pages. +text_align: + # Available values: start | end | left | right | center | justify | justify-all | match-parent + desktop: justify + mobile: justify + +# Reduce padding / margin indents on devices with narrow width. +mobile_layout_economy: false + +# Browser header panel color. +theme_color: + light: '#222' + dark: '#222' + +# Override browsers' default behavior. +body_scrollbar: + # Place the scrollbar over the content. + overlay: false + # Present the scrollbar even if the content is not overflowing. + stable: false + +codeblock: + # Code Highlight theme + # All available themes: https://theme-next.js.org/highlight/ + theme: + light: atom-one-light + dark: atom-one-dark + prism: + light: atom-one-light + dark: atom-one-dark + # Add copy button on codeblock + copy_button: + enable: false + # Available values: default | flat | mac + style: + +back2top: + enable: true + # Back to top in sidebar. + sidebar: true + # Scroll percent label in b2t button. + scrollpercent: true + +# Reading progress bar +reading_progress: + enable: true + # Available values: left | right + start_at: left + # Available values: top | bottom + position: top + reversed: false + color: '#37c6c0' + height: 3px + +# Bookmark Support +bookmark: + enable: false + # Customize the color of the bookmark. + color: '#222' + # If auto, save the reading progress when closing the page or clicking the bookmark-icon. + # If manual, only save it by clicking the bookmark-icon. + save: auto + +# `Follow me on GitHub` banner in the top-right corner. +github_banner: + enable: true + permalink: https://github.com/dunwu/blog + title: Follow me on GitHub + +# --------------------------------------------------------------- +# Font Settings +# --------------------------------------------------------------- +# Find fonts on Google Fonts (https://fonts.google.com) +# All fonts set here will have the following styles: +# light | light italic | normal | normal italic | bold | bold italic +# Be aware that setting too much fonts will cause site running slowly +# --------------------------------------------------------------- +# Web Safe fonts are recommended for `global` (and `title`): +# Arial | Tahoma | Helvetica | Times New Roman | Courier New | Verdana | Georgia | Palatino | Garamond | Comic Sans MS | Trebuchet MS +# --------------------------------------------------------------- + +font: + enable: false + + # Uri of fonts host, e.g. https://fonts.googleapis.com (Default). + host: + + # Font options: + # `external: true` will load this font family from `host` above. + # `family: Times New Roman`. Without any quotes. + # `size: x.x`. Use `em` as unit. Default: 1 (16px) + + # Global font settings used for all elements inside . + global: + external: true + family: Lato + size: + + # Font settings for site title (.site-title). + title: + external: true + family: + size: + + # Font settings for headlines (

to

). + headings: + external: true + family: + size: + + # Font settings for posts (.post-body). + posts: + external: true + family: + + # Font settings for and code blocks. + codes: + external: true + family: + +# --------------------------------------------------------------- +# SEO Settings +# See: https://theme-next.js.org/docs/theme-settings/seo +# --------------------------------------------------------------- + +# If true, site-subtitle will be added to index page. +# Remember to set up your site-subtitle in Hexo `_config.yml` (e.g. subtitle: Subtitle) +index_with_subtitle: false + +# Automatically add external URL with Base64 encrypt & decrypt. +exturl: false +# If true, an icon will be attached to each external URL +exturl_icon: true + +# Google Webmaster tools verification. +# See: https://developers.google.com/search +google_site_verification: + +# Bing Webmaster tools verification. +# See: https://www.bing.com/webmasters +bing_site_verification: + +# Yandex Webmaster tools verification. +# See: https://webmaster.yandex.ru +yandex_site_verification: + +# Baidu Webmaster tools verification. +# See: https://ziyuan.baidu.com/site +baidu_site_verification: + +# --------------------------------------------------------------- +# Third Party Plugins & Services Settings +# See: https://theme-next.js.org/docs/third-party-services/ +# More plugins: https://github.com/next-theme/awesome-next +# You may need to install the corresponding dependency packages +# --------------------------------------------------------------- + +# Math Formulas Render Support +# Warning: Please install / uninstall the relevant renderer according to the documentation. +# See: https://theme-next.js.org/docs/third-party-services/math-equations +# Server-side plugin: https://github.com/next-theme/hexo-filter-mathjax +math: + # Default (false) will load mathjax / katex script on demand. + # That is it only render those page which has `mathjax: true` in front-matter. + # If you set it to true, it will load mathjax / katex script EVERY PAGE. + every_page: false + + mathjax: + enable: false + # Available values: none | ams | all + tags: none + + katex: + enable: false + # See: https://github.com/KaTeX/KaTeX/tree/master/contrib/copy-tex + copy_tex: false + +# Easily enable fast Ajax navigation on your website. +# For more information: https://github.com/next-theme/pjax +pjax: false + +# FancyBox is a tool that offers a nice and elegant way to add zooming functionality for images. +# For more information: https://fancyapps.com/fancybox/ +fancybox: false + +# A JavaScript library for zooming images like Medium. +# Warning: Do not enable both `fancybox` and `mediumzoom`. +# For more information: https://medium-zoom.francoischalifour.com +mediumzoom: false + +# Vanilla JavaScript plugin for lazyloading images. +# For more information: https://apoorv.pro/lozad.js/demo/ +lazyload: false + +# Pangu Support +# For more information: https://github.com/vinta/pangu.js +# Server-side plugin: https://github.com/next-theme/hexo-pangu +pangu: false + +# Quicklink Support +# For more information: https://getquick.link +# Front-matter variable (nonsupport home archive). +quicklink: + enable: false + + # Home page and archive page can be controlled through home and archive options below. + # This configuration item is independent of `enable`. + home: false + archive: false + + # Default (true) will initialize quicklink after the load event fires. + delay: true + # Custom a time in milliseconds by which the browser must execute prefetching. + timeout: 3000 + # Default (true) will attempt to use the fetch() API if supported (rather than link[rel=prefetch]). + priority: true + +# --------------------------------------------------------------- +# Comments Settings +# See: https://theme-next.js.org/docs/third-party-services/comments +# --------------------------------------------------------------- + +# Multiple Comment System Support +comments: + # Available values: tabs | buttons + style: tabs + # Choose a comment system to be displayed by default. + # Available values: disqus | disqusjs | changyan | livere | gitalk | utterances + active: gitalk + # Setting `true` means remembering the comment system selected by the visitor. + storage: true + # Lazyload all comment systems. + lazyload: true + # Modify texts or order for any naves, here are some examples. + nav: + #disqus: + # text: Load Disqus + # order: -1 + #gitalk: + # order: -2 + +# Disqus +# For more information: https://disqus.com +disqus: + enable: false + shortname: blog-ajay4qmfci + count: true + +# DisqusJS +# For more information: https://disqusjs.skk.moe +disqusjs: + enable: false + # API Endpoint of Disqus API (https://disqus.com/api/docs/). + # Leave api empty if you are able to connect to Disqus API. Otherwise you need a reverse proxy for it. + # For example: + # api: https://disqus.skk.moe/disqus/ + api: + apikey: # Register new application from https://disqus.com/api/applications/ + shortname: # See: https://disqus.com/admin/settings/general/ + +# Changyan +# For more information: https://changyan.kuaizhan.com +changyan: + enable: false + appid: + appkey: + +# LiveRe comments system +# You can get your uid from https://livere.com/insight/myCode (General web site) +livere_uid: # + +# Gitalk +# For more information: https://gitalk.github.io +gitalk: + enable: true + github_id: dunwu # GitHub repo owner + repo: blog # Repository name to store issues + client_id: c45bc13ca1d3d3aa4836 # GitHub Application Client ID + client_secret: 1907a9f0c22087badad3938e1d7dcba9078f88ac # GitHub Application Client Secret + admin_user: dunwu # GitHub repo owner and collaborators, only these guys can initialize gitHub issues + distraction_free_mode: true # Facebook-like distraction free mode + # When the official proxy is not available, you can change it to your own proxy address + proxy: https://cors-anywhere.azm.workers.dev/https://github.com/login/oauth/access_token # This is official proxy address + # Gitalk's display language depends on user's browser or system environment + # If you want everyone visiting your site to see a uniform language, you can set a force language value + # Available values: en | es-ES | fr | ru | zh-CN | zh-TW + language: zh-CN + +# Utterances +# For more information: https://utteranc.es +utterances: + enable: false + repo: user-name/repo-name # Github repository owner and name + # Available values: pathname | url | title | og:title + issue_term: pathname + # Available values: github-light | github-dark | preferred-color-scheme | github-dark-orange | icy-dark | dark-blue | photon-dark | boxy-light + theme: github-light + +# Isso +# For more information: https://posativ.org/isso/ +isso: # + +# --------------------------------------------------------------- +# Post Widgets & Content Sharing Services +# See: https://theme-next.js.org/docs/third-party-services/post-widgets +# --------------------------------------------------------------- + +# Star rating support to each article. +# To get your ID visit https://widgetpack.com +rating: + enable: false + id: # + color: '#fc6423' + +# AddThis Share. See: https://www.addthis.com +# Go to https://www.addthis.com/dashboard to customize your tools. +add_this_id: + +# --------------------------------------------------------------- +# Statistics and Analytics +# See: https://theme-next.js.org/docs/third-party-services/statistics-and-analytics +# --------------------------------------------------------------- + +# Google Analytics +# See: https://analytics.google.com +google_analytics: + tracking_id: # + # By default, NexT will load an external gtag.js script on your site. + # If you only need the pageview feature, set the following option to true to get a better performance. + only_pageview: false + +# Baidu Analytics +# See: https://tongji.baidu.com +baidu_analytics: # + +# Growingio Analytics +# See: https://www.growingio.com +growingio_analytics: # + +# Cloudflare Web Analytics +# See: https://www.cloudflare.com/web-analytics/ +cloudflare_analytics: + +# Microsoft Clarity Analytics +# See: https://clarity.microsoft.com/ +clarity_analytics: # + +# Show number of visitors of each article. +# You can visit https://www.leancloud.cn to get AppID and AppKey. +leancloud_visitors: + enable: false + app_id: # + app_key: # + # Required for apps from CN region + server_url: # + # Dependencies: https://github.com/theme-next/hexo-leancloud-counter-security + # If you don't care about security in leancloud counter and just want to use it directly + # (without hexo-leancloud-counter-security plugin), set `security` to `false`. + security: true + +# Another tool to show number of visitors to each article. +# Visit https://console.firebase.google.com/u/0/ to get apiKey and projectId. +# Visit https://firebase.google.com/docs/firestore/ to get more information about firestore. +firestore: + enable: false + collection: articles # Required, a string collection name to access firestore database + apiKey: # Required + projectId: # Required + +# Show Views / Visitors of the website / page with busuanzi. +# For more information: http://ibruce.info/2015/04/04/busuanzi/ +busuanzi_count: + enable: false + total_visitors: true + total_visitors_icon: fa fa-user + total_views: true + total_views_icon: fa fa-eye + post_views: true + post_views_icon: far fa-eye + +# --------------------------------------------------------------- +# Search Services +# See: https://theme-next.js.org/docs/third-party-services/search-services +# --------------------------------------------------------------- + +# Algolia Search +# For more information: https://www.algolia.com +algolia_search: + enable: false + hits: + per_page: 10 + +# Local Search +# Dependencies: https://github.com/next-theme/hexo-generator-searchdb +local_search: + enable: true + # If auto, trigger search by changing input. + # If manual, trigger search by pressing enter key or search button. + trigger: auto + # Show top n results per article, show all results by setting to -1 + top_n_per_article: 1 + # Unescape html strings to the readable one. + unescape: false + # Preload the search data when the page loads. + preload: false + +# --------------------------------------------------------------- +# Chat Services +# See: https://theme-next.js.org/docs/third-party-services/chat-services +# --------------------------------------------------------------- + +# A button to open designated chat widget in sidebar. +# Firstly, you need to enable and configure the chat service. +chat: + enable: false + icon: fa fa-comment # Icon name in Font Awesome, set false to disable icon. + text: Chat # Button text, change it as you wish. + +# Chatra Support +# For more information: https://chatra.com +# Dashboard: https://app.chatra.io/settings/general +chatra: + enable: false + async: true + id: # Visit Dashboard to get your ChatraID + #embed: # Unfinished experimental feature for developers. See: https://chatra.com/help/api/#injectto + +# Tidio Support +# For more information: https://www.tidio.com +# Dashboard: https://www.tidio.com/panel/dashboard +tidio: + enable: false + key: # Public Key, get it from dashboard. See: https://www.tidio.com/panel/settings/developer + +# Gitter Support +# For more information: https://gitter.im +gitter: + enable: false + room: + +# --------------------------------------------------------------- +# Tags Settings +# See: https://theme-next.js.org/docs/tag-plugins/ +# --------------------------------------------------------------- + +# Note tag (bootstrap callout) +note: + # Note tag style values: + # - simple bootstrap callout old alert style. Default. + # - modern bootstrap callout new (v2-v3) alert style. + # - flat flat callout style with background, like on Mozilla or StackOverflow. + # - disabled disable all CSS styles import of note tag. + style: simple + icons: false + # Offset lighter of background in % for modern and flat styles (modern: -12 | 12; flat: -18 | 6). + # Offset also applied to label tag variables. This option can work with disabled note tag. + light_bg_offset: 0 + +# Tabs tag +tabs: + # Make the nav bar of tabs with long content stick to the top. + sticky: false + transition: + tabs: false + labels: true + +# PDF tag +# NexT will try to load pdf files natively, if failed, pdf.js will be used. +# So, you have to install the dependency of pdf.js if you want to use pdf tag and make it available to all browsers. +# Dependencies: https://github.com/next-theme/theme-next-pdf +pdf: + enable: false + # Default height + height: 500px + +# Mermaid tag +mermaid: + enable: false + # Available themes: default | dark | forest | neutral + theme: + light: default + dark: dark + +# --------------------------------------------------------------- +# Animation Settings +# --------------------------------------------------------------- + +# Use Animate.css to animate everything. +# For more information: https://animate.style +motion: + enable: true + async: false + transition: + # All available transition variants: https://theme-next.js.org/animate/ + post_block: fadeIn + post_header: fadeInDown + post_body: fadeInDown + coll_header: fadeInLeft + # Only for Pisces | Gemini. + sidebar: fadeInUp + +# Progress bar in the top during page loading. +# For more information: https://github.com/CodeByZach/pace +pace: + enable: true + # All available colors: + # black | blue | green | orange | pink | purple | red | silver | white | yellow + color: blue + # All available themes: + # big-counter | bounce | barber-shop | center-atom | center-circle | center-radar | center-simple + # corner-indicator | fill-left | flat-top | flash | loading-bar | mac-osx | material | minimal + theme: minimal + +# Canvas ribbon +# For more information: https://github.com/hustcc/ribbon.js +canvas_ribbon: + enable: false + size: 300 # The width of the ribbon + alpha: 0.6 # The transparency of the ribbon + zIndex: -1 # The display level of the ribbon + +# --------------------------------------------------------------- +# CDN Settings +# See: https://theme-next.js.org/docs/advanced-settings/vendors +# --------------------------------------------------------------- + +vendors: + # The CDN provider of NexT internal scripts. + # Available values: local | jsdelivr | unpkg | cdnjs | custom + # Warning: If you are using the latest master branch of NexT, please set `internal: local` + internal: local + # The default CDN provider of third-party plugins. + # Available values: local | jsdelivr | unpkg | cdnjs | custom + # Dependencies for `plugins: local`: https://github.com/next-theme/plugins + plugins: jsdelivr + # Custom CDN URL + # For example: + # custom_cdn_url: https://cdn.jsdelivr.net/npm/${npm_name}@${version}/${minified} + # custom_cdn_url: https://cdnjs.cloudflare.com/ajax/libs/${cdnjs_name}/${version}/${cdnjs_file} + custom_cdn_url: + +# Assets +# Accelerate delivery of static files using a CDN +# The js option is only valid when vendors.internal is local. +css: css +js: js +images: images diff --git a/_config.yml b/_config.yml new file mode 100644 index 0000000000..4580848ef0 --- /dev/null +++ b/_config.yml @@ -0,0 +1,154 @@ +# Hexo Configuration +## Docs: https://hexo.io/docs/configuration.html +## Source: https://github.com/hexojs/hexo/ + +# Site +title: Dunwu Blog +subtitle: 大道至简,知易行难 +author: 钝悟 ◾ Dunwu +description: '钝悟的个人博客' +language: zh-CN +keywords: +timezone: + +# URL +## Set your site url here. For example, if you use GitHub Page, set url as 'https://username.github.io/project' +url: https://dunwu.github.io/blog +root: /blog/ +#permalink: :year/:month/:day/:title/ +#permalink: :abbrlink.html +permalink_defaults: +pretty_urls: + trailing_index: true # Set to false to remove trailing 'index.html' from permalinks + trailing_html: true # Set to false to remove trailing '.html' from permalinks +abbrlink: + alg: crc32 #算法: crc16(default) and crc32 + rep: hex #进制: dec(default) and hex + +# Directory +source_dir: source +public_dir: .temp +tag_dir: tags +archive_dir: archives +category_dir: categories +code_dir: downloads/code +i18n_dir: :lang +skip_render: README.md + +# Writing +new_post_name: :title.md # File name of new posts +default_layout: post +titlecase: false # Transform title into titlecase +external_link: + enable: true # Open external links in new tab + field: site # Apply to the whole site + exclude: '' +filename_case: 0 +render_drafts: false +post_asset_folder: false +relative_link: false +future: true +highlight: + enable: true + line_number: true + auto_detect: true + tab_replace: '' + wrap: true + hljs: false +prismjs: + enable: false + preprocess: true + line_number: true + tab_replace: '' + +# hexo-hide-posts +hide_posts: + # 可以改成其他你喜欢的名字 + filter: hidden + # 指定你想要传递隐藏文章的位置,比如让所有隐藏文章在存档页面可见 + # 常见的位置有:index, tag, category, archive, sitemap, feed, etc. + # 留空则默认全部隐藏 + public_generators: [] + # 为隐藏的文章添加 noindex meta 标签,阻止搜索引擎收录 + noindex: true + +# Home page setting +# path: Root path for your blogs index page. (default = '') +# per_page: Posts displayed per page. (0 = disable pagination) +# order_by: Posts order. (Order by date descending by default) +index_generator: + path: '' + per_page: 10 + order_by: -date + +# Category & Tag +default_category: uncategorized +category_map: +tag_map: + +# Metadata elements +## https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta +meta_generator: true + +# Date / Time format +## Hexo uses Moment.js to parse and display date +## You can customize the date format as defined in +## http://momentjs.com/docs/#/displaying/format/ +date_format: YYYY-MM-DD +time_format: HH:mm:ss +## updated_option supports 'mtime', 'date', 'empty' +updated_option: 'mtime' + +# Pagination +## Set per_page to 0 to disable pagination +per_page: 10 +pagination_dir: page + +# Include / Exclude file(s) +## include:/exclude: options only apply to the 'source/' folder +include: +exclude: +ignore: + +# Extensions +## Plugins: https://hexo.io/plugins/ +Plugins: hexo-generator-cname + +## Themes: https://hexo.io/themes/ +theme: next + +# Search +# https://github.com/SuperKieran/hexo-generator-search-zip +search: + path: search.xml + field: post + format: html + limit: 10000 + +symbols_count_time: + symbols: true + total_symbols: true + time: true + total_time: true + +# index2 generator是否包含官方的hexo-generator-index,默认true(包含) +index2_include_index: true # defult is true + +# https://github.com/Jamling/hexo-generator-index2 +# 配置index2 generator,可以是数组或对象 +index2_generator: + per_page: 10 + order_by: -date + # include: + # - category Web # 只包含Web分类下的文章 + exclude: + - tag hide # 不包含标签为 Hexo 的文章 + - category hide # 不包含标签为 Hexo 的文章 + +# Deployment +## Docs: https://hexo.io/docs/one-command-deployment +deploy: + type: git + repo: git@github.com:dunwu/blog.git + branch: gh-pages + message: Update blog. diff --git a/algorithm/README.md b/algorithm/README.md deleted file mode 100644 index 0715626a9d..0000000000 --- a/algorithm/README.md +++ /dev/null @@ -1,80 +0,0 @@ -# 算法和数据结构 - -## 数据结构 - -> `数据结构` 是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成。 -> -> 记为:`Data_Structure=(D,R)`。其中 D 是数据元素的集合,R 是该集合中所有元素之间的关系的有限集合。 - -- **常用结构** - - [数组](data-structure/array.md) - - [栈](data-structure/stack.md) - - [队列](data-structure/queue.md) - - [链表](data-structure/list.md) - - [树](data-structure/tree) - [树](data-structure/tree/tree.md)、[二叉树](data-structure/tree/binary-tree.md)、[红黑树](data-structure/tree/red-black-tree.md) - - [图](data-structure/graph.md) - - [堆](data-structure/heap.md) - - [散列表](data-structure/hash.md) -- **结构算法** - - [查找](data-structure/search) - - [排序](data-structure/sort) - [冒泡排序](data-structure/sort/bubble-sort.md)、[快速排序](data-structure/sort/quick-sort.md)、[直接插入排序](data-structure/sort/insert-sort.md)、[希尔排序](data-structure/sort/shell-sort.md)、[简单选择排序](data-structure/sort/selection-sort.md)、[堆排序](data-structure/sort/heap-sort.md)、[归并排序](data-structure/sort/merge-sort.md)、[基数排序](data-structure/sort/radix-sort.md) - -## 学习资源 - -### 书 - -#### 刷题必备 - -- 《剑指 offer》 -- 《编程之美》 -- 《编程之法:面试和算法心得》 -- 《算法谜题》 都是思维题 - -#### 基础 - -- 《[编程珠玑(第 2 版)](https://www.amazon.cn/gp/product/B00SFZH0DC/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&camp=536&creative=3200&creativeASIN=B00SFZH0DC&linkCode=as2&tag=vastwork-23)》 -- 《[编程珠玑(续)](https://www.amazon.cn/gp/product/B0150BMQDM/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&camp=536&creative=3200&creativeASIN=B0150BMQDM&linkCode=as2&tag=vastwork-23)》 -- 《[数据结构与算法分析 : C++描述(第 4 版)](https://www.amazon.cn/gp/product/B01LDG2DSG/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&camp=536&creative=3200&creativeASIN=B01LDG2DSG&linkCode=as2&tag=vastwork-23)》 -- 《[数据结构与算法分析 : C 语言描述(第 2 版)](https://www.amazon.cn/gp/product/B002WC7NGS/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&camp=536&creative=3200&creativeASIN=B002WC7NGS&linkCode=as2&tag=vastwork-23)》 -- 《[数据结构与算法分析 : Java 语言描述(第 2 版)](https://www.amazon.cn/gp/product/B01CNP0CG6/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&camp=536&creative=3200&creativeASIN=B01CNP0CG6&linkCode=as2&tag=vastwork-23)》 -- 《[算法(第 4 版)](https://www.amazon.cn/gp/product/B009OCFQ0O/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&camp=536&creative=3200&creativeASIN=B009OCFQ0O&linkCode=as2&tag=vastwork-23)》- 这本近千页的书只有 6 章,其中四章分别是排序,查找,图,字符串,足见介绍细致 - -#### 算法设计 - -- 《[算法设计与分析基础(第 3 版)](https://www.amazon.cn/gp/product/B00S4HCQUI/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&camp=536&creative=3200&creativeASIN=B00S4HCQUI&linkCode=as2&tag=vastwork-23)》 -- 《算法引论》 - 告诉你如何创造算法 断货 -- 《Algorithm Design Manual》 - 算法设计手册 红皮书 -- [《算法导论》](https://www.amazon.cn/gp/product/B00AK7BYJY/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&camp=536&creative=3200&creativeASIN=B00AK7BYJY&linkCode=as2&tag=vastwork-23) - 是一本对算法介绍比较全面的经典书籍 -- 《Algorithms on Strings,Trees and Sequences》 -- 《Advanced Data Structures》 - 各种诡异高级的数据结构和算法 如元胞自动机、斐波纳契堆、线段树 600 块 - -### 参考链接和学习网站 - -- https://github.com/nonstriater/Learn-Algorithms -- https://github.com/trekhleb/javascript-algorithms -- https://github.com/kdn251/interviews/blob/master/README-zh-cn.md#%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84 -- [July 博客](http://blog.csdn.net/v_july_v) - - 《数学建模十大经典算法》 - - 《数据挖掘领域十大经典算法》 - - 《十道海量数据处理面试题》 - - 《数字图像处理领域的二十四个经典算法》 - - 《精选微软等公司经典的算法面试 100 题》 -- [The-Art-Of-Programming-By-July](https://github.com/julycoding/The-Art-Of-Programming-By-July) -- [微软面试 100 题](http://blog.csdn.net/column/details/ms100.html) -- [程序员编程艺术](http://blog.csdn.net/v_JULY_v/article/details/6460494) - -### 基本算法演示 - -- -- - -### 编程网站 - -- [leetcode](http://leetcode.com/) -- [openjudge](http://openjudge.cn/) 开放在线程序评测平台,可以创建自己的 OJ 小组 [九度 OJ](http://ac.jobdu.com/index.php) -- 这有个[ACM 训练方案](http://www.java3z.com/cwbwebhome/article/article19/res041.html) - -### 其它 - -- [高级数据结构和算法](https://www.coursera.org/learn/gaoji-shuju-jiegou/) 北大教授张铭老师在 coursera 上的课程。完成这门课之时,你将掌握多维数组、广义表、Trie 树、AVL 树、伸展树等高级数据结构,并结合内排序、外排序、检索、索引有关的算法,高效地解决现实生活中一些比较复杂的应用问题。当然 coursera 上也还有很多其它算法方面的视频课程。 -- [算法设计与分析 Design and Analysis of Algorithms](https://class.coursera.org/algorithms-001/lecture) 由北大教授 Wanling Qu 在 coursera 讲授的一门算法课程。首先介绍一些与算法有关的基础知识,然后阐述经典的算法设计思想和分析技术,主要涉及的算法设计技术是:分治策略、动态规划、贪心法、回溯与分支限界等。每个视频都配有相应的讲义(pdf 文件)以便阅读和复习。 diff --git a/algorithm/data-structure/README.md b/algorithm/data-structure/README.md deleted file mode 100644 index 8f09e5579c..0000000000 --- a/algorithm/data-structure/README.md +++ /dev/null @@ -1,18 +0,0 @@ -## 数据结构 - -> `数据结构` 是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成。 -> -> 记为:`Data_Structure=(D,R)`。其中 D 是数据元素的集合,R 是该集合中所有元素之间的关系的有限集合。 - -- **常用结构** - - [数组](array.md) - - [栈](stack.md) - - [队列](queue.md) - - [链表](list.md) - - [树](tree) - [树](tree/tree.md)、[二叉树](tree/binary-tree.md)、[红黑树](tree/red-black-tree.md) - - [图](graph.md) - - [堆](heap.md) - - [散列表](hash.md) -- **结构算法** - - [查找](search) - - [排序](sort) - [冒泡排序](sort/bubble-sort.md)、[快速排序](sort/quick-sort.md)、[直接插入排序](sort/insert-sort.md)、[希尔排序](sort/shell-sort.md)、[简单选择排序](sort/selection-sort.md)、[堆排序](sort/heap-sort.md)、[归并排序](sort/merge-sort.md)、[基数排序](sort/radix-sort.md) diff --git a/algorithm/data-structure/array.md b/algorithm/data-structure/array.md deleted file mode 100644 index 4ca9aae20b..0000000000 --- a/algorithm/data-structure/array.md +++ /dev/null @@ -1,135 +0,0 @@ -# 数组 - -> 所谓数组,是有序的元素序列。若将有限个类型相同的变量的集合命名,那么这个名称为数组名。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。用于区分数组的各个元素的数字编号称为下标。数组是在程序设计中,为了处理方便, 把具有相同类型的若干元素按无序的形式组织起来的一种形式。这些无序排列的同类数据元素的集合称为数组。 - - - -- [简介](#简介) - - [一维数组](#一维数组) - - [二维数组](#二维数组) - - [多维数组](#多维数组) - - [数组的特性](#数组的特性) -- [数组中的操作](#数组中的操作) -- [引申和引用](#引申和引用) - - - -## 简介 - -`数组`是一种基本的数据结构,用于按顺序`存储元素的集合`。但是元素可以随机存取,因为数组中的每个元素都可以通过数组`索引`来识别。 - -数组可以有一个或多个维度。 - -### 一维数组 - -一维(或单维)数组是一种线性数组,其中元素的访问是以行或列索引的单一下标表示。 - -这里有一个例子: - -![](http://dunwu.test.upcdn.net/images/data-structure/array/一维数组.png) - -在上面的例子中,数组 A 中有 6 个元素。也就是说,A 的长度是 6 。我们可以使用 A[0] 来表示数组中的第一个元素。因此,A[0] = 6 。类似地,A[1] = 3,A[2] = 8,依此类推。 - -### 二维数组 - -类似于一维数组,二维数组也是由元素的序列组成。但是这些元素可以排列在矩形网格中而不是直线上。 - -类似于一维数组,`二维数组`也是由元素的序列组成。但是这些元素可以排列在矩形网格中而不是直线上。 - -在一些语言中,多维数组实际上是在`内部`作为一维数组实现的,而在其他一些语言中,`实际上`根本没有`多维数组`。 - -**1. C++ 将二维数组存储为一维数组。** - -下图显示了*大小为 M \* N 的数组 A* 的实际结构: - -![](http://dunwu.test.upcdn.net/images/data-structure/array/C++二维数组.png) - -因此,如果我们将 A 定义为也包含 _M \* N_ 个元素的一维数组,那么实际上 A[i][j] 就等于 A[i * N + j]。 - -**2. 在 Java 中,二维数组实际上是包含着 M 个元素的一维数组,每个元素都是包含有 N 个整数的数组。** - -下图显示了 Java 中二维数组 A 的实际结构: - -![](http://dunwu.test.upcdn.net/images/data-structure/array/JAVA二维数组.png) - -二维数组示例: - -```java -public class TwoDimensionArray { - private static void printArray(int[][] a) { - for (int i = 0; i < a.length; ++i) { - System.out.println(a[i]); - } - for (int i = 0; i < a.length; ++i) { - for (int j = 0; a[i] != null && j < a[i].length; ++j) { - System.out.print(a[i][j] + " "); - } - System.out.println(); - } - } - - public static void main(String[] args) { - System.out.println("Example I:"); - int[][] a = new int[2][5]; - printArray(a); - System.out.println("Example II:"); - int[][] b = new int[2][]; - printArray(b); - System.out.println("Example III:"); - b[0] = new int[3]; - b[1] = new int[5]; - printArray(b); - } -} -``` - -### 多维数组 - -普通数组采用一个整数来作下标。多维数组(高维数组)的概念特别是在数值计算和图形应用方面非常有用。我们在多维数组之中采用一系列有序的整数来标注,如在[ 3,1,5 ] 。这种整数列表之中整数的个数始终相同,且被称为数组的“维度”。关于每个数组维度的边界称为“维”。维度为 k 的数组通常被称为 k 维。 - -多维数组的数组名字,在表达式中自动转换为数组首元素地址值,但这个首元素实际上是去除数组下标第一维之后的数组剩余部分。 - -### 数组的特性 - -数组设计之初是在形式上依赖内存分配而成的,所以必须在使用前预先请求空间。这使得数组有以下特性: - -1. 请求空间以后大小固定,不能再改变(数据溢出问题); -2. 在内存中有空间连续性的表现,中间不会存在其他程序需要调用的数据,为此数组的专用内存空间; -3. 在旧式编程语言中(如有中阶语言之称的 C),程序不会对数组的操作做下界判断,也就有潜在的越界操作的风险(比如会把数据写在运行中程序需要调用的核心部分的内存上)。 - -因为简单数组强烈倚赖计算机硬件之内存,所以不适用于现代的程序设计。欲使用可变大小、硬件无关性的数据类型,Java 等程序设计语言均提供了更高级的数据结构:ArrayList、Vector 等动态数组。 - -## 数组中的操作 - -```java -public class Main { - public static void main(String[] args) { - // 1. Initialize - int[] a0 = new int[5]; - int[] a1 = {1, 2, 3}; - // 2. Get Length - System.out.println("The size of a1 is: " + a1.length); - // 3. Access Element - System.out.println("The first element is: " + a1[0]); - // 4. Iterate all Elements - System.out.print("[Version 1] The contents of a1 are:"); - for (int i = 0; i < a1.length; ++i) { - System.out.print(" " + a1[i]); - } - System.out.println(); - System.out.print("[Version 2] The contents of a1 are:"); - for (int item: a1) { - System.out.print(" " + item); - } - System.out.println(); - // 5. Modify Element - a1[0] = 4; - // 6. Sort - Arrays.sort(a1); - } -} -``` - -## 引申和引用 - -- https://zh.wikipedia.org/wiki/数组 diff --git a/algorithm/data-structure/graph.md b/algorithm/data-structure/graph.md deleted file mode 100644 index 2a4bb69e76..0000000000 --- a/algorithm/data-structure/graph.md +++ /dev/null @@ -1,35 +0,0 @@ -# 图 - -在计算机科学中,一个图就是一些*顶点*的集合,这些顶点通过一系列*边*结对(连接)。顶点用圆圈表示,边就是这些圆圈之间的连线。顶点之间通过边连接。 - -![](http://dunwu.test.upcdn.net/images/data-structure/graph/graph.png) - -## 术语 - -- **阶(Order)** - 图 G 中点集 V 的大小称作图 G 的阶。 -- **子图(Sub-Graph)** - 当图 G'=(V',E')其中 V‘包含于 V,E’包含于 E,则 G'称作图 G=(V,E)的子图。每个图都是本身的子图。 -- 生成子图(Spanning Sub-Graph) - 指满足条件 V(G') = V(G)的 G 的子图 G'。 -- 导出子图(Induced Subgraph) - 以图 G 的顶点集 V 的[非空子集](https://baike.baidu.com/item/%E9%9D%9E%E7%A9%BA%E5%AD%90%E9%9B%86/10180460)V1 为顶点集,以两端点均在 V1 中的全体边为边集的 G 的子图,称为 V1 导出的导出子图;以图 G 的边集 E 的非空子集 E1 为边集,以 E1 中边关联的顶点的全体为顶点集的 G 的子图,称为 E1 导出的导出子图。 -- **有向图** - 如果给图的每条边规定一个方向,那么得到的图称为有向图。 -- **无向图** - 边没有方向的图称为无向图。 -- **度(Degree)** - 一个顶点的度是指与该顶点相关联的边的条数,顶点 v 的度记作 d(v)。 -- **入度(In-degree)**和**出度(Out-degree)** - 对于有向图来说,一个顶点的度可细分为入度和出度。一个顶点的入度是指与其关联的各边之中,以其为终点的边数;出度则是相对的概念,指以该顶点为起点的边数。 -- **自环(Loop)** - 若一条边的两个顶点为同一顶点,则此边称作自环。 -- 路径(Path) - 从 u 到 v 的一条路径是指一个序列 v0,e1,v1,e2,v2,...ek,vk,其中 ei 的顶点为 vi 及 vi - 1,k 称作路径的长度。如果它的起止顶点相同,该路径是“闭”的,反之,则称为“开”的。一条路径称为一简单路径(simple path),如果路径中除起始与终止[顶点](https://baike.baidu.com/item/%E9%A1%B6%E7%82%B9)可以重合外,所有顶点两两不等。 -- **行迹(Trace)** - 如果路径 P(u,v)中的边各不相同,则该路径称为 u 到 v 的一条行迹。闭的行迹称作回路(Circuit)。 -- **轨迹(Track)** - 如果路径 P(u,v)中的顶点各不相同,则该路径称为 u 到 v 的一条轨迹。闭的轨迹称作圈(Cycle)。 -- **桥(Bridge)** - 若去掉一条边,便会使得整个图不连通,该边称为[桥](https://baike.baidu.com/item/%E6%A1%A5)。 - -## 图的基本操作 - -- 创建一个图结构 - CreateGraph(G) -- 检索给定顶点 - LocateVex(G,elem) -- 获取图中某个顶点 - GetVex(G,v) -- 为图中顶点赋值 - PutVex(G,v,value) -- 返回第一个邻接点 - FirstAdjVex(G,v) -- 返回下一个邻接点 - NextAdjVex(G,v,w) -- 插入一个顶点 - InsertVex(G,v) -- 删除一个顶点 - DeleteVex(G,v) -- 插入一条边 - InsertEdge(G,v,w) -- 删除一条边 - DeleteEdge(G,v,w) -- 遍历图 - Traverse(G,v) diff --git a/algorithm/data-structure/hash.md b/algorithm/data-structure/hash.md deleted file mode 100644 index a0f938481f..0000000000 --- a/algorithm/data-structure/hash.md +++ /dev/null @@ -1,81 +0,0 @@ -# 哈希表 - -> 关键词: hash, 哈希表, 哈希函数 - - - -- [简介](#简介) -- [原理](#原理) -- [引申和引用](#引申和引用) - - - -## 简介 - ---- - -`哈希表`是一种使用`哈希函数`组织数据,以支持快速插入和搜索的数据结构。 - -有两种不同类型的哈希表:哈希集合和哈希映射。 - -- `哈希集合`是`集合`数据结构的实现之一,用于存储`非重复值`。 -- `哈希映射`是`映射` 数据结构的实现之一,用于存储`(key, value)`键值对。 - -在`标准模板库`的帮助下,哈希表是`易于使用的`。大多数常见语言(如 Java,C ++ 和 Python)都支持哈希集合和哈希映射。 - -通过选择合适的哈希函数,哈希表可以在插入和搜索方面实现`出色的性能`。 - -## 原理 - ---- - -哈希表的关键思想是使用哈希函数将键映射到存储桶。更确切地说, - -1. 当我们插入一个新的键时,哈希函数将决定该键应该分配到哪个桶中,并将该键存储在相应的桶中; -2. 当我们想要搜索一个键时,哈希表将使用相同的哈希函数来查找对应的桶,并只在特定的桶中进行搜索。 - -### 哈希函数示例 - -![](http://dunwu.test.upcdn.net/images/data-structure/hash/哈希函数.png) - -在示例中,我们使用 y = x % 5 作为哈希函数。让我们使用这个例子来完成插入和搜索策略: - -1. 插入:我们通过哈希函数解析键,将它们映射到相应的桶中。 - - 例如,1987 分配给桶 2,而 24 分配给桶 4。 -2. 搜索:我们通过相同的哈希函数解析键,并仅在特定存储桶中搜索。 - - 如果我们搜索 1987,我们将使用相同的哈希函数将 1987 映射到 2。因此我们在桶 2 中搜索,我们在那个桶中成功找到了 1987。 - - 例如,如果我们搜索 23,将映射 23 到 3,并在桶 3 中搜索。我们发现 23 不在桶 3 中,这意味着 23 不在哈希表中。 - -### 哈希表的关键 - -#### 1. 哈希函数 - -哈希函数是哈希表中最重要的组件,该哈希表用于将键映射到特定的桶。在上一节的示例中,我们使用 `y = x % 5` 作为散列函数,其中 `x` 是键值,`y` 是分配的桶的索引。 - -散列函数将取决于`键值的范围`和`桶的数量。` - -下面是一些哈希函数的示例: - -![](http://dunwu.test.upcdn.net/images/data-structure/hash/哈希函数示例.png) - -哈希函数的设计是一个开放的问题。其思想是尽可能将键分配到桶中,理想情况下,完美的哈希函数将是键和桶之间的一对一映射。然而,在大多数情况下,哈希函数并不完美,它需要在桶的数量和桶的容量之间进行权衡。 - -#### 2. 冲突解决 - -理想情况下,如果我们的哈希函数是完美的一对一映射,我们将不需要处理冲突。不幸的是,在大多数情况下,冲突几乎是不可避免的。例如,在我们之前的哈希函数(_y = x % 5_)中,1987 和 2 都分配给了桶 2,这是一个`冲突`。 - -冲突解决算法应该解决以下几个问题: - -1. 如何组织在同一个桶中的值? -2. 如果为同一个桶分配了太多的值,该怎么办? -3. 如何在特定的桶中搜索目标值? - -根据我们的哈希函数,这些问题与`桶的容量`和可能映射到`同一个桶`的`键的数目`有关。 - -让我们假设存储最大键数的桶有 `N` 个键。 - -通常,如果 _N_ 是常数且很小,我们可以简单地使用一个数组将键存储在同一个桶中。如果 _N_ 是可变的或很大,我们可能需要使用`高度平衡的二叉树`来代替。 - -## 引申和引用 - -https://leetcode-cn.com/explore/learn/card/hash-table/ diff --git a/algorithm/data-structure/heap.md b/algorithm/data-structure/heap.md deleted file mode 100644 index 50c9471f4b..0000000000 --- a/algorithm/data-structure/heap.md +++ /dev/null @@ -1,12 +0,0 @@ -# 堆 - -堆是一种特殊的基于树的满足某些特性的数据结构,整个堆中的所有父子节点的键值都会满足相同的排序条件。堆更准确地可以分为最大堆与最小堆,在最大堆中,父节点的键值永远大于或者等于子节点的值,并且整个堆中的最大值存储于根节点;而最小堆中,父节点的键值永远小于或者等于其子节点的键值,并且整个堆中的最小值存储于根节点。 - -![](http://dunwu.test.upcdn.net/images/data-structure/heap/heap.png) - -时间复杂度: - -- 访问最大值 / 最小值: `O(1)` -- 插入: `O(log(n))` -- 移除最大值 / 最小值: `O(log(n))` - diff --git a/algorithm/data-structure/list.md b/algorithm/data-structure/list.md deleted file mode 100644 index 4bb3cb171e..0000000000 --- a/algorithm/data-structure/list.md +++ /dev/null @@ -1,23 +0,0 @@ -# 线性表 - -## 单链表 - -单链表中的每个结点不仅包含值,还包含链接到下一个结点的`引用字段`。通过这种方式,单链表将所有结点按顺序组织起来。、 - -下面是一个单链表的例子: - -![](http://dunwu.test.upcdn.net/images/data-structure/list/单链表.png) - -蓝色箭头显示单个链接列表中的结点是如何组合在一起的。 - -与数组不同,我们无法在常量时间内访问单链表中的随机元素。 如果我们想要获得第 i 个元素,我们必须从头结点逐个遍历。 我们按`索引`来`访问元素`平均要花费 `O(N)`时间,其中 N 是链表的长度。 - -## 双链表 - -双链表以类似的方式工作,但`还有一个引用字段`,称为`“prev”`字段。有了这个额外的字段,您就能够知道当前结点的前一个结点。 - -让我们看一个例子: - -![](http://dunwu.test.upcdn.net/images/data-structure/list/双链表.png) - -绿色箭头表示我们的“prev”字段是如何工作的。 diff --git a/algorithm/data-structure/queue.md b/algorithm/data-structure/queue.md deleted file mode 100644 index adbd514f9c..0000000000 --- a/algorithm/data-structure/queue.md +++ /dev/null @@ -1,12 +0,0 @@ -# 队列 - -队列是元素的集合,其包含了两个基本操作:入队(enqueue) 操作可以用于将元素插入到队列中,而出队(dequeue)操作则是将元素从队列中移除。 - -遵循先入先出原则 (FIFO)。 - -时间复杂度: - -- 索引: `O(n)` -- 搜索: `O(n)` -- 插入: `O(1)` -- 移除: `O(1)` \ No newline at end of file diff --git a/algorithm/data-structure/search/README.md b/algorithm/data-structure/search/README.md deleted file mode 100644 index bc2b7d0206..0000000000 --- a/algorithm/data-structure/search/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# 查找 - -## 目录 - -* [哈希表的查找](hash-search.md) diff --git a/algorithm/data-structure/search/hash-search.md b/algorithm/data-structure/search/hash-search.md deleted file mode 100644 index 7f25a608c3..0000000000 --- a/algorithm/data-structure/search/hash-search.md +++ /dev/null @@ -1,232 +0,0 @@ -# Hash 表的查找 - -## 要点 - -### 哈希表和哈希函数 - -在记录的存储位置和它的关键字之间是建立一个确定的对应关系(映射函数),使每个关键字和一个存储位置能**唯一对应**。这个映射函数称为**哈希函数**,根据这个原则建立的表称为**哈希表(Hash Table)**,也叫**散列表**。 - -以上描述,如果通过数学形式来描述就是: - -若查找关键字为 **key**,则其值存放在 **f(key)** 的存储位置上。由此,**不需比较便可直接取得所查记录**。 - -***注:哈希查找与线性表查找和树表查找最大的区别在于,不用数值比较。*** - -### 冲突 - -若 key1 ≠ key2 ,而 f(key1) = f(key2),这种情况称为**冲突(Collision)**。 - -根据哈希函数f(key)和处理冲突的方法将一组关键字映射到一个有限的连续的地址集(区间)上,并以关键字在地址集中的“像”作为记录在表中的存储位置,这一映射过程称为**构造哈希表**。 - -构造哈希表这个场景就像汽车找停车位,如果车位被人占了,只能找空的地方停。 - -![image](http://upload-images.jianshu.io/upload_images/3101171-4f4e0c3def86f7bb.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 "点击查看源网页") - -## 构造哈希表 - -由以上内容可知,哈希查找本身其实不费吹灰之力,问题的关键在于如何构造哈希表和处理冲突。 - -常见的构造哈希表的方法有 `5` 种: - -### 直接定址法 - -说白了,就是小学时学过的**一元一次方程**。 - -即 f(key) = a * key + b。其中,a和b 是常数。 - -### 数字分析法 - -假设关键字是R进制数(如十进制)。并且哈希表中**可能出现的关键字都是事先知道的**,则可选取关键字的若干数位组成哈希地址。 - -选取的原则是使得到的哈希地址尽量避免冲突,即所选数位上的数字尽可能是随机的。 - -### 平方取中法 - -取关键字平方后的中间几位为哈希地址。通常在选定哈希函数时不一定能知道关键字的全部情况,仅取其中的几位为地址不一定合适; - -而一个数平方后的中间几位数和数的每一位都相关, 由此得到的哈希地址随机性更大。取的位数由表长决定。 - -### 除留余数法 - -取关键字被某个**不大于哈希表表长** m 的数 p 除后所得的余数为哈希地址。 - -即 f(key) = key % p (p ≤ m) - -这是一种**最简单、最常用**的方法,它不仅可以对关键字直接取模,也可在折叠、平方取中等运算之后取模。 - -注意:p的选择很重要,如果选的不好,容易产生冲突。根据经验,**一般情况下可以选p为素数**。 - -### 随机数法 - -选择一个随机函数,取关键字的随机函数值为它的哈希地址,即 f(key) = random(key)。 - -通常,在关键字长度不等时采用此法构造哈希函数较为恰当。 - -## 解决冲突 - -设计合理的哈希函数可以减少冲突,但不能完全避免冲突。 - -所以需要有解决冲突的方法,常见有两类: - -### 开放定址法 - -如果两个数据元素的哈希值相同,则在哈希表中为后插入的数据元素另外选择一个表项。 -当程序查找哈希表时,如果没有在第一个对应的哈希表项中找到符合查找要求的数据元素,程序就会继续往后查找,直到找到一个符合查找要求的数据元素,或者遇到一个空的表项。 - -**示例** - -若要将一组关键字序列 {1, 9, 25, 11, 12, 35, 17, 29} 存放到哈希表中。 - -采用除留余数法构造哈希表;采用开放定址法处理冲突。 - -不妨设选取的p和m为13,由 f(key) = key % 13 可以得到下表。 - -![image.png](https://upload-images.jianshu.io/upload_images/3101171-06a789e7f9b31da6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -需要注意的是,在上图中有两个关键字的探查次数为 2 ,其他都是1。 - -这个过程是这样的: - -a. 12 % 13 结果是12,而它的前面有个 25 ,25 % 13 也是12,存在冲突。 - -我们使用开放定址法 (12 + 1) % 13 = 0,没有冲突,完成。 - -b. 35 % 13 结果是 9,而它的前面有个 9,9 % 13也是 9,存在冲突。 - -我们使用开放定址法 (9 + 1) % 13 = 10,没有冲突,完成。 - -### 拉链法 - -将哈希值相同的数据元素存放在一个链表中,在查找哈希表的过程中,当查找到这个链表时,必须采用线性查找方法。 - -在这种方法中,哈希表中每个单元存放的不再是记录本身,而是相应同义词单链表的头指针。 - -**示例** - -如果对开放定址法示例中提到的序列使用拉链法,得到的结果如下图所示: - -![image.png](https://upload-images.jianshu.io/upload_images/3101171-c14e03882e8a0f3a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -## 实现一个哈希表 - -假设要实现一个哈希表,要求 - -a. 哈希函数采用**除留余数法**,即 f(key) = key % p (p ≤ m) - -b. 解决冲突采用**开放定址法**,即 f2(key) = (f(key)+i) % size (p ≤ m) - -(1)定义哈希表的数据结构 - -```java -class HashTable { - public int key = 0; // 关键字 - public int data = 0; // 数值 - public int count = 0; // 探查次数 -} -``` - -(2)在哈希表中查找关键字key - -根据设定的哈希函数,计算哈希地址。如果出现地址冲突,则按设定的处理冲突的方法寻找下一个地址。 - -如此反复,直到不冲突为止(查找成功)或某个地址为空(查找失败)。 - -```java -/** - * 查找哈希表 - * 构造哈希表采用除留取余法,即f(key) = key mod p (p ≤ size) - * 解决冲突采用开放定址法,即f2(key) = (f(key) + i) mod p (1 ≤ i ≤ size-1) - * ha为哈希表,p为模,size为哈希表大小,key为要查找的关键字 - */ -public int searchHashTable(HashTable[] ha, int p, int size, int key) { - int addr = key % p; // 采用除留取余法找哈希地址 - - // 若发生冲突,用开放定址法找下一个哈希地址 - while (ha[addr].key != NULLKEY && ha[addr].key != key) { - addr = (addr + 1) % size; - } - - if (ha[addr].key == key) { - return addr; // 查找成功 - } else { - return FAILED; // 查找失败 - } -} -``` - -(3)删除关键字为key的记录 - -在采用开放定址法处理冲突的哈希表上执行删除操作,只能在被删记录上做删除标记,而不能真正删除记录。 - -找到要删除的记录,将关键字置为删除标记DELKEY。 - -```java -public int deleteHashTable(HashTable[] ha, int p, int size, int key) { - int addr = 0; - addr = searchHashTable(ha, p, size, key); - if (FAILED != addr) { // 找到记录 - ha[addr].key = DELKEY; // 将该位置的关键字置为DELKEY - return SUCCESS; - } else { - return NULLKEY; // 查找不到记录,直接返回NULLKEY - } -} -``` - -(4)插入关键字为key的记录 - -将待插入的关键字key插入哈希表 -先调用查找算法,若在表中找到待插入的关键字,则插入失败; -若在表中找到一个开放地址,则将待插入的结点插入到其中,则插入成功。 - -```java -public void insertHashTable(HashTable[] ha, int p, int size, int key) { - int i = 1; - int addr = 0; - addr = key % p; // 通过哈希函数获取哈希地址 - if (ha[addr].key == NULLKEY || ha[addr].key == DELKEY) { // 如果没有冲突,直接插入 - ha[addr].key = key; - ha[addr].count = 1; - } else { // 如果有冲突,使用开放定址法处理冲突 - do { - addr = (addr + 1) % size; // 寻找下一个哈希地址 - i++; - } while (ha[addr].key != NULLKEY && ha[addr].key != DELKEY); - - ha[addr].key = key; - ha[addr].count = i; - } -} -``` - -(5)建立哈希表 - -先将哈希表中各关键字清空,使其地址为开放的,然后调用插入算法将给定的关键字序列依次插入。 - -```java -public void insertHashTable(HashTable[] ha, int p, int size, int key) { - int i = 1; - int addr = 0; - addr = key % p; // 通过哈希函数获取哈希地址 - if (ha[addr].key == NULLKEY || ha[addr].key == DELKEY) { // 如果没有冲突,直接插入 - ha[addr].key = key; - ha[addr].count = 1; - } else { // 如果有冲突,使用开放定址法处理冲突 - do { - addr = (addr + 1) % size; // 寻找下一个哈希地址 - i++; - } while (ha[addr].key != NULLKEY && ha[addr].key != DELKEY); - - ha[addr].key = key; - ha[addr].count = i; - } -} -``` - -### 完整示例 - -[示例代码](https://github.com/dunwu/algorithm/blob/master/codes/src/main/java/io/github/dunwu/algorithm/search/HashDemo.java) - -## 资源 - -《数据结构习题与解析》(B级第3版) diff --git a/algorithm/data-structure/search/linear-list-search.md b/algorithm/data-structure/search/linear-list-search.md deleted file mode 100644 index d08cc68f67..0000000000 --- a/algorithm/data-structure/search/linear-list-search.md +++ /dev/null @@ -1,302 +0,0 @@ -# 线性表的查找 - -## 概念 - -### 什么是查找? - -**查找**是根据给定的某个值,在表中确定一个关键字的值等于给定值的记录或数据元素。 - -### 查找算法的分类 - -若在查找的同时对表记录做修改操作(如插入和删除),则相应的表称之为**动态查找表**; - -否则,称之为**静态查找表**。 - -此外,如果查找的全过程都在内存中进行,称之为**内查找**; - -反之,如果查找过程中需要访问外存,称之为**外查找**。 - -### 查找算法性能比较的标准 - -**——平均查找长度ASL(Average Search Length)** - -由于查找算法的主要运算是关键字的比较过程,所以通常把查找过程中对关键字需要执行的**平均比较长度**(也称为**平均比较次数**)作为衡量一个查找算法效率优劣的比较标准。 - -![image.gif](https://upload-images.jianshu.io/upload_images/3101171-a38f84148d091364.gif?imageMogr2/auto-orient/strip) - -**选取查找算法的因素** - -(1) 使用什么数据存储结构(如线性表、树形表等)。 - -(2) 表中的次序,即对无序表还是有序表进行查找。 - -## 顺序查找 - -**要点** - -它是一种最简单的查找算法,效率也很低下。 - -**存储结构** - -没有存储结构要求,可以无序,也可以有序。 - -**基本思想** - -从数据结构线形表的**一端**开始,**顺序扫描**,**依次**将扫描到的结点关键字与给定值k相**比较**,若相等则表示查找成功; - -若扫描结束仍没有找到关键字等于k的结点,表示查找失败。 - -**核心代码** - -```java -public int orderSearch(int[] list, int length, int key) { - // 从前往后扫描list数组,如果有元素的值与key相等,直接返回其位置 - for (int i = 0; i < length; i++) { - if (key == list[i]) { - return i; - } - } - - // 如果扫描完,说明没有元素的值匹配key,返回-1,表示查找失败 - return -1; -} -``` - -**算法分析** - -顺序查找算法**最好的情况**是,第一个记录即匹配关键字,则需要比较 **1** 次; - -**最坏的情况**是,最后一个记录匹配关键字,则需要比较 **N** 次。 - -所以,顺序查找算法的平均查找长度为 - -ASL = (N + N-1 + ... + 2 + 1) / N = (N+1) / 2 - -顺序查找的**平均时间复杂度**为**O(N)**。 - -## 二分查找 - -**要点** - -二分查找又称**折半查找**,它是一种效率较高的查找方法。 - -**存储结构** - -使用二分查找需要两个前提: - -(1) 必须是**顺序**存储结构。 - -(2) 必须是**有序**的表。 - -**基本思想** - -首先,将表**中间位置**记录的关键字与查找关键字比较,如果两者相等,则查找成功; - -否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。 -重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。 - -**核心代码** - -```java -public int binarySearch(int[] list, int length, int key) { - int low = 0, mid = 0, high = length - 1; - while (low <= high) { - mid = (low + high) / 2; - if (list[mid] == key) { - return mid; // 查找成功,直接返回位置 - } else if (list[mid] < key) { - low = mid + 1; // 关键字大于中间位置的值,则在大值区间[mid+1, high]继续查找 - } else { - high = mid - 1; // 关键字小于中间位置的值,则在小值区间[low, mid-1]继续查找 - } - } - return -1; -} -``` - -**算法分析** - -**二分查找的过程可看成一个二叉树**。 - -把查找区间的中间位置视为树的根,左区间和右区间视为根的左子树和右子树。 - -由此得到的二叉树,称为二分查找的判定树或比较树。 - -由此可知,二分查找的**平均查找长度**实际上就是树的高度**O(log2N)**。 - -## 分块查找 - -**要点** - -分块查找(Blocking Search)又称**索引顺序查找**。它是一种性能介于顺序查找和二分查找之间的查找方法。 - -分块查找由于只要求索引表是有序的,对块内节点没有排序要求,因此特别适合于节点动态变化的情况。 - -**存储结构** - -分块查找表是由**“分块有序”的线性表**和**索引表**两部分构成的。 - -所谓**“分块有序”的线性表**,是指: - -假设要排序的表为R[0...N-1],**将表均匀分成b块**,前b-1块中记录个数为s=N/b,最后一块记录数小于等于s; - -每一块中的关键字不一定有序,但**前一块中的最大关键字必须小于后一块中的最小关键字**。 - -***注:这是使用分块查找的前提条件。*** - -如上将表均匀分成b块后,抽取各块中的**最大关键字**和**起始位置**构成一个索引表IDX[0...b-1]。 - -由于表R是分块有序的,所以**索引表是一个递增有序表**。 - -下图就是一个分块查找表的存储结构示意图 - -![image.png](https://upload-images.jianshu.io/upload_images/3101171-b7ad44c68d0c3c75.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) - -**基本思想** - -分块查找算法有两个处理步骤: - -**(1) 首先查找索引表** - -因为分块查找表是“分块有序”的,所以我们可以通过索引表来锁定关键字所在的区间。 - -又因为索引表是递增有序的,所以查找索引可以使用顺序查找或二分查找。 - -**(2) 然后在已确定的块中进行顺序查找** - -因为块中不一定是有序的,所以只能使用顺序查找。 - -**代码范例** - -![image](http://upload-images.jianshu.io/upload_images/3101171-2737612c781e66e8.gif?imageMogr2/auto-orient/strip) - -```java -class BlockSearch { - - class IndexType { - public int key; // 分块中的最大值 - public int link; // 分块的起始位置 - } - - // 建立索引方法,n 是线性表最大长度,gap是分块的最大长度 - public IndexType[] createIndex(int[] list, int n, int gap) { - int i = 0, j = 0, max = 0; - int num = n / gap; - IndexType[] idxGroup = new IndexType[num]; // 根据步长数分配索引数组大小 - - while (i < num) { - j = 0; - idxGroup[i] = new IndexType(); - idxGroup[i].link = gap * i; // 确定当前索引组的第一个元素位置 - max = list[gap * i]; // 每次假设当前组的第一个数为最大值 - // 遍历这个分块,找到最大值 - while (j < gap) { - if (max < list[gap * i + j]) { - max = list[gap * i + j]; - } - j++; - } - idxGroup[i].key = max; - i++; - } - - return idxGroup; - } - - // 分块查找算法 - public int blockSearch(IndexType[] idxGroup, int m, int[] list, int n, int key) { - int mid = 0; - int low = 0; - int high = m -1; - int gap = n / m; // 分块大小等于线性表长度除以组数 - - // 先在索引表中进行二分查找,找到的位置存放在 low 中 - while (low <= high) { - mid = (low + high) / 2; - if (idxGroup[mid].key >= key) { - high = mid - 1; - } else { - low = mid + 1; - } - } - - // 在索引表中查找成功后,再在线性表的指定块中进行顺序查找 - if (low < m) { - for (int i = idxGroup[low].link; i < idxGroup[low].link + gap; i++) { - if (list[i] == key) - return i; - } - } - - return -1; - } - - // 打印完整序列 - public void printAll(int[] list) { - for (int value : list) { - System.out.print(value + " "); - } - System.out.println(); - } - - // 打印索引表 - public void printIDX(IndexType[] list) { - System.out.println("构造索引表如下:"); - for (IndexType elem : list) { - System.out.format("key = %d, link = %d\n", elem.key, elem.link); - } - System.out.println(); - } - - public static void main(String[] args) { - int key = 85; - int array[] = { 8, 14, 6, 9, 10, 22, 34, 18, 19, 31, 40, 38, 54, 66, 46, 71, 78, 68, 80, 85 }; - BlockSearch search = new BlockSearch(); - - System.out.print("线性表: "); - search.printAll(array); - - IndexType[] idxGroup = search.createIndex(array, array.length, 5); - search.printIDX(idxGroup); - int pos = search.blockSearch(idxGroup, idxGroup.length, array, - array.length, key); - if (-1 == pos) { - System.out.format("查找key = %d失败", key); - } else { - System.out.format("查找key = %d成功,位置为%d", key, pos); - } - } - -} -``` - -**运行结果** - -``` -线性表: 8 14 6 9 10 22 34 18 19 31 40 38 54 66 46 71 78 68 80 85  -构造索引表如下: -key = 14, link = 0 -key = 34, link = 5 -key = 66, link = 10 -key = 85, link = 15 - -查找key = 85成功,位置为19 -``` - -**算法分析** - -因为分块查找实际上是两次查找过程之和。若以二分查找来确定块,显然它的查找效率介于顺序查找和二分查找之间。 - -## 三种线性查找的PK - -(1) 以平均查找长度而言,二分查找 > 分块查找 > 顺序查找。 - -(2) 从适用性而言,顺序查找无限制条件,二分查找仅适用于有序表,分块查找要求“分块有序”。 - -(3) 从存储结构而言,顺序查找和分块查找既可用于顺序表也可用于链表;而二分查找只适用于顺序表。 - -(4) 分块查找综合了顺序查找和二分查找的优点,既可以较为快速,也能使用动态变化的要求。 - -## 资源 - -《数据结构习题与解析》(B级第3版) \ No newline at end of file diff --git a/algorithm/data-structure/sort/bubble-sort.md b/algorithm/data-structure/sort/bubble-sort.md deleted file mode 100644 index 56df9025c5..0000000000 --- a/algorithm/data-structure/sort/bubble-sort.md +++ /dev/null @@ -1,158 +0,0 @@ ---- -title: 冒泡排序 -date: 2015/03/03 -categories: -- algorithm -tags: -- algorithm -- sort ---- - -# 冒泡排序 - -## 要点 - -冒泡排序是一种交换排序。 - -什么是交换排序呢? - -> 交换排序:两两比较待排序的关键字,并交换不满足次序要求的那对数,直到整个表都满足次序要求为止。 - -## 算法思想 - -它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。 - -这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端,故名。 - -假设有一个大小为 N 的无序序列。冒泡排序就是要每趟排序过程中通过两两比较,找到第 i 个小(大)的元素,将其往上排。 - -![冒泡排序示例图.png](http://oyz7npk35.bkt.clouddn.com//image/algorithm/sort/bubble-sort.png) - -以上图为例,演示一下冒泡排序的实际流程: - -假设有一个无序序列 { 4. 3. 1. 2, 5 } - -- 第一趟排序:通过两两比较,找到第一小的数值 1 ,将其放在序列的第一位。 - -- 第二趟排序:通过两两比较,找到第二小的数值 2 ,将其放在序列的第二位。 - -- 第三趟排序:通过两两比较,找到第三小的数值 3 ,将其放在序列的第三位。 - -至此,所有元素已经有序,排序结束。 - -要将以上流程转化为代码,我们需要像机器一样去思考,不然编译器可看不懂。 - -- 假设要对一个大小为 N 的无序序列进行升序排序(即从小到大)。 - - 每趟排序过程中需要通过比较找到第 i 个小的元素。 - - 所以,我们需要一个外部循环,从数组首端(下标 0) 开始,一直扫描到倒数第二个元素(即下标 N - 2) ,剩下最后一个元素,必然为最大。 - -- 假设是第 i 趟排序,可知,前 i-1 个元素已经有序。现在要找第 i 个元素,只需从数组末端开始,扫描到第 i 个元素,将它们两两比较即可。 - - 所以,需要一个内部循环,从数组末端开始(下标 N - 1),扫描到 (下标 i + 1)。 - -**核心代码** - -```java -public void bubbleSort(int[] list) { - int temp = 0; // 用来交换的临时数 - - // 要遍历的次数 - for (int i = 0; i < list.length - 1; i++) { - // 从后向前依次的比较相邻两个数的大小,遍历一次后,把数组中第i小的数放在第i个位置上 - for (int j = list.length - 1; j > i; j--) { - // 比较相邻的元素,如果前面的数大于后面的数,则交换 - if (list[j - 1] > list[j]) { - temp = list[j - 1]; - list[j - 1] = list[j]; - list[j] = temp; - } - } - - System.out.format("第 %d 趟:\t", i); - printAll(list); - } -} -``` - -## 算法分析 - -**冒泡排序算法的性能** - -| 参数 | 结果 | -| --------- | ----- | -| 排序类别 | 交换排序 | -| 排序方法 | 冒泡排序 | -| 时间复杂度平均情况 | O(N2) | -| 时间复杂度最坏情况 | O(N3) | -| 时间复杂度最好情况 | O(N) | -| 空间复杂度 | O(1) | -| 稳定性 | 稳定 | -| 复杂性 | 简单 | - -### 时间复杂度 - -若文件的初始状态是正序的,一趟扫描即可完成排序。所需的关键字比较次数C和记录移动次数M均达到最小值:Cmin = N - 1, Mmin = 0。所以,冒泡排序最好时间复杂度为O(N)。 - -若初始文件是反序的,需要进行 N -1 趟排序。每趟排序要进行 N - i 次关键字的比较(1 ≤ i ≤ N - 1),且每次比较都必须移动记录三次来达到交换记录位置。在这种情况下,比较和移动次数均达到最大值: - -Cmax = N(N-1)/2 = O(N2) - -Mmax = 3N(N-1)/2 = O(N2) - -冒泡排序的最坏时间复杂度为O(N2)。 - -因此,冒泡排序的平均时间复杂度为O(N2)。 - -总结起来,其实就是一句话:当数据越接近正序时,冒泡排序性能越好。 - -### 算法稳定性 - -冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。 - -所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。 - -### 优化 - -对冒泡排序常见的改进方法是加入标志性变量exchange,用于标志某一趟排序过程中是否有数据交换。 - -如果进行某一趟排序时并没有进行数据交换,则说明所有数据已经有序,可立即结束排序,避免不必要的比较过程。 - -**核心代码** - -```java -// 对 bubbleSort 的优化算法 -public void bubbleSort_2(int[] list) { - int temp = 0; // 用来交换的临时数 - boolean bChange = false; // 交换标志 - - // 要遍历的次数 - for (int i = 0; i < list.length - 1; i++) { - bChange = false; - // 从后向前依次的比较相邻两个数的大小,遍历一次后,把数组中第i小的数放在第i个位置上 - for (int j = list.length - 1; j > i; j--) { - // 比较相邻的元素,如果前面的数大于后面的数,则交换 - if (list[j - 1] > list[j]) { - temp = list[j - 1]; - list[j - 1] = list[j]; - list[j] = temp; - bChange = true; - } - } - - // 如果标志为false,说明本轮遍历没有交换,已经是有序数列,可以结束排序 - if (false == bChange) - break; - - System.out.format("第 %d 趟:\t", i); - printAll(list); - } -} -``` - -## 示例代码 - -[我的 Github 测试例](https://github.com/dunwu/algorithm-notes/blob/master/codes/src/test/java/io/github/dunwu/algorithm/sort/SortStrategyTest.java) - -样本包含:数组个数为奇数、偶数的情况;元素重复或不重复的情况。且样本均为随机样本,实测有效。 diff --git a/algorithm/data-structure/sort/heap-sort.md b/algorithm/data-structure/sort/heap-sort.md deleted file mode 100644 index a4d9de9af9..0000000000 --- a/algorithm/data-structure/sort/heap-sort.md +++ /dev/null @@ -1,168 +0,0 @@ ---- -title: 堆排序 -date: 2015/03/08 -categories: -- algorithm -tags: -- algorithm -- sort ---- - -# 堆排序 - -## 要点 - -在介绍堆排序之前,首先需要说明一下,堆是个什么玩意儿。 - -**堆**是一棵**顺序存储**的**完全二叉树**。 - -其中每个结点的关键字都**不大于**其孩子结点的关键字,这样的堆称为**小根堆**。 - -其中每个结点的关键字都**不小于**其孩子结点的关键字,这样的堆称为**大根堆**。 - -举例来说,对于 n 个元素的序列 {R0, R1, ... , Rn} 当且仅当满足下列关系之一时,称之为堆: - -- **Ri <= R2i+1 且 Ri <= R2i+2 (小根堆)** - -- **Ri >= R2i+1 且 Ri >= R2i+2 (大根堆)** - -其中 i=1,2,…,n/2 向下取整; - -![堆排序示例图.png](http://oyz7npk35.bkt.clouddn.com//image/algorithm/sort/heap-sort.png) - -如上图所示,序列 R{3, 8,15, 31, 25} 是一个典型的小根堆。 - -堆中有两个父结点,元素 3 和元素 8。 - -元素 3 在数组中以 R[0] 表示,它的左孩子结点是 R[1],右孩子结点是 R[2]。 - -元素 8 在数组中以 R[1] 表示,它的左孩子结点是 R[3],右孩子结点是 R[4],它的父结点是 R[0]。可以看出,它们**满足以下规律**: - -设当前元素在数组中以 **R[i]** 表示,那么, - -- 它的**左孩子结点**是:**R[2\*i+1]**; - -- 它的**右孩子结点**是:**R[2\*i+2]**; - -- (3) 它的**父结点**是:**R[(i-1)/2]**; - -- R[i] <= R[2*i+1] 且 R[i] <= R[2i+2]。 - - -## 算法思想 - -- 首先,按堆的定义将数组R[0..n]调整为堆(这个过程称为创建初始堆),交换R[0]和R[n]; - -- 然后,将R[0..n-1]调整为堆,交换R[0]和R[n-1]; - -- 如此反复,直到交换了R[0]和R[1]为止。 - - -以上思想可归纳为两个操作: - -1. 根据初始数组去**构造初始堆**(构建一个完全二叉树,保证所有的父结点都比它的孩子结点数值大)。 - -2. 每次**交换第一个和最后一个元素,输出最后一个元素**(最大值),然后把剩下元素**重新调整**为大根堆。 - - -当输出完最后一个元素后,这个数组已经是按照从小到大的顺序排列了。 - -先通过详细的实例图来看一下,如何构建初始堆。 - -设有一个无序序列 { 1, 3,4, 5, 2, 6, 9, 7, 8, 0 }。 - -![堆排序示例图2.png](http://oyz7npk35.bkt.clouddn.com//image/algorithm/sort/heap-sort-02.png) - -构造了初始堆后,我们来看一下完整的堆排序处理: - -还是针对前面提到的无序序列 { 1,3, 4, 5, 2, 6, 9, 7, 8, 0 } 来加以说明。 - -![堆排序示例图3.png](http://oyz7npk35.bkt.clouddn.com//image/algorithm/sort/heap-sort-03.png) - -相信,通过以上两幅图,应该能很直观的演示堆排序的操作处理。 - -**核心代码** - -```java -public void HeapAdjust(int[] array, int parent, int length) { - int temp = array[parent]; // temp保存当前父节点 - int child = 2 * parent + 1; // 先获得左孩子 - - while (child < length) { - // 如果有右孩子结点,并且右孩子结点的值大于左孩子结点,则选取右孩子结点 - if (child + 1 < length && array[child] < array[child + 1]) { - child++; - } - - // 如果父结点的值已经大于孩子结点的值,则直接结束 - if (temp >= array[child]) - break; - - // 把孩子结点的值赋给父结点 - array[parent] = array[child]; - - // 选取孩子结点的左孩子结点,继续向下筛选 - parent = child; - child = 2 * child + 1; - } - - array[parent] = temp; -} - -public void heapSort(int[] list) { - // 循环建立初始堆 - for (int i = list.length / 2; i >= 0; i--) { - HeapAdjust(list, i, list.length); - } - - // 进行n-1次循环,完成排序 - for (int i = list.length - 1; i > 0; i--) { - // 最后一个元素和第一元素进行交换 - int temp = list[i]; - list[i] = list[0]; - list[0] = temp; - - // 筛选 R[0] 结点,得到i-1个结点的堆 - HeapAdjust(list, 0, i); - System.out.format("第 %d 趟: \t", list.length - i); - printPart(list, 0, list.length - 1); - } -} -``` - -## 算法分析 - -**堆排序算法的总体情况** - -| 参数 | 结果 | -| --------- | --------- | -| 排序类别 | 选择排序 | -| 排序方法 | 堆排序 | -| 时间复杂度平均情况 | O(nlog2n) | -| 时间复杂度最坏情况 | O(nlog2n) | -| 时间复杂度最好情况 | O(nlog2n) | -| 空间复杂度 | O(1) | -| 稳定性 | 不稳定 | -| 复杂性 | 较复杂 | - -### 时间复杂度 - -堆的存储表示是**顺序的**。因为堆所对应的二叉树为完全二叉树,而完全二叉树通常采用顺序存储方式。 - -当想得到一个序列中第 **k** 个最小的元素之前的部分排序序列,最好采用堆排序。 - -因为堆排序的时间复杂度是 **O(n+klog2n)**,若 **k ≤ n/log2n**,则可得到的时间复杂度为 **O(n)**。 - -### 算法稳定性 - -堆排序是一种**不稳定**的排序方法。 - -因为在堆的调整过程中,关键字进行比较和交换所走的是该结点到叶子结点的一条路径, - -因此对于相同的关键字就可能出现排在后面的关键字被交换到前面来的情况。 - -## 示例代码 - -[我的 Github 测试例](https://github.com/dunwu/algorithm-notes/blob/master/codes/src/test/java/io/github/dunwu/algorithm/sort/SortStrategyTest.java) - -样本包含:数组个数为奇数、偶数的情况;元素重复或不重复的情况。且样本均为随机样本,实测有效。 diff --git a/algorithm/data-structure/sort/insert-sort.md b/algorithm/data-structure/sort/insert-sort.md deleted file mode 100644 index 870f86645e..0000000000 --- a/algorithm/data-structure/sort/insert-sort.md +++ /dev/null @@ -1,114 +0,0 @@ ---- -title: 插入排序 -date: 2015/03/05 -categories: -- algorithm -tags: -- algorithm -- sort ---- - -# 插入排序 - -## 要点 - -> 直接插入排序是一种最简单的**插入排序**。 -> -> **插入排序**:每一趟将一个待排序的记录,按照其关键字的大小插入到有序队列的合适位置里,知道全部插入完成。 -> - -## 算法思想 - -在讲解直接插入排序之前,先让我们脑补一下我们打牌的过程。 - -![插入排序示例图.png](http://oyz7npk35.bkt.clouddn.com//image/algorithm/sort/insert-sort.png) - -- 先拿一张5在手里, - -- 再摸到一张4,比5小,插到5前面, - -- 摸到一张6,嗯,比5大,插到5后面, - -- 摸到一张8,比6大,插到6后面, - -- 。。。 - -- 最后一看,我靠,凑到的居然是同花顺,这下牛逼大了。 - - -以上的过程,其实就是典型的**直接插入排序,每次将一个新数据插入到有序队列中的合适位置里**。 - -很简单吧,接下来,我们要将这个算法转化为编程语言。 - -假设有一组无序序列 R0, R1, ... , RN-1。 - -- 我们先将这个序列中下标为 0 的元素视为元素个数为 1 的有序序列。 - -- 然后,我们要依次把 R1, R2, ... , RN-1 插入到这个有序序列中。所以,我们需要一个**外部循环**,从下标 1 扫描到 N-1 。 - -- 接下来描述插入过程。假设这是要将 Ri 插入到前面有序的序列中。由前面所述,我们可知,插入Ri时,前 i-1 个数肯定已经是有序了。 - - -所以我们需要将Ri 和R0 ~ Ri-1 进行比较,确定要插入的合适位置。这就需要一个**内部循环**,我们一般是从后往前比较,即从下标 i-1 开始向 0 进行扫描。 - -**核心代码** - - ```java -public void insertSort(int[] list) { - // 打印第一个元素 - System.out.format("i = %d:\t", 0); - printPart(list, 0, 0); - - // 第1个数肯定是有序的,从第2个数开始遍历,依次插入有序序列 - for (int i = 1; i < list.length; i++) { - int j = 0; - int temp = list[i]; // 取出第i个数,和前i-1个数比较后,插入合适位置 - - // 因为前i-1个数都是从小到大的有序序列,所以只要当前比较的数(list[j])比temp大,就把这个数后移一位 - for (j = i - 1; j >= 0 && temp < list[j]; j--) { - list[j + 1] = list[j]; - } - list[j + 1] = temp; - - System.out.format("i = %d:\t", i); - printPart(list, 0, i); - } -} - ``` - -## 算法分析 - -**直接插入排序的算法性能** - -| 参数 | 结果 | -| --------- | ------ | -| 排序类别 | 插入排序 | -| 排序方法 | 直接插入排序 | -| 时间复杂度平均情况 | O(N2) | -| 时间复杂度最坏情况 | O(N2) | -| 时间复杂度最好情况 | O(N) | -| 空间复杂度 | O(1) | -| 稳定性 | 稳定 | -| 复杂性 | 简单 | - -### 时间复杂度 - -当数据**正序**时,执行效率**最好**,每次插入都不用移动前面的元素,时间复杂度为 **O(N)**。 - -当数据**反序**时,执行效率**最差**,每次插入都要前面的元素后移,时间复杂度为 **O(N2)**。 - -所以,**数据越接近正序,直接插入排序的算法性能越好**。 - -### 空间复杂度 - -由直接插入排序算法可知,我们在排序过程中,需要一个临时变量存储要插入的值,所以空间复杂度为 **1** 。 - -### 算法稳定性 - -直接插入排序的过程中,不需要改变相等数值元素的位置,所以它是**稳定的**算法。 - -## 示例代码 - -[我的 Github 测试例](https://github.com/dunwu/algorithm-notes/blob/master/codes/src/test/java/io/github/dunwu/algorithm/sort/SortStrategyTest.java) - -样本包含:数组个数为奇数、偶数的情况;元素重复或不重复的情况。且样本均为随机样本,实测有效。 diff --git a/algorithm/data-structure/sort/merge-sort.md b/algorithm/data-structure/sort/merge-sort.md deleted file mode 100644 index 147a9b9630..0000000000 --- a/algorithm/data-structure/sort/merge-sort.md +++ /dev/null @@ -1,165 +0,0 @@ ---- -title: 归并排序 -date: 2015/03/09 -categories: -- algorithm -tags: -- algorithm -- sort ---- - -# 归并排序 - -## 要点 - -> 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用**分治法(Divide and Conquer)**的一个非常典型的应用。 -> -> 将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为**二路归并**。 -> - -## 算法思想 - -将待排序序列 R[0...n-1] 看成是 n 个长度为 1 的有序序列,将相邻的有序表成对归并,得到 n/2 个长度为2的有序表;将这些有序序列再次归并,得到 n/4 个长度为 4 的有序序列;如此反复进行下去,最后得到一个长度为 n 的有序序列。 - -综上可知: - -归并排序其实要做两件事: - -- “分解”——将序列每次**折半划分**。 -- “合并”——将划分后的序列段**两两合并后排序**。 - -我们先来考虑第二步,**如何合并**? - -在每次合并过程中,都是对两个有序的序列段进行合并,然后排序。 - -这两个有序序列段分别为 R[low, mid] 和 R[mid+1, high]。 - -先将他们合并到一个局部的**暂存数组**R2中,带合并完成后再将R2复制回R中。 - -为了方便描述,我们称 R[low, mid] 第一段,R[mid+1, high] 为第二段。 - -每次从两个段中取出一个记录进行关键字的比较,将较小者放入R2中。最后将各段中余下的部分直接复制到R2中。 - -经过这样的过程,R2已经是一个有序的序列,再将其复制回R中,一次合并排序就完成了。 - -**核心代码** - -```java -public void Merge(int[] array, int low, int mid, int high) { - int i = low; // i是第一段序列的下标 - int j = mid + 1; // j是第二段序列的下标 - int k = 0; // k是临时存放合并序列的下标 - int[] array2 = new int[high - low + 1]; // array2是临时合并序列 - - // 扫描第一段和第二段序列,直到有一个扫描结束 - while (i <= mid && j <= high) { - // 判断第一段和第二段取出的数哪个更小,将其存入合并序列,并继续向下扫描 - if (array[i] <= array[j]) { - array2[k] = array[i]; - i++; - k++; - } else { - array2[k] = array[j]; - j++; - k++; - } - } - - // 若第一段序列还没扫描完,将其全部复制到合并序列 - while (i <= mid) { - array2[k] = array[i]; - i++; - k++; - } - - // 若第二段序列还没扫描完,将其全部复制到合并序列 - while (j <= high) { - array2[k] = array[j]; - j++; - k++; - } - - // 将合并序列复制到原始序列中 - for (k = 0, i = low; i <= high; i++, k++) { - array[i] = array2[k]; - } -} -``` - -掌握了合并的方法,接下来,让我们来了解**如何分解**。 - -![归并排序示例图.png](http://oyz7npk35.bkt.clouddn.com//image/algorithm/sort/merge-sort.png) - -在某趟归并中,设各子表的长度为 **gap**,则归并前 R[0...n-1] 中共有 **n/gap** 个有序的子表:`R[0...gap-1]`, `R[gap...2*gap-1]`, ... , `R[(n/gap)*gap ... n-1]`。 - -调用 Merge **将相邻的子表归并**时,必须对表的特殊情况进行特殊处理。 - -若子表个数为奇数,则最后一个子表无须和其他子表归并(即本趟处理轮空):若子表个数为偶数,则要注意到最后一对子表中后一个子表区间的上限为n-1。 - -**核心代码** - -```java -public void MergePass(int[] array, int gap, int length) { - int i = 0; - - // 归并gap长度的两个相邻子表 - for (i = 0; i + 2 * gap - 1 < length; i = i + 2 * gap) { - Merge(array, i, i + gap - 1, i + 2 * gap - 1); - } - - // 余下两个子表,后者长度小于gap - if (i + gap - 1 < length) { - Merge(array, i, i + gap - 1, length - 1); - } -} - -public int[] sort(int[] list) { - for (int gap = 1; gap < list.length; gap = 2 * gap) { - MergePass(list, gap, list.length); - System.out.print("gap = " + gap + ":\t"); - this.printAll(list); - } - return list; -} -``` - -## 算法分析 - -**归并排序算法的性能** - -| 参数 | 结果 | -| --------- | --------- | -| 排序类别 | 归并排序 | -| 排序方法 | 归并排序 | -| 时间复杂度平均情况 | O(nlog2n) | -| 时间复杂度最坏情况 | O(nlog2n) | -| 时间复杂度最好情况 | O(nlog2n) | -| 空间复杂度 | O(n) | -| 稳定性 | 稳定 | -| 复杂性 | 较复杂 | - -### 时间复杂度 - -归并排序的形式就是一棵二叉树,它需要遍历的次数就是二叉树的深度,而根据完全二叉树的可以得出它的时间复杂度是 **O(n\*log2n)**。 - -### 空间复杂度 - -由前面的算法说明可知,算法处理过程中,需要一个大小为 **n** 的临时存储空间用以保存合并序列。 - -### 算法稳定性 - -在归并排序中,相等的元素的顺序不会改变,所以它是**稳定的**算法。 - -### 归并排序和堆排序、快速排序的比较 - -若从空间复杂度来考虑:首选堆排序,其次是快速排序,最后是归并排序。 - -若从稳定性来考虑,应选取归并排序,因为堆排序和快速排序都是不稳定的。 - -若从平均情况下的排序速度考虑,应该选择快速排序。 - -## 示例代码 - -[我的 Github 测试例](https://github.com/dunwu/algorithm-notes/blob/master/codes/src/test/java/io/github/dunwu/algorithm/sort/SortStrategyTest.java) - -样本包含:数组个数为奇数、偶数的情况;元素重复或不重复的情况。且样本均为随机样本,实测有效。 diff --git a/algorithm/data-structure/sort/quick-sort.md b/algorithm/data-structure/sort/quick-sort.md deleted file mode 100644 index a3211c2f92..0000000000 --- a/algorithm/data-structure/sort/quick-sort.md +++ /dev/null @@ -1,125 +0,0 @@ ---- -title: 快速排序 -date: 2015/03/04 -categories: -- algorithm -tags: -- algorithm -- sort ---- - -# 快速排序 - -## 要点 - -> 快速排序是一种交换排序。 - -快速排序由C. A. R. Hoare在1962年提出。 - -## 算法思想 - -它的基本思想是: - -通过一趟排序将要排序的数据分割成独立的两部分:分割点左边都是比它小的数,右边都是比它大的数。 - -然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。 - -详细的图解往往比大堆的文字更有说明力,所以直接上图: - -![快速排序示例图.png](http://oyz7npk35.bkt.clouddn.com//image/algorithm/sort/quick-sort.png) - -上图中,演示了快速排序的处理过程: - -1. 初始状态为一组无序的数组:2、4、5、1、3。 - -2. 经过以上操作步骤后,完成了第一次的排序,得到新的数组:1、2、5、4、3。 - -3. 新的数组中,以 2 为分割点,左边都是比 2 小的数,右边都是比 2 大的数。 - -4. 因为2已经在数组中找到了合适的位置,所以不用再动。 - -5. 2左边的数组只有一个元素 1,所以显然不用再排序,位置也被确定。(注:这种情况时,left指针和right指针显然是重合的。因此在代码中,我们可以通过设置判定条件left必须小于right,如果不满足,则不用排序了)。 - -6. 而对于2右边的数组 5、4、3,设置left指向 5,right指向 3,开始继续重复图中的一、二、三、四步骤,对新的数组进行排序。 - -**核心代码** - -```java -public int division(int[] list, int left, int right) { - // 以最左边的数(left)为基准 - int base = list[left]; - while (left < right) { - // 从序列右端开始,向左遍历,直到找到小于base的数 - while (left < right && list[right] >= base) - right--; - // 找到了比base小的元素,将这个元素放到最左边的位置 - list[left] = list[right]; - - // 从序列左端开始,向右遍历,直到找到大于base的数 - while (left < right && list[left] <= base) - left++; - // 找到了比base大的元素,将这个元素放到最右边的位置 - list[right] = list[left]; - } - - // 最后将base放到left位置。此时,left位置的左侧数值应该都比left小; - // 而left位置的右侧数值应该都比left大。 - list[left] = base; - return left; -} - -private void quickSort(int[] list, int left, int right) { - - // 左下标一定小于右下标,否则就越界了 - if (left < right) { - // 对数组进行分割,取出下次分割的基准标号 - int base = division(list, left, right); - - System.out.format("base = %d:\t", list[base]); - printPart(list, left, right); - - // 对“基准标号“左侧的一组数值进行递归的切割,以至于将这些数值完整的排序 - quickSort(list, left, base - 1); - - // 对“基准标号“右侧的一组数值进行递归的切割,以至于将这些数值完整的排序 - quickSort(list, base + 1, right); - } -} -``` - -## 算法分析 - -快速排序算法的性能 - -| 参数 | 结果 | -| --------- | --------- | -| 排序类别 | 交换排序 | -| 排序方法 | 快速排序 | -| 时间复杂度平均情况 | O(Nlog2N) | -| 时间复杂度最坏情况 | O(N2) | -| 时间复杂度最好情况 | O(Nlog2N) | -| 空间复杂度 | O(Nlog2N) | -| 稳定性 | 不稳定 | -| 复杂性 | 较复杂 | - -### 时间复杂度 - -当数据有序时,以第一个关键字为基准分为两个子序列,前一个子序列为空,此时执行效率最差。 - -而当数据随机分布时,以第一个关键字为基准分为两个子序列,两个子序列的元素个数接近相等,此时执行效率最好。 - -所以,数据越随机分布时,快速排序性能越好;数据越接近有序,快速排序性能越差。 - -### 空间复杂度 - -快速排序在每次分割的过程中,需要 1 个空间存储基准值。而快速排序的大概需要 Nlog2N 次的分割处理,所以占用空间也是 Nlog2N 个。 - -### 算法稳定性 - -在快速排序中,相等元素可能会因为分区而交换顺序,所以它是不稳定的算法。 - -## 示例代码 - -[我的 Github 测试例](https://github.com/dunwu/algorithm-notes/blob/master/codes/src/test/java/io/github/dunwu/algorithm/sort/SortStrategyTest.java) - -样本包含:数组个数为奇数、偶数的情况;元素重复或不重复的情况。且样本均为随机样本,实测有效。 diff --git a/algorithm/data-structure/sort/radix-sort.md b/algorithm/data-structure/sort/radix-sort.md deleted file mode 100644 index 0af830f198..0000000000 --- a/algorithm/data-structure/sort/radix-sort.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: 基数排序 -date: 2015/03/10 -categories: -- algorithm -tags: -- algorithm -- sort ---- - -# 基数排序 - -## 要点 - -基数排序与本系列前面讲解的七种排序方法都不同,它**不需要比较关键字的大小**。 - -它是根据关键字中各位的值,通过对排序的N个元素进行若干趟“分配”与“收集”来实现排序的。 - -不妨通过一个具体的实例来展示一下,基数排序是如何进行的。 - -设有一个初始序列为: R {50, 123, 543, 187, 49, 30,0, 2, 11, 100}。 - -我们知道,任何一个阿拉伯数,它的各个位数上的基数都是以 0~9 来表示的。 - -所以我们不妨把 0~9 视为 10 个桶。 - -我们先根据序列的个位数的数字来进行分类,将其分到指定的桶中。例如:R[0] = 50,个位数上是0,将这个数存入编号为 0 的桶中。 - -![基数排序示例图.png](http://oyz7npk35.bkt.clouddn.com//image/algorithm/sort/radix-sort.png) - -分类后,我们在从各个桶中,将这些数按照从编号0到编号9的顺序依次将所有数取出来。 - -这时,得到的序列就是个位数上呈递增趋势的序列。 - -按照个位数排序: {50, 30, 0, 100, 11, 2, 123,543, 187, 49}。 - -接下来,可以对十位数、百位数也按照这种方法进行排序,最后就能得到排序完成的序列。 - - -## 算法分析 - -**基数排序的性能** - -| 参数 | 结果 | -| --------- | --------- | -| 排序类别 | 基数排序 | -| 排序方法 | 基数排序 | -| 时间复杂度平均情况 | O(d(n+r)) | -| 时间复杂度最坏情况 | O(d(n+r)) | -| 时间复杂度最好情况 | O(d(n+r)) | -| 空间复杂度 | O(n+r) | -| 稳定性 | 稳定 | -| 复杂性 | 较复杂 | - -### 时间复杂度 - -通过上文可知,假设在基数排序中,r 为基数,d 为位数。则基数排序的时间复杂度为 **O(d(n+r))**。 - -我们可以看出,基数排序的效率和初始序列是否有序没有关联。 - -### 空间复杂度 - -在基数排序过程中,对于任何位数上的基数进行“装桶”操作时,都需要 **n+r** 个临时空间。 - -### 算法稳定性 - -在基数排序过程中,每次都是将当前位数上相同数值的元素统一“装桶”,并不需要交换位置。所以基数排序是**稳定**的算法。 - -## 示例代码 - -[我的 Github 测试例](https://github.com/dunwu/algorithm-notes/blob/master/codes/src/test/java/io/github/dunwu/algorithm/sort/SortStrategyTest.java) - -样本包含:数组个数为奇数、偶数的情况;元素重复或不重复的情况。且样本均为随机样本,实测有效。 diff --git a/algorithm/data-structure/sort/selection-sort.md b/algorithm/data-structure/sort/selection-sort.md deleted file mode 100644 index d9382e9601..0000000000 --- a/algorithm/data-structure/sort/selection-sort.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: 简单选择排序 -date: 2015/03/07 -categories: -- algorithm -tags: -- algorithm -- sort ---- - -# 简单选择排序 - -## 要点 - -> 简单选择排序是一种**选择排序**。 -> -> **选择排序**:每趟从待排序的记录中选出关键字最小的记录,顺序放在已排序的记录序列末尾,直到全部排序结束为止。 -> - -## 算法思想 - -1. 从待排序序列中,找到关键字最小的元素; - -2. 如果最小元素不是待排序序列的第一个元素,将其和第一个元素互换; - -3. 从余下的 N - 1 个元素中,找出关键字最小的元素,重复 1、2 步,直到排序结束。 - -如图所示,每趟排序中,将当前**第 i 小的元素放在位置 i **上。 - -**核心代码** - -![选择排序示例图.png](http://oyz7npk35.bkt.clouddn.com//image/algorithm/sort/selection-sort.png) - -## 算法分析 - -**简单选择排序算法的性能** - -| 参数 | 结果 | -| --------- | ------ | -| 排序类别 | 选择排序 | -| 排序方法 | 简单选择排序 | -| 时间复杂度平均情况 | O(N2) | -| 时间复杂度最坏情况 | O(N2) | -| 时间复杂度最好情况 | O(N2) | -| 空间复杂度 | O(1) | -| 稳定性 | 不稳定 | -| 复杂性 | 简单 | - -### 时间复杂度 - -简单选择排序的比较次数与序列的初始排序无关。 假设待排序的序列有 **N** 个元素,则**比较次数总是 N (N - 1) / 2 **。 - -而移动次数与序列的初始排序有关。当序列正序时,移动次数最少,为 **0**. - -当序列反序时,移动次数最多,为 **3N (N - 1) / 2**。 - -所以,综合以上,简单排序的时间复杂度为 **O(N2)**。 - -### 空间复杂度 - -简单选择排序需要占用一个临时空间,在交换数值时使用。 - -## 示例代码 - -[我的 Github 测试例](https://github.com/dunwu/algorithm-notes/blob/master/codes/src/test/java/io/github/dunwu/algorithm/sort/SortStrategyTest.java) - -样本包含:数组个数为奇数、偶数的情况;元素重复或不重复的情况。且样本均为随机样本,实测有效。 diff --git a/algorithm/data-structure/sort/shell-sort.md b/algorithm/data-structure/sort/shell-sort.md deleted file mode 100644 index ae88d20e77..0000000000 --- a/algorithm/data-structure/sort/shell-sort.md +++ /dev/null @@ -1,127 +0,0 @@ ---- -title: 希尔排序 -date: 2015/03/06 -categories: -- algorithm -tags: -- algorithm -- sort ---- - -# 希尔排序 - -## 要点 - -> 希尔(Shell)排序又称为**缩小增量排序**,它是一种**插入排序**。它**是直接插入排序算法的一种威力加强版**。 -> - -该方法因DL.Shell于1959年提出而得名。 - -## 算法思想 - -希尔排序的**基本思想**是: - -把记录按**步长 gap** 分组,对每组记录采用**直接插入排序**方法进行排序。 -随着**步长逐渐减小**,所分成的组包含的记录越来越多,当步长的值减小到 **1** 时,整个数据合成为一组,构成一组有序记录,则完成排序。 - -我们来通过演示图,更深入的理解一下这个过程。 - -![希尔排序示例图.png](http://oyz7npk35.bkt.clouddn.com//image/algorithm/sort/shell-sort.png) - -在上面这幅图中: - -初始时,有一个大小为 10 的无序序列。 - -- 在**第一趟排序中**,我们不妨设 gap1 = N / 2 = 5,即相隔距离为 5 的元素组成一组,可以分为 5 组。 - - 接下来,按照直接插入排序的方法对每个组进行排序。 - - -- 在**第二趟排序中**,我们把上次的 gap 缩小一半,即 gap2 = gap1 / 2 = 2 (取整数)。这样每相隔距离为 2 的元素组成一组,可以分为 2 组。 - - 按照直接插入排序的方法对每个组进行排序。 - - -- 在**第三趟排序中**,再次把 gap 缩小一半,即gap3 = gap2 / 2 = 1。 这样相隔距离为 1 的元素组成一组,即只有一组。 - - 按照直接插入排序的方法对每个组进行排序。此时,**排序已经结束**。 - -需要注意一下的是,图中有两个相等数值的元素 **5** 和 **5** 。我们可以清楚的看到,在排序过程中,**两个元素位置交换了**。 - -所以,希尔排序是不稳定的算法。 - -**核心代码** - - ```java -public void shellSort(int[] list) { - int gap = list.length / 2; - - while (1 <= gap) { - // 把距离为 gap 的元素编为一个组,扫描所有组 - for (int i = gap; i < list.length; i++) { - int j = 0; - int temp = list[i]; - - // 对距离为 gap 的元素组进行排序 - for (j = i - gap; j >= 0 && temp < list[j]; j = j - gap) { - list[j + gap] = list[j]; - } - list[j + gap] = temp; - } - - System.out.format("gap = %d:\t", gap); - printAll(list); - gap = gap / 2; // 减小增量 - } -} - ``` - -## 算法分析 - -**希尔排序的算法性能** - -| 参数 | 结果 | -| --------- | --------- | -| 排序类别 | 插入排序 | -| 排序方法 | 希尔排序 | -| 时间复杂度平均情况 | O(Nlog2N) | -| 时间复杂度最坏情况 | O(N1.5) | -| 时间复杂度最好情况 | | -| 空间复杂度 | O(1) | -| 稳定性 | 不稳定 | -| 复杂性 | 较复杂 | - -### 时间复杂度 - -步长的选择是希尔排序的重要部分。只要最终步长为1任何步长序列都可以工作。 - -算法最开始以一定的步长进行排序。然后会继续以一定步长进行排序,最终算法以步长为1进行排序。当步长为1时,算法变为插入排序,这就保证了数据一定会被排序。 - -Donald Shell 最初建议步长选择为N/2并且对步长取半直到步长达到1。虽然这样取可以比O(N2)类的算法(插入排序)更好,但这样仍然有减少平均时间和最差时间的余地。可能希尔排序最重要的地方在于当用较小步长排序后,以前用的较大步长仍然是有序的。比如,如果一个数列以步长5进行了排序然后再以步长3进行排序,那么该数列不仅是以步长3有序,而且是以步长5有序。如果不是这样,那么算法在迭代过程中会打乱以前的顺序,那就不会以如此短的时间完成排序了。 - -已知的最好步长序列是由Sedgewick提出的(1, 5, 19, 41, 109,...),该序列的项来自这两个算式。 - -这项研究也表明“比较在希尔排序中是最主要的操作,而不是交换。”用这样步长序列的希尔排序比插入排序和堆排序都要快,甚至在小数组中比快速排序还快,但是在涉及大量数据时希尔排序还是比快速排序慢。 - -### 算法稳定性 - -由上文的**希尔排序算法演示图**即可知,希尔排序中相等数据可能会交换位置,所以希尔排序是**不稳定**的算法。 - -### 直接插入排序和希尔排序的比较 - -- 直接插入排序是**稳定的**;而希尔排序是**不稳定**的。 - -- 直接插入排序更适合于原始记录基本**有序**的集合。 - -- 希尔排序的比较次数和移动次数都要比直接插入排序少,当N越大时,效果越明显。 - -- 在希尔排序中,增量序列gap的取法必须满足:**最后一个步长必须是 1 。 ** - -- 直接插入排序也**适用于链式存储结构**;希尔排序**不适用于链式结构**。 - - -## 示例代码 - -[我的 Github 测试例](https://github.com/dunwu/algorithm-notes/blob/master/codes/src/test/java/io/github/dunwu/algorithm/sort/SortStrategyTest.java) - -样本包含:数组个数为奇数、偶数的情况;元素重复或不重复的情况。且样本均为随机样本,实测有效。 diff --git a/algorithm/data-structure/stack.md b/algorithm/data-structure/stack.md deleted file mode 100644 index 963f48bc0f..0000000000 --- a/algorithm/data-structure/stack.md +++ /dev/null @@ -1,41 +0,0 @@ -# 堆栈 - -> 堆栈(英语:stack)又称为栈或堆叠,是计算机科学中一种特殊的串列形式的抽象数据类型,其特殊之处在于只能允许在链表或数组的一端(称为堆栈顶端指针,英语:top)进行加入数据(英语:push)和输出数据(英语:pop)的运算。另外堆栈也可以用一维数组或链表的形式来完成。堆栈的另外一个相对的操作方式称为队列。 -> -> 由于堆栈数据结构只允许在一端进行操作,因而按照后进先出(LIFO, Last In First Out)的原理运作。 - -![](http://dunwu.test.upcdn.net/images/data-structure/stack/stack.png) - - - -- [概念](#概念) -- [应用](#应用) -- [引申和引用](#引申和引用) - - - -## 概念 - -### 特点 - -堆栈的基本特点: - -1. 先入后出,后入先出。 -2. 除头尾节点之外,每个元素有一个前驱,一个后继。 - -### 操作 - -堆栈数据结构使用两种基本操作:推入(压栈,push)和弹出(弹栈,pop): - -- 推入 - 将数据放入堆栈的顶端(数组形式或串列形式),堆栈顶端 top 指针加一。 -- 弹出 - 将顶端数据数据输出(回传),堆栈顶端数据减一。 - -## 应用 - -- 回溯 -- 递归 -- 深度优先搜索 - -## 引申和引用 - -- https://zh.wikipedia.org/wiki/堆栈 diff --git a/algorithm/data-structure/tree/binary-tree.md b/algorithm/data-structure/tree/binary-tree.md deleted file mode 100644 index 1a57ff0983..0000000000 --- a/algorithm/data-structure/tree/binary-tree.md +++ /dev/null @@ -1,37 +0,0 @@ -# 二叉树 - -![](http://dunwu.test.upcdn.net/images/data-structure/tree/二叉树.png) - - - -- [简介](#简介) - - [二叉树的性质](#二叉树的性质) - - [满二叉树](#满二叉树) - - [完全二叉树](#完全二叉树) - - - -## 简介 - -二叉树是 N 个节点的有限集合,它或者是空树,或者是由一个根节点及两棵不想交的且分别称为左右子树的二叉树所组成。 - -### 二叉树的性质 - -1. 二叉树第 i 层上的结点数目最多为 **2i-1** (i≥1)。 -2. 深度为 k 的二叉树至多有 **2k-1** 个结点(k≥1)。 -3. 包含 n 个结点的二叉树的高度至少为 **log2(n+1)**。 -4. 在任意一棵二叉树中,若终端结点的个数为 n0,度为 2 的结点数为 n2,则 n0=n2+1。 - -### 满二叉树 - -定义:高度为 h,并且由 **2h–1** 个结点的二叉树,被称为满二叉树。 - -![](http://dunwu.test.upcdn.net/images/data-structure/tree/满二叉树.png) - -### 完全二叉树 - -定义:一棵二叉树中,只有最下面两层结点的度可以小于 2,并且最下一层的叶结点集中在靠左的若干位置上。这样的二叉树称为完全二叉树。 - -特点:叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左部。显然,一棵满二叉树必定是一棵完全二叉树,而完全二叉树未必是满二叉树。 - -![](http://dunwu.test.upcdn.net/images/data-structure/tree/完全二叉树.png) diff --git a/algorithm/data-structure/tree/red-black-tree.md b/algorithm/data-structure/tree/red-black-tree.md deleted file mode 100644 index f5817b841a..0000000000 --- a/algorithm/data-structure/tree/red-black-tree.md +++ /dev/null @@ -1,268 +0,0 @@ ---- -title: 红黑树 -date: 2018/06/01 -categories: -- algorithm -tags: -- algorithm -- tree ---- - -# 红黑树 - -> 红黑树(英语:Red–black tree)是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。它是复杂的,但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的:它可以在 $O(\log_2 N)$ 时间内做查找,插入和删除,这里的 n 是树中元素的数目。 - -## 红黑树的性质 - -红黑树,顾名思义,通过红黑两种颜色域保证树的高度近似平衡。它的每个节点是一个五元组:color(颜色),key(数据),left(左孩子),right(右孩子)和 p(父节点)。 - -红黑树的定义也是它的性质,有以下五条: - -1. 节点是红色或黑色。 - -2. 根是黑色。 - -3. 所有叶子都是黑色(叶子是 NIL 节点)。 - -4. 每个红色节点必须有两个黑色的子节点。(从每个叶子到根的所有路径上不能有两个连续的红色节点。 - -5. 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。 - -
- -
- -这五个性质强制了红黑树的关键性质: 从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。为什么呢?性质 4 暗示着任何一个简单路径上不能有两个毗连的红色节点,这样,最短的可能路径全是黑色节点,最长的可能路径有交替的红色和黑色节点。同时根据性质 5 知道:所有最长的路径都有相同数目的黑色节点,这就表明了没有路径能多于任何其他路径的两倍长。 - -## 红黑树的操作 - -因为红黑树也是二叉查找树,因此红黑树上的查找操作与普通二叉查找树上的查找操作相同。然而,红黑树上的插入操作和删除操作会导致不再符合红黑树的性质。恢复红黑树的性质需要少量($O(\log_2 N)$)的颜色变更(实际是非常快速的)和不超过三次树旋转(对于插入操作是两次)。虽然插入和删除很复杂,但操作时间仍可以保持为 $O(\log_2 N)$ 次。 - -### 插入操作 - -插入操作可以概括为以下几个步骤: - -1. 查找要插入的位置,时间复杂度为:$O(N)$ - -2. 将新节点的 color 赋为红色 - -3. 自下而上重新调整该树为红黑树 - -其中,第 1 步的查找方法跟普通二叉查找树一样,第 2 步之所以将新插入的节点的颜色赋为红色,是因为:如果设为黑色,就会导致根到叶子的路径上有一条路上,多一个额外的黑节点,这个是很难调整的。但是设为红色节点后,可能会导致出现两个连续红色节点的冲突,那么可以通过颜色调换(color flips)和树旋转来调整,这样简单多了。下面讨论步骤 3 的一些细节: - -设要插入的节点为 N,其父节点为 P,其父节点 P 的兄弟节点为 U(即 P 和 U 是同一个节点的两个子节点)。 - -* 如果 P 是黑色的,则整棵树不必调整便是红黑树。 - -* 如果 P 是红色的(可知,其父节点 G 一定是黑色的),则插入 N 后,违背了性质 4,需要进行调整。调整时分以下 3 种情况: - - 3.1. 如果父节点 P 和叔父节点 U 二者都是红色 - -
- -
- -如上图所示,我们将 P 和 U 重绘为黑色,并重绘节点 G 为红色(用来保持性质 5)。 - -现在新节点 N 有了一个黑色的父节点 P,因为通过父节点 P 或叔父节点 U 的任何路径都必定通过祖父节点 G,在这些路径上的黑节点数目没有改变。 - -但是,红色的祖父节点 G 的父节点也有可能是红色的,这就违反了性质 4。为了解决这个问题,我们在祖父节点 G 上递归调整颜色。 - -3.2. 父节点 P 是红色而叔父节点 U 是黑色或缺少,新节点 N 是右孩子节点,而父节点 P 又是其父节点 G 的左孩子节点。 - -
- -
- -在这种情形下,我们进行一次左旋转调换新节点和其父节点的角色;接着,我们按情形 3.3 处理以前的父节点 P 以解决仍然失效的性质 4。注意这个改变会导致某些路径通过它们以前不通过的新节点 N(比如图中 1 号叶子节点)或不通过节点 P(比如图中 3 号叶子节点),但由于这两个节点都是红色的,所以性质 5 仍有效。 - -3.3. 父节点 P 是红色而叔父节点 U 是黑色或缺少,新节点 N 是左孩子节点,而父节点 P 又是其父节点 G 的左孩子节点。 - -
- -
- -在这种情形下,我们进行针对祖父节点 G 的一次右旋转;在旋转产生的树中,以前的父节点 P 现在是新节点 N 和以前的祖父节点 G 的父节点。我们知道以前的祖父节点 G 是黑色,否则父节点 P 就不可能是红色(如果 P 和 G 都是红色就违反了性质 4,所以 G 必须是黑色)。我们切换以前的父节点 P 和祖父节点 G 的颜色,结果的树满足性质 4。性质 5 也仍然保持满足,因为通过这三个节点中任何一个的所有路径以前都通过祖父节点 G,现在它们都通过以前的父节点 P。在各自的情形下,这都是三个节点中唯一的黑色节点。 - -### 删除操作 - -删除操作可以概括为以下几个步骤: - -1. 查找要删除位置,时间复杂度为:O(N) - -2. 用删除节点后继或者节点替换该节点(只进行数据替换即可,不必调整指针,后继节点是中序遍历中紧挨着该节点的节点,即:右孩子的最左孩子节点) - -3. 如果删除节点的替换节点为黑色,则需重新调整该树为红黑树 - -其中,第 1 步的查找方法跟普通二叉查找树一样,第 2 步之所以用后继节点替换删除节点,是因为这样可以保证该后继节点之上仍是一个红黑树,而后继节点可能是一个叶节点或者只有右子树的节点,这样只需用有节点替换后继节点即可达到删除的目的。如果需要删除的节点有两个儿子,那么问题可以被转化成删除另一个只有一个儿子的节点的问题。 - -在第 3 步中 - -* 如果,如果删除节点为红色节点,则他的父亲和孩子全为黑节点,这样直接删除该节点即可,不必进行任何调整。 - -* 如果删除节点是黑节点,分四种情况: - -设要删除的节点为 N,其父节点为 P,其兄弟节点为 S。 - -由于 N 是黑色的,则 P 可能是黑色的,也可能是红色的,S 也可能是黑色的或者红色的 - -3.1 S 是红色的 - -此时 P 肯定是红色的。我们对 N 的父节点进行左旋转,然后把红色兄弟转换成 N 的祖父。我们接着对调 N 的父亲和祖父的颜色。尽管所有的路径仍然有相同数目的黑色节点,现在 N 有了一个黑色的兄弟和一个红色的父亲,所以我们可以接下去按 (2)、(3)或(4)情况来处理。 - -
- -
- -3.2 S和S的孩子全是黑色的 - -在这种情况下,P 可能是黑色的或者红色的,我们简单的重绘 S 为红色。结果是通过 S 的所有路径,它们就是以前不通过 N 的那些路径,都少了一个黑色节点。因为删除 N 的初始的父亲使通过 N 的所有路径少了一个黑色节点,这使事情都平衡了起来。但是,通过 P 的所有路径现在比不通过 P 的路径少了一个黑色节点。接下来,要调整以 P 作为 N 递归调整树。 - -
- -
- -3.3 S是黑色的,S的左孩子是红色,右孩子是黑色 - -这种情况下我们在 S 上做右旋转,这样 S 的左儿子成为 S 的父亲和 N 的新兄弟。我们接着交换 S 和它的新父亲的颜色。所有路径仍有同样数目的黑色节点,但是现在 N 有了一个右儿子是红色的黑色兄弟,所以我们进入了情况(4)。N 和它的父亲都不受这个变换的影响。 - -
- -
- -3.4 S是黑色的,S的右孩子是红色 - -在这种情况下我们在 N 的父亲上做左旋转,这样 S 成为 N 的父亲和 S 的右儿子的父亲。我们接着交换 N 的父亲和 S 的颜色,并使 S 的右儿子为黑色。子树在它的根上的仍是同样的颜色,所以属性 3 没有被违反。但是,N 现在增加了一个黑色祖先: 要么 N 的父亲变成黑色,要么它是黑色而 S 被增加为一个黑色祖父。所以,通过 N 的路径都增加了一个黑色节点。 - -
- -
- -## 示例代码 - -### 红黑树插入操作调整 - -fixAfterInsertion 方法摘自 JDK8 的 TreeMap.java。 - -阅读本示例前,请参看本文的“插入操作”一节。 - -```java - private void fixAfterInsertion(Entry x) { - // 2. 将新节点的 color 赋为红色 - x.color = RED; - - // 3. 自下而上重新调整该树为红黑树 - while (x != null && x != root && x.parent.color == RED) { // 如果父节点是黑色的,则整棵树不必调整便是红黑树。 - if (parentOf(x) == leftOf(parentOf(parentOf(x)))) { // 父节点是祖父节点的左节点 - Entry y = rightOf(parentOf(parentOf(x))); // 叔叔节点 - if (colorOf(y) == RED) { // 3.1 叔叔节点是红色的 - setColor(parentOf(x), BLACK); - setColor(y, BLACK); - setColor(parentOf(parentOf(x)), RED); - x = parentOf(parentOf(x)); - } else { - // 3.2 新节点是右孩子节点:左旋新节点和父节点;调换新节点和父节点的颜色;右旋祖父节点 - if (x == rightOf(parentOf(x))) { - x = parentOf(x); - rotateLeft(x); // 父节点左旋 - } - setColor(parentOf(x), BLACK); - setColor(parentOf(parentOf(x)), RED); - rotateRight(parentOf(parentOf(x))); - } - } else { // 父节点是祖父节点的右节点 - Entry y = leftOf(parentOf(parentOf(x))); // 叔叔节点 - if (colorOf(y) == RED) { // 3.1 叔叔节点是红色的 - setColor(parentOf(x), BLACK); - setColor(y, BLACK); - setColor(parentOf(parentOf(x)), RED); - x = parentOf(parentOf(x)); - } else { - // 新节点是左孩子节点 - if (x == leftOf(parentOf(x))) { - x = parentOf(x); - rotateRight(x); // 父节点右旋 - } - setColor(parentOf(x), BLACK); // 原父亲节点设为黑色 - setColor(parentOf(parentOf(x)), RED); // 原祖父节点设为红色 - rotateLeft(parentOf(parentOf(x))); - } - } - } - root.color = BLACK; -} -``` - -### 红黑树删除操作调整 - -fixAfterDeletion 方法摘自 JDK8 的 TreeMap.java。 - -阅读本示例前,请参看本文的“删除操作”一节。 - -```java -private void fixAfterDeletion(Entry x) { - while (x != root && colorOf(x) == BLACK) { - if (x == leftOf(parentOf(x))) { - Entry sib = rightOf(parentOf(x)); - - if (colorOf(sib) == RED) { - setColor(sib, BLACK); - setColor(parentOf(x), RED); - rotateLeft(parentOf(x)); - sib = rightOf(parentOf(x)); - } - - if (colorOf(leftOf(sib)) == BLACK && - colorOf(rightOf(sib)) == BLACK) { - setColor(sib, RED); - x = parentOf(x); - } else { - if (colorOf(rightOf(sib)) == BLACK) { - setColor(leftOf(sib), BLACK); - setColor(sib, RED); - rotateRight(sib); - sib = rightOf(parentOf(x)); - } - setColor(sib, colorOf(parentOf(x))); - setColor(parentOf(x), BLACK); - setColor(rightOf(sib), BLACK); - rotateLeft(parentOf(x)); - x = root; - } - } else { // symmetric - Entry sib = leftOf(parentOf(x)); - - if (colorOf(sib) == RED) { - setColor(sib, BLACK); - setColor(parentOf(x), RED); - rotateRight(parentOf(x)); - sib = leftOf(parentOf(x)); - } - - if (colorOf(rightOf(sib)) == BLACK && - colorOf(leftOf(sib)) == BLACK) { - setColor(sib, RED); - x = parentOf(x); - } else { - if (colorOf(leftOf(sib)) == BLACK) { - setColor(rightOf(sib), BLACK); - setColor(sib, RED); - rotateLeft(sib); - sib = leftOf(parentOf(x)); - } - setColor(sib, colorOf(parentOf(x))); - setColor(parentOf(x), BLACK); - setColor(leftOf(sib), BLACK); - rotateRight(parentOf(x)); - x = root; - } - } - } - - setColor(x, BLACK); -} -``` - -## 资料 - -https://zh.wikipedia.org/wiki/%E7%BA%A2%E9%BB%91%E6%A0%91 diff --git a/algorithm/data-structure/tree/tree.md b/algorithm/data-structure/tree/tree.md deleted file mode 100644 index 196d2c668c..0000000000 --- a/algorithm/data-structure/tree/tree.md +++ /dev/null @@ -1,47 +0,0 @@ -# 树 - -## 概念 - -### 什么是树? - -在计算器科学中,树(英语:tree)是一种抽象数据类型(ADT)或是实现这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合。它是由 n(n>0)个有限节点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点: - -- 每个节点有零个或多个子节点; -- 没有父节点的节点称为根节点; -- 每一个非根节点有且只有一个父节点; -- 除了根节点外,每个子节点可以分为多个不相交的子树; - -![](http://dunwu.test.upcdn.net/images/data-structure/tree/tree.png) - -### 树的术语 - -- 节点的度 - 一个节点含有的子树的个数称为该节点的度; -- 树的度 - 一棵树中,最大的节点的度称为树的度; -- 叶节点或终端节点 - 度为零的节点; -- 非终端节点或分支节点 - 度不为零的节点; -- 父亲节点或父节点 - 若一个节点含有子节点,则这个节点称为其子节点的父节点; -- 孩子节点或子节点 - 一个节点含有的子树的根节点称为该节点的子节点; -- 兄弟节点 - 具有相同父节点的节点互称为兄弟节点; -- 节点的层次 - 从根开始定义起,根为第 1 层,根的子节点为第 2 层,以此类推; -- 深度 - 对于任意节点 n,n 的深度为从根到 n 的唯一路径长,根的深度为 0; -- 高度 - 对于任意节点 n,n 的高度为从 n 到一片树叶的最长路径长,所有树叶的高度为 0; -- 堂兄弟节点 - 父节点在同一层的节点互为堂兄弟; -- 节点的祖先 - 从根到该节点所经分支上的所有节点; -- 子孙 - 以某节点为根的子树中任一节点都称为该节点的子孙。 -- 森林 - 由 m(m>=0)棵互不相交的树的集合称为森林; - -## 树的种类 - -- 无序树 - 树中任意节点的子节点之间没有顺序关系,这种树称为无序树,也称为自由树; -- 有序树 - 树中任意节点的子节点之间有顺序关系,这种树称为有序树; -- 二叉树 - 每个节点最多含有两个子树的树称为二叉树; -- 完全二叉树 - 对于一颗二叉树,假设其深度为 d(d>1)。除了第 d 层外,其它各层的节点数目均已达最大值,且第 d 层所有节点从左向右连续地紧密排列,这样的二叉树被称为完全二叉树; -- 满二叉树 - 所有叶节点都在最底层的完全二叉树; -- 平衡二叉树(AVL 树) - 当且仅当任何节点的两棵子树的高度差不大于 1 的二叉树; -- 排序二叉树(二叉查找树(英语 - Binary Search Tree)) - 也称二叉搜索树、有序二叉树; -- 霍夫曼树 - 带权路径最短的二叉树称为哈夫曼树或最优二叉树; -- B 树 - 一种对读写操作进行优化的自平衡的二叉查找树,能够保持数据有序,拥有多于两个子树。 - -## 引申和引用 - -- https://zh.wikipedia.org/wiki/树_(数据结构) diff --git a/big-data/BigData.md b/big-data/BigData.md deleted file mode 100644 index 46926ee4f4..0000000000 --- a/big-data/BigData.md +++ /dev/null @@ -1,190 +0,0 @@ ---- -title: 大数据简介 -date: 2018/09/03 -categories: -- bigdata -tags: -- bigdata ---- - -# 大数据简介 - - - -- [简介](#简介) - - [什么是大数据](#什么是大数据) - - [应用场景](#应用场景) - - [Hadoop 编年史](#hadoop-编年史) -- [技术体系](#技术体系) - - [HDFS](#hdfs) - - [MapReduce](#mapreduce) - - [Spark](#spark) - - [YARN](#yarn) - - [Hive](#hive) - - [HBase](#hbase) - - [ElasticSearch](#elasticsearch) -- [术语](#术语) -- [资源](#资源) - - - -## 简介 - -### 什么是大数据 - -大数据是指超出传统数据库工具收集、存储、管理和分析能力的数据集。与此同时,及时采集、存储、聚合、管理数据,以及对数据深度分析的新技术和新能力,正在快速增长,就像预测计算芯片增长速度的摩尔定律一样。 - -- **Volume** - 数据规模巨大 -- **Velocity** - 生成和处理速度极快 -- **Variety** - 数据规模巨大 -- **Value** - 生成和处理速度极快 - -### 应用场景 - -基于大数据的数据仓库 - -基于大数据的实时流处理 - -### Hadoop 编年史 - -| 时间 | 事件 | -|:--------|:-----------------------------------------------------------------| -| 2003.01 | Google发表了Google File System论文 | -| 2004.01 | Google发表了MapReduce论文 | -| 2006.02 | Apache Hadoop项目正式启动,并支持MapReduce和HDFS独立发展 | -| 2006.11 | Google发表了Bigtable论文 | -| 2008.01 | Hadoop成为Apache顶级项目 | -| 2009.03 | Cloudera推出世界上首个Hadoop发行版——CDH,并完全开放源码 | -| 2012.03 | HDFS NameNode HA加入Hadoop主版本 | -| 2014.02 | Spark代替MapReduce成为Hadoop的缺省计算引擎,并成为Apache顶级项目 | - -## 技术体系 - -### HDFS - -**概念** - -- Hadoop 分布式文件系统(Hadoop Distributed File System) -- 在开源大数据技术体系中,地位无可替代 - -**特点** - -- 高容错:数据多副本,副本丢失后自动恢复 -- 高可用:NameNode HA,安全模式 -- 高扩展:10K 节点规模 -- 简单一致性模型:一次写入多次读取,支持追加,不允许修改 -- 流式数据访问:批量读而非随机读,关注吞吐量而非时间 -- 大规模数据集:典型文件大小 GB~TB 级,百万以上文件数量, PB 以上数据规模 -- 构建成本低且安全可靠:运行在大量的廉价商用机器上,硬件错误是常态,提供容错机制 - -### MapReduce - -**概念** - -- 面向批处理的分布式计算框架 -- 编程模型:将 MapReduce 程序分为 Map、Reduce 两个阶段 - -**核心思想** - -- 分而治之,分布式计算 -- 移动计算,而非移动数据 - -**特点** - -- 高容错:任务失败,自动调度到其他节点重新执行 -- 高扩展:计算能力随着节点数增加,近似线性递增 -- 适用于海量数据的离线批处理 -- 降低了分布式编程的门槛 - -### Spark - -高性能分布式通用计算引擎 - -- Spark Core - 基础计算框架(批处理、交互式分析) -- Spark SQL - SQL 引擎(海量结构化数据的高性能查询) -- Spark Streaming - 实时流处理(微批) -- Spark MLlib - 机器学习 -- Spark GraphX - 图计算 - -采用 Scala 语言开发 - -**特点** - -- 计算高效 - 内存计算、Cache 缓存机制、DAG 引擎、多线程池模型 -- 通用易用 - 适用于批处理、交互式计算、流处理、机器学习、图计算等多种场景 -- 运行模式多样 - Local、Standalone、YARN/Mesos - -### YARN - -**概念** - -- Yet Another Resource Negotiator,另一种资源管理器 -- 为了解决 Hadoop 1.x 中 MapReduce 的先天缺陷 -- 分布式通用资源管理系统 -- 负责集群资源的统一管理 -- 从 Hadoop 2.x 开始,YARN 成为 Hadoop 的核心组件 - -**特点** - -- 专注于资源管理和作业调度 -- 通用 - 适用各种计算框架,如 - MapReduce、Spark -- 高可用 - ResourceManager 高可用、HDFS 高可用 -- 高扩展 - -### Hive - -**概念** - -- Hadoop 数据仓库 - 企业决策支持 -- SQL 引擎 - 对海量结构化数据进行高性能的 SQL 查询 -- 采用 HDFS 或 HBase 为数据存储 -- 采用 MapReduce 或 Spark 为计算框架 - -**特点** - -- 提供类 SQL 查询语言 -- 支持命令行或 JDBC/ODBC -- 提供灵活的扩展性 -- 提供复杂数据类型、扩展函数、脚本等 - -### HBase - -**概念** - -- Hadoop Database -- Google BigTable 的开源实现 -- 分布式 NoSQL 数据库 -- 列式存储 - 主要用于半结构化、非结构化数据 -- 采用 HDFS 为文件存储系统 - -**特点** - -- 高性能 - 支持高并发写入和查询 -- 高可用 - HDFS 高可用、Region 高可用 -- 高扩展 - 数据自动切分和分布,可动态扩容,无需停机 -- 海量存储 - 单表可容纳数十亿行,上百万列 - -### ElasticSearch - -- 开源的分布式全文检索引擎 -- 基于 Lucene 实现全文数据的快速存储、搜索和分析 -- 处理大规模数据 - PB 级以上 -- 具有较强的扩展性,集群规模可达上百台 -- 首选的分布式搜索引擎 - -## 术语 - -**数据仓库(Data Warehouse)** - 数据仓库,是为企业所有级别的决策制定过程,提供所有类型数据支持的战略集合。它是单个数据存储,出于分析性报告和决策支持目的而创建。 为需要业务智能的企业,提供指导业务流程改进、监视时间、成本、质量以及控制。 - -## 资源 - -- [awesome-bigdata](https://github.com/onurakpolat/awesome-bigdata) -- [Hadoop](http://hadoop.apache.org/) -- [HBase](http://hbase.apache.org/) -- [Hive](http://hive.apache.org/) -- [Impala](http://impala.apache.org/) -- [Flume](http://flume.apache.org/) -- [Kafka](http://kafka.apache.org/) -- [Spark](http://spark.apache.org/) -- [Sqoop](http://sqoop.apache.org/) -- [ElasticSearch](https://www.elastic.co/guide/index.html) diff --git a/big-data/Flume.md b/big-data/Flume.md deleted file mode 100644 index ee828e7d08..0000000000 --- a/big-data/Flume.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: Flume -date: 2018/09/04 -categories: - - bigdata -tags: - - bigdata - - hadoop ---- - -# Flume - -> **Sqoop 是一个主要在 Hadoop 和关系数据库之间进行批量数据迁移的工具。** - - - -- [Flume 简介](#flume-简介) - - [什么是 Flume ?](#什么是-flume-) - - [应用场景](#应用场景) -- [Flume 原理](#flume-原理) - - [Flume 基本概念](#flume-基本概念) - - [Flume 基本组件](#flume-基本组件) - - [Flume 数据流](#flume-数据流) -- [资源](#资源) - - - -## Flume 简介 - -### 什么是 Flume ? - -Flume 是一个分布式海量数据采集、聚合和传输系统。 - -特点 - -- 基于事件的海量数据采集 -- 数据流模型:Source -> Channel -> Sink -- 事务机制:支持重读重写,保证消息传递的可靠性 -- 内置丰富插件:轻松与各种外部系统集成 -- 高可用:Agent 主备切换 -- Java 实现:开源,优秀的系统设计 - -### 应用场景 - -## Flume 原理 - -### Flume 基本概念 - -- Event:事件,最小数据传输单元,由 Header 和 Body 组成。 -- Agent:代理,JVM 进程,最小运行单元,由 Source、Channel、Sink 三个基本组件构成,负责将外部数据源产生的数据以 Event 的形式传输到目的地 - - Source:负责对接各种外部数据源,将采集到的数据封装成 Event,然后写入 Channel - - Channel:Event 暂存容器,负责保存 Source 发送的 Event,直至被 Sink 成功读取 - - Sink:负责从 Channel 读取 Event,然后将其写入外部存储,或传输给下一阶段的 Agent - - 映射关系:1 个 Source -> 多个 Channel,1 个 Channel -> 多个 Sink,1 个 Sink -> 1 个 Channel - -### Flume 基本组件 - -#### Source 组件 - -- 对接各种外部数据源,将采集到的数据封装成 Event,然后写入 Channel -- 一个 Source 可向多个 Channel 发送 Event -- Flume 内置类型丰富的 Source,同时用户可自定义 Source - -#### Channel 组件 - -- Event 中转暂存区,存储 Source 采集但未被 Sink 读取的 Event -- 为了平衡 Source 采集、Sink 读取的速度,可视为 Flume 内部的消息队列 -- 线程安全并具有事务性,支持 Source 写失败重写和 Sink 读失败重读 - -#### Sink 组件 - -- 从 Channel 读取 Event,将其写入外部存储,或传输到下一阶段的 Agent -- 一个 Sink 只能从一个 Channel 中读取 Event -- Sink 成功读取 Event 后,向 Channel 提交事务,Event 被删除,否则 Channel 会等待 Sink 重新读取 - -### Flume 数据流 - -单层架构 - -优点:架构简单,使用方便,占用资源较少 -缺点 -如果采集的数据源或Agent较多,将Event写入到HDFS会产生很多小文件 -外部存储升级维护或发生故障,需对采集层的所有Agent做处理,人力成本较高,系统稳定性较差 -系统安全性较差 -数据源管理较混乱 - - -## 资源 diff --git a/big-data/HDFS.md b/big-data/HDFS.md deleted file mode 100644 index 9e232701a7..0000000000 --- a/big-data/HDFS.md +++ /dev/null @@ -1,224 +0,0 @@ ---- -title: HDFS -date: 2018/09/03 -categories: - - bigdata -tags: - - bigdata - - hadoop ---- - -# HDFS - -> **HDFS 是 Hadoop 分布式文件系统。** -> -> 关键词:分布式、文件系统 - - - -- [概述](#概述) - - [HDFS 的特点](#hdfs-的特点) -- [HDFS 的概念](#hdfs-的概念) - - [NameNode](#namenode) - - [DataNode](#datanode) - - [Block 数据块](#block-数据块) - - [Client](#client) -- [Block 副本策略](#block-副本策略) -- [数据流](#数据流) - - [HDFS 读文件](#hdfs-读文件) - - [HDFS 写文件](#hdfs-写文件) -- [HDFS 安全模式](#hdfs-安全模式) - - [什么是安全模式?](#什么是安全模式) - - [何时正常离开安全模式](#何时正常离开安全模式) - - [触发安全模式的原因](#触发安全模式的原因) - - [故障排查](#故障排查) -- [HDFS 高可用](#hdfs-高可用) - - [NameNode 的 HA 机制](#namenode-的-ha-机制) - - [利用 QJM 实现元数据高可用](#利用-qjm-实现元数据高可用) -- [资源](#资源) - - - -## 概述 - -HDFS 是 Hadoop 的核心子项目。 - -HDFS 是 Hadoop Distributed File System 的缩写,即 Hadoop 分布式文件系统。 - -### HDFS 的特点 - -HDFS 是一个文件系统,通过流式数据访问模式来存储海量文件。 - -优点: - -- **高容错** - 数据冗余多副本,副本丢失后自动恢复 -- **高可用** - NameNode HA、安全模式 -- **高扩展** - 能够处理 10K 节点的规模;处理数据达到 GB、TB、甚至 PB 级别的数据;能够处理百万规模以上的文件数量,数量相当之大。 -- **批处理** - 流式数据访问;数据位置暴露给计算框架 -- **构建在廉价商用机器上** - 提供了容错和恢复机制 - -缺点: - -- **不适合低延迟数据访问** - 适合高吞吐率的场景,就是在某一时间内写入大量的数据。但是它在低延时的情况下是不行的,比如毫秒级以内读取数据,它是很难做到的。 -- **不适合大量小文件存储** - - 存储大量小文件(这里的小文件是指小于 HDFS 系统的 Block 大小的文件(默认 64M))的话,它会占用 NameNode 大量的内存来存储文件、目录和块信息。这样是不可取的,因为 NameNode 的内存总是有限的。 - - 磁盘寻道时间超过读取时间 -- **不支持并发写入** - 一个文件同时只能有一个写入者 -- **不支持文件随机修改** - 仅支持追加写入 - -## HDFS 的概念 - -![架构](http://oyz7npk35.bkt.clouddn.com/images/bigdata/HDFS架构.png) - -HDFS 采用 Master/Slave 的架构来存储数据。在这个架构中,有以下重要概念,需要了解: - -### NameNode - -NameNode 就是 master 工作节点。 - -- 管理命名空间 -- 管理元数据:文件的位置、所有者、权限、数据块等 -- 管理 Block 副本策略:默认 3 个副本 -- 处理客户端读写请求,为 DataNode 分配任务 - -#### Active NameNode 和 Standby NameNode - -NameNode 通过 HA 机制来容错。 - -- **Active NameNode** 是正在工作的 NameNode; -- **Standby NameNode** 是备份的 NameNode。 - -Active NameNode 宕机后,Standby NameNode 快速升级为新的 Active NameNode。 - -Standby NameNode 周期性同步 edits 编辑日志,定期合并 fsimage 与 edits 到本地磁盘。 - -Hadoop 3.0 允许配置多个 Standby NameNode。 - -#### 元数据文件 - -- **edits(编辑日志文件)** - 保存了自最新检查点(Checkpoint)之后的所有文件更新操作。 -- **fsimage(元数据检查点镜像文件)** - 保存了文件系统中所有的目录和文件信息,如:某个目录下有哪些子目录和文件,以及文件名、文件副本数、文件由哪些 Block 组成等。 - -Active NameNode 内存中有一份最新的元数据(= fsimage + edits)。 - -Standby NameNode 在检查点定期将内存中的元数据保存到 fsimage 文件中。 - -### DataNode - -DataNode 就是 slave 工作节点。NameNode 下达命令,DataNode 执行实际的操作。 - -- 存储 Block 和数据校验和 -- 执行客户端发送的读写操作 -- 通过心跳机制定期(默认 3 秒)向 NameNode 汇报运行状态和 Block 列表信息 -- 集群启动时,DataNode 向 NameNode 提供 Block 列表信息 - -### Block 数据块 - -- HDFS 最小存储单元 -- 文件写入 HDFS 会被切分成若干个 Block -- Block 大小固定,默认为 128MB,可自定义 -- 若一个 Block 的大小小于设定值,不会占用整个块空间 -- 默认情况下每个 Block 有 3 个副本 - -### Client - -- 将文件切分为 Block 数据块 -- 与 NameNode 交互,获取文件元数据 -- 与 DataNode 交互,读取或写入数据 -- 管理 HDFS - -## Block 副本策略 - -Block 副本策略是由 NameNode 来控制的。 - -![HDFS 副本策略](http://oyz7npk35.bkt.clouddn.com/images/bigdata/HDFS数据中心.png) - -- 副本 1:放在 Client 所在节点 - - 对于远程 Client,系统会随机选择节点 -- 副本 2:放在不同的机架节点上 -- 副本 3:放在与第二个副本同一机架的不同节点上 -- 副本 N:随机选择 -- 节点选择:同等条件下优先选择空闲节点 - -## 数据流 - -### HDFS 读文件 - -![HDFS 读文件](http://oyz7npk35.bkt.clouddn.com/images/bigdata/HDFS读文件.png) - -1. 客户端调用 FileSyste 对象的 open() 方法在分布式文件系统中**打开要读取的文件**。 -2. 分布式文件系统通过使用 RPC(远程过程调用)来调用 namenode,**确定文件起始块的位置**。 -3. 分布式文件系统的 DistributedFileSystem 类返回一个支持文件定位的输入流 FSDataInputStream 对象,FSDataInputStream 对象接着封装 DFSInputStream 对象(**存储着文件起始几个块的 datanode 地址**),客户端对这个输入流调用 read()方法。 -4. DFSInputStream 连接距离最近的 datanode,通过反复调用 read 方法,**将数据从 datanode 传输到客户端**。 -5. 到达块的末端时,DFSInputStream 关闭与该 datanode 的连接,**寻找下一个块的最佳 datanode**。 -6. 客户端完成读取,对 FSDataInputStream 调用 close()方法**关闭连接**。 - -### HDFS 写文件 - -![HDFS 写文件](http://oyz7npk35.bkt.clouddn.com/images/bigdata/HDFS写文件.png) - -1. 客户端通过对 DistributedFileSystem 对象调用 create() 函数来**新建文件**。 -2. 分布式文件系统对 namenod 创建一个 RPC 调用,在文件系统的**命名空间中新建一个文件**。 -3. Namenode 对新建文件进行检查无误后,分布式文件系统返回给客户端一个 FSDataOutputStream 对象,FSDataOutputStream 对象封装一个 DFSoutPutstream 对象,负责处理 namenode 和 datanode 之间的通信,**客户端开始写入数据**。 -4. FSDataOutputStream 将**数据分成一个一个的数据包,写入内部队列“数据队列”**,DataStreamer 负责将数据包依次流式传输到由一组 namenode 构成的管线中。 -5. DFSOutputStream 维护着确认队列来等待 datanode 收到确认回执,**收到管道中所有 datanode 确认后,数据包从确认队列删**除。 -6. **客户端完成数据的写入**,对数据流调用 close() 方法。 -7. namenode **确认完成**。 - -## HDFS 安全模式 - -### 什么是安全模式? - -- 安全模式是 HDFS 的一种特殊状态,在这种状态下,HDFS 只接收读数据请求,而不接收写入、删除、修改等变更请求。 -- 安全模式是 HDFS 确保 Block 数据安全的一种保护机制。 -- Active NameNode 启动时,HDFS 会进入安全模式,DataNode 主动向 NameNode 汇报可用 Block 列表等信息,在系统达到安全标准前,HDFS 一直处于“只读”状态。 - -### 何时正常离开安全模式 - -- Block 上报率:DataNode 上报的可用 Block 个数 / NameNode 元数据记录的 Block 个数 -- 当 Block 上报率 >= 阈值时,HDFS 才能离开安全模式,默认阈值为 0.999 -- 不建议手动强制退出安全模式 - -### 触发安全模式的原因 - -- NameNode 重启 -- NameNode 磁盘空间不足 -- Block 上报率低于阈值 -- DataNode 无法正常启动 -- 日志中出现严重异常 -- 用户操作不当,如:**强制关机(特别注意!)** - -### 故障排查 - -- 找到 DataNode 不能正常启动的原因,重启 DataNode -- 清理 NameNode 磁盘 -- 谨慎操作,有问题找星环,以免丢失数据 - -## HDFS 高可用 - -### NameNode 的 HA 机制 - -Active NameNode 和 Standby NameNode 实现主备。 - -### 利用 QJM 实现元数据高可用 - -> 基于 Paxos 算法 - -QJM 机制(Quorum Journal Manager) - -只要保证 Quorum(法定人数)数量的操作成功,就认为这是一次最终成功的操作 - -QJM 共享存储系统 - -- 部署奇数(2N+1)个 JournalNode -- JournalNode 负责存储 edits 编辑日志 -- 写 edits 的时候,只要超过半数(N+1)的 JournalNode 返回成功,就代表本次写入成功 -- 最多可容忍 N 个 JournalNode 宕机 - -利用 ZooKeeper 实现 Active 节点选举。 - -## 资源 - -- [HDFS 官方文档](http://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html) -- [HDFS 知识点总结](https://www.cnblogs.com/caiyisen/p/7395843.html) -- [Hadoop: The Definitive Guide, Fourth Edition](http://shop.oreilly.com/product/0636920033448.do) by Tom White diff --git a/big-data/MapReduce.md b/big-data/MapReduce.md deleted file mode 100644 index 01dfa9036b..0000000000 --- a/big-data/MapReduce.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -title: MapReduce -date: 2018/09/03 -categories: - - bigdata -tags: - - bigdata - - hadoop ---- - -# MapReduce - - - -- [MapReduce 简介](#mapreduce-简介) - - [概念](#概念) - - [思想](#思想) - - [特点](#特点) - - [适用场景](#适用场景) - - [不适用场景](#不适用场景) -- [MapReduce 原理](#mapreduce-原理) - - [Job & Task(作业与任务)](#job--task作业与任务) - - [Split(切片)](#split切片) - - [Map 阶段(映射)](#map-阶段映射) - - [Reduce 阶段(化简)](#reduce-阶段化简) - - [Shuffle 阶段(洗牌)](#shuffle-阶段洗牌) -- [Shuffle 详解](#shuffle-详解) - - [Map 端](#map-端) - - [Reduce 端](#reduce-端) -- [作业运行模式](#作业运行模式) - - [JobTracker/TaskTracker 模式(Hadoop 1.X)](#jobtrackertasktracker-模式hadoop-1x) - - [YARN 模式(Hadoop 2.X)](#yarn-模式hadoop-2x) - - - -## MapReduce 简介 - -### 概念 - -MapReduce 是一个面向批处理的分布式计算框架。 - -编程模型:MapReduce 程序被分为 Map(映射)阶段和 Reduce(化简)阶段。 - -### 思想 - -分而治之,并行计算 -移动计算,而非移动数据 - -### 特点 - -- 计算跟着数据走 -- 良好的扩展性:计算能力随着节点数增加,近似线性递增 -- 高容错 -- 状态监控 -- 适合海量数据的离线批处理 -- 降低了分布式编程的门槛 - -### 适用场景 - -- 数据统计,如:网站的 PV、UV 统计 -- 搜索引擎构建索引 -- 海量数据查询 - -### 不适用场景 - -- OLAP - - 要求毫秒或秒级返回结果 -- 流计算 - - 流计算的输入数据集是动态的,而 MapReduce 是静态的 -- DAG 计算 - - 多个作业存在依赖关系,后一个的输入是前一个的输出,构成有向无环图 DAG - - 每个 MapReduce 作业的输出结果都会落盘,造成大量磁盘 IO,导致性能非常低下 - -## MapReduce 原理 - -### Job & Task(作业与任务) - -- 作业是客户端请求执行的一个工作单元 - - 包括输入数据、MapReduce 程序、配置信息 -- 任务是将作业分解后得到的细分工作单元 - - 分为 Map 任务和 Reduce 任务 - -### Split(切片) - -- 输入数据被划分成等长的小数据块,称为输入切片(Input Split),简称切片 -- Split 是逻辑概念,仅包含元数据信息,如:数据的起始位置、长度、所在节点等 -- 每个 Split 交给一个 Map 任务处理,Split 的数量决定 Map 任务的数量 -- Split 的划分方式由程序设定,Split 与 HDFS Block 没有严格的对应关系 -- Split 的大小默认等于 Block 大小 -- Split 越小,负载越均衡,但集群的开销越大 - -### Map 阶段(映射) - -- 由若干 Map 任务组成,任务数量由 Split 数量决定 -- 输入:Split 切片(key-value),输出:中间计算结果(key-value) - -### Reduce 阶段(化简) - -- 由若干 Reduce 任务组成,任务数量由程序指定 -- 输入:Map 阶段输出的中间结果(key-value),输出:最终结果(key-value) - -### Shuffle 阶段(洗牌) - -- Map、Reduce 阶段的中间环节,负责执行 Partition(分区)、Sort(排序)、Spill(溢写)、Merge(合并)、抓取(Fetch)等工作 -- Partition 决定了 Map 任务输出的每条数据放入哪个分区,交给哪个 Reduce 任务处理 -- Reduce 任务的数量决定了 Partition 数量 -- Partition 编号 = Reduce 任务编号 =“key hashcode % reduce task number” -- 避免和减少 Shuffle 是 MapReduce 程序调优的重点 - -## Shuffle 详解 - -### Map 端 - -Map 任务将中间结果写入专用内存缓冲区 Buffer(默认 100M),同时进行 Partition 和 Sort(先按“key hashcode % reduce task number”对数据进行分区,分区内再按 key 排序) -当 Buffer 的数据量达到阈值(默认 80%)时,将数据溢写(Spill)到磁盘的一个临时文件中,文件内数据先分区后排序 -Map 任务结束前,将多个临时文件合并(Merge)为一个 Map 输出文件,文件内数据先分区后排序 - -### Reduce 端 - -Reduce 任务从多个 Map 输出文件中主动抓取(Fetch)属于自己的分区数据,先写入 Buffer,数据量达到阈值后,溢写到磁盘的一个临时文件中 -数据抓取完成后,将多个临时文件合并为一个 Reduce 输入文件,文件内数据按 key 排序 - -## 作业运行模式 - -### JobTracker/TaskTracker 模式(Hadoop 1.X) - -**JobTracker 节点(Master)** - -- 调度任务在 TaskTracker 上运行 -- 若任务失败,指定新 TaskTracker 重新运行 - -**TaskTracker 节点(Slave)** - -- 执行任务,发送进度报告 - -**存在的问题** - -- JobTracker 存在单点故障 -- JobTracker 负载太重(上限 4000 节点) -- JobTracker 缺少对资源的全面管理 -- TaskTracker 对资源的描述过于简单 -- 源码很难理解 - -### YARN 模式(Hadoop 2.X) - -- 提交作业 -- 查看作业 -- 终止作业 - diff --git a/big-data/Sqoop.md b/big-data/Sqoop.md deleted file mode 100644 index 8900217ece..0000000000 --- a/big-data/Sqoop.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: Sqoop -date: 2018/09/04 -categories: - - bigdata -tags: - - bigdata - - hadoop ---- - -# Sqoop - -> **Sqoop 是一个主要在 Hadoop 和关系数据库之间进行批量数据迁移的工具。** - - - -- [Sqoop 简介](#sqoop-简介) - - [提供多种 Sqoop 连接器](#提供多种-sqoop-连接器) - - [Sqoop 版本](#sqoop-版本) -- [Sqoop 原理](#sqoop-原理) - - [导入](#导入) - - [导出](#导出) - - - -## Sqoop 简介 - -**Sqoop 是一个主要在 Hadoop 和关系数据库之间进行批量数据迁移的工具。** - -- Hadoop:HDFS、Hive、HBase、Inceptor、Hyperbase -- 面向大数据集的批量导入导出 -- 将输入数据集分为 N 个切片,然后启动 N 个 Map 任务并行传输 -- 支持全量、增量两种传输方式 - -### 提供多种 Sqoop 连接器 - -#### 内置连接器 - -- 经过优化的专用 RDBMS 连接器:MySQL、PostgreSQL、Oracle、DB2、SQL Server、Netzza 等 -- 通用的 JDBC 连接器:支持 JDBC 协议的数据库 - -#### 第三方连接器 - -- 数据仓库:Teradata -- NoSQL 数据库:Couchbase - -### Sqoop 版本 - -#### Sqoop 1 优缺点 - -![sqoop-architecture](http://dunwu.test.upcdn.net/images/bigdata/Sqoop/sqoop-architecture.png) - -优点 - -- 架构简单 -- 部署简单 -- 功能全面 -- 稳定性较高 -- 速度较快 - -缺点 - -- 访问方式单一 -- 命令行方式容易出错,格式紧耦合 -- 安全机制不够完善,存在密码泄露风险 - -#### Sqoop 2 优缺点 - -![sqoop-v2-architecture](http://dunwu.test.upcdn.net/images/bigdata/Sqoop/sqoop-v2-architecture.png) - -优点 - -- 访问方式多样 -- 集中管理连接器 -- 安全机制较完善 -- 支持多用户 - -缺点 - -- 架构较复杂 -- 部署较繁琐 -- 稳定性一般 -- 速度一般 - -## Sqoop 原理 - -### 导入 - -![import](http://dunwu.test.upcdn.net/images/bigdata/Sqoop/sqoop-import.png) - -### 导出 - -![export](http://dunwu.test.upcdn.net/images/bigdata/Sqoop/sqoop-export.png) diff --git a/big-data/YARN.md b/big-data/YARN.md deleted file mode 100644 index c9d5521cd5..0000000000 --- a/big-data/YARN.md +++ /dev/null @@ -1,176 +0,0 @@ ---- -title: YARN -date: 2018/09/03 -categories: - - bigdata -tags: - - bigdata - - hadoop ---- - -# YARN - -> YARN 的目标是解决 MapReduce 的缺陷。 - - - -- [MapReduce 的缺陷(Hadoop 1.x)](#mapreduce-的缺陷hadoop-1x) -- [YARN 简介](#yarn-简介) -- [YARN 系统架构](#yarn-系统架构) - - [ResourceManager(RM)](#resourcemanagerrm) - - [NodeManager(NM)](#nodemanagernm) - - [ApplicationMaster(AM)](#applicationmasteram) - - [Container](#container) -- [YARN 高可用](#yarn-高可用) -- [YARN 资源调度策略](#yarn-资源调度策略) - - [FIFO Scheduler(先进先出调度器)](#fifo-scheduler先进先出调度器) - - [Capacity Scheduler(容量调度器)](#capacity-scheduler容量调度器) - - [Fair Scheduler(公平调度器)](#fair-scheduler公平调度器) -- [资源](#资源) - - - -## MapReduce 的缺陷(Hadoop 1.x) - -- 身兼两职:计算框架 + 资源管理框架 -- JobTracker - - 既做资源管理,又做任务调度 - - 任务太重,开销过大 - - 存在单点故障 -- 资源描述模型过于简单,资源利用率较低 - - 仅把 Task 数量看作资源,没有考虑 CPU 和内存 - - 强制把资源分成 Map Task Slot 和 Reduce Task Slot -- 扩展性较差,集群规模上限 4K -- 源码难于理解,升级维护困难 - -## YARN 简介 - -YARN(Yet Another Resource Negotiator,另一种资源管理器)是一个**分布式通用资源管理系统**。 - -设计目标:聚焦资源管理、通用(适用各种计算框架)、高可用、高扩展。 - -## YARN 系统架构 - -- 主从结构(master/slave) -- 将 JobTracker 的资源管理、任务调度功能分离 -- 三种角色: - - ResourceManager(Master) - 集群资源的统一管理和分配 - - NodeManager(Slave) - 管理节点资源,以及容器的生命周期 - - ApplicationMaster(新角色) - 管理应用程序实例,包括任务调度和资源申请 - -### ResourceManager(RM) - -**主要功能** - -- 统一管理集群的所有资源 -- 将资源按照一定策略分配给各个应用(ApplicationMaster) -- 接收 NodeManager 的资源上报信息 - -**核心组件** - -- 用户交互服务(User Service) -- NodeManager 管理 -- ApplicationMaster 管理 -- Application 管理 -- 安全管理 -- 资源管理 - -### NodeManager(NM) - -**主要功能** - -- 管理单个节点的资源 -- 向 ResourceManager 汇报节点资源使用情况 -- 管理 Container 的生命周期 - -**核心组件** - -- NodeStatusUpdater -- ContainerManager -- ContainerExecutor -- NodeHealthCheckerService -- Security -- WebServer - -### ApplicationMaster(AM) - -**主要功能** - -- 管理应用程序实例 -- 向 ResourceManager 申请任务执行所需的资源 -- 任务调度和监管 - -**实现方式** - -- 需要为每个应用开发一个 AM 组件 -- YARN 提供 MapReduce 的 ApplicationMaster 实现 -- 采用基于事件驱动的异步编程模型,由中央事件调度器统一管理所有事件 -- 每种组件都是一种事件处理器,在中央事件调度器中注册 - -### Container - -- 概念:Container 封装了节点上进程的相关资源,是 YARN 中资源的抽象 -- 分类:运行 ApplicationMaster 的 Container 、运行应用任务的 Container - -## YARN 高可用 - -ResourceManager 高可用 - -- 1 个 Active RM、多个 Standby RM -- 宕机后自动实现主备切换 -- ZooKeeper 的核心作用 - - Active 节点选举 - - 恢复 Active RM 的原有状态信息 -- 重启 AM,杀死所有运行中的 Container -- 切换方式:手动、自动 - -## YARN 资源调度策略 - -### FIFO Scheduler(先进先出调度器) - -**调度策略** - -将所有任务放入一个队列,先进队列的先获得资源,排在后面的任务只有等待 - -**缺点** - -- 资源利用率低,无法交叉运行任务 -- 灵活性差,如:紧急任务无法插队,耗时长的任务拖慢耗时短的任务 - -### Capacity Scheduler(容量调度器) - -**核心思想** - 提前**做预算**,在预算指导下分享集群资源。 - -**调度策略** - -- 集群资源由多个队列分享 -- 每个队列都要预设资源分配的比例(提前做预算) -- 空闲资源优先分配给“实际资源/预算资源”比值最低的队列 -- 队列内部采用 FIFO 调度策略 - -**特点** - -- 层次化的队列设计:子队列可使用父队列资源 -- 容量保证:每个队列都要预设资源占比,防止资源独占 -- 弹性分配:空闲资源可以分配给任何队列,当多个队列争用时,会按比例进行平衡 -- 支持动态管理:可以动态调整队列的容量、权限等参数,也可动态增加、暂停队列 -- 访问控制:用户只能向自己的队列中提交任务,不能访问其他队列 -- 多租户:多用户共享集群资源 - -### Fair Scheduler(公平调度器) - -**调度策略** - -- 多队列公平共享集群资源 -- 通过平分的方式,动态分配资源,无需预先设定资源分配比例 -- 队列内部可配置调度策略:FIFO、Fair(默认) - -**资源抢占** - -- 终止其他队列的任务,使其让出所占资源,然后将资源分配给占用资源量少于最小资源量限制的队列 - -**队列权重** - -- 当队列中有任务等待,并且集群中有空闲资源时,每个队列可以根据权重获得不同比例的空闲资源 - -## 资源 diff --git a/database/nosql/mongodb/install-mongodb.md b/database/nosql/mongodb/install-mongodb.md deleted file mode 100644 index 760558ab6e..0000000000 --- a/database/nosql/mongodb/install-mongodb.md +++ /dev/null @@ -1,49 +0,0 @@ -# Mongodb 安装 - - - -- [安装](#安装) -- [启动](#启动) -- [脚本](#脚本) - - - -## 安装 - -安装步骤如下: - -(1)下载并解压到本地 - -进入官网下载地址:https://www.mongodb.com/download-center#community ,选择合适的版本下载。 - -我选择的是最新稳定版本 3.6.3:https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.6.3.tgz - -我个人喜欢存放在:`/opt/mongodb` - -``` -wget -O /opt/mongodb/mongodb-linux-x86_64-3.6.3.tgz https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.6.3.tgz -cd /opt/mongodb -tar zxvf mongodb-linux-x86_64-3.6.3.tgz -mv mongodb-linux-x86_64-3.6.3 mongodb-3.6.3 -mkdir -p /data/db -``` - -## 启动 - -**启动 mongodb 服务** - -``` -cd /opt/mongodb/mongodb-3.6.3/bin -./mongod --dbpath=/data/db -``` - -**启动 mongodb 客户端** - -``` -cd /opt/mongodb/mongodb-3.6.3/bin -./mongo -``` - -## 脚本 - -| [安装脚本](https://github.com/dunwu/linux/tree/master/codes/deploy/tool/mongodb) | diff --git a/database/nosql/redis/README.md b/database/nosql/redis/README.md deleted file mode 100644 index 96d3f920a2..0000000000 --- a/database/nosql/redis/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# redis 简介 - -**Redis 是一个基于内存的 key- value 数据库,也可用作缓存和消息代理。** - -它支持多种数据类型: - -- String -- Hash -- List -- Set -- Sorted Set -- Bitmap -- HyperLogLog - -## 命令行 - -[Redis 官方命令行字典](https://redis.io/commands) - -## 客户端 - -它提供了多种语言的客户端,如:Python,Ruby,PHP,Java,使用方便。 - -更多内容参考:[Redis 官方列出的 Redis 客户端列表](https://redis.io/clients)。 - -## 资源 - -[redis 官网](https://redis.io/) -[redis github](https://github.com/antirez/redis) - -### Sentinel - -- [官方文档](https://redis.io/topics/sentinel) 最全 -- [官方文档翻译](http://ifeve.com/redis-sentinel/) 翻译,排版一般,新 -- [官方文档翻译](http://redisdoc.com/topic/sentinel.html) 翻译有段时间了,但主要部分都包含,排版好 -- [redis sentinel实战](https://blog.csdn.net/yanggd1987/article/details/78364667) 简要实战,能快速看出来是怎么回事 - -### redis client - -- [spring-data-redis 官方文档 ](https://docs.spring.io/spring-data/redis/docs/1.8.13.RELEASE/reference/html/) -- [redisson 官方文档(中文,略有滞后)](https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95) -- [redisson 官方文档(英文)](https://github.com/redisson/redisson/wiki/Table-of-Content) -- [CRUG | Redisson PRO vs. Jedis: Which Is Faster? 翻译](https://www.jianshu.com/p/82f0d5abb002) -- [redis分布锁Redisson性能测试](https://blog.csdn.net/everlasting_188/article/details/51073505) - diff --git "a/database/nosql/redis/Redis\344\272\213\344\273\266.md" "b/database/nosql/redis/Redis\344\272\213\344\273\266.md" deleted file mode 100644 index 1fecfa1166..0000000000 --- "a/database/nosql/redis/Redis\344\272\213\344\273\266.md" +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: Redis 事件 -date: 2018/06/11 -categories: -- database -tags: -- database -- nosql ---- - -# Redis 事件 - -Redis 服务器是一个事件驱动程序。 - -## 文件事件 - -服务器通过套接字与客户端或者其它服务器进行通信,文件事件就是对套接字操作的抽象。 - -Redis 基于 Reactor 模式开发了自己的网络事件处理器,使用 I/O 多路复用程序来同时监听多个套接字,并将到达的事件传送给文件事件分派器,分派器会根据套接字产生的事件类型调用响应的事件处理器。 - -## 时间事件 - -服务器有一些操作需要在给定的时间点执行,时间事件是对这类定时操作的抽象。 - -时间事件又分为: - -- 定时事件:是让一段程序在指定的时间之内执行一次; -- 周期性事件:是让一段程序每隔指定时间就执行一次。 - -Redis 将所有时间事件都放在一个无序链表中,通过遍历整个链表查找出已到达的时间事件,并调用响应的事件处理器。 - -## 事件的调度与执行 - -服务器需要不断监听文件事件的套接字才能得到待处理的文件事件,但是不能一直监听,否则时间事件无法在规定的时间内执行,因此监听时间应该根据距离现在最近的时间事件来决定。 - -事件调度与执行由 aeProcessEvents 函数负责,伪代码如下: - -```py -def aeProcessEvents(): - - # 获取到达时间离当前时间最接近的时间事件 - time_event = aeSearchNearestTimer() - - # 计算最接近的时间事件距离到达还有多少毫秒 - remaind_ms = time_event.when - unix_ts_now() - - # 如果事件已到达,那么 remaind_ms 的值可能为负数,将它设为 0 - if remaind_ms < 0: - remaind_ms = 0 - - # 根据 remaind_ms 的值,创建 timeval - timeval = create_timeval_with_ms(remaind_ms) - - # 阻塞并等待文件事件产生,最大阻塞时间由传入的 timeval 决定 - aeApiPoll(timeval) - - # 处理所有已产生的文件事件 - procesFileEvents() - - # 处理所有已到达的时间事件 - processTimeEvents() -``` - -将 aeProcessEvents 函数置于一个循环里面,加上初始化和清理函数,就构成了 Redis 服务器的主函数,伪代码如下: - -```py -def main(): - - # 初始化服务器 - init_server() - - # 一直处理事件,直到服务器关闭为止 - while server_is_not_shutdown(): - aeProcessEvents() - - # 服务器关闭,执行清理操作 - clean_server() -``` - -从事件处理的角度来看,服务器运行流程如下: - -
- -
\ No newline at end of file diff --git "a/database/nosql/redis/Redis\344\272\213\345\212\241.md" "b/database/nosql/redis/Redis\344\272\213\345\212\241.md" deleted file mode 100644 index fce25fe679..0000000000 --- "a/database/nosql/redis/Redis\344\272\213\345\212\241.md" +++ /dev/null @@ -1,150 +0,0 @@ ---- -title: Redis 事务 -date: 2018/06/11 -categories: -- database -tags: -- database -- nosql -- key-value -- transaction ---- - -# Redis 事务 - - - -- [事务简介](#事务简介) -- [EXEC](#exec) -- [MULTI](#multi) -- [DISCARD](#discard) -- [WATCH](#watch) - - [取消 WATCH 的场景](#取消-watch-的场景) - - [使用 WATCH 创建原子操作](#使用-watch-创建原子操作) -- [Redis 不支持回滚](#redis-不支持回滚) -- [Redis 脚本和事务](#redis-脚本和事务) -- [资料](#资料) - - - -## 事务简介 - -事务可以一次执行多个命令,并且有以下两个重要的保证: - -- 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。 -- 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。 - -## EXEC - -**EXEC 命令负责触发并执行事务中的所有命令。** - -如果客户端在使用 MULTI 开启了一个事务之后,却因为断线而没有成功执行 EXEC ,那么事务中的所有命令都不会被执行。 -另一方面,如果客户端成功在开启事务之后执行 EXEC ,那么事务中的所有命令都会被执行。 - -## MULTI - -**MULTI 命令用于开启一个事务,它总是返回 OK。** - -MULTI 执行之后,客户端可以继续向服务器发送任意多条命令,这些命令不会立即被执行,而是被放到一个队列中,当 EXEC 命令被调用时,所有队列中的命令才会被执行。 - -以下是一个事务例子, 它原子地增加了 foo 和 bar 两个键的值: - -```py -> MULTI -OK -> INCR foo -QUEUED -> INCR bar -QUEUED -> EXEC -1) (integer) 1 -2) (integer) 1 -``` - -## DISCARD - -**当执行 DISCARD 命令时,事务会被放弃,事务队列会被清空,并且客户端会从事务状态中退出。** - -示例: - -```py -> SET foo 1 -OK -> MULTI -OK -> INCR foo -QUEUED -> DISCARD -OK -> GET foo -"1" -``` - -## WATCH - -WATCH 命令可以为 Redis 事务提供 check-and-set (CAS)行为。 - -被 WATCH 的键会被监视,并会发觉这些键是否被改动过了。 如果有至少一个被监视的键在 EXEC 执行之前被修改了, 那么整个事务都会被取消, EXEC 返回 null 来表示事务已经失败。 - -``` -WATCH mykey -val = GET mykey -val = val + 1 -MULTI -SET mykey $val -EXEC -``` - -使用上面的代码,如果在 WATCH 执行之后, EXEC 执行之前,有其他客户端修改了 mykey 的值,那么当前客户端的事务就会失败。程序需要做的,就是不断重试这个操作,直到没有发生碰撞为止。 - -这种形式的锁被称作乐观锁,它是一种非常强大的锁机制。并且因为大多数情况下,不同的客户端会访问不同的键,碰撞的情况一般都很少,所以通常并不需要进行重试。 - -**WATCH 使得 EXEC 命令需要有条件地执行:事务只能在所有被监视键都没有被修改的前提下执行,如果这个前提不能满足的话,事务就不会被执行。** - -WATCH 命令可以被调用多次。对键的监视从 WATCH 执行之后开始生效,直到调用 EXEC 为止。 - -用户还可以在单个 WATCH 命令中监视任意多个键,例如: - -```py -redis> WATCH key1 key2 key3 -OK -``` - -### 取消 WATCH 的场景 - -当 EXEC 被调用时,不管事务是否成功执行,对所有键的监视都会被取消。 - -另外,当客户端断开连接时,该客户端对键的监视也会被取消。 - -使用无参数的 UNWATCH 命令可以手动取消对所有键的监视。对于一些需要改动多个键的事务,有时候程序需要同时对多个键进行加锁,然后检查这些键的当前值是否符合程序的要求。当值达不到要求时,就可以使用 UNWATCH 命令来取消目前对键的监视,中途放弃这个事务,并等待事务的下次尝试。 - -### 使用 WATCH 创建原子操作 - -WATCH 可以用于创建 Redis 没有内置的原子操作。 - -举个例子,以下代码实现了原创的 ZPOP 命令,它可以原子地弹出有序集合中分值(score)最小的元素: - -``` -WATCH zset -element = ZRANGE zset 0 0 -MULTI -ZREM zset element -EXEC -``` - -## Redis 不支持回滚 - -Redis 不支持回滚的理由: - -- Redis 命令只会因为错误的语法而失败,或是命令用在了错误类型的键上面。 -- 因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。 - -## Redis 脚本和事务 - -从定义上来说,Redis 中的脚本本身就是一种事务,所以任何在事务里可以完成的事,在脚本里面也能完成。并且一般来说,使用脚本要来得更简单,并且速度更快。 - -## 资料 - -- [Redis 官网](https://redis.io/) -- [事务](http://redis.cn/topics/transactions.html) -- [Redis 实战](https://item.jd.com/11791607.html) diff --git "a/database/nosql/redis/Redis\345\217\221\345\270\203\350\256\242\351\230\205.md" "b/database/nosql/redis/Redis\345\217\221\345\270\203\350\256\242\351\230\205.md" deleted file mode 100644 index 1ab07aed7a..0000000000 --- "a/database/nosql/redis/Redis\345\217\221\345\270\203\350\256\242\351\230\205.md" +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: Redis 发布订阅 -date: 2018/06/11 -categories: -- database -tags: -- database -- nosql -- key-value ---- - -# Redis 发布订阅 - -Redis 通过 PUBLISH 、SUBSCRIBE 等命令实现了订阅与发布模式,这个功能提供两种信息机制,分别是订阅/发布到频道和订阅/发布到模式。 - -| 命令 | 描述 | -| ------------ | ------------------------------------------------------------------------ | -| SUBSCRIBE | 订阅给定的一个或多个频道。 | -| UNSUBSCRIBE | 退订给定的一个或多个频道,如果执行时灭有给定任何频道,那么退订所有频道。 | -| PUBLISH | 向给定频道发送消息。 | -| PSUBSCRIBE | 订阅与给定模式相匹配的所有频道。 | -| PUNSUBSCRIBE | 退订给定的模式,如果执行时没有给定任何模式,那么退订所有模式。 | - -## 频道的订阅与信息发送 - -Redis 的 SUBSCRIBE 命令可以让客户端订阅任意数量的频道,每当有新信息发送到被订阅的频道时,信息就会被发送给所有订阅指定频道的客户端。 - -### 订阅频道 - -### 发送信息到频道 - -## 模式的订阅与信息发送 - -## 资料 - -- [Redis 官网](https://redis.io/) -- [Redis 实战](https://item.jd.com/11791607.html) -- [Redis 设计与实现](https://item.jd.com/11486101.html) diff --git "a/database/nosql/redis/Redis\345\223\250\345\205\265.md" "b/database/nosql/redis/Redis\345\223\250\345\205\265.md" deleted file mode 100644 index ff5a29b0df..0000000000 --- "a/database/nosql/redis/Redis\345\223\250\345\205\265.md" +++ /dev/null @@ -1,883 +0,0 @@ ---- -title: Redis 哨兵 -date: 2018/06/19 -categories: -- database -tags: -- database -- nosql ---- - -# Redis 哨兵 - - - -- [QuickStart](#quickstart) - - [获取 Sentinel](#获取-sentinel) - - [运行 Sentinel](#运行-sentinel) - - [部署之前了解关于 Sentinel 的基本东西](#部署之前了解关于-sentinel-的基本东西) - - [Sentinel 配置](#sentinel-配置) - - [其他的 Sentinels 选项](#其他的-sentinels-选项) - - [Sentinel 部署示例](#sentinel-部署示例) -- [快速教程](#快速教程) - - [询问 Sentinel 关于主节点的状态](#询问-sentinel-关于主节点的状态) - - [获取当前主节点的地址](#获取当前主节点的地址) - - [故障转移测试](#故障转移测试) -- [Sentinel API](#sentinel-api) - - [Sentinel 命令](#sentinel-命令) - - [运行时重新配置 Sentinel](#运行时重新配置-sentinel) - - [添加和移除 sentinels](#添加和移除-sentinels) - - [移除旧的主节点或不可达的从节点](#移除旧的主节点或不可达的从节点) - - [发布/订阅消息](#发布订阅消息) - - [BUSY 状态的处理](#busy-状态的处理) -- [更高级的概念](#更高级的概念) - - [SDOWN 和 ODOWN 失败状态](#sdown-和-odown-失败状态) - - [Sentinels 和从节点自动发现](#sentinels-和从节点自动发现) - - [故障转移之外重新配置](#故障转移之外重新配置) - - [从节点选举和优先级](#从节点选举和优先级) -- [算法和内部结构](#算法和内部结构) - - [Quorum](#quorum) - - [配置 epochs](#配置-epochs) - - [配置传播](#配置传播) - - [Sentinel 持久化状态](#sentinel-持久化状态) - - [TILT 模式](#tilt-模式) - - - -Redis Sentinel 为 Redis 提供了高可用解决方案。实际上这意味着使用 Sentinel 可以部署一套 Redis,在没有人为干预的情况下去应付各种各样的失败事件。 - -Redis Sentinel 同时提供了一些其他的功能,例如:监控、通知、并为 client 提供配置。 - -下面是 Sentinel 的功能列表: - -- 监控(Monitoring):Sentinel 不断的去检查你的主从实例是否按照预期在工作。 -- 通知(Notification):Sentinel 可以通过一个 api 来通知系统管理员或者另外的应用程序,被监控的 Redis 实例有一些问题。 -- 自动故障转移(Automatic failover):如果一个主节点没有按照预期工作,Sentinel 会开始故障转移过程,把一个从节点提升为主节点,并重新配置其他的从节点使用新的主节点,使用 Redis 服务的应用程序在连接的时候也被通知新的地址。 -- 配置提供者(Configuration provider):Sentinel 给客户端的服务发现提供来源:对于一个给定的服务,客户端连接到 Sentinels 来寻找当前主节点的地址。当故障转移发生的时候,Sentinels 将报告新的地址。 - -**Sentinel 的分布式特性** - -Redis Sentinel 是一个分布式系统,Sentinel 运行在有许多 Sentinel 进程互相合作的环境下,它本身就是这样被设计的。有许多 Sentinel 进程互相合作的优点如下: - -- 当多个 Sentinel 同意一个 master 不再可用的时候,就执行故障检测。这明显降低了错误概率。 -- 即使并非全部的 Sentinel 都在工作,Sentinel 也可以正常工作,这种特性,让系统非常的健康。 - -所有的 Sentinels,Redis 实例,连接到 Sentinel 和 Redis 的客户端,本身就是一个有着特殊性质的大型分布式系统。在这篇文章中,我将逐步地介绍这些概念,最开始是一些基本的信息来理解 Sentinel 的基本属性,后面是更复杂的信息来理解 Sentinel 是怎么工作的。 - -## QuickStart - -### 获取 Sentinel - -当前版本的 Sentinel 的被称为 Sentinel 2 。它使用更强更简单的预测算法重写了 Sentinel 的初始化实现(文章的后面将会解释)。 - -Redis Sentinel 的一个稳定版本是随着 Redis2.8 和 3.0 一起的。这两个是 Redis 最新的稳定版。 - -新的进展在 unstable 分支下进行,一旦新的特性是稳定的,就会被合并到 2.8 和 3.0 分支。 - -和 Redis 2.6 一起的 Redis Sentinel 版本 1,是过时的。我们不该使用它。 - -### 运行 Sentinel - -如果你使用 redis-sentinel 可执行文件,你可以使用下面的命令来运行 Sentinel: - -``` -redis-sentinel /path/to/sentinel.conf -``` - -另外,你可以直接使用 redis-server 并以 Sentinel 模式来启动: - -``` -redis-server /path/to/sentinel.conf --sentinel -``` - -两种方式是一样的。 - -不管咋样,使用一个配置文件来运行 Sentinel 是必须的,这个文件被系统使用来存储当前状态,如果重启,这些状态会被重新载入。如果没有配置文件或者配置文件的路径不对,Sentinel 将会拒绝启动。 - -默认情况下,Sentinels 监听 TCP 端口 26379,所以为了让 Sentinels 运行,你的机器的 26379 端口必须是打开的,用来接收其他 Sentinel 实例的连接,否则,Sentinels 不能互相交流,也不知道该干什么,也不会执行故障转移。 - -### 部署之前了解关于 Sentinel 的基本东西 - -- 一个健康的集群部署,至少需要三个 Sentinel 实例 -- 三个 Sentinel 实例应该被放在失败独立的电脑上或虚拟机中,比如说不同的物理机或者在不同的可用区域上执行的虚拟机。 -- Sentinel + Redis 分布式系统在失败期间并不确保写入请求被保存,因为 Redis 使用异步拷贝。可是有很多部署 Sentinel 的 方式来让窗口把丢失写入限制在特定的时刻,当然也有另外的不安全的方式来部署。 -- 如果你在开发环境中没有经常测试,或者在生产环境中也没有,那就没有高可用的设置是安全的。你或许有一个错误的配置而仅仅只是在很晚的时候才出现(凌晨 3 点你的主节点宕掉了)。 -- Sentinel,Docker ,其他的网络地址转换表,端口映射 使用应该很小心的使用:Docker 执行端口重新映射,破坏 Sentinel 自动发现另外的 Sentinel 进程和一个主节点的从节点列表。在文章的稍后部分查看更过关于 Sentinel 和 Docker 的信息。 - -### Sentinel 配置 - -Redis 源码中包含一个名为 sentinel.conf 的文件,是一个你可以用来配置 Sentinel 的示例配置文件。一个典型的最小配置文件像下面这样: - -``` -sentinel monitor mymaster 127.0.0.1 6379 2 -sentinel down-after-milliseconds mymaster 60000 -sentinel failover-timeout mymaster 180000 -sentinel parallel-syncs mymaster 1 - -sentinel monitor resque 192.168.1.3 6380 4 -sentinel down-after-milliseconds resque 10000 -sentinel failover-timeout resque 180000 -sentinel parallel-syncs resque 5 -``` - -你仅仅只需要指定要监控的主节点,并给每个单独的主节点一个不同的名称。不需要指定从节点,从节点会被自动发现。Sentinel 将会根据从节点额外的信息自动更新配置(为了在重启时保留信息)。在故障转移中每当一个从节点被提升为主节点或者当一个新的 Sentinel 被发现的时候,配置信息也被重新写入。 - -示例配置在上面,监控两个 Redis 实例集合,每个集合由一个主节点和不明确数量的从节点组成。一个集合叫做 mymaster,另外一个叫做 resque。 - -sentinel monitor 参数的意思在下面 - -``` -sentinel monitor -``` - -为了更加清晰明了,让我们一行一行来检查配置选项的意思: - -第一行用来告诉 Redis 监控一个叫做 mymaster 的主节点,地址是 127.0.0.1 端口号是 6379,并且有 2 个仲裁机器。所有的意思都很明显,但是除了这个 quorum 参数: - -- quorum 是 需要同意主节点不可用的 Sentinels 的数量 -- 然而 quorum 仅仅只是用来检测失败。为了实际的执行故障转移,Sentinels 中的一个需要被选定为 leader 并且被授权进行操作,这仅仅发生在大多数 Sentinels 进行投票的时候。 - -比如如果你有五个 Sentinel 进程,对于一个主节点 quorum 被设置为 2,下面是发生的事情: - -- 同时有两个 Sentinels 同意主节点不可用,其中的一个将会尝试开始故障转移。 -- 如果至少有三个 Sentinels 是可用的,故障转移将会被授权并且开始。 - -实际中,这意味着在失败时,如果大多数的 Sentinel 进程没有同意,Sentinel 永远不会开始故障转移。 - -### 其他的 Sentinels 选项 - -其他的选项几乎都是如下形式: - -``` -sentinel -``` - -用途如下: - -down-after-milliseconds:当一个实例失去联系(要么不回复我们的请求,要么回复一个错误)超过了这个时间(毫秒为单位),Sentinel 就开始认为这个实例挂掉了。 - -parallel-syncs:设置的从节点的数量,这些从节点在一次故障转移过后可以使用新的主节点进行重新配置。数量越少,完成故障转移过程将花费更多的时间,如果从节点为旧的数据提供服务,你或许不想所有的从节点使用主节点进行重新同步。复制进程对于从节点来说大部分是非阻塞的,还是有一个时刻它会停下来去从主节点加载数据。你或许想确保一次只有一个从节点是不可达的,可以通过设置这个选项的值为 1 来完成。 - -别的选项在文章的其他部分进行描述。 - -所有的配置参数都可以在运行时使用 SENTINEL SET 命令进行更改,查看 Reconfiguring Sentinel at runtime 章节获取更多内容。 - -### Sentinel 部署示例 - -现在你已经知道了 Sentinel 的基本信息,你或许想知道哪里放置你的 Sentinel 进程,需要多少个 Sentinel 进程等等。这个章节给出了几个部署的例子。 - -为了以图形(graphical )格式展示配置示例,我们使用 ASCII 艺术。下面是不同的符号的意思: - -``` -+--------------------+ -| 这是一个独立电脑 | -| 或者VM。我们称它为 | -| “box” | -+--------------------+ -``` - -我们把我们想要运行的东西写到 boxes 里: - -``` -+-------------------+ -| Redis master M1 | -| Redis Sentinel S1 | -+-------------------+ -``` - -不同的 box 之间通过一条线连接,表示他们之间可以互相交流: - -``` -+-------------+ +-------------+ -| Sentinel S1 |---------------| Sentinel S2 | -+-------------+ +-------------+ -``` - -中断的线条表示不同的网络分区: - -``` -+-------------+ +-------------+ -| Sentinel S1 |------ // ------| Sentinel S2 | -+-------------+ +-------------+ -``` - -同时还要注意: - -- 主节点称为 M1,M2,M3,…,Mn。 -- 从节点称为 R1,R2,R3,…,Rn。 -- Sentinels 称为 S1,S2,S3,…,Sn。 -- 客户端称为 C1,C2,C3,…,Cn。 -- 当一个实例因为 Sentinels 的行为转换角色,我们把它放在方括号里,所以[M1]表示一个实例现在是主节点。 - -注意永远不要设置只有两个 Sentinels,因为开始一个故障转移,Sentinels 总是需要和大多数 Sentinels 交流。 - -#### 示例 1:仅仅只有两个 Sentinels,永远不要这么做 - -``` -+----+ +----+ -| M1 |---------| R1 | -| S1 | | S2 | -+----+ +----+ - -Configuration: quorum = 1 -``` - -在这个设置中,如果 M1 宕掉了,R1 将会被提升至主节点,因为两个 Sentinels 将会达成一致(显然把 quorum 设置为 1),并且授权开始一个故障转移因为大多数是两个。显然,表面上可以工作,但是请检查下一个点来看看为什么这种设置是不可以的。 - -如果 M1 的 box 停止工作,M1 也会停止。运行在另外一个 box 中的 S2 将不会被授权进行故障转移,所以系统将不可用。 - -注意,需要大多数是为了应付不同的故障,最新的配置稍后会传播给所有的 Sentinels。同时注意在上述设置中单独一边的故障转移能力,没有任何协议,将是非常危险的: - -``` -+----+ +------+ -| M1 |----//-----| [M1] | -| S1 | | S2 | -+----+ +------+ -``` - -在上面的配置中,我们完美对称地创建了两个主节点(假设 S2 在没有授权的情况下可以进行故障转移),客户端或许会不确定写往哪一边,并且没有办法理解当分区治愈时候哪边的配置是正确的。 - -所以请至少部署三个 Sentinels 在三个不同的 box 当中。 - -#### 示例 2:三个 box 的基本设置 - -这是一个非常简单的设置,拥有更加安全的优点。它是基于三个 boxes 的,每个 box 运行一个 Redis 进程和 Sentinel 进程。 - -``` - +----+ - | M1 | - | S1 | - +----+ - | -+----+ | +----+ -| R2 |----+----| R3 | -| S2 | | S3 | -+----+ +----+ - -Configuration: quorum = 2 -``` - -如果 M1 挂掉,S2 和 S3 将认同这次失败,并且能授权开始一次故障转移,这样使客户端可以继续使用。 - -在每一个 Sentinel 设置中,Redis 是异步复制的,总是有丢失一些写入数据的危险,因为当一个从节点被提升为主节点的时候一个写入确认还没有到达。然而在上面的设置中,还有一种更加危险的情况,由于客户端和一个老的主节点在一个网络分区中,就像下面这样: - -``` - +----+ - | M1 | - | S1 | <- C1 (writes will be lost) - +----+ - | - / - / -+------+ | +----+ -| [M2] |----+----| R3 | -| S2 | | S3 | -+------+ +----+ -``` - -在这种情况下,网络分区把旧的主节点[M1]给孤立了,所以从节点 R2 被提升为主节点。然而,像客户端 C1,和旧的主节点在同一个网络分区中,或许继续像旧的主节点写入数据。当分区治愈,这些数据将永久丢失,这个旧得主节点将会被重新配置,作为新的主节点下的一个从节点,并丢弃它自己的数据。 - -可以使用下面的 Redis 复制特性减轻这个问题,如果一个主节点发现它不再能够把它的写入请求发送给指定数量的从节点,它就停止接受写入请求。 - -``` -min-slaves-to-write 1 -min-slaves-max-lag 10 -``` - -当上面的配置应用于一个 Redis 实例。Redis 发现它不能写入至少一个 1 从节点,作为主节点的 Reids 将会停止接受写入请求。由于复制是异步,不能写入也意味着从节点也是断开的,或者超过了指定的 max-lag 秒数没有发送异步回应。 - -在上面的示例中,使用这个配置的旧的主节点 M1,在 10 秒过后就不可用了。当分区治愈,Sentinel 配置将会统一为新的,客户端 C1 将获取到一个有效的配置并且继续。 - -然而天下没有免费的午餐,在这种改进下,如果两个从节点挂掉了,主节点将会停止接收写入请求,这就是一个权衡。 - -#### 示例 3:Sentinel 在客户端所在的 box 中 - -有时候,我们只有两个 Redis box 是可用的,一个给主节点,一个给从节点。在那种情况下,示例 2 中的配置是不可行的,我们可以采取下面的方法,Sentinels 被放置在客户端所在的地方: - -``` - +----+ +----+ - | M1 |----+----| R1 | - | S1 | | | S2 | - +----+ | +----+ - | - +------------+------------+ - | | | - | | | - +----+ +----+ +----+ - | C1 | | C2 | | C3 | - | S1 | | S2 | | S3 | - +----+ +----+ +----+ - - Configuration: quorum = 2 -在这种设置下,Sentinels的视角和客户端是 一样的:如 -``` - -在这种设置下,Sentinels 的视角和客户端是 一样的:如果大部分的客户端认为一个主节点是可用的,它就是可用的。这里的 C1,C2,C3 是一般的客户端, 并不意味着 C1 是连接到 Redis 的单个客户端,它更像一个应用服务器,一个 Redis app,或者类似的东西。 - -如果 M1 和 S1 所在的 box 挂掉了,故障转移将会进行,但是很明显的看到不同的网络分区将导致不同的行为。比如说,如果客户端和 Redis 服务断开连接,Sentinel 将不会被设置,因为 Redis 的主节点和从节点都是不可用的。 - -注意如果 C3 和 M1 在一个分区,我们有了一个和示例 2 中描述的类似的问题,不同的是,这里我们没有办法打破对称,因为只有一个主节点和从节点,所以主节点不会停止接收请求。 - -所以这是一个有效的设置,但是实例 2 中的设置更有优势,比如 Redis 高可用系统,Redis 运行在同一个 box 中,更容易被管理,并且可以限制在小部分的分区中主节点接收写入请求的时间。 - -#### 示例 4:Sentinel 客户端 这一边少于三个客户端 - -示例 3 描述的设置中,如果客户端这一边的 box 少于不够三个,这个 设置就不能使用。在这种情况下,我们需要借助混合设置,像下面这样: - -``` - +----+ +----+ - | M1 |----+----| R1 | - | S1 | | | S2 | - +----+ | +----+ - | - +------+-----+ - | | - | | - +----+ +----+ - | C1 | | C2 | - | S3 | | S4 | - +----+ +----+ - - Configuration: quorum = 3 -``` - -这和示例 3 中的设置非常相似,但是这里我们在可用的四个 box 中运行了四个 Sentinel。如果主节点 M1 变成不可用节点,其他三个 Sentinel 将执行故障转移。 - -理论上,当移除 S2 和 S4 正在运行的 box,这个设置可以工作,把 quorum 设置为 2。然而,在应用层没有高可用的系统,想在 Redis 这一边得到高可用是不太可能的。 - -#### Sentinel,Docker,NAT 和可能的问题 - -Docker 使用被称为端口映射的技术:与一个程序认为他使用的端口相比,运行在 Docker 容器里面的程序可能被暴露在不同的端口上。为了运行多个容器在相同的服务器上同时使用同一个端口,这是非常有用的。 - -Docker 不是唯一会发生这件事情的软件系统,也有其他的网络地址转换设置导致端口是被重映射,并且有时候没有端口,只有 IP 地址。 - -端口和地址重映射在两个方面制造了与 Sentinel 有关的问题: - -Sentinel 的自动发现服务将停止工作,因为它使基于每个 Sentinel 往它监听的端口和 IP 地址广播 hello 消息来实现的。但是 Sentinels 没有办法来理解端口和 IP 地址被重映射了,所以他会宣布它和其他的 Sentinels 的连接是不正常的。 -在一个主节点的 INFO 输出中,从节点 被列出来也是类似的方式:主节点检查远端对等的 TCP 连接来发现地址,在握手过程中,从节点自己广告他的端口,然而由于相同的原因,端口或许是错误的。 -因为 Sentinels 自动发现从节点使用主节点的 INFO 输出信息,发现的从节点是不可达的,并且 Sentinel 将永远不会开始故障转移,因为从系统的观点来看,没有好的从节点,所以目前没有方式监控使用 Docker 部署的主节点和从节点实例,除非你通知 Docker 以 1:1 映射端口。 - -对于第一个问题,万一你想使用 Docker 运行一堆 Sentinel 实例,你可以使用下面的两个 Sentinel 配置,为了强迫 Sentinel 宣布一个指定的端口和 IP: - -``` -sentinel announce-ip -sentinel announce-port -``` - -注意,Docker 可以运行 host networking 模式。这就不会有问题因为端口不会被重新映射。 - -## 快速教程 - -在文章接下来的部分中,所有的说明都是关于 Sentinel API,配置和语义。对于想尽快上手的人,这部分的教程展示了三个 Sentinel 怎么配置和交互。 - -现在我假设三个实例分别在端口 5000、5001、5002 上。我也假设你在 6379 上有一个主节点 Redis 实例,6380 上有一个从节点实例。在本教程中我们将使用 IPV4 回调地址 127.0.0.1,假设你在你的电脑上运行了 模拟环境。 - -三个 Sentinel 配置文件应该看起来像下面这样: - -``` -port 5000 -sentinel monitor mymaster 127.0.0.1 6379 2 -sentinel down-after-milliseconds mymaster 5000 -sentinel failover-timeout mymaster 60000 -sentinel parallel-syncs mymaster 1 -``` - -另外的两个配置文件也是相同的,但是使用 5001,5002 作为端口号。 - -上面的配置中需要注意的一些事情: - -主节点集群称为 mymaster,它定义了主节点和它的从节点。因为每个 master set 有一个不同的名称,Sentinel 能同时监控不同的主节点和从节点的集合。 -quorum 被设置为 2。 -down-after-milliseconds 的值是 5000 毫秒,就是 5 秒钟,所以在这个时间内一旦我们不能收到回复,主节点将发现失败。 -一旦你启动了三个 Sentinels,可以看到他们打印的一些信息: - -``` -+monitor master mymaster 127.0.0.1 637这是一个Sentinel事件,如果你 -``` - -SUBSCRIBE 了指定名称的事件,你可以收到这种事件通过发布/订阅。 - -Sentinel 在故障检测和故障转移中生成和打印不同的事件。 - -### 询问 Sentinel 关于主节点的状态 - -Sentinel 开始启动的时候,要做的事情是检查主节点的监控是否正常: - -```py -$ redis-cli -p 5000 -127.0.0.1:5000> sentinel master mymaster - 1) "name" - 2) "mymaster" - 3) "ip" - 4) "127.0.0.1" - 5) "port" - 6) "6379" - 7) "runid" - 8) "953ae6a589449c13ddefaee3538d356d287f509b" - 9) "flags" -10) "master" -11) "link-pending-commands" -12) "0" -13) "link-refcount" -14) "1" -15) "last-ping-sent" -16) "0" -17) "last-ok-ping-reply" -18) "735" -19) "last-ping-reply" -20) "735" -21) "down-after-milliseconds" -22) "5000" -23) "info-refresh" -24) "126" -25) "role-reported" -26) "master" -27) "role-reported-time" -28) "532439" -29) "config-epoch" -30) "1" -31) "num-slaves" -32) "1" -33) "num-other-sentinels" -34) "2" -35) "quorum" -36) "2" -37) "failover-timeout" -38) "60000" -39) "parallel-syncs" -40) "1" -``` - -像你所见的,它打印了主节点的一些信息。有几个是我们特别有兴趣的: - -1. num-other-sentinels 是 2,所以我们知道对于这个主节点 Sentinel 已经发现了两个以上的 Sentinels。如果你检查日志,你可以看到+sentinel 事件发生。 -2. flags 是 master。如果主节点挂掉了,我们可以看到 s_down 或者 o_down 标志。 -3. num-slaves 现在是 1,所以 Sentinel 发现有一个从节点。 - -为了探测关于这个实例更多的信息,你可以尝试下面的两个命令: - -``` -SENTINEL slaves mymaster -SENTINEL sentinels mymaster -``` - -第一个将提供关于从节点类似的信息,第二个是关于另外的 Sentinels。 - -### 获取当前主节点的地址 - -Sentinel 也作为一个配置提供者,提供给客户端它们想连接的主节点和从节点的集群。因为可能的故障转移和重配置,客户端不知道一个集群实例内当前的活着的主节点,所以 Sentinel 提供了一个 API: - -```py -127.0.0.1:5000> SENTINEL get-master-addr-by-name mymaster -1) "127.0.0.1" -2) "6379" -``` - -### 故障转移测试 - -现在我们部署 Sentinel 可以被测试了。我们可以杀死主节点然后查看配置变化。做我们可以做的: - -``` -redis-cli -p 6379 DEBUG sleep 30 -``` - -这个命令让我们的主节点变为不可达,睡眠 30 秒,它基本上模拟了主节点挂掉的一些原因。 - -如果你检查 Sentinel 的日志,你应该能看到许多动作: - -1. 每个 Sentinel 发现了主节点挂掉了并有一个+sdown 事件 -2. 这个事件稍候升级到+odown,意味着大多数 Sentinel 已经同意了主节点是不可达的。 -3. Sentinels 开始投票一个 Sentinel 开始并尝试故障转移 -4. 故障转移开始 - -如果你重新询问 mymaster 的当前主节点的地址,这次我们会得到一个不同的回复: - -``` -127.0.0.1:5000> SENTINEL get-master-addr-by-name mymaster -1) "127.0.0.1" -2) "6380" -``` - -目前为止一切都很顺利,现在你可以创建你自己的 Sentinel 部署或者阅读更多来理解 Sentinel 的命令和内部原理。 - -## Sentinel API - -Sentinel 提供了一个 API,可以用来检查它的状态,检查主节点和从节点的健康,订阅具体的通知并在运行时改变 Sentinel 的配置。 - -默认情况下 Sentinel 使用 TCP 端口号 26379。Sentinels 接收使用 Redis 的协议命令,所以你可以使用 redis-cli 或者其他未修改的 Redis 客户端来和 Sentinel 交流。 - -直接查询一个 Sentinel 来检查所监控的 Redis 实例的状态,看看另外的 Sentinels 所知道是可能的。有两种方式,使用发布/订阅,每当一些事件发生,比如说一次故障转移,或一个实例发生错误等,都可能接收到一个从 Sentinels 推送过来的通知。 - -### Sentinel 命令 - -下面是可以接收的命令列表,没有覆盖到那些用来改变 Sentinel 配置的命令: - -- PING 这个命令仅仅返回 PONG。 -- SENTINEL masters 展示监控的主节点和它们的状态列表 -- SENTINEL master 展示指定的主节点的信息 -- SENTINEL salves 展示这个主节点的从节点,以及它们的状态 -- SENTINEL sentinels 展示这个主节点的 sentinel 实例,以及它们的状态 -- SENTINEL get-master-addr-by-name 返回主节点的 IP 和端口号。如果这个主节点的一次故障转移正在进行,就返回提升的从节点的 IP 和端口号 -- SENTINEL reset 这个命令将会根据匹配的名称重置主节点,pattern 参数是通配符(glob-style)类型,重置进程清除主节点中之前的所有状态,并且移除主节点发现和关联的从节点和 sentinel。 -- SENTINEL failover 如果主节点不可达,强制开始故障转移,不需要另外的 Sentinels 同意。 -- SENTINEL ckquorum 检查当前的 Sentinel 配置对于主节点的故障转移是否能达到仲裁人数,并且大多数是需要的来授权故障转移。这个命令应该在监控系统中使用来检查一个 Sentinel 部署是否正常。 -- SENTINEL flushconfig 强制 Sentinel 重新写入它的配置到磁盘上,包括当前 Sentinel 状态。通常,每次当它状态里的一些东西改变,Sentinel 就会重写配置信息。然而有时候配置文件会丢失,由于错误的操作、磁盘故障、包升级脚本、或配置管理。在那种情况下,强制 Sentinel 重写它的配置文件是容易的。甚至之前的配置文件完全丢失,这个命令也能很好的工作。 - -### 运行时重新配置 Sentinel - -从 Redis 2.8.4 开始,Sentinel 提供了一个 API 为了增加、移除或者改变一个给定的主节点的配置。注意如果你有多个 sentinels,为了工作正常,你应该改变所有的 Redis Sentinel 实例。这意味着改变单个 Sentinel 的配置不会把变化发送给在网络中另外的 Sentinels. - -下面是 SENTINEL 自命令列表,用来更新一个 Sentinel 实例的配置: - -- SENTINEL MONITOR 这个命令告诉 Sentinel 开始监控一个指定名称、IP、端口号、quorum 的主节点,它和 sentinel.conf 配置文件中的 sentinel monitor 配置指令是完全相同的,不同的是这里不能使用主机名作为 IP,需要提供一个 IPV4 或 IPV6 地址。 -- SENTINEL REMOVE 用来移除指定的主节点:主节点不再被监控,并且将被从 Sentinel 的内部状态中被完全移除,所以不会被 SENTINEL masters 列出。 -- SENTINEL SET