├── .gitattributes ├── .gitignore ├── .nojekyll ├── HomePage.md ├── README.md ├── _coverpage.md ├── code └── java │ └── ThreadPoolExecutorDemo │ ├── .idea │ ├── .gitignore │ ├── checkstyle-idea.xml │ ├── inspectionProfiles │ │ └── Project_Default.xml │ ├── misc.xml │ ├── modules.xml │ ├── uiDesigner.xml │ └── vcs.xml │ ├── ThreadPoolExecutorDemo.iml │ ├── out │ └── production │ │ └── ThreadPoolExecutorDemo │ │ ├── META-INF │ │ └── ThreadPoolExecutorDemo.kotlin_module │ │ ├── callable │ │ ├── CallableDemo.class │ │ └── MyCallable.class │ │ ├── common │ │ └── ThreadPoolConstants.class │ │ ├── scheduledThreadPoolExecutor │ │ ├── ScheduledThreadPoolExecutorDemo.class │ │ └── Task.class │ │ └── threadPoolExecutor │ │ ├── MyRunnable.class │ │ └── ThreadPoolExecutorDemo.class │ └── src │ ├── callable │ ├── CallableDemo.java │ └── MyCallable.java │ ├── common │ └── ThreadPoolConstants.java │ └── threadPoolExecutor │ ├── MyRunnable.java │ └── ThreadPoolExecutorDemo.java ├── docs ├── data │ ├── java-recommended-books.md │ └── spring-boot-practical-projects.md ├── dataStructures-algorithms │ ├── Backtracking-NQueens.md │ ├── data-structure │ │ └── bloom-filter.md │ ├── 公司真题.md │ ├── 几道常见的子符串算法题.md │ ├── 几道常见的链表算法题.md │ ├── 剑指offer部分编程题.md │ ├── 数据结构.md │ └── 算法学习资源推荐.md ├── database │ ├── MySQL Index.md │ ├── MySQL.md │ ├── MySQL高性能优化规范建议.md │ ├── Redis │ │ ├── Redis.md │ │ ├── Redis持久化.md │ │ ├── Redlock分布式锁.md │ │ ├── redis集群以及应用场景.md │ │ └── 如何做可靠的分布式锁,Redlock真的可行么.md │ ├── 一千行MySQL命令.md │ ├── 一条sql语句在mysql中如何执行的.md │ ├── 事务隔离级别(图文详解).md │ ├── 数据库连接池.md │ └── 阿里巴巴开发手册数据库部分的一些最佳实践.md ├── essential-content-for-interview │ ├── BATJrealInterviewExperience │ │ ├── 2019alipay-pinduoduo-toutiao.md │ │ ├── 5面阿里,终获offer.md │ │ └── 蚂蚁金服实习生面经总结(已拿口头offer).md │ ├── PreparingForInterview │ │ ├── JavaInterviewLibrary.md │ │ ├── JavaProgrammerNeedKnow.md │ │ ├── interviewPrepare.md │ │ ├── 应届生面试最爱问的几道Java基础问题.md │ │ ├── 程序员的简历之道.md │ │ ├── 美团面试常见问题总结.md │ │ └── 面试官-你有什么问题要问我.md │ ├── real-interview-experience-analysis │ │ └── alibaba-1.md │ ├── 手把手教你用Markdown写一份高质量的简历.md │ ├── 简历模板.md │ └── 面试必备之乐观锁与悲观锁.md ├── github-trending │ ├── 2018-12.md │ ├── 2019-1.md │ ├── 2019-2.md │ ├── 2019-3.md │ ├── 2019-4.md │ ├── 2019-5.md │ ├── 2019-6.md │ └── JavaGithubTrending.md ├── java │ ├── BIO-NIO-AIO.md │ ├── Basis │ │ ├── Arrays,CollectionsCommonMethods.md │ │ └── final、static、this、super.md │ ├── J2EE基础知识.md │ ├── Java IO与NIO.md │ ├── Java基础知识.md │ ├── Java疑难点.md │ ├── Java程序设计题.md │ ├── Java编程规范.md │ ├── Multithread │ │ ├── AQS.md │ │ ├── Atomic.md │ │ ├── JavaConcurrencyAdvancedCommonInterviewQuestions.md │ │ ├── JavaConcurrencyBasicsCommonInterviewQuestionsSummary.md │ │ ├── ThredLocal.md │ │ ├── java线程池学习总结.md │ │ ├── synchronized.md │ │ ├── 并发容器总结.md │ │ └── 并发编程基础知识.md │ ├── What's New in JDK8 │ │ ├── Java8Tutorial.md │ │ ├── Java8foreach指南.md │ │ └── Java8教程推荐.md │ ├── collection │ │ ├── ArrayList-Grow.md │ │ ├── ArrayList.md │ │ ├── HashMap.md │ │ ├── Java集合框架常见面试题.md │ │ └── LinkedList.md │ ├── jvm │ │ ├── GC调优参数.md │ │ ├── JDK监控和故障处理工具总结.md │ │ ├── JVM垃圾回收.md │ │ ├── Java内存区域.md │ │ ├── jvm 知识点汇总.md │ │ ├── 最重要的JVM参数指南.md │ │ ├── 类加载器.md │ │ ├── 类加载过程.md │ │ └── 类文件结构.md │ └── 多线程系列.md ├── network │ ├── HTTPS中的TLS.md │ ├── 干货:计算机网络知识总结.md │ └── 计算机网络.md ├── operating-system │ ├── Shell.md │ └── 后端程序员必备的Linux基础知识.md ├── questions │ ├── java-learning-path-and-methods.md │ ├── java-learning-website-blog.md │ └── java-training-4-month.md ├── system-design │ ├── authority-certification │ │ ├── JWT-advantages-and-disadvantages.md │ │ └── basis-of-authority-certification.md │ ├── data-communication │ │ ├── Kafka入门看这一篇就够了.md │ │ ├── Kafka系统设计开篇-面试看这篇就够了.md │ │ ├── RocketMQ-Questions.md │ │ ├── dubbo.md │ │ ├── message-queue.md │ │ ├── rabbitmq.md │ │ ├── summary.md │ │ └── why-use-rpc.md │ ├── framework │ │ ├── ZooKeeper.md │ │ ├── ZooKeeper数据模型和常见命令.md │ │ └── spring │ │ │ ├── Spring-Design-Patterns.md │ │ │ ├── Spring.md │ │ │ ├── SpringBean.md │ │ │ ├── SpringInterviewQuestions.md │ │ │ └── SpringMVC-Principle.md │ ├── micro-service │ │ ├── API网关.md │ │ └── 分布式id生成方案总结.md │ ├── website-architecture │ │ ├── 8 张图读懂大型网站技术架构.md │ │ ├── 关于大型网站系统架构你不得不懂的10个问题.md │ │ └── 分布式.md │ └── 设计模式.md ├── tools │ ├── Docker-Image.md │ ├── Docker.md │ ├── Git.md │ ├── github │ │ └── github-star-ranking.md │ └── 阿里云服务器使用经验.md └── 公众号历史文章汇总.md ├── index.html ├── media ├── pictures │ ├── kafka │ │ ├── Broker和集群.png │ │ ├── Partition与消费模型.png │ │ ├── kafka存在文件系统上.png │ │ ├── segment是kafka文件存储的最小单位.png │ │ ├── 主题与分区.png │ │ ├── 前言.md │ │ ├── 发送消息.png │ │ ├── 启动服务.png │ │ ├── 消费者设计概要1.png │ │ ├── 消费者设计概要2.png │ │ ├── 消费者设计概要3.png │ │ ├── 消费者设计概要4.png │ │ ├── 消费者设计概要5.png │ │ ├── 生产者和消费者.png │ │ └── 生产者设计概要.png │ └── rostyslav-savchyn-5joK905gcGc-unsplash.jpg └── sponsor │ └── WechatIMG143.jpeg └── submission.html /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.js linguist-language=java 3 | *.css linguist-language=java 4 | *.html linguist-language=java 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | /**/build/ 4 | 5 | ### STS ### 6 | .apt_generated 7 | .classpath 8 | .factorypath 9 | .project 10 | .settings 11 | .springBeans 12 | .sts4-cache 13 | 14 | ### IntelliJ IDEA ### 15 | .idea 16 | *.iws 17 | *.iml 18 | *.ipr 19 | /out/ 20 | /**/out/ 21 | .shelf/ 22 | .ideaDataSources/ 23 | dataSources/ 24 | 25 | ### NetBeans ### 26 | /nbproject/private/ 27 | /nbbuild/ 28 | /dist/ 29 | /nbdist/ 30 | /.nb-gradle/ 31 | /node_modules/ 32 | 33 | ### OS ### 34 | .DS_Store 35 | -------------------------------------------------------------------------------- /.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/.nojekyll -------------------------------------------------------------------------------- /_coverpage.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 |

Java 学习/面试指南

6 | 7 | [常用资源](https://shimo.im/docs/MuiACIg1HlYfVxrj/) 8 | [GitHub]() 9 | [开始阅读](#java) 10 | 11 | ![](./media/pictures/rostyslav-savchyn-5joK905gcGc-unsplash.jpg) 12 | 13 | 14 | -------------------------------------------------------------------------------- /code/java/ThreadPoolExecutorDemo/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml -------------------------------------------------------------------------------- /code/java/ThreadPoolExecutorDemo/.idea/checkstyle-idea.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | -------------------------------------------------------------------------------- /code/java/ThreadPoolExecutorDemo/.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 36 | -------------------------------------------------------------------------------- /code/java/ThreadPoolExecutorDemo/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /code/java/ThreadPoolExecutorDemo/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /code/java/ThreadPoolExecutorDemo/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /code/java/ThreadPoolExecutorDemo/ThreadPoolExecutorDemo.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /code/java/ThreadPoolExecutorDemo/out/production/ThreadPoolExecutorDemo/META-INF/ThreadPoolExecutorDemo.kotlin_module: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /code/java/ThreadPoolExecutorDemo/out/production/ThreadPoolExecutorDemo/callable/CallableDemo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/code/java/ThreadPoolExecutorDemo/out/production/ThreadPoolExecutorDemo/callable/CallableDemo.class -------------------------------------------------------------------------------- /code/java/ThreadPoolExecutorDemo/out/production/ThreadPoolExecutorDemo/callable/MyCallable.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/code/java/ThreadPoolExecutorDemo/out/production/ThreadPoolExecutorDemo/callable/MyCallable.class -------------------------------------------------------------------------------- /code/java/ThreadPoolExecutorDemo/out/production/ThreadPoolExecutorDemo/common/ThreadPoolConstants.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/code/java/ThreadPoolExecutorDemo/out/production/ThreadPoolExecutorDemo/common/ThreadPoolConstants.class -------------------------------------------------------------------------------- /code/java/ThreadPoolExecutorDemo/out/production/ThreadPoolExecutorDemo/scheduledThreadPoolExecutor/ScheduledThreadPoolExecutorDemo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/code/java/ThreadPoolExecutorDemo/out/production/ThreadPoolExecutorDemo/scheduledThreadPoolExecutor/ScheduledThreadPoolExecutorDemo.class -------------------------------------------------------------------------------- /code/java/ThreadPoolExecutorDemo/out/production/ThreadPoolExecutorDemo/scheduledThreadPoolExecutor/Task.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/code/java/ThreadPoolExecutorDemo/out/production/ThreadPoolExecutorDemo/scheduledThreadPoolExecutor/Task.class -------------------------------------------------------------------------------- /code/java/ThreadPoolExecutorDemo/out/production/ThreadPoolExecutorDemo/threadPoolExecutor/MyRunnable.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/code/java/ThreadPoolExecutorDemo/out/production/ThreadPoolExecutorDemo/threadPoolExecutor/MyRunnable.class -------------------------------------------------------------------------------- /code/java/ThreadPoolExecutorDemo/out/production/ThreadPoolExecutorDemo/threadPoolExecutor/ThreadPoolExecutorDemo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/code/java/ThreadPoolExecutorDemo/out/production/ThreadPoolExecutorDemo/threadPoolExecutor/ThreadPoolExecutorDemo.class -------------------------------------------------------------------------------- /code/java/ThreadPoolExecutorDemo/src/callable/CallableDemo.java: -------------------------------------------------------------------------------- 1 | package callable; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Date; 5 | import java.util.List; 6 | import java.util.concurrent.ArrayBlockingQueue; 7 | import java.util.concurrent.Callable; 8 | import java.util.concurrent.ExecutionException; 9 | import java.util.concurrent.Future; 10 | import java.util.concurrent.ThreadPoolExecutor; 11 | import java.util.concurrent.TimeUnit; 12 | 13 | import static common.ThreadPoolConstants.CORE_POOL_SIZE; 14 | import static common.ThreadPoolConstants.KEEP_ALIVE_TIME; 15 | import static common.ThreadPoolConstants.MAX_POOL_SIZE; 16 | import static common.ThreadPoolConstants.QUEUE_CAPACITY; 17 | 18 | public class CallableDemo { 19 | public static void main(String[] args) { 20 | //使用阿里巴巴推荐的创建线程池的方式 21 | //通过ThreadPoolExecutor构造函数自定义参数创建 22 | ThreadPoolExecutor executor = new ThreadPoolExecutor( 23 | CORE_POOL_SIZE, 24 | MAX_POOL_SIZE, 25 | KEEP_ALIVE_TIME, 26 | TimeUnit.SECONDS, 27 | new ArrayBlockingQueue<>(QUEUE_CAPACITY), 28 | new ThreadPoolExecutor.CallerRunsPolicy()); 29 | 30 | List> futureList = new ArrayList<>(); 31 | Callable callable = new MyCallable(); 32 | for (int i = 0; i < 10; i++) { 33 | //提交任务到线程池 34 | Future future = executor.submit(callable); 35 | //将返回值 future 添加到 list,我们可以通过 future 获得 执行 Callable 得到的返回值 36 | futureList.add(future); 37 | } 38 | for (Future fut : futureList) { 39 | try { 40 | System.out.println(new Date() + "::" + fut.get()); 41 | } catch (InterruptedException | ExecutionException e) { 42 | e.printStackTrace(); 43 | } 44 | } 45 | //关闭线程池 46 | executor.shutdown(); 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /code/java/ThreadPoolExecutorDemo/src/callable/MyCallable.java: -------------------------------------------------------------------------------- 1 | package callable; 2 | 3 | import java.util.concurrent.Callable; 4 | 5 | public class MyCallable implements Callable { 6 | 7 | @Override 8 | public String call() throws Exception { 9 | Thread.sleep(1000); 10 | //返回执行当前 Callable 的线程名字 11 | return Thread.currentThread().getName(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /code/java/ThreadPoolExecutorDemo/src/common/ThreadPoolConstants.java: -------------------------------------------------------------------------------- 1 | package common; 2 | 3 | public class ThreadPoolConstants { 4 | public static final int CORE_POOL_SIZE = 5; 5 | public static final int MAX_POOL_SIZE = 10; 6 | public static final int QUEUE_CAPACITY = 100; 7 | public static final Long KEEP_ALIVE_TIME = 1L; 8 | private ThreadPoolConstants(){ 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /code/java/ThreadPoolExecutorDemo/src/threadPoolExecutor/MyRunnable.java: -------------------------------------------------------------------------------- 1 | package threadPoolExecutor; 2 | 3 | import java.util.Date; 4 | 5 | /** 6 | * 这是一个简单的Runnable类,需要大约5秒钟来执行其任务。 7 | * @author shuang.kou 8 | */ 9 | public class MyRunnable implements Runnable { 10 | 11 | private String command; 12 | 13 | public MyRunnable(String s) { 14 | this.command = s; 15 | } 16 | 17 | @Override 18 | public void run() { 19 | System.out.println(Thread.currentThread().getName() + " Start. Time = " + new Date()); 20 | processCommand(); 21 | System.out.println(Thread.currentThread().getName() + " End. Time = " + new Date()); 22 | } 23 | 24 | private void processCommand() { 25 | try { 26 | Thread.sleep(5000); 27 | } catch (InterruptedException e) { 28 | e.printStackTrace(); 29 | } 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | return this.command; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /code/java/ThreadPoolExecutorDemo/src/threadPoolExecutor/ThreadPoolExecutorDemo.java: -------------------------------------------------------------------------------- 1 | package threadPoolExecutor; 2 | 3 | import java.util.concurrent.ArrayBlockingQueue; 4 | import java.util.concurrent.ThreadPoolExecutor; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | import static common.ThreadPoolConstants.CORE_POOL_SIZE; 8 | import static common.ThreadPoolConstants.KEEP_ALIVE_TIME; 9 | import static common.ThreadPoolConstants.MAX_POOL_SIZE; 10 | import static common.ThreadPoolConstants.QUEUE_CAPACITY; 11 | 12 | 13 | public class ThreadPoolExecutorDemo { 14 | 15 | public static void main(String[] args) { 16 | 17 | //使用阿里巴巴推荐的创建线程池的方式 18 | //通过ThreadPoolExecutor构造函数自定义参数创建 19 | ThreadPoolExecutor executor = new ThreadPoolExecutor( 20 | CORE_POOL_SIZE, 21 | MAX_POOL_SIZE, 22 | KEEP_ALIVE_TIME, 23 | TimeUnit.SECONDS, 24 | new ArrayBlockingQueue<>(QUEUE_CAPACITY), 25 | new ThreadPoolExecutor.CallerRunsPolicy()); 26 | 27 | for (int i = 0; i < 10; i++) { 28 | //创建WorkerThread对象(WorkerThread类实现了Runnable 接口) 29 | Runnable worker = new MyRunnable("" + i); 30 | //执行Runnable 31 | executor.execute(worker); 32 | } 33 | //终止线程池 34 | executor.shutdown(); 35 | while (!executor.isTerminated()) { 36 | } 37 | System.out.println("Finished all threads"); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /docs/data/spring-boot-practical-projects.md: -------------------------------------------------------------------------------- 1 | 最近经常被读者问到有没有 Spring Boot 实战项目可以学习,于是,我就去 Github 上找了 10 个我觉得还不错的实战项目。对于这些实战项目,有部分是比较适合 Spring Boot 刚入门的朋友学习的,还有一部分可能要求你对 Spring Boot 相关技术比较熟悉。需要的朋友可以根据个人实际情况进行选择。如果你对 Spring Boot 不太熟悉的话,可以看我最近开源的 springboot-guide:https://github.com/Snailclimb/springboot-guide 入门(还在持续更新中)。 2 | 3 | ### mall 4 | 5 | - **Github地址**: [https://github.com/macrozheng/mall](https://github.com/macrozheng/mall) 6 | - **star**: 22.9k 7 | - **介绍**: mall项目是一套电商系统,包括前台商城系统及后台管理系统,基于SpringBoot+MyBatis实现。 前台商城系统包含首页门户、商品推荐、商品搜索、商品展示、购物车、订单流程、会员中心、客户服务、帮助中心等模块。 后台管理系统包含商品管理、订单管理、会员管理、促销管理、运营管理、内容管理、统计报表、财务管理、权限管理、设置等模块。 8 | 9 | ### jeecg-boot 10 | 11 | - **Github地址**:[https://github.com/zhangdaiscott/jeecg-boot](https://github.com/zhangdaiscott/jeecg-boot) 12 | - **star**: 6.4k 13 | - **介绍**: 一款基于代码生成器的JAVA快速开发平台!采用最新技术,前后端分离架构:SpringBoot 2.x,Ant Design&Vue,Mybatis,Shiro,JWT。强大的代码生成器让前后端代码一键生成,无需写任何代码,绝对是全栈开发福音!! JeecgBoot的宗旨是提高UI能力的同时,降低前后分离的开发成本,JeecgBoot还独创在线开发模式,No代码概念,一系列在线智能开发:在线配置表单、在线配置报表、在线设计流程等等。 14 | 15 | ### eladmin 16 | 17 | - **Github地址**:[https://github.com/elunez/eladmin](https://github.com/elunez/eladmin) 18 | - **star**: 3.9k 19 | - **介绍**: 项目基于 Spring Boot 2.1.0 、 Jpa、 Spring Security、redis、Vue的前后端分离的后台管理系统,项目采用分模块开发方式, 权限控制采用 RBAC,支持数据字典与数据权限管理,支持一键生成前后端代码,支持动态路由。 20 | 21 | ### paascloud-master 22 | 23 | - **Github地址**:[https://github.com/paascloud/paascloud-master](https://github.com/paascloud/paascloud-master) 24 | - **star**: 5.9k 25 | - **介绍**: spring cloud + vue + oAuth2.0全家桶实战,前后端分离模拟商城,完整的购物流程、后端运营平台,可以实现快速搭建企业级微服务项目。支持微信登录等三方登录。 26 | 27 | ### vhr 28 | 29 | - **Github地址**:[https://github.com/lenve/vhr](https://github.com/lenve/vhr) 30 | - **star**: 10.6k 31 | - **介绍**: 微人事是一个前后端分离的人力资源管理系统,项目采用SpringBoot+Vue开发。 32 | 33 | ### One mall 34 | 35 | - **Github地址**:[https://github.com/YunaiV/onemall](https://github.com/YunaiV/onemall) 36 | - **star**: 1.2k 37 | - **介绍**: mall 商城,基于微服务的思想,构建在 B2C 电商场景下的项目实战。核心技术栈,是 Spring Boot + Dubbo 。未来,会重构成 Spring Cloud Alibaba 。 38 | 39 | ### Guns 40 | 41 | - **Github地址**:[https://github.com/stylefeng/Guns](https://github.com/stylefeng/Guns) 42 | - **star**: 2.3k 43 | - **介绍**: Guns基于SpringBoot 2,致力于做更简洁的后台管理系统,完美整合springmvc + shiro + mybatis-plus + beetl!Guns项目代码简洁,注释丰富,上手容易,同时Guns包含许多基础模块(用户管理,角色管理,部门管理,字典管理等10个模块),可以直接作为一个后台管理系统的脚手架! 44 | 45 | ### SpringCloud 46 | 47 | - **Github地址**:[https://github.com/YunaiV/onemall](https://github.com/YunaiV/onemall) 48 | - **star**: 1.2k 49 | - **介绍**: mall 商城,基于微服务的思想,构建在 B2C 电商场景下的项目实战。核心技术栈,是 Spring Boot + Dubbo 。未来,会重构成 Spring Cloud Alibaba 。 50 | 51 | ### SpringBoot-Shiro-Vue 52 | 53 | - **Github地址**:[https://github.com/Heeexy/SpringBoot-Shiro-Vue](https://github.com/Heeexy/SpringBoot-Shiro-Vue) 54 | - **star**: 1.8k 55 | - **介绍**: 提供一套基于Spring Boot-Shiro-Vue的权限管理思路.前后端都加以控制,做到按钮/接口级别的权限。 56 | 57 | ### newbee-mall 58 | 59 | 最近开源的一个商城项目。 60 | 61 | - **Github地址**:[https://github.com/newbee-ltd/newbee-mall](https://github.com/newbee-ltd/newbee-mall) 62 | - **star**: 50 63 | - **介绍**: newbee-mall 项目是一套电商系统,包括 newbee-mall 商城系统及 newbee-mall-admin 商城后台管理系统,基于 Spring Boot 2.X 及相关技术栈开发。 前台商城系统包含首页门户、商品分类、新品上线、首页轮播、商品推荐、商品搜索、商品展示、购物车、订单结算、订单流程、个人订单管理、会员中心、帮助中心等模块。 后台管理系统包含数据面板、轮播图管理、商品管理、订单管理、会员管理、分类管理、设置等模块。 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /docs/dataStructures-algorithms/Backtracking-NQueens.md: -------------------------------------------------------------------------------- 1 | # N皇后 2 | [51. N皇后](https://leetcode-cn.com/problems/n-queens/) 3 | ### 题目描述 4 | > n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。 5 | > 6 | ![ANUzjA.png](https://s2.ax1x.com/2019/03/26/ANUzjA.png) 7 | > 8 | 上图为 8 皇后问题的一种解法。 9 | > 10 | 给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。 11 | > 12 | 每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。 13 | 14 | 示例: 15 | 16 | ``` 17 | 输入: 4 18 | 输出: [ 19 | [".Q..", // 解法 1 20 | "...Q", 21 | "Q...", 22 | "..Q."], 23 | 24 | ["..Q.", // 解法 2 25 | "Q...", 26 | "...Q", 27 | ".Q.."] 28 | ] 29 | 解释: 4 皇后问题存在两个不同的解法。 30 | ``` 31 | 32 | ### 问题分析 33 | 约束条件为每个棋子所在的行、列、对角线都不能有另一个棋子。 34 | 35 | 使用一维数组表示一种解法,下标(index)表示行,值(value)表示该行的Q(皇后)在哪一列。 36 | 每行只存储一个元素,然后递归到下一行,这样就不用判断行了,只需要判断列和对角线。 37 | ### Solution1 38 | 当result[row] = column时,即row行的棋子在column列。 39 | 40 | 对于[0, row-1]的任意一行(i 行),若 row 行的棋子和 i 行的棋子在同一列,则有result[i] == column; 41 | 若 row 行的棋子和 i 行的棋子在同一对角线,等腰直角三角形两直角边相等,即 row - i == Math.abs(result[i] - column) 42 | 43 | 布尔类型变量 isValid 的作用是剪枝,减少不必要的递归。 44 | ``` 45 | public List> solveNQueens(int n) { 46 | // 下标代表行,值代表列。如result[0] = 3 表示第1行的Q在第3列 47 | int[] result = new int[n]; 48 | List> resultList = new LinkedList<>(); 49 | dfs(resultList, result, 0, n); 50 | return resultList; 51 | } 52 | 53 | void dfs(List> resultList, int[] result, int row, int n) { 54 | // 递归终止条件 55 | if (row == n) { 56 | List list = new LinkedList<>(); 57 | for (int x = 0; x < n; ++x) { 58 | StringBuilder sb = new StringBuilder(); 59 | for (int y = 0; y < n; ++y) 60 | sb.append(result[x] == y ? "Q" : "."); 61 | list.add(sb.toString()); 62 | } 63 | resultList.add(list); 64 | return; 65 | } 66 | for (int column = 0; column < n; ++column) { 67 | boolean isValid = true; 68 | result[row] = column; 69 | /* 70 | * 逐行往下考察每一行。同列,result[i] == column 71 | * 同对角线,row - i == Math.abs(result[i] - column) 72 | */ 73 | for (int i = row - 1; i >= 0; --i) { 74 | if (result[i] == column || row - i == Math.abs(result[i] - column)) { 75 | isValid = false; 76 | break; 77 | } 78 | } 79 | if (isValid) dfs(resultList, result, row + 1, n); 80 | } 81 | } 82 | ``` 83 | ### Solution2 84 | 使用LinkedList表示一种解法,下标(index)表示行,值(value)表示该行的Q(皇后)在哪一列。 85 | 86 | 解法二和解法一的不同在于,相同列以及相同对角线的校验。 87 | 将对角线抽象成【一次函数】这个简单的数学模型,根据一次函数的截距是常量这一特性进行校验。 88 | 89 | 这里,我将右上-左下对角线,简称为“\”对角线;左上-右下对角线简称为“/”对角线。 90 | 91 | “/”对角线斜率为1,对应方程为y = x + b,其中b为截距。 92 | 对于线上任意一点,均有y - x = b,即row - i = b; 93 | 定义一个布尔类型数组anti_diag,将b作为下标,当anti_diag[b] = true时,表示相应对角线上已经放置棋子。 94 | 但row - i有可能为负数,负数不能作为数组下标,row - i 的最小值为-n(当row = 0,i = n时),可以加上n作为数组下标,即将row -i + n 作为数组下标。 95 | row - i + n 的最大值为 2n(当row = n,i = 0时),故anti_diag的容量设置为 2n 即可。 96 | 97 | ![ANXG79.png](https://s2.ax1x.com/2019/03/26/ANXG79.png) 98 | 99 | “\”对角线斜率为-1,对应方程为y = -x + b,其中b为截距。 100 | 对于线上任意一点,均有y + x = b,即row + i = b; 101 | 同理,定义数组main_diag,将b作为下标,当main_diag[row + i] = true时,表示相应对角线上已经放置棋子。 102 | 103 | 有了两个校验对角线的数组,再来定义一个用于校验列的数组cols,这个太简单啦,不解释。 104 | 105 | **解法二时间复杂度为O(n!),在校验相同列和相同对角线时,引入三个布尔类型数组进行判断。相比解法一,少了一层循环,用空间换时间。** 106 | 107 | ``` 108 | List> resultList = new LinkedList<>(); 109 | 110 | public List> solveNQueens(int n) { 111 | boolean[] cols = new boolean[n]; 112 | boolean[] main_diag = new boolean[2 * n]; 113 | boolean[] anti_diag = new boolean[2 * n]; 114 | LinkedList result = new LinkedList<>(); 115 | dfs(result, 0, cols, main_diag, anti_diag, n); 116 | return resultList; 117 | } 118 | 119 | void dfs(LinkedList result, int row, boolean[] cols, boolean[] main_diag, boolean[] anti_diag, int n) { 120 | if (row == n) { 121 | List list = new LinkedList<>(); 122 | for (int x = 0; x < n; ++x) { 123 | StringBuilder sb = new StringBuilder(); 124 | for (int y = 0; y < n; ++y) 125 | sb.append(result.get(x) == y ? "Q" : "."); 126 | list.add(sb.toString()); 127 | } 128 | resultList.add(list); 129 | return; 130 | } 131 | for (int i = 0; i < n; ++i) { 132 | if (cols[i] || main_diag[row + i] || anti_diag[row - i + n]) 133 | continue; 134 | result.add(i); 135 | cols[i] = true; 136 | main_diag[row + i] = true; 137 | anti_diag[row - i + n] = true; 138 | dfs(result, row + 1, cols, main_diag, anti_diag, n); 139 | result.removeLast(); 140 | cols[i] = false; 141 | main_diag[row + i] = false; 142 | anti_diag[row - i + n] = false; 143 | } 144 | } 145 | ``` -------------------------------------------------------------------------------- /docs/dataStructures-algorithms/公司真题.md: -------------------------------------------------------------------------------- 1 | # 网易 2018 2 | 3 | 下面三道编程题来自网易2018校招编程题,这三道应该来说是非常简单的编程题了,这些题目大家稍微有点编程和数学基础的话应该没什么问题。看答案之前一定要自己先想一下如果是自己做的话会怎么去做,然后再对照这我的答案看看,和你自己想的有什么区别?那一种方法更好? 4 | 5 | ## 问题 6 | 7 | ### 一 获得特定数量硬币问题 8 | 9 | 小易准备去魔法王国采购魔法神器,购买魔法神器需要使用魔法币,但是小易现在一枚魔法币都没有,但是小易有两台魔法机器可以通过投入x(x可以为0)个魔法币产生更多的魔法币。 10 | 11 | 魔法机器1:如果投入x个魔法币,魔法机器会将其变为2x+1个魔法币 12 | 13 | 魔法机器2:如果投入x个魔法币,魔法机器会将其变为2x+2个魔法币 14 | 15 | 小易采购魔法神器总共需要n个魔法币,所以小易只能通过两台魔法机器产生恰好n个魔法币,小易需要你帮他设计一个投入方案使他最后恰好拥有n个魔法币。 16 | 17 | **输入描述:** 输入包括一行,包括一个正整数n(1 ≤ n ≤ 10^9),表示小易需要的魔法币数量。 18 | 19 | **输出描述:** 输出一个字符串,每个字符表示该次小易选取投入的魔法机器。其中只包含字符'1'和'2'。 20 | 21 | **输入例子1:** 10 22 | 23 | **输出例子1:** 122 24 | 25 | ### 二 求“相反数”问题 26 | 27 | 为了得到一个数的"相反数",我们将这个数的数字顺序颠倒,然后再加上原先的数得到"相反数"。例如,为了得到1325的"相反数",首先我们将该数的数字顺序颠倒,我们得到5231,之后再加上原先的数,我们得到5231+1325=6556.如果颠倒之后的数字有前缀零,前缀零将会被忽略。例如n = 100, 颠倒之后是1. 28 | 29 | **输入描述:** 输入包括一个整数n,(1 ≤ n ≤ 10^5) 30 | 31 | **输出描述:** 输出一个整数,表示n的相反数 32 | 33 | **输入例子1:** 1325 34 | 35 | **输出例子1:** 6556 36 | 37 | ### 三 字符串碎片的平均长度 38 | 39 | 一个由小写字母组成的字符串可以看成一些同一字母的最大碎片组成的。例如,"aaabbaaac"是由下面碎片组成的:'aaa','bb','c'。牛牛现在给定一个字符串,请你帮助计算这个字符串的所有碎片的平均长度是多少。 40 | 41 | **输入描述:** 输入包括一个字符串s,字符串s的长度length(1 ≤ length ≤ 50),s只含小写字母('a'-'z') 42 | 43 | **输出描述:** 输出一个整数,表示所有碎片的平均长度,四舍五入保留两位小数。 44 | 45 | **如样例所示:** s = "aaabbaaac" 46 | 所有碎片的平均长度 = (3 + 2 + 3 + 1) / 4 = 2.25 47 | 48 | **输入例子1:** aaabbaaac 49 | 50 | **输出例子1:** 2.25 51 | 52 | ## 答案 53 | 54 | ### 一 获得特定数量硬币问题 55 | 56 | #### 分析: 57 | 58 | 作为该试卷的第一题,这道题应该只要思路正确就很简单了。 59 | 60 | 解题关键:明确魔法机器1只能产生奇数,魔法机器2只能产生偶数即可。我们从后往前一步一步推回去即可。 61 | 62 | #### 示例代码 63 | 64 | 注意:由于用户的输入不确定性,一般是为了程序高可用性使需要将捕获用户输入异常然后友好提示用户输入类型错误并重新输入的。所以下面我给了两个版本,这两个版本都是正确的。这里只是给大家演示如何捕获输入类型异常,后面的题目中我给的代码没有异常处理的部分,参照下面两个示例代码,应该很容易添加。(PS:企业面试中没有明确就不用添加异常处理,当然你有的话也更好) 65 | 66 | **不带输入异常处理判断的版本:** 67 | 68 | ```java 69 | import java.util.Scanner; 70 | 71 | public class Main2 { 72 | // 解题关键:明确魔法机器1只能产生奇数,魔法机器2只能产生偶数即可。我们从后往前一步一步推回去即可。 73 | 74 | public static void main(String[] args) { 75 | System.out.println("请输入要获得的硬币数量:"); 76 | Scanner scanner = new Scanner(System.in); 77 | int coincount = scanner.nextInt(); 78 | StringBuilder sb = new StringBuilder(); 79 | while (coincount >= 1) { 80 | // 偶数的情况 81 | if (coincount % 2 == 0) { 82 | coincount = (coincount - 2) / 2; 83 | sb.append("2"); 84 | // 奇数的情况 85 | } else { 86 | coincount = (coincount - 1) / 2; 87 | sb.append("1"); 88 | } 89 | } 90 | // 输出反转后的字符串 91 | System.out.println(sb.reverse()); 92 | 93 | } 94 | } 95 | ``` 96 | 97 | **带输入异常处理判断的版本(当输入的不是整数的时候会提示重新输入):** 98 | 99 | ```java 100 | import java.util.InputMismatchException; 101 | import java.util.Scanner; 102 | 103 | 104 | public class Main { 105 | // 解题关键:明确魔法机器1只能产生奇数,魔法机器2只能产生偶数即可。我们从后往前一步一步推回去即可。 106 | 107 | public static void main(String[] args) { 108 | System.out.println("请输入要获得的硬币数量:"); 109 | Scanner scanner = new Scanner(System.in); 110 | boolean flag = true; 111 | while (flag) { 112 | try { 113 | int coincount = scanner.nextInt(); 114 | StringBuilder sb = new StringBuilder(); 115 | while (coincount >= 1) { 116 | // 偶数的情况 117 | if (coincount % 2 == 0) { 118 | coincount = (coincount - 2) / 2; 119 | sb.append("2"); 120 | // 奇数的情况 121 | } else { 122 | coincount = (coincount - 1) / 2; 123 | sb.append("1"); 124 | } 125 | } 126 | // 输出反转后的字符串 127 | System.out.println(sb.reverse()); 128 | flag=false;//程序结束 129 | } catch (InputMismatchException e) { 130 | System.out.println("输入数据类型不匹配,请您重新输入:"); 131 | scanner.nextLine(); 132 | continue; 133 | } 134 | } 135 | 136 | } 137 | } 138 | 139 | ``` 140 | 141 | ### 二 求“相反数”问题 142 | 143 | #### 分析: 144 | 145 | 解决本道题有几种不同的方法,但是最快速的方法就是利用reverse()方法反转字符串然后再将字符串转换成int类型的整数,这个方法是快速解决本题关键。我们先来回顾一下下面两个知识点: 146 | 147 | **1)String转int;** 148 | 149 | 在 Java 中要将 String 类型转化为 int 类型时,需要使用 Integer 类中的 parseInt() 方法或者 valueOf() 方法进行转换. 150 | 151 | ```java 152 | String str = "123"; 153 | int a = Integer.parseInt(str); 154 | ``` 155 | 156 | 或 157 | 158 | ```java 159 | String str = "123"; 160 | int a = Integer.valueOf(str).intValue(); 161 | ``` 162 | 163 | **2)next()和nextLine()的区别** 164 | 165 | 在Java中输入字符串有两种方法,就是next()和nextLine().两者的区别就是:nextLine()的输入是碰到回车就终止输入,而next()方法是碰到空格,回车,Tab键都会被视为终止符。所以next()不会得到带空格的字符串,而nextLine()可以得到带空格的字符串。 166 | 167 | #### 示例代码: 168 | 169 | ```java 170 | import java.util.Scanner; 171 | 172 | /** 173 | * 本题关键:①String转int;②next()和nextLine()的区别 174 | */ 175 | public class Main { 176 | 177 | public static void main(String[] args) { 178 | 179 | System.out.println("请输入一个整数:"); 180 | Scanner scanner = new Scanner(System.in); 181 | String s=scanner.next(); 182 | //将字符串转换成数字 183 | int number1=Integer.parseInt(s); 184 | //将字符串倒序后转换成数字 185 | //因为Integer.parseInt()的参数类型必须是字符串所以必须加上toString() 186 | int number2=Integer.parseInt(new StringBuilder(s).reverse().toString()); 187 | System.out.println(number1+number2); 188 | 189 | } 190 | } 191 | ``` 192 | 193 | ### 三 字符串碎片的平均长度 194 | 195 | #### 分析: 196 | 197 | 这道题的意思也就是要求:(字符串的总长度)/(相同字母团构成的字符串的个数)。 198 | 199 | 这样就很简单了,就变成了字符串的字符之间的比较。如果需要比较字符串的字符的话,我们可以利用charAt(i)方法:取出特定位置的字符与后一个字符比较,或者利用toCharArray()方法将字符串转换成字符数组采用同样的方法做比较。 200 | 201 | #### 示例代码 202 | 203 | **利用charAt(i)方法:** 204 | 205 | ```java 206 | import java.util.Scanner; 207 | 208 | public class Main { 209 | 210 | public static void main(String[] args) { 211 | 212 | Scanner sc = new Scanner(System.in); 213 | while (sc.hasNext()) { 214 | String s = sc.next(); 215 | //个数至少为一个 216 | float count = 1; 217 | for (int i = 0; i < s.length() - 1; i++) { 218 | if (s.charAt(i) != s.charAt(i + 1)) { 219 | count++; 220 | } 221 | } 222 | System.out.println(s.length() / count); 223 | } 224 | } 225 | 226 | } 227 | ``` 228 | 229 | **利用toCharArray()方法:** 230 | 231 | ```java 232 | import java.util.Scanner; 233 | 234 | public class Main2 { 235 | 236 | public static void main(String[] args) { 237 | 238 | Scanner sc = new Scanner(System.in); 239 | while (sc.hasNext()) { 240 | String s = sc.next(); 241 | //个数至少为一个 242 | float count = 1; 243 | char [] stringArr = s.toCharArray(); 244 | for (int i = 0; i < stringArr.length - 1; i++) { 245 | if (stringArr[i] != stringArr[i + 1]) { 246 | count++; 247 | } 248 | } 249 | System.out.println(s.length() / count); 250 | } 251 | } 252 | 253 | } 254 | ``` -------------------------------------------------------------------------------- /docs/dataStructures-algorithms/数据结构.md: -------------------------------------------------------------------------------- 1 | 下面只是简单地总结,给了一些参考文章,后面会对这部分内容进行重构。 2 | 3 | 4 | - [Queue](#queue) 5 | - [什么是队列](#什么是队列) 6 | - [队列的种类](#队列的种类) 7 | - [Java 集合框架中的队列 Queue](#java-集合框架中的队列-queue) 8 | - [推荐文章](#推荐文章) 9 | - [Set](#set) 10 | - [什么是 Set](#什么是-set) 11 | - [补充:有序集合与无序集合说明](#补充:有序集合与无序集合说明) 12 | - [HashSet 和 TreeSet 底层数据结构](#hashset-和-treeset-底层数据结构) 13 | - [推荐文章](#推荐文章-1) 14 | - [List](#list) 15 | - [什么是List](#什么是list) 16 | - [List的常见实现类](#list的常见实现类) 17 | - [ArrayList 和 LinkedList 源码学习](#arraylist-和-linkedlist-源码学习) 18 | - [推荐阅读](#推荐阅读) 19 | - [Map](#map) 20 | - [树](#树) 21 | 22 | 23 | 24 | 25 | ## Queue 26 | 27 | ### 什么是队列 28 | 队列是数据结构中比较重要的一种类型,它支持 FIFO,尾部添加、头部删除(先进队列的元素先出队列),跟我们生活中的排队类似。 29 | 30 | ### 队列的种类 31 | 32 | - **单队列**(单队列就是常见的队列, 每次添加元素时,都是添加到队尾,存在“假溢出”的问题也就是明明有位置却不能添加的情况) 33 | - **循环队列**(避免了“假溢出”的问题) 34 | 35 | ### Java 集合框架中的队列 Queue 36 | 37 | Java 集合中的 Queue 继承自 Collection 接口 ,Deque, LinkedList, PriorityQueue, BlockingQueue 等类都实现了它。 38 | Queue 用来存放 等待处理元素 的集合,这种场景一般用于缓冲、并发访问。 39 | 除了继承 Collection 接口的一些方法,Queue 还添加了额外的 添加、删除、查询操作。 40 | 41 | ### 推荐文章 42 | 43 | - [Java 集合深入理解(9):Queue 队列](https://blog.csdn.net/u011240877/article/details/52860924) 44 | 45 | ## Set 46 | 47 | ### 什么是 Set 48 | Set 继承于 Collection 接口,是一个不允许出现重复元素,并且无序的集合,主要 HashSet 和 TreeSet 两大实现类。 49 | 50 | 在判断重复元素的时候,HashSet 集合会调用 hashCode()和 equal()方法来实现;TreeSet 集合会调用compareTo方法来实现。 51 | 52 | ### 补充:有序集合与无序集合说明 53 | - 有序集合:集合里的元素可以根据 key 或 index 访问 (List、Map) 54 | - 无序集合:集合里的元素只能遍历。(Set) 55 | 56 | 57 | ### HashSet 和 TreeSet 底层数据结构 58 | 59 | **HashSet** 是哈希表结构,主要利用 HashMap 的 key 来存储元素,计算插入元素的 hashCode 来获取元素在集合中的位置; 60 | 61 | **TreeSet** 是红黑树结构,每一个元素都是树中的一个节点,插入的元素都会进行排序; 62 | 63 | 64 | ### 推荐文章 65 | 66 | - [Java集合--Set(基础)](https://www.jianshu.com/p/b48c47a42916) 67 | 68 | ## List 69 | 70 | ### 什么是List 71 | 72 | 在 List 中,用户可以精确控制列表中每个元素的插入位置,另外用户可以通过整数索引(列表中的位置)访问元素,并搜索列表中的元素。 与 Set 不同,List 通常允许重复的元素。 另外 List 是有序集合而 Set 是无序集合。 73 | 74 | ### List的常见实现类 75 | 76 | **ArrayList** 是一个数组队列,相当于动态数组。它由数组实现,随机访问效率高,随机插入、随机删除效率低。 77 | 78 | **LinkedList** 是一个双向链表。它也可以被当作堆栈、队列或双端队列进行操作。LinkedList随机访问效率低,但随机插入、随机删除效率高。 79 | 80 | **Vector** 是矢量队列,和ArrayList一样,它也是一个动态数组,由数组实现。但是ArrayList是非线程安全的,而Vector是线程安全的。 81 | 82 | **Stack** 是栈,它继承于Vector。它的特性是:先进后出(FILO, First In Last Out)。相关阅读:[java数据结构与算法之栈(Stack)设计与实现](https://blog.csdn.net/javazejian/article/details/53362993) 83 | 84 | ### ArrayList 和 LinkedList 源码学习 85 | 86 | - [ArrayList 源码学习](https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/collection/ArrayList.md) 87 | - [LinkedList 源码学习](https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/collection/LinkedList.md) 88 | 89 | ### 推荐阅读 90 | 91 | - [java 数据结构与算法之顺序表与链表深入分析](https://blog.csdn.net/javazejian/article/details/52953190) 92 | 93 | 94 | ## Map 95 | 96 | 97 | - [集合框架源码学习之 HashMap(JDK1.8)](https://juejin.im/post/5ab0568b5188255580020e56) 98 | - [ConcurrentHashMap 实现原理及源码分析](https://link.juejin.im/?target=http%3A%2F%2Fwww.cnblogs.com%2Fchengxiao%2Fp%2F6842045.html) 99 | 100 | ## 树 101 | * ### 1 二叉树 102 | 103 | [二叉树](https://baike.baidu.com/item/%E4%BA%8C%E5%8F%89%E6%A0%91)(百度百科) 104 | 105 | (1)[完全二叉树](https://baike.baidu.com/item/%E5%AE%8C%E5%85%A8%E4%BA%8C%E5%8F%89%E6%A0%91)——若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。 106 | 107 | (2)[满二叉树](https://baike.baidu.com/item/%E6%BB%A1%E4%BA%8C%E5%8F%89%E6%A0%91)——除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。 108 | 109 | (3)[平衡二叉树](https://baike.baidu.com/item/%E5%B9%B3%E8%A1%A1%E4%BA%8C%E5%8F%89%E6%A0%91/10421057)——平衡二叉树又被称为AVL树(区别于AVL算法),它是一棵二叉排序树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。 110 | 111 | * ### 2 完全二叉树 112 | 113 | [完全二叉树](https://baike.baidu.com/item/%E5%AE%8C%E5%85%A8%E4%BA%8C%E5%8F%89%E6%A0%91)(百度百科) 114 | 115 | 完全二叉树:叶节点只能出现在最下层和次下层,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树。 116 | * ### 3 满二叉树 117 | 118 | [满二叉树](https://baike.baidu.com/item/%E6%BB%A1%E4%BA%8C%E5%8F%89%E6%A0%91)(百度百科,国内外的定义不同) 119 | 120 | 国内教程定义:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是(2^k) -1 ,则它就是满二叉树。 121 | * ### 堆 122 | 123 | [数据结构之堆的定义](https://blog.csdn.net/qq_33186366/article/details/51876191) 124 | 125 | 堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。 126 | * ### 4 二叉查找树(BST) 127 | 128 | [浅谈算法和数据结构: 七 二叉查找树](http://www.cnblogs.com/yangecnu/p/Introduce-Binary-Search-Tree.html) 129 | 130 | 二叉查找树的特点: 131 | 132 | 1. 若任意节点的左子树不空,则左子树上所有结点的 值均小于它的根结点的值; 133 | 2. 若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 134 | 3. 任意节点的左、右子树也分别为二叉查找树; 135 | 4. 没有键值相等的节点(no duplicate nodes)。 136 | 137 | * ### 5 平衡二叉树(Self-balancing binary search tree) 138 | 139 | [ 平衡二叉树](https://baike.baidu.com/item/%E5%B9%B3%E8%A1%A1%E4%BA%8C%E5%8F%89%E6%A0%91)(百度百科,平衡二叉树的常用实现方法有红黑树、AVL、替罪羊树、Treap、伸展树等) 140 | * ### 6 红黑树 141 | 142 | - 红黑树特点: 143 | 1. 每个节点非红即黑; 144 | 2. 根节点总是黑色的; 145 | 3. 每个叶子节点都是黑色的空节点(NIL节点); 146 | 4. 如果节点是红色的,则它的子节点必须是黑色的(反之不一定); 147 | 5. 从根节点到叶节点或空子节点的每条路径,必须包含相同数目的黑色节点(即相同的黑色高度)。 148 | 149 | - 红黑树的应用: 150 | 151 | TreeMap、TreeSet以及JDK1.8之后的HashMap底层都用到了红黑树。 152 | 153 | - 为什么要用红黑树 154 | 155 | 简单来说红黑树就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构。详细了解可以查看 [漫画:什么是红黑树?](https://juejin.im/post/5a27c6946fb9a04509096248#comment)(也介绍到了二叉查找树,非常推荐) 156 | 157 | - 推荐文章: 158 | - [漫画:什么是红黑树?](https://juejin.im/post/5a27c6946fb9a04509096248#comment)(也介绍到了二叉查找树,非常推荐) 159 | - [寻找红黑树的操作手册](http://dandanlove.com/2018/03/18/red-black-tree/)(文章排版以及思路真的不错) 160 | - [红黑树深入剖析及Java实现](https://zhuanlan.zhihu.com/p/24367771)(美团点评技术团队) 161 | * ### 7 B-,B+,B*树 162 | 163 | [二叉树学习笔记之B树、B+树、B*树 ](https://yq.aliyun.com/articles/38345) 164 | 165 | [《B-树,B+树,B*树详解》](https://blog.csdn.net/aqzwss/article/details/53074186) 166 | 167 | [《B-树,B+树与B*树的优缺点比较》](https://blog.csdn.net/bigtree_3721/article/details/73632405) 168 | 169 | B-树(或B树)是一种平衡的多路查找(又称排序)树,在文件系统中有所应用。主要用作文件的索引。其中的B就表示平衡(Balance) 170 | 1. B+ 树的叶子节点链表结构相比于 B- 树便于扫库,和范围检索。 171 | 2. B+树支持range-query(区间查询)非常方便,而B树不支持。这是数据库选用B+树的最主要原因。 172 | 3. B\*树 是B+树的变体,B\*树分配新结点的概率比B+树要低,空间使用率更高; 173 | * ### 8 LSM 树 174 | 175 | [[HBase] LSM树 VS B+树](https://blog.csdn.net/dbanote/article/details/8897599) 176 | 177 | B+树最大的性能问题是会产生大量的随机IO 178 | 179 | 为了克服B+树的弱点,HBase引入了LSM树的概念,即Log-Structured Merge-Trees。 180 | 181 | [LSM树由来、设计思想以及应用到HBase的索引](http://www.cnblogs.com/yanghuahui/p/3483754.html) 182 | 183 | 184 | ## 图 185 | 186 | 187 | 188 | 189 | ## BFS及DFS 190 | 191 | - [《使用BFS及DFS遍历树和图的思路及实现》](https://blog.csdn.net/Gene1994/article/details/85097507) 192 | 193 | -------------------------------------------------------------------------------- /docs/dataStructures-algorithms/算法学习资源推荐.md: -------------------------------------------------------------------------------- 1 | 我比较推荐大家可以刷一下 Leetcode ,我自己平时没事也会刷一下,我觉得刷 Leetcode 不仅是为了能让你更从容地面对面试中的手撕算法问题,更可以提高你的编程思维能力、解决问题的能力以及你对某门编程语言 API 的熟练度。当然牛客网也有一些算法题,我下面也整理了一些。 2 | 3 | ## LeetCode 4 | 5 | - [LeetCode(中国)官网](https://leetcode-cn.com/) 6 | 7 | - [如何高效地使用 LeetCode](https://leetcode-cn.com/articles/%E5%A6%82%E4%BD%95%E9%AB%98%E6%95%88%E5%9C%B0%E4%BD%BF%E7%94%A8-leetcode/) 8 | 9 | 10 | ## 牛客网 11 | 12 | - [牛客网官网](https://www.nowcoder.com) 13 | - [剑指offer编程题](https://www.nowcoder.com/ta/coding-interviews) 14 | 15 | - [2017校招真题](https://www.nowcoder.com/ta/2017test) 16 | - [华为机试题](https://www.nowcoder.com/ta/huawei) 17 | 18 | 19 | ## 公司真题 20 | 21 | - [ 网易2018校园招聘编程题真题集合](https://www.nowcoder.com/test/6910869/summary) 22 | - [ 网易2018校招内推编程题集合](https://www.nowcoder.com/test/6291726/summary) 23 | - [2017年校招全国统一模拟笔试(第五场)编程题集合](https://www.nowcoder.com/test/5986669/summary) 24 | - [2017年校招全国统一模拟笔试(第四场)编程题集合](https://www.nowcoder.com/test/5507925/summary) 25 | - [2017年校招全国统一模拟笔试(第三场)编程题集合](https://www.nowcoder.com/test/5217106/summary) 26 | - [2017年校招全国统一模拟笔试(第二场)编程题集合](https://www.nowcoder.com/test/4546329/summary) 27 | - [ 2017年校招全国统一模拟笔试(第一场)编程题集合](https://www.nowcoder.com/test/4236887/summary) 28 | - [百度2017春招笔试真题编程题集合](https://www.nowcoder.com/test/4998655/summary) 29 | - [网易2017春招笔试真题编程题集合](https://www.nowcoder.com/test/4575457/summary) 30 | - [网易2017秋招编程题集合](https://www.nowcoder.com/test/2811407/summary) 31 | - [网易有道2017内推编程题](https://www.nowcoder.com/test/2385858/summary) 32 | - [ 滴滴出行2017秋招笔试真题-编程题汇总](https://www.nowcoder.com/test/3701760/summary) 33 | - [腾讯2017暑期实习生编程题](https://www.nowcoder.com/test/1725829/summary) 34 | - [今日头条2017客户端工程师实习生笔试题](https://www.nowcoder.com/test/1649301/summary) 35 | - [今日头条2017后端工程师实习生笔试题](https://www.nowcoder.com/test/1649268/summary) 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /docs/database/MySQL Index.md: -------------------------------------------------------------------------------- 1 | 2 | # 思维导图-索引篇 3 | 4 | > 系列思维导图源文件(数据库+架构)以及思维导图制作软件—XMind8 破解安装,公众号后台回复:**“思维导图”** 免费领取!(下面的图片不是很清楚,原图非常清晰,另外提供给大家源文件也是为了大家根据自己需要进行修改) 5 | 6 | ![【思维导图-索引篇】](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-10-2/70973487.jpg) 7 | 8 | > **下面是我补充的一些内容** 9 | 10 | # 为什么索引能提高查询速度 11 | 12 | > 以下内容整理自: 13 | > 地址: https://juejin.im/post/5b55b842f265da0f9e589e79 14 | > 作者 :Java3y 15 | 16 | ### 先从 MySQL 的基本存储结构说起 17 | 18 | MySQL的基本存储结构是页(记录都存在页里边): 19 | 20 | ![MySQL的基本存储结构是页](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-10-2/28559421.jpg) 21 | 22 | ![](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-10-2/82053134.jpg) 23 | 24 | - **各个数据页可以组成一个双向链表** 25 | - **每个数据页中的记录又可以组成一个单向链表** 26 | - 每个数据页都会为存储在它里边儿的记录生成一个页目录,在通过主键查找某条记录的时候可以在页目录中使用二分法快速定位到对应的槽,然后再遍历该槽对应分组中的记录即可快速找到指定的记录 27 | - 以其他列(非主键)作为搜索条件:只能从最小记录开始依次遍历单链表中的每条记录。 28 | 29 | 所以说,如果我们写select * from user where indexname = 'xxx'这样没有进行任何优化的sql语句,默认会这样做: 30 | 31 | 1. **定位到记录所在的页:需要遍历双向链表,找到所在的页** 32 | 2. **从所在的页内中查找相应的记录:由于不是根据主键查询,只能遍历所在页的单链表了** 33 | 34 | 很明显,在数据量很大的情况下这样查找会很慢!这样的时间复杂度为O(n)。 35 | 36 | 37 | ### 使用索引之后 38 | 39 | 索引做了些什么可以让我们查询加快速度呢?其实就是将无序的数据变成有序(相对): 40 | 41 | ![](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-10-2/5373082.jpg) 42 | 43 | 要找到id为8的记录简要步骤: 44 | 45 | ![](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-10-2/89338047.jpg) 46 | 47 | 很明显的是:没有用索引我们是需要遍历双向链表来定位对应的页,现在通过 **“目录”** 就可以很快地定位到对应的页上了!(二分查找,时间复杂度近似为O(logn)) 48 | 49 | 其实底层结构就是B+树,B+树作为树的一种实现,能够让我们很快地查找出对应的记录。 50 | 51 | # 关于索引其他重要的内容补充 52 | 53 | > 以下内容整理自:《Java工程师修炼之道》 54 | 55 | 56 | ### 最左前缀原则 57 | 58 | MySQL中的索引可以以一定顺序引用多列,这种索引叫作联合索引。如User表的name和city加联合索引就是(name,city),而最左前缀原则指的是,如果查询的时候查询条件精确匹配索引的左边连续一列或几列,则此列就可以被用到。如下: 59 | 60 | ``` 61 | select * from user where name=xx and city=xx ; //可以命中索引 62 | select * from user where name=xx ; // 可以命中索引 63 | select * from user where city=xx ; // 无法命中索引 64 | ``` 65 | 这里需要注意的是,查询的时候如果两个条件都用上了,但是顺序不同,如 `city= xx and name =xx`,那么现在的查询引擎会自动优化为匹配联合索引的顺序,这样是能够命中索引的。 66 | 67 | 由于最左前缀原则,在创建联合索引时,索引字段的顺序需要考虑字段值去重之后的个数,较多的放前面。ORDER BY子句也遵循此规则。 68 | 69 | ### 注意避免冗余索引 70 | 71 | 冗余索引指的是索引的功能相同,能够命中 就肯定能命中 ,那么 就是冗余索引如(name,city )和(name )这两个索引就是冗余索引,能够命中后者的查询肯定是能够命中前者的 在大多数情况下,都应该尽量扩展已有的索引而不是创建新索引。 72 | 73 | MySQL 5.7 版本后,可以通过查询 sys 库的 `schema_redundant_indexes` 表来查看冗余索引 74 | 75 | ### Mysql如何为表字段添加索引??? 76 | 77 | 1.添加PRIMARY KEY(主键索引) 78 | 79 | ``` 80 | ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` ) 81 | ``` 82 | 2.添加UNIQUE(唯一索引) 83 | 84 | ``` 85 | ALTER TABLE `table_name` ADD UNIQUE ( `column` ) 86 | ``` 87 | 88 | 3.添加INDEX(普通索引) 89 | 90 | ``` 91 | ALTER TABLE `table_name` ADD INDEX index_name ( `column` ) 92 | ``` 93 | 94 | 4.添加FULLTEXT(全文索引) 95 | 96 | ``` 97 | ALTER TABLE `table_name` ADD FULLTEXT ( `column`) 98 | ``` 99 | 100 | 5.添加多列索引 101 | 102 | ``` 103 | ALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` ) 104 | ``` 105 | 106 | 107 | # 参考 108 | 109 | - 《Java工程师修炼之道》 110 | - 《MySQL高性能书籍_第3版》 111 | - https://juejin.im/post/5b55b842f265da0f9e589e79 112 | 113 | -------------------------------------------------------------------------------- /docs/database/Redis/Redis持久化.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 非常感谢《redis实战》真本书,本文大多内容也参考了书中的内容。非常推荐大家看一下《redis实战》这本书,感觉书中的很多理论性东西还是很不错的。 4 | 5 | 为什么本文的名字要加上春夏秋冬又一春,哈哈 ,这是一部韩国的电影,我感觉电影不错,所以就用在文章名字上了,没有什么特别的含义,然后下面的有些配图也是电影相关镜头。 6 | 7 | ![春夏秋冬又一春](https://user-gold-cdn.xitu.io/2018/6/13/163f97071d71f6de?w=1280&h=720&f=jpeg&s=205252) 8 | 9 | **很多时候我们需要持久化数据也就是将内存中的数据写入到硬盘里面,大部分原因是为了之后重用数据(比如重启机器、机器故障之后回复数据),或者是为了防止系统故障而将数据备份到一个远程位置。** 10 | 11 | Redis不同于Memcached的很重一点就是,**Redis支持持久化**,而且支持两种不同的持久化操作。Redis的一种持久化方式叫**快照(snapshotting,RDB)**,另一种方式是**只追加文件(append-only file,AOF)**.这两种方法各有千秋,下面我会详细这两种持久化方法是什么,怎么用,如何选择适合自己的持久化方法。 12 | 13 | 14 | ## 快照(snapshotting)持久化 15 | 16 | Redis可以通过创建快照来获得存储在内存里面的数据在某个时间点上的副本。Redis创建快照之后,可以对快照进行备份,可以将快照复制到其他服务器从而创建具有相同数据的服务器副本(Redis主从结构,主要用来提高Redis性能),还可以将快照留在原地以便重启服务器的时候使用。 17 | 18 | 19 | ![春夏秋冬又一春](https://user-gold-cdn.xitu.io/2018/6/13/163f97568281782a?w=600&h=329&f=jpeg&s=88616) 20 | 21 | **快照持久化是Redis默认采用的持久化方式**,在redis.conf配置文件中默认有此下配置: 22 | ``` 23 | 24 | save 900 1 #在900秒(15分钟)之后,如果至少有1个key发生变化,Redis就会自动触发BGSAVE命令创建快照。 25 | 26 | save 300 10 #在300秒(5分钟)之后,如果至少有10个key发生变化,Redis就会自动触发BGSAVE命令创建快照。 27 | 28 | save 60 10000 #在60秒(1分钟)之后,如果至少有10000个key发生变化,Redis就会自动触发BGSAVE命令创建快照。 29 | ``` 30 | 31 | 根据配置,快照将被写入dbfilename选项指定的文件里面,并存储在dir选项指定的路径上面。如果在新的快照文件创建完毕之前,Redis、系统或者硬件这三者中的任意一个崩溃了,那么Redis将丢失最近一次创建快照写入的所有数据。 32 | 33 | 举个例子:假设Redis的上一个快照是2:35开始创建的,并且已经创建成功。下午3:06时,Redis又开始创建新的快照,并且在下午3:08快照创建完毕之前,有35个键进行了更新。如果在下午3:06到3:08期间,系统发生了崩溃,导致Redis无法完成新快照的创建工作,那么Redis将丢失下午2:35之后写入的所有数据。另一方面,如果系统恰好在新的快照文件创建完毕之后崩溃,那么Redis将丢失35个键的更新数据。 34 | 35 | **创建快照的办法有如下几种:** 36 | 37 | - **BGSAVE命令:** 客户端向Redis发送 **BGSAVE命令** 来创建一个快照。对于支持BGSAVE命令的平台来说(基本上所有平台支持,除了Windows平台),Redis会调用fork来创建一个子进程,然后子进程负责将快照写入硬盘,而父进程则继续处理命令请求。 38 | - **SAVE命令:** 客户端还可以向Redis发送 **SAVE命令** 来创建一个快照,接到SAVE命令的Redis服务器在快照创建完毕之前不会再响应任何其他命令。SAVE命令不常用,我们通常只会在没有足够内存去执行BGSAVE命令的情况下,又或者即使等待持久化操作执行完毕也无所谓的情况下,才会使用这个命令。 39 | - **save选项:** 如果用户设置了save选项(一般会默认设置),比如 **save 60 10000**,那么从Redis最近一次创建快照之后开始算起,当“60秒之内有10000次写入”这个条件被满足时,Redis就会自动触发BGSAVE命令。 40 | - **SHUTDOWN命令:** 当Redis通过SHUTDOWN命令接收到关闭服务器的请求时,或者接收到标准TERM信号时,会执行一个SAVE命令,阻塞所有客户端,不再执行客户端发送的任何命令,并在SAVE命令执行完毕之后关闭服务器。 41 | - **一个Redis服务器连接到另一个Redis服务器:** 当一个Redis服务器连接到另一个Redis服务器,并向对方发送SYNC命令来开始一次复制操作的时候,如果主服务器目前没有执行BGSAVE操作,或者主服务器并非刚刚执行完BGSAVE操作,那么主服务器就会执行BGSAVE命令 42 | 43 | 如果系统真的发生崩溃,用户将丢失最近一次生成快照之后更改的所有数据。因此,快照持久化只适用于即使丢失一部分数据也不会造成一些大问题的应用程序。不能接受这个缺点的话,可以考虑AOF持久化。 44 | 45 | 46 | 47 | ## **AOF(append-only file)持久化** 48 | 与快照持久化相比,AOF持久化 的实时性更好,因此已成为主流的持久化方案。默认情况下Redis没有开启AOF(append only file)方式的持久化,可以通过appendonly参数开启: 49 | ``` 50 | appendonly yes 51 | ``` 52 | 53 | 开启AOF持久化后每执行一条会更改Redis中的数据的命令,Redis就会将该命令写入硬盘中的AOF文件。AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的,默认的文件名是appendonly.aof。 54 | 55 | ![春夏秋冬又一春](https://user-gold-cdn.xitu.io/2018/6/13/163f976818876166?w=400&h=219&f=jpeg&s=91022) 56 | 57 | **在Redis的配置文件中存在三种同步方式,它们分别是:** 58 | 59 | ``` 60 | 61 | appendfsync always #每次有数据修改发生时都会写入AOF文件,这样会严重降低Redis的速度 62 | appendfsync everysec #每秒钟同步一次,显示地将多个写命令同步到硬盘 63 | appendfsync no #让操作系统决定何时进行同步 64 | ``` 65 | 66 | **appendfsync always** 可以实现将数据丢失减到最少,不过这种方式需要对硬盘进行大量的写入而且每次只写入一个命令,十分影响Redis的速度。另外使用固态硬盘的用户谨慎使用appendfsync always选项,因为这会明显降低固态硬盘的使用寿命。 67 | 68 | 为了兼顾数据和写入性能,用户可以考虑 **appendfsync everysec选项** ,让Redis每秒同步一次AOF文件,Redis性能几乎没受到任何影响。而且这样即使出现系统崩溃,用户最多只会丢失一秒之内产生的数据。当硬盘忙于执行写入操作的时候,Redis还会优雅的放慢自己的速度以便适应硬盘的最大写入速度。 69 | 70 | 71 | **appendfsync no** 选项一般不推荐,这种方案会使Redis丢失不定量的数据而且如果用户的硬盘处理写入操作的速度不够的话,那么当缓冲区被等待写入的数据填满时,Redis的写入操作将被阻塞,这会导致Redis的请求速度变慢。 72 | 73 | **虽然AOF持久化非常灵活地提供了多种不同的选项来满足不同应用程序对数据安全的不同要求,但AOF持久化也有缺陷——AOF文件的体积太大。** 74 | 75 | ## 重写/压缩AOF 76 | 77 | AOF虽然在某个角度可以将数据丢失降低到最小而且对性能影响也很小,但是极端的情况下,体积不断增大的AOF文件很可能会用完硬盘空间。另外,如果AOF体积过大,那么还原操作执行时间就可能会非常长。 78 | 79 | 为了解决AOF体积过大的问题,用户可以向Redis发送 **BGREWRITEAOF命令** ,这个命令会通过移除AOF文件中的冗余命令来重写(rewrite)AOF文件来减小AOF文件的体积。BGREWRITEAOF命令和BGSAVE创建快照原理十分相似,所以AOF文件重写也需要用到子进程,这样会导致性能问题和内存占用问题,和快照持久化一样。更糟糕的是,如果不加以控制的话,AOF文件的体积可能会比快照文件大好几倍。 80 | 81 | **文件重写流程:** 82 | 83 | ![文件重写流程](https://user-gold-cdn.xitu.io/2018/6/13/163f97f9bd0eea50?w=380&h=345&f=jpeg&s=14501) 84 | 和快照持久化可以通过设置save选项来自动执行BGSAVE一样,AOF持久化也可以通过设置 85 | 86 | ``` 87 | auto-aof-rewrite-percentage 88 | ``` 89 | 90 | 选项和 91 | 92 | ``` 93 | auto-aof-rewrite-min-size 94 | ``` 95 | 96 | 选项自动执行BGREWRITEAOF命令。举例:假设用户对Redis设置了如下配置选项并且启用了AOF持久化。那么当AOF文件体积大于64mb,并且AOF的体积比上一次重写之后的体积大了至少一倍(100%)的时候,Redis将执行BGREWRITEAOF命令。 97 | 98 | ``` 99 | auto-aof-rewrite-percentage 100 100 | auto-aof-rewrite-min-size 64mb 101 | ``` 102 | 103 | 无论是AOF持久化还是快照持久化,将数据持久化到硬盘上都是非常有必要的,但除了进行持久化外,用户还必须对持久化得到的文件进行备份(最好是备份到不同的地方),这样才能尽量避免数据丢失事故发生。如果条件允许的话,最好能将快照文件和重新重写的AOF文件备份到不同的服务器上面。 104 | 105 | 随着负载量的上升,或者数据的完整性变得 越来越重要时,用户可能需要使用到复制特性。 106 | 107 | ## Redis 4.0 对于持久化机制的优化 108 | Redis 4.0 开始支持 RDB 和 AOF 的混合持久化(默认关闭,可以通过配置项 `aof-use-rdb-preamble` 开启)。 109 | 110 | 如果把混合持久化打开,AOF 重写的时候就直接把 RDB 的内容写到 AOF 文件开头。这样做的好处是可以结合 RDB 和 AOF 的优点, 快速加载同时避免丢失过多的数据。当然缺点也是有的, AOF 里面的 RDB 部分就是压缩格式不再是 AOF 格式,可读性较差。 111 | 112 | 参考: 113 | 114 | 《Redis实战》 115 | 116 | [深入学习Redis(2):持久化](https://www.cnblogs.com/kismetv/p/9137897.html) 117 | 118 | 119 | -------------------------------------------------------------------------------- /docs/database/Redis/Redlock分布式锁.md: -------------------------------------------------------------------------------- 1 | 这篇文章主要是对 Redis 官方网站刊登的 [Distributed locks with Redis](https://redis.io/topics/distlock) 部分内容的总结和翻译。 2 | 3 | ## 什么是 RedLock 4 | 5 | Redis 官方站这篇文章提出了一种权威的基于 Redis 实现分布式锁的方式名叫 *Redlock*,此种方式比原先的单节点的方法更安全。它可以保证以下特性: 6 | 7 | 1. 安全特性:互斥访问,即永远只有一个 client 能拿到锁 8 | 2. 避免死锁:最终 client 都可能拿到锁,不会出现死锁的情况,即使原本锁住某资源的 client crash 了或者出现了网络分区 9 | 3. 容错性:只要大部分 Redis 节点存活就可以正常提供服务 10 | 11 | ## 怎么在单节点上实现分布式锁 12 | 13 | > SET resource_name my_random_value NX PX 30000 14 | 15 | 主要依靠上述命令,该命令仅当 Key 不存在时(NX保证)set 值,并且设置过期时间 3000ms (PX保证),值 my_random_value 必须是所有 client 和所有锁请求发生期间唯一的,释放锁的逻辑是: 16 | 17 | ```lua 18 | if redis.call("get",KEYS[1]) == ARGV[1] then 19 | return redis.call("del",KEYS[1]) 20 | else 21 | return 0 22 | end 23 | ``` 24 | 25 | 上述实现可以避免释放另一个client创建的锁,如果只有 del 命令的话,那么如果 client1 拿到 lock1 之后因为某些操作阻塞了很长时间,此时 Redis 端 lock1 已经过期了并且已经被重新分配给了 client2,那么 client1 此时再去释放这把锁就会造成 client2 原本获取到的锁被 client1 无故释放了,但现在为每个 client 分配一个 unique 的 string 值可以避免这个问题。至于如何去生成这个 unique string,方法很多随意选择一种就行了。 26 | 27 | ## Redlock 算法 28 | 29 | 算法很易懂,起 5 个 master 节点,分布在不同的机房尽量保证可用性。为了获得锁,client 会进行如下操作: 30 | 31 | 1. 得到当前的时间,微秒单位 32 | 2. 尝试顺序地在 5 个实例上申请锁,当然需要使用相同的 key 和 random value,这里一个 client 需要合理设置与 master 节点沟通的 timeout 大小,避免长时间和一个 fail 了的节点浪费时间 33 | 3. 当 client 在大于等于 3 个 master 上成功申请到锁的时候,且它会计算申请锁消耗了多少时间,这部分消耗的时间采用获得锁的当下时间减去第一步获得的时间戳得到,如果锁的持续时长(lock validity time)比流逝的时间多的话,那么锁就真正获取到了。 34 | 4. 如果锁申请到了,那么锁真正的 lock validity time 应该是 origin(lock validity time) - 申请锁期间流逝的时间 35 | 5. 如果 client 申请锁失败了,那么它就会在少部分申请成功锁的 master 节点上执行释放锁的操作,重置状态 36 | 37 | ## 失败重试 38 | 39 | 如果一个 client 申请锁失败了,那么它需要稍等一会在重试避免多个 client 同时申请锁的情况,最好的情况是一个 client 需要几乎同时向 5 个 master 发起锁申请。另外就是如果 client 申请锁失败了它需要尽快在它曾经申请到锁的 master 上执行 unlock 操作,便于其他 client 获得这把锁,避免这些锁过期造成的时间浪费,当然如果这时候网络分区使得 client 无法联系上这些 master,那么这种浪费就是不得不付出的代价了。 40 | 41 | ## 放锁 42 | 43 | 放锁操作很简单,就是依次释放所有节点上的锁就行了 44 | 45 | ## 性能、崩溃恢复和 fsync 46 | 47 | 如果我们的节点没有持久化机制,client 从 5 个 master 中的 3 个处获得了锁,然后其中一个重启了,这是注意 **整个环境中又出现了 3 个 master 可供另一个 client 申请同一把锁!** 违反了互斥性。如果我们开启了 AOF 持久化那么情况会稍微好转一些,因为 Redis 的过期机制是语义层面实现的,所以在 server 挂了的时候时间依旧在流逝,重启之后锁状态不会受到污染。但是考虑断电之后呢,AOF部分命令没来得及刷回磁盘直接丢失了,除非我们配置刷回策略为 fsnyc = always,但这会损伤性能。解决这个问题的方法是,当一个节点重启之后,我们规定在 max TTL 期间它是不可用的,这样它就不会干扰原本已经申请到的锁,等到它 crash 前的那部分锁都过期了,环境不存在历史锁了,那么再把这个节点加进来正常工作。 48 | -------------------------------------------------------------------------------- /docs/database/Redis/如何做可靠的分布式锁,Redlock真的可行么.md: -------------------------------------------------------------------------------- 1 | 本文是对 [Martin Kleppmann](https://martin.kleppmann.com/) 的文章 [How to do distributed locking](https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html) 部分内容的翻译和总结,上次写 Redlock 的原因就是看到了 Martin 的这篇文章,写得很好,特此翻译和总结。感兴趣的同学可以翻看原文,相信会收获良多。 2 | 3 | 开篇作者认为现在 Redis 逐渐被使用到数据管理领域,这个领域需要更强的数据一致性和耐久性,这使得他感到担心,因为这不是 Redis 最初设计的初衷(事实上这也是很多业界程序员的误区,越来越把 Redis 当成数据库在使用),其中基于 Redis 的分布式锁就是令人担心的其一。 4 | 5 | Martin 指出首先你要明确你为什么使用分布式锁,为了性能还是正确性?为了帮你区分这二者,在这把锁 fail 了的时候你可以询问自己以下问题: 6 | 1. **要性能的:** 拥有这把锁使得你不会重复劳动(例如一个 job 做了两次),如果这把锁 fail 了,两个节点同时做了这个 Job,那么这个 Job 增加了你的成本。 7 | 2. **要正确性的:** 拥有锁可以防止并发操作污染你的系统或者数据,如果这把锁 fail 了两个节点同时操作了一份数据,结果可能是数据不一致、数据丢失、file 冲突等,会导致严重的后果。 8 | 9 | 上述二者都是需求锁的正确场景,但是你必须清楚自己是因为什么原因需要分布式锁。 10 | 11 | 如果你只是为了性能,那没必要用 Redlock,它成本高且复杂,你只用一个 Redis 实例也够了,最多加个从防止主挂了。当然,你使用单节点的 Redis 那么断电或者一些情况下,你会丢失锁,但是你的目的只是加速性能且断电这种事情不会经常发生,这并不是什么大问题。并且如果你使用了单节点 Redis,那么很显然你这个应用需要的锁粒度是很模糊粗糙的,也不会是什么重要的服务。 12 | 13 | 那么是否 Redlock 对于要求正确性的场景就合适呢?Martin 列举了若干场景证明 Redlock 这种算法是不可靠的。 14 | 15 | ## 用锁保护资源 16 | 这节里 Martin 先将 Redlock 放在了一边而是仅讨论总体上一个分布式锁是怎么工作的。在分布式环境下,锁比 mutex 这类复杂,因为涉及到不同节点、网络通信并且他们随时可能无征兆的 fail 。 17 | Martin 假设了一个场景,一个 client 要修改一个文件,它先申请得到锁,然后修改文件写回,放锁。另一个 client 再申请锁 ... 代码流程如下: 18 | 19 | ```java 20 | // THIS CODE IS BROKEN 21 | function writeData(filename, data) { 22 | var lock = lockService.acquireLock(filename); 23 | if (!lock) { 24 | throw 'Failed to acquire lock'; 25 | } 26 | 27 | try { 28 | var file = storage.readFile(filename); 29 | var updated = updateContents(file, data); 30 | storage.writeFile(filename, updated); 31 | } finally { 32 | lock.release(); 33 | } 34 | } 35 | ``` 36 | 37 | 可惜即使你的锁服务非常完美,上述代码还是可能跪,下面的流程图会告诉你为什么: 38 | 39 | ![](https://martin.kleppmann.com/2016/02/unsafe-lock.png) 40 | 41 | 上述图中,得到锁的 client1 在持有锁的期间 pause 了一段时间,例如 GC 停顿。锁有过期时间(一般叫租约,为了防止某个 client 崩溃之后一直占有锁),但是如果 GC 停顿太长超过了锁租约时间,此时锁已经被另一个 client2 所得到,原先的 client1 还没有感知到锁过期,那么奇怪的结果就会发生,曾经 HBase 就发生过这种 Bug。即使你在 client1 写回之前检查一下锁是否过期也无助于解决这个问题,因为 GC 可能在任何时候发生,即使是你非常不便的时候(在最后的检查与写操作期间)。 42 | 如果你认为自己的程序不会有长时间的 GC 停顿,还有其他原因会导致你的进程 pause。例如进程可能读取尚未进入内存的数据,所以它得到一个 page fault 并且等待 page 被加载进缓存;还有可能你依赖于网络服务;或者其他进程占用 CPU;或者其他人意外发生 SIGSTOP 等。 43 | 44 | ... .... 这里 Martin 又增加了一节列举各种进程 pause 的例子,为了证明上面的代码是不安全的,无论你的锁服务多完美。 45 | 46 | ## 使用 Fencing (栅栏)使得锁变安全 47 | 修复问题的方法也很简单:你需要在每次写操作时加入一个 fencing token。这个场景下,fencing token 可以是一个递增的数字(lock service 可以做到),每次有 client 申请锁就递增一次: 48 | 49 | ![](https://martin.kleppmann.com/2016/02/fencing-tokens.png) 50 | 51 | client1 申请锁同时拿到 token33,然后它进入长时间的停顿锁也过期了。client2 得到锁和 token34 写入数据,紧接着 client1 活过来之后尝试写入数据,自身 token33 比 34 小因此写入操作被拒绝。注意这需要存储层来检查 token,但这并不难实现。如果你使用 Zookeeper 作为 lock service 的话那么你可以使用 zxid 作为递增数字。 52 | 但是对于 Redlock 你要知道,没什么生成 fencing token 的方式,并且怎么修改 Redlock 算法使其能产生 fencing token 呢?好像并不那么显而易见。因为产生 token 需要单调递增,除非在单节点 Redis 上完成但是这又没有高可靠性,你好像需要引进一致性协议来让 Redlock 产生可靠的 fencing token。 53 | 54 | ## 使用时间来解决一致性 55 | Redlock 无法产生 fencing token 早该成为在需求正确性的场景下弃用它的理由,但还有一些值得讨论的地方。 56 | 57 | 学术界有个说法,算法对时间不做假设:因为进程可能pause一段时间、数据包可能因为网络延迟延后到达、时钟可能根本就是错的。而可靠的算法依旧要在上述假设下做正确的事情。 58 | 59 | 对于 failure detector 来说,timeout 只能作为猜测某个节点 fail 的依据,因为网络延迟、本地时钟不正确等其他原因的限制。考虑到 Redis 使用 gettimeofday,而不是单调的时钟,会受到系统时间的影响,可能会突然前进或者后退一段时间,这会导致一个 key 更快或更慢地过期。 60 | 61 | 可见,Redlock 依赖于许多时间假设,它假设所有 Redis 节点都能对同一个 Key 在其过期前持有差不多的时间、跟过期时间相比网络延迟很小、跟过期时间相比进程 pause 很短。 62 | 63 | ## 用不可靠的时间打破 Redlock 64 | 这节 Martin 举了个因为时间问题,Redlock 不可靠的例子。 65 | 66 | 1. client1 从 ABC 三个节点处申请到锁,DE由于网络原因请求没有到达 67 | 2. C节点的时钟往前推了,导致 lock 过期 68 | 3. client2 在CDE处获得了锁,AB由于网络原因请求未到达 69 | 4. 此时 client1 和 client2 都获得了锁 70 | 71 | **在 Redlock 官方文档中也提到了这个情况,不过是C崩溃的时候,Redlock 官方本身也是知道 Redlock 算法不是完全可靠的,官方为了解决这种问题建议使用延时启动,相关内容可以看之前的[这篇文章](https://zhuanlan.zhihu.com/p/40915772)。但是 Martin 这里分析得更加全面,指出延时启动不也是依赖于时钟的正确性的么?** 72 | 73 | 接下来 Martin 又列举了进程 Pause 时而不是时钟不可靠时会发生的问题: 74 | 75 | 1. client1 从 ABCDE 处获得了锁 76 | 2. 当获得锁的 response 还没到达 client1 时 client1 进入 GC 停顿 77 | 3. 停顿期间锁已经过期了 78 | 4. client2 在 ABCDE 处获得了锁 79 | 5. client1 GC 完成收到了获得锁的 response,此时两个 client 又拿到了同一把锁 80 | 81 | **同时长时间的网络延迟也有可能导致同样的问题。** 82 | 83 | ## Redlock 的同步性假设 84 | 这些例子说明了,仅有在你假设了一个同步性系统模型的基础上,Redlock 才能正常工作,也就是系统能满足以下属性: 85 | 86 | 1. 网络延时边界,即假设数据包一定能在某个最大延时之内到达 87 | 2. 进程停顿边界,即进程停顿一定在某个最大时间之内 88 | 3. 时钟错误边界,即不会从一个坏的 NTP 服务器处取得时间 89 | 90 | ## 结论 91 | Martin 认为 Redlock 实在不是一个好的选择,对于需求性能的分布式锁应用它太重了且成本高;对于需求正确性的应用来说它不够安全。因为它对高危的时钟或者说其他上述列举的情况进行了不可靠的假设,如果你的应用只需要高性能的分布式锁不要求多高的正确性,那么单节点 Redis 够了;如果你的应用想要保住正确性,那么不建议 Redlock,建议使用一个合适的一致性协调系统,例如 Zookeeper,且保证存在 fencing token。 92 | -------------------------------------------------------------------------------- /docs/database/一条sql语句在mysql中如何执行的.md: -------------------------------------------------------------------------------- 1 | 本文来自[木木匠](https://github.com/kinglaw1204)投稿。 2 | 3 | 4 | 5 | - [一 MySQL 基础架构分析](#一-mysql-基础架构分析) 6 | - [1.1 MySQL 基本架构概览](#11-mysql-基本架构概览) 7 | - [1.2 Server 层基本组件介绍](#12-server-层基本组件介绍) 8 | - [1) 连接器](#1-连接器) 9 | - [2) 查询缓存(MySQL 8.0 版本后移除)](#2-查询缓存mysql-80-版本后移除) 10 | - [3) 分析器](#3-分析器) 11 | - [4) 优化器](#4-优化器) 12 | - [5) 执行器](#5-执行器) 13 | - [二 语句分析](#二-语句分析) 14 | - [2.1 查询语句](#21-查询语句) 15 | - [2.2 更新语句](#22-更新语句) 16 | - [三 总结](#三-总结) 17 | - [四 参考](#四-参考) 18 | 19 | 20 | 21 | 本篇文章会分析下一个 sql 语句在 MySQL 中的执行流程,包括 sql 的查询在 MySQL 内部会怎么流转,sql 语句的更新是怎么完成的。 22 | 23 | 在分析之前我会先带着你看看 MySQL 的基础架构,知道了 MySQL 由那些组件组成已经这些组件的作用是什么,可以帮助我们理解和解决这些问题。 24 | 25 | ## 一 MySQL 基础架构分析 26 | 27 | ### 1.1 MySQL 基本架构概览 28 | 29 | 下图是 MySQL 的一个简要架构图,从下图你可以很清晰的看到用户的 SQL 语句在 MySQL 内部是如何执行的。 30 | 31 | 先简单介绍一下下图涉及的一些组件的基本作用帮助大家理解这幅图,在 1.2 节中会详细介绍到这些组件的作用。 32 | 33 | - **连接器:** 身份认证和权限相关(登录 MySQL 的时候)。 34 | - **查询缓存:** 执行查询语句的时候,会先查询缓存(MySQL 8.0 版本后移除,因为这个功能不太实用)。 35 | - **分析器:** 没有命中缓存的话,SQL 语句就会经过分析器,分析器说白了就是要先看你的 SQL 语句要干嘛,再检查你的 SQL 语句语法是否正确。 36 | - **优化器:** 按照 MySQL 认为最优的方案去执行。 37 | - **执行器:** 执行语句,然后从存储引擎返回数据。 38 | 39 | ![](https://user-gold-cdn.xitu.io/2019/3/23/169a8bc60a083849?w=950&h=1062&f=jpeg&s=38189) 40 | 41 | 简单来说 MySQL 主要分为 Server 层和存储引擎层: 42 | 43 | - **Server 层**:主要包括连接器、查询缓存、分析器、优化器、执行器等,所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图,函数等,还有一个通用的日志模块 binglog 日志模块。 44 | - **存储引擎**: 主要负责数据的存储和读取,采用可以替换的插件式架构,支持 InnoDB、MyISAM、Memory 等多个存储引擎,其中 InnoDB 引擎有自有的日志模块 redolog 模块。**现在最常用的存储引擎是 InnoDB,它从 MySQL 5.5.5 版本开始就被当做默认存储引擎了。** 45 | 46 | ### 1.2 Server 层基本组件介绍 47 | 48 | #### 1) 连接器 49 | 50 | 连接器主要和身份认证和权限相关的功能相关,就好比一个级别很高的门卫一样。 51 | 52 | 主要负责用户登录数据库,进行用户的身份认证,包括校验账户密码,权限等操作,如果用户账户密码已通过,连接器会到权限表中查询该用户的所有权限,之后在这个连接里的权限逻辑判断都是会依赖此时读取到的权限数据,也就是说,后续只要这个连接不断开,即时管理员修改了该用户的权限,该用户也是不受影响的。 53 | 54 | #### 2) 查询缓存(MySQL 8.0 版本后移除) 55 | 56 | 查询缓存主要用来缓存我们所执行的 SELECT 语句以及该语句的结果集。 57 | 58 | 连接建立后,执行查询语句的时候,会先查询缓存,MySQL 会先校验这个 sql 是否执行过,以 Key-Value 的形式缓存在内存中,Key 是查询预计,Value 是结果集。如果缓存 key 被命中,就会直接返回给客户端,如果没有命中,就会执行后续的操作,完成后也会把结果缓存起来,方便下一次调用。当然在真正执行缓存查询的时候还是会校验用户的权限,是否有该表的查询条件。 59 | 60 | MySQL 查询不建议使用缓存,因为查询缓存失效在实际业务场景中可能会非常频繁,假如你对一个表更新的话,这个表上的所有的查询缓存都会被清空。对于不经常更新的数据来说,使用缓存还是可以的。 61 | 62 | 所以,一般在大多数情况下我们都是不推荐去使用查询缓存的。 63 | 64 | MySQL 8.0 版本后删除了缓存的功能,官方也是认为该功能在实际的应用场景比较少,所以干脆直接删掉了。 65 | 66 | #### 3) 分析器 67 | 68 | MySQL 没有命中缓存,那么就会进入分析器,分析器主要是用来分析 SQL 语句是来干嘛的,分析器也会分为几步: 69 | 70 | **第一步,词法分析**,一条 SQL 语句有多个字符串组成,首先要提取关键字,比如 select,提出查询的表,提出字段名,提出查询条件等等。做完这些操作后,就会进入第二步。 71 | 72 | **第二步,语法分析**,主要就是判断你输入的 sql 是否正确,是否符合 MySQL 的语法。 73 | 74 | 完成这 2 步之后,MySQL 就准备开始执行了,但是如何执行,怎么执行是最好的结果呢?这个时候就需要优化器上场了。 75 | 76 | #### 4) 优化器 77 | 78 | 优化器的作用就是它认为的最优的执行方案去执行(有时候可能也不是最优,这篇文章涉及对这部分知识的深入讲解),比如多个索引的时候该如何选择索引,多表查询的时候如何选择关联顺序等。 79 | 80 | 可以说,经过了优化器之后可以说这个语句具体该如何执行就已经定下来。 81 | 82 | #### 5) 执行器 83 | 84 | 当选择了执行方案后,MySQL 就准备开始执行了,首先执行前会校验该用户有没有权限,如果没有权限,就会返回错误信息,如果有权限,就会去调用引擎的接口,返回接口执行的结果。 85 | 86 | ## 二 语句分析 87 | 88 | ### 2.1 查询语句 89 | 90 | 说了以上这么多,那么究竟一条 sql 语句是如何执行的呢?其实我们的 sql 可以分为两种,一种是查询,一种是更新(增加,更新,删除)。我们先分析下查询语句,语句如下: 91 | 92 | ```sql 93 | select * from tb_student A where A.age='18' and A.name=' 张三 '; 94 | ``` 95 | 96 | 结合上面的说明,我们分析下这个语句的执行流程: 97 | 98 | * 先检查该语句是否有权限,如果没有权限,直接返回错误信息,如果有权限,在 MySQL8.0 版本以前,会先查询缓存,以这条 sql 语句为 key 在内存中查询是否有结果,如果有直接缓存,如果没有,执行下一步。 99 | * 通过分析器进行词法分析,提取 sql 语句的关键元素,比如提取上面这个语句是查询 select,提取需要查询的表名为 tb_student,需要查询所有的列,查询条件是这个表的 id='1'。然后判断这个 sql 语句是否有语法错误,比如关键词是否正确等等,如果检查没问题就执行下一步。 100 | * 接下来就是优化器进行确定执行方案,上面的 sql 语句,可以有两种执行方案: 101 | 102 | a.先查询学生表中姓名为“张三”的学生,然后判断是否年龄是 18。 103 | b.先找出学生中年龄 18 岁的学生,然后再查询姓名为“张三”的学生。 104 | 那么优化器根据自己的优化算法进行选择执行效率最好的一个方案(优化器认为,有时候不一定最好)。那么确认了执行计划后就准备开始执行了。 105 | 106 | * 进行权限校验,如果没有权限就会返回错误信息,如果有权限就会调用数据库引擎接口,返回引擎的执行结果。 107 | 108 | ### 2.2 更新语句 109 | 110 | 以上就是一条查询 sql 的执行流程,那么接下来我们看看一条更新语句如何执行的呢?sql 语句如下: 111 | 112 | ``` 113 | update tb_student A set A.age='19' where A.name=' 张三 '; 114 | ``` 115 | 我们来给张三修改下年龄,在实际数据库肯定不会设置年龄这个字段的,不然要被技术负责人打的。其实条语句也基本上会沿着上一个查询的流程走,只不过执行更新的时候肯定要记录日志啦,这就会引入日志模块了,MySQL 自带的日志模块式 **binlog(归档日志)** ,所有的存储引擎都可以使用,我们常用的 InnoDB 引擎还自带了一个日志模块 **redo log(重做日志)**,我们就以 InnoDB 模式下来探讨这个语句的执行流程。流程如下: 116 | 117 | * 先查询到张三这一条数据,如果有缓存,也是会用到缓存。 118 | * 然后拿到查询的语句,把 age 改为 19,然后调用引擎 API 接口,写入这一行数据,InnoDB 引擎把数据保存在内存中,同时记录 redo log,此时 redo log 进入 prepare 状态,然后告诉执行器,执行完成了,随时可以提交。 119 | * 执行器收到通知后记录 binlog,然后调用引擎接口,提交 redo log 为提交状态。 120 | * 更新完成。 121 | 122 | **这里肯定有同学会问,为什么要用两个日志模块,用一个日志模块不行吗?** 123 | 124 | 这是因为最开始 MySQL 并没与 InnoDB 引擎( InnoDB 引擎是其他公司以插件形式插入 MySQL 的) ,MySQL 自带的引擎是 MyISAM,但是我们知道 redo log 是 InnoDB 引擎特有的,其他存储引擎都没有,这就导致会没有 crash-safe 的能力(crash-safe 的能力即使数据库发生异常重启,之前提交的记录都不会丢失),binlog 日志只能用来归档。 125 | 126 | 并不是说只用一个日志模块不可以,只是 InnoDB 引擎就是通过 redo log 来支持事务的。那么,又会有同学问,我用两个日志模块,但是不要这么复杂行不行,为什么 redo log 要引入 prepare 预提交状态?这里我们用反证法来说明下为什么要这么做? 127 | 128 | * **先写 redo log 直接提交,然后写 binlog**,假设写完 redo log 后,机器挂了,binlog 日志没有被写入,那么机器重启后,这台机器会通过 redo log 恢复数据,但是这个时候 bingog 并没有记录该数据,后续进行机器备份的时候,就会丢失这一条数据,同时主从同步也会丢失这一条数据。 129 | * **先写 binlog,然后写 redo log**,假设写完了 binlog,机器异常重启了,由于没有 redo log,本机是无法恢复这一条记录的,但是 binlog 又有记录,那么和上面同样的道理,就会产生数据不一致的情况。 130 | 131 | 如果采用 redo log 两阶段提交的方式就不一样了,写完 binglog 后,然后再提交 redo log 就会防止出现上述的问题,从而保证了数据的一致性。那么问题来了,有没有一个极端的情况呢?假设 redo log 处于预提交状态,binglog 也已经写完了,这个时候发生了异常重启会怎么样呢? 132 | 这个就要依赖于 MySQL 的处理机制了,MySQL 的处理过程如下: 133 | 134 | * 判断 redo log 是否完整,如果判断是完整的,就立即提交。 135 | * 如果 redo log 只是预提交但不是 commit 状态,这个时候就会去判断 binlog 是否完整,如果完整就提交 redo log, 不完整就回滚事务。 136 | 137 | 这样就解决了数据一致性的问题。 138 | 139 | ## 三 总结 140 | 141 | * MySQL 主要分为 Server 层和引擎层,Server 层主要包括连接器、查询缓存、分析器、优化器、执行器,同时还有一个日志模块(binlog),这个日志模块所有执行引擎都可以共用,redolog 只有 InnoDB 有。 142 | * 引擎层是插件式的,目前主要包括,MyISAM,InnoDB,Memory 等。 143 | * 查询语句的执行流程如下:权限校验(如果命中缓存)---》查询缓存---》分析器---》优化器---》权限校验---》执行器---》引擎 144 | * 更新语句执行流程如下:分析器----》权限校验----》执行器---》引擎---redo log(prepare 状态---》binlog---》redo log(commit状态) 145 | 146 | ## 四 参考 147 | 148 | * 《MySQL 实战45讲》 149 | * MySQL 5.6参考手册: 150 | -------------------------------------------------------------------------------- /docs/database/事务隔离级别(图文详解).md: -------------------------------------------------------------------------------- 1 | > 本文由 [SnailClimb](https://github.com/Snailclimb) 和 [BugSpeak](https://github.com/BugSpeak) 共同完成。 2 | 3 | 4 | - [事务隔离级别(图文详解)](#事务隔离级别图文详解) 5 | - [什么是事务?](#什么是事务) 6 | - [事务的特性(ACID)](#事务的特性acid) 7 | - [并发事务带来的问题](#并发事务带来的问题) 8 | - [事务隔离级别](#事务隔离级别) 9 | - [实际情况演示](#实际情况演示) 10 | - [脏读(读未提交)](#脏读读未提交) 11 | - [避免脏读(读已提交)](#避免脏读读已提交) 12 | - [不可重复读](#不可重复读) 13 | - [可重复读](#可重复读) 14 | - [防止幻读(可重复读)](#防止幻读可重复读) 15 | - [参考](#参考) 16 | 17 | 18 | 19 | ## 事务隔离级别(图文详解) 20 | 21 | ### 什么是事务? 22 | 23 | 事务是逻辑上的一组操作,要么都执行,要么都不执行。 24 | 25 | 事务最经典也经常被拿出来说例子就是转账了。假如小明要给小红转账1000元,这个转账会涉及到两个关键操作就是:将小明的余额减少1000元,将小红的余额增加1000元。万一在这两个操作之间突然出现错误比如银行系统崩溃,导致小明余额减少而小红的余额没有增加,这样就不对了。事务就是保证这两个关键操作要么都成功,要么都要失败。 26 | 27 | ### 事务的特性(ACID) 28 | 29 | ![事务的特性](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/事务特性.png) 30 | 31 | 32 | 1. **原子性:** 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用; 33 | 2. **一致性:** 执行事务前后,数据保持一致,例如转账业务中,无论事务是否成功,转账者和收款人的总额应该是不变的; 34 | 3. **隔离性:** 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的; 35 | 4. **持久性:** 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。 36 | 37 | ### 并发事务带来的问题 38 | 39 | 在典型的应用程序中,多个事务并发运行,经常会操作相同的数据来完成各自的任务(多个用户对统一数据进行操作)。并发虽然是必须的,但可能会导致以下的问题。 40 | 41 | - **脏读(Dirty read):** 当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的。 42 | - **丢失修改(Lost to modify):** 指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。 例如:事务1读取某表中的数据A=20,事务2也读取A=20,事务1修改A=A-1,事务2也修改A=A-1,最终结果A=19,事务1的修改被丢失。 43 | - **不可重复读(Unrepeatableread):** 指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。 44 | - **幻读(Phantom read):** 幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。 45 | 46 | **不可重复度和幻读区别:** 47 | 48 | 不可重复读的重点是修改,幻读的重点在于新增或者删除。 49 | 50 | 例1(同样的条件, 你读取过的数据, 再次读取出来发现值不一样了 ):事务1中的A先生读取自己的工资为 1000的操作还没完成,事务2中的B先生就修改了A的工资为2000,导 致A再读自己的工资时工资变为 2000;这就是不可重复读。 51 | 52 | 例2(同样的条件, 第1次和第2次读出来的记录数不一样 ):假某工资单表中工资大于3000的有4人,事务1读取了所有工资大于3000的人,共查到4条记录,这时事务2 又插入了一条工资大于3000的记录,事务1再次读取时查到的记录就变为了5条,这样就导致了幻读。 53 | 54 | ### 事务隔离级别 55 | 56 | **SQL 标准定义了四个隔离级别:** 57 | 58 | - **READ-UNCOMMITTED(读取未提交):** 最低的隔离级别,允许读取尚未提交的数据变更,**可能会导致脏读、幻读或不可重复读**。 59 | - **READ-COMMITTED(读取已提交):** 允许读取并发事务已经提交的数据,**可以阻止脏读,但是幻读或不可重复读仍有可能发生**。 60 | - **REPEATABLE-READ(可重复读):** 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,**可以阻止脏读和不可重复读,但幻读仍有可能发生**。 61 | - **SERIALIZABLE(可串行化):** 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,**该级别可以防止脏读、不可重复读以及幻读**。 62 | 63 | ---- 64 | 65 | | 隔离级别 | 脏读 | 不可重复读 | 幻影读 | 66 | | :---: | :---: | :---:| :---: | 67 | | READ-UNCOMMITTED | √ | √ | √ | 68 | | READ-COMMITTED | × | √ | √ | 69 | | REPEATABLE-READ | × | × | √ | 70 | | SERIALIZABLE | × | × | × | 71 | 72 | MySQL InnoDB 存储引擎的默认支持的隔离级别是 **REPEATABLE-READ(可重读)**。我们可以通过`SELECT @@tx_isolation;`命令来查看,MySQL 8.0 该命令改为`SELECT @@transaction_isolation;` 73 | 74 | ```sql 75 | mysql> SELECT @@tx_isolation; 76 | +-----------------+ 77 | | @@tx_isolation | 78 | +-----------------+ 79 | | REPEATABLE-READ | 80 | +-----------------+ 81 | ``` 82 | 83 | 这里需要注意的是:与 SQL 标准不同的地方在于InnoDB 存储引擎在 **REPEATABLE-READ(可重读)**事务隔离级别下使用的是Next-Key Lock 锁算法,因此可以避免幻读的产生,这与其他数据库系统(如 SQL Server)是不同的。所以说InnoDB 存储引擎的默认支持的隔离级别是 **REPEATABLE-READ(可重读)** 已经可以完全保证事务的隔离性要求,即达到了 SQL标准的**SERIALIZABLE(可串行化)**隔离级别。 84 | 85 | 因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是**READ-COMMITTED(读取提交内容):**,但是你要知道的是InnoDB 存储引擎默认使用 **REPEATABLE-READ(可重读)**并不会有任何性能损失。 86 | 87 | InnoDB 存储引擎在 **分布式事务** 的情况下一般会用到**SERIALIZABLE(可串行化)**隔离级别。 88 | 89 | ### 实际情况演示 90 | 91 | 在下面我会使用 2 个命令行mysql ,模拟多线程(多事务)对同一份数据的脏读问题。 92 | 93 | MySQL 命令行的默认配置中事务都是自动提交的,即执行SQL语句后就会马上执行 COMMIT 操作。如果要显式地开启一个事务需要使用命令:`START TARNSACTION`。 94 | 95 | 我们可以通过下面的命令来设置隔离级别。 96 | 97 | ```sql 98 | SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE] 99 | ``` 100 | 101 | 我们再来看一下我们在下面实际操作中使用到的一些并发控制语句: 102 | 103 | - `START TARNSACTION` |`BEGIN`:显式地开启一个事务。 104 | - `COMMIT`:提交事务,使得对数据库做的所有修改成为永久性。 105 | - `ROLLBACK`:回滚会结束用户的事务,并撤销正在进行的所有未提交的修改。 106 | 107 | #### 脏读(读未提交) 108 | 109 |
110 | 111 |
112 | 113 | #### 避免脏读(读已提交) 114 | 115 |
116 | 117 |
118 | 119 | #### 不可重复读 120 | 121 | 还是刚才上面的读已提交的图,虽然避免了读未提交,但是却出现了,一个事务还没有结束,就发生了 不可重复读问题。 122 | 123 |
124 | 125 |
126 | 127 | #### 可重复读 128 | 129 |
130 | 131 |
132 | 133 | #### 防止幻读(可重复读) 134 | 135 |
136 | 137 |
138 | 139 | 一个事务对数据库进行操作,这种操作的范围是数据库的全部行,然后第二个事务也在对这个数据库操作,这种操作可以是插入一行记录或删除一行记录,那么第一个是事务就会觉得自己出现了幻觉,怎么还有没有处理的记录呢? 或者 怎么多处理了一行记录呢? 140 | 141 | 幻读和不可重复读有些相似之处 ,但是不可重复读的重点是修改,幻读的重点在于新增或者删除。 142 | 143 | ### 参考 144 | 145 | - 《MySQL技术内幕:InnoDB存储引擎》 146 | - 147 | - [Mysql 锁:灵魂七拷问](https://tech.youzan.com/seven-questions-about-the-lock-of-mysql/) 148 | - [Innodb 中的事务隔离级别和锁的关系](https://tech.meituan.com/2014/08/20/innodb-lock.html) 149 | -------------------------------------------------------------------------------- /docs/database/数据库连接池.md: -------------------------------------------------------------------------------- 1 | - 公众号和Github待发文章:[数据库:数据库连接池原理详解与自定义连接池实现](https://www.fangzhipeng.com/javainterview/2019/07/15/mysql-connector-pool.html) 2 | - [基于JDBC的数据库连接池技术研究与应用](http://blog.itpub.net/9403012/viewspace-111794/) 3 | - [数据库连接池技术详解](https://juejin.im/post/5b7944c6e51d4538c86cf195) 4 | 5 | 数据库连接本质就是一个 socket 的连接。数据库服务端还要维护一些缓存和用户权限信息之类的 所以占用了一些内存 6 | 7 | 连接池是维护的数据库连接的缓存,以便将来需要对数据库的请求时可以重用这些连接。为每个用户打开和维护数据库连接,尤其是对动态数据库驱动的网站应用程序的请求,既昂贵又浪费资源。**在连接池中,创建连接后,将其放置在池中,并再次使用它,因此不必建立新的连接。如果使用了所有连接,则会建立一个新连接并将其添加到池中。**连接池还减少了用户必须等待建立与数据库的连接的时间。 8 | 9 | 操作过数据库的朋友应该都知道数据库连接池这个概念,它几乎每天都在和我们打交道,但是你真的了解 **数据库连接池** 吗? 10 | 11 | ### 没有数据库连接池之前 12 | 13 | 我相信你一定听过这样一句话:**Java语言中,JDBC(Java DataBase Connection)是应用程序与数据库沟通的桥梁**。 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /docs/database/阿里巴巴开发手册数据库部分的一些最佳实践.md: -------------------------------------------------------------------------------- 1 | # 阿里巴巴Java开发手册数据库部分的一些最佳实践总结 2 | 3 | ## 模糊查询 4 | 5 | 对于模糊查询阿里巴巴开发手册这样说到: 6 | 7 | > 【强制】页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。 8 | > 9 | > 说明:索引文件具有 B-Tree 的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索引。 10 | 11 | ## 外键和级联 12 | 13 | 对于外键和级联,阿里巴巴开发手册这样说到: 14 | 15 | >【强制】不得使用外键与级联,一切外键概念必须在应用层解决。 16 | > 17 | >说明:以学生和成绩的关系为例,学生表中的 student_id 是主键,那么成绩表中的 student_id 则为外键。如果更新学生表中的 student_id,同时触发成绩表中的 student_id 更新,即为级联更新。外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风 险;外键影响数据库的插入速度 18 | 19 | 为什么不要用外键呢?大部分人可能会这样回答: 20 | 21 | > 1. **增加了复杂性:** a.每次做DELETE 或者UPDATE都必须考虑外键约束,会导致开发的时候很痛苦,测试数据极为不方便;b.外键的主从关系是定的,假如那天需求有变化,数据库中的这个字段根本不需要和其他表有关联的话就会增加很多麻烦。 22 | > 2. **增加了额外工作**: 数据库需要增加维护外键的工作,比如当我们做一些涉及外键字段的增,删,更新操作之后,需要触发相关操作去检查,保证数据的的一致性和正确性,这样会不得不消耗资源;(个人觉得这个不是不用外键的原因,因为即使你不使用外键,你在应用层面也还是要保证的。所以,我觉得这个影响可以忽略不计。) 23 | > 3. 外键还会因为需要请求对其他表内部加锁而容易出现死锁情况; 24 | > 4. **对分不分表不友好** :因为分库分表下外键是无法生效的。 25 | > 5. ...... 26 | 27 | 我个人觉得上面这种回答不是特别的全面,只是说了外键存在的一个常见的问题。实际上,我们知道外键也是有很多好处的,比如: 28 | 29 | 1. 保证了数据库数据的一致性和完整性; 30 | 2. 级联操作方便,减轻了程序代码量; 31 | 3. ...... 32 | 33 | 所以说,不要一股脑的就抛弃了外键这个概念,既然它存在就有它存在的道理,如果系统不涉及分不分表,并发量不是很高的情况还是可以考虑使用外键的。 34 | 35 | 我个人是不太喜欢外键约束,比较喜欢在应用层去进行相关操作。 36 | 37 | ## 关于@Transactional注解 38 | 39 | 对于`@Transactional`事务注解,阿里巴巴开发手册这样说到: 40 | 41 | >【参考】@Transactional事务不要滥用。事务会影响数据库的QPS,另外使用事务的地方需要考虑各方面的回滚方案,包括缓存回滚、搜索引擎回滚、消息补偿、统计修正等。 42 | -------------------------------------------------------------------------------- /docs/essential-content-for-interview/BATJrealInterviewExperience/5面阿里,终获offer.md: -------------------------------------------------------------------------------- 1 | > 作者:ppxyn。本文来自读者投稿,同时也欢迎各位投稿,**对于不错的原创文章我根据你的选择给予现金(50-200)、付费专栏或者任选书籍进行奖励!所以,快提 pr 或者邮件的方式(邮件地址在主页)给我投稿吧!** 当然,我觉得奖励是次要的,最重要的是你可以从自己整理知识点的过程中学习到很多知识。 2 | 3 | **目录** 4 | 5 | 6 | 7 | - [前言](#前言) 8 | - [一面\(技术面\)](#一面技术面) 9 | - [二面\(技术面\)](#二面技术面) 10 | - [三面\(技术面\)](#三面技术面) 11 | - [四面\(半个技术面\)](#四面半个技术面) 12 | - [五面\(HR面\)](#五面hr面) 13 | - [总结](#总结) 14 | 15 | 16 | 17 | ### 前言 18 | 19 | 在接触 Java 之前我接触的比较多的是硬件方面,用的比较多的语言就是C和C++。到了大三我才正式选择 Java 方向,到目前为止使用Java到现在大概有一年多的时间,所以Java算不上很好。刚开始投递的时候,实习刚辞职,也没准备笔试面试,很多东西都忘记了。所以,刚开始我并没有直接就投递阿里,毕竟心里还是有一点点小害怕的。于是,我就先投递了几个不算大的公司来练手,就是想着刷刷经验而已或者说是练练手(ps:还是挺对不起那些公司的)。面了一个月其他公司后,我找了我实验室的学长内推我,后面就有了这5次面试。 20 | 21 | 下面简单的说一下我的这5次面试:4次技术面+1次HR面,希望我的经历能对你有所帮助。 22 | 23 | ### 一面(技术面) 24 | 25 | 1. 自我介绍(主要讲自己会的技术细节,项目经验,经历那些就一语带过,后面面试官会问你的)。 26 | 2. 聊聊项目(就是一个很普通的分布式商城,自己做了一些改进),让我画了整个项目的架构图,然后针对项目抛了一系列的提高性能的问题,还问了我做项目的过程中遇到了那些问题,如何解决的,差不读就这些吧。 27 | 3. 可能是我前面说了我会数据库优化,然后面试官就开始问索引、事务隔离级别、悲观锁和乐观锁、索引、ACID、MVVC这些问题。 28 | 4. 浏览器输入URL发生了什么? TCP和UDP区别? TCP如何保证传输可靠性? 29 | 5. 讲下跳表怎么实现的?哈夫曼编码是怎么回事?非递归且不用额外空间(不用栈),如何遍历二叉树 30 | 6. 后面又问了很多JVM方面的问题,比如Java内存模型、常见的垃圾回收器、双亲委派模型这些 31 | 7. 你有什么问题要问吗? 32 | 33 | ### 二面(技术面) 34 | 35 | 1. 自我介绍(主要讲自己会的技术细节,项目经验,经历那些就一语带过,后面面试官会问你的)。 36 | 2. 操作系统的内存管理机制 37 | 3. 进程和线程的区别 38 | 4. 说下你对线程安全的理解 39 | 5. volatile 有什么作用 ,sychronized和lock有什么区别 40 | 6. ReentrantLock实现原理 41 | 7. 用过CountDownLatch么?什么场景下用的? 42 | 8. AQS底层原理。 43 | 9. 造成死锁的原因有哪些,如何预防? 44 | 10. 加锁会带来哪些性能问题。如何解决? 45 | 11. HashMap、ConcurrentHashMap源码。HashMap是线程安全的吗?Hashtable呢?ConcurrentHashMap有了解吗? 46 | 12. 是否可以实习? 47 | 13. 你有什么问题要问吗? 48 | 49 | ### 三面(技术面) 50 | 51 | 1. 有没有参加过 ACM 或者他竞赛,有没有拿过什么奖?( 我说我没参加过ACM,本科参加过数学建模竞赛,名次并不好,没拿过什么奖。面试官好像有点失望,然后我又赶紧补充说我和老师一起做过一个项目,目前已经投入使用。面试官还比较感兴趣,后面又和他聊了一下这个项目。) 52 | 2. 研究生期间,做过什么项目,发过论文吗?有什么成果吗? 53 | 3. 你觉得你有什么优点和缺点?你觉得你相比于那些比你更优秀的人欠缺什么? 54 | 4. 有读过什么源码吗?(我说我读过 Java 集合框架和 Netty 的,面试官说 Java 集合前几面一定问的差不多,就不问了,然后就问我 Netty的,我当时很慌啊!) 55 | 5. 介绍一下自己对 Netty 的认识,为什么要用。说说业务中,Netty 的使用场景。什么是TCP 粘包/拆包,解决办法。Netty线程模型。Dubbo 在使用 Netty 作为网络通讯时候是如何避免粘包与半包问题?讲讲Netty的零拷贝?巴拉巴拉问了好多,我记得有好几个我都没回答上来,心里想着凉凉了啊。 56 | 6. 用到了那些开源技术、在开源领域做过贡献吗? 57 | 7. 常见的排序算法及其复杂度,现场写了快排。 58 | 8. 红黑树,B树的一些问题。 59 | 9. 讲讲算法及数据结构在实习项目中的用处。 60 | 10. 自己的未来规划(就简单描述了一下自己未来的设想啊,说的还挺诚恳,面试官好像还挺满意的) 61 | 11. 你有什么问题要问吗? 62 | 63 | ### 四面(半个技术面) 64 | 65 | 三面面完当天,晚上9点接到面试电话,感觉像是部门或者项目主管。 这个和之前的面试不大相同,感觉面试官主要考察的是你解决问题的能力、学习能力和团队协作能力。 66 | 67 | 1. 让我讲一个自己觉得最不错的项目。然后就巴拉巴拉的聊,我记得主要是问了项目是如何进行协作的、遇到问题是如何解决的、与他人发生冲突是如何解决的这些。感觉聊了挺久。 68 | 2. 出现 OOM 后你会怎么排查问题? 69 | 3. 自己平时是如何学习新技术的?除了 Java 还回去了解其他技术吗? 70 | 4. 上一段实习经历的收获。 71 | 5. NginX如何做负载均衡、常见的负载均衡算法有哪些、一致性哈希的一致性是什么意思、一致性哈希是如何做哈希的 72 | 6. 你有什么问题问我吗? 73 | 7. 还有一些其他的,想不起来了,感觉这一面不是偏向技术来问。 74 | 75 | ## 五面(HR面) 76 | 77 | 1. 自我介绍(主要讲能突出自己的经历,会的编程技术一语带过)。 78 | 2. 你觉得你有什么优点和缺点?如何克服这些缺点? 79 | 3. 说一件大学里你自己比较有成就感的一件事情,为此付出了那些努力。 80 | 4. 你前面跟其他面试官讲过一些你做的项目吧?可以给我讲讲吗?你要考虑到我不是一个做技术的人,怎么让我也听得懂。项目中有什么问题,你怎么解决的?你最大的收获是什么? 81 | 5. 你目前有面试过其他公司吗?如果让你选,这些公司和阿里,你选哪个?(送分题,回答不好可能送命) 82 | 6. 你期望的工作地点是哪里? 83 | 7. 你有什么问题吗? 84 | 85 | ### 总结 86 | 87 | 1. 可以看出面试官问我的很多问题都是比较常见的问题,所以记得一定要提前准备,还要深入准备,不要回答的太皮毛。很多时候一个问题可能会牵扯出很多问题,遇到不会的问题不要慌,冷静分析,如果你真的回答不上来,也不要担心自己是不是就要挂了,很可能这个问题本身就比较难。 88 | 2. 表达能力和沟通能力太重要了,一定要提前练一下,我自身就是一个不太会说话的人,所以,面试前我对于自我介绍、项目介绍和一些常见问题都在脑子里练了好久,确保面试的时候能够很清晰和简洁的说出来。 89 | 3. 等待面试的过程和面试的过程真的好熬人,那段时间我压力也比较大,好在我私下找到学长聊了很多,心情也好了很多。 90 | 4. 面试之后及时总结,面的好的话,不要得意,尽快准备下一场面试吧! 91 | 92 | 我觉得我还算是比较幸运的,最后也祝大家都能获得心仪的Offer。 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /docs/essential-content-for-interview/PreparingForInterview/JavaInterviewLibrary.md: -------------------------------------------------------------------------------- 1 | 昨天我整理了公众号历史所有和面试相关的我觉得还不错的文章:[整理了一些有助于你拿Offer的文章]() 。今天分享一下最近逛Github看到了一些我觉得对于Java面试以及学习有帮助的仓库,这些仓库涉及Java核心知识点整理、Java常见面试题、算法、基础知识点比如网络和操作系统等等。 2 | 3 | ## 知识点相关 4 | 5 | ### 1.JavaGuide 6 | 7 | - Github地址: [https://github.com/Snailclimb/JavaGuide](https://github.com/Snailclimb/JavaGuide) 8 | - star: 64.0k 9 | - 介绍: 【Java学习+面试指南】 一份涵盖大部分Java程序员所需要掌握的核心知识。 10 | 11 | ### 2.CS-Notes 12 | 13 | - Github 地址: 14 | - Star: 68.3k 15 | - 介绍: 技术面试必备基础知识、Leetcode 题解、后端面试、Java 面试、春招、秋招、操作系统、计算机网络、系统设计。 16 | 17 | ### 3. advanced-java 18 | 19 | - Github地址:[https://github.com/doocs/advanced-java](https://github.com/doocs/advanced-java) 20 | - star: 23.4k 21 | - 介绍: 互联网 Java 工程师进阶知识完全扫盲:涵盖高并发、分布式、高可用、微服务等领域知识,后端同学必看,前端同学也可学习。 22 | 23 | ### 4.JCSprout 24 | 25 | - Github地址:[https://github.com/crossoverJie/JCSprout](https://github.com/crossoverJie/JCSprout) 26 | - star: 21.2k 27 | - 介绍: Java Core Sprout:处于萌芽阶段的 Java 核心知识库。 28 | 29 | ### 5.toBeTopJavaer 30 | 31 | - Github地址:[https://github.com/hollischuang/toBeTopJavaer](https://github.com/hollischuang/toBeTopJavaer) 32 | - star: 4.0 k 33 | - 介绍: Java工程师成神之路。 34 | 35 | ### 6.architect-awesome 36 | 37 | - Github地址:[https://github.com/xingshaocheng/architect-awesome](https://github.com/xingshaocheng/architect-awesome) 38 | - star: 34.4 k 39 | - 介绍:后端架构师技术图谱。 40 | 41 | ### 7.technology-talk 42 | 43 | - Github地址: [https://github.com/aalansehaiyang/technology-talk](https://github.com/aalansehaiyang/technology-talk) 44 | - star: 6.1k 45 | - 介绍: 汇总java生态圈常用技术框架、开源中间件,系统架构、项目管理、经典架构案例、数据库、常用三方库、线上运维等知识。 46 | 47 | ### 8.fullstack-tutorial 48 | 49 | - Github地址: [https://github.com/frank-lam/fullstack-tutorial](https://github.com/frank-lam/fullstack-tutorial) 50 | - star: 4.0k 51 | - 介绍: fullstack tutorial 2019,后台技术栈/架构师之路/全栈开发社区,春招/秋招/校招/面试。 52 | 53 | ### 9.3y 54 | 55 | - Github地址:[https://github.com/ZhongFuCheng3y/3y](https://github.com/ZhongFuCheng3y/3y) 56 | - star: 1.9 k 57 | - 介绍: Java 知识整合。 58 | 59 | ### 10.java-bible 60 | 61 | - Github地址:[https://github.com/biezhi/java-bible](https://github.com/biezhi/java-bible) 62 | - star: 2.3k 63 | - 介绍: 这里记录了一些技术摘要,部分文章来自网络,本项目的目的力求分享精品技术干货,以Java为主。 64 | 65 | ### 11.interviews 66 | 67 | - Github地址: [https://github.com/kdn251/interviews/blob/master/README-zh-cn.md](https://github.com/kdn251/interviews/blob/master/README-zh-cn.md) 68 | - star: 35.3k 69 | - 介绍: 软件工程技术面试个人指南(国外的一个项目,虽然有翻译版,但是不太推荐,因为很多内容并不适用于国内)。 70 | 71 | ## 算法相关 72 | 73 | ### 1.LeetCodeAnimation 74 | 75 | - Github 地址: 76 | - Star: 33.4k 77 | - 介绍: Demonstrate all the questions on LeetCode in the form of animation.(用动画的形式呈现解LeetCode题目的思路)。 78 | 79 | ### 2.awesome-java-leetcode 80 | 81 | - Github地址:[https://github.com/Blankj/awesome-java-leetcode](https://github.com/Blankj/awesome-java-leetcode) 82 | - star: 6.1k 83 | - 介绍: LeetCode 上 Facebook 的面试题目。 84 | 85 | ### 3.leetcode 86 | 87 | - Github地址:[https://github.com/azl397985856/leetcode](https://github.com/azl397985856/leetcode) 88 | - star: 12.0k 89 | - 介绍: LeetCode Solutions: A Record of My Problem Solving Journey.( leetcode题解,记录自己的leetcode解题之路。) -------------------------------------------------------------------------------- /docs/essential-content-for-interview/PreparingForInterview/JavaProgrammerNeedKnow.md: -------------------------------------------------------------------------------- 1 |   身边的朋友或者公众号的粉丝很多人都向我询问过:“我是双非/三本/专科学校的,我有机会进入大厂吗?”、“非计算机专业的学生能学好吗?”、“如何学习Java?”、“Java学习该学哪些东西?”、“我该如何准备Java面试?”......这些方面的问题。我会根据自己的一点经验对大部分人关心的这些问题进行答疑解惑。现在又刚好赶上考研结束,这篇文章也算是给考研结束准备往Java后端方向发展的朋友们指明一条学习之路。道理懂了如果没有实际行动,那这篇文章对你或许没有任何意义。 2 | 3 | ### Question1:我是双非/三本/专科学校的,我有机会进入大厂吗? 4 | 5 |   我自己也是非985非211学校的,结合自己的经历以及一些朋友的经历,我觉得让我回答这个问题再好不过。 6 | 7 |   首先,我觉得学校歧视很正常,真的太正常了,如果要抱怨的话,你只能抱怨自己没有进入名校。但是,千万不要动不动说自己学校差,动不动拿自己学校当做自己进不了大厂的借口,学历只是筛选简历的很多标准中的一个而已,如果你够优秀,简历够丰富,你也一样可以和名校同学一起同台竞争。 8 | 9 |   企业HR肯定是更喜欢高学历的人,毕竟985、211优秀人才比例肯定比普通学校高很多,HR团队肯定会优先在这些学校里选。这就好比相亲,你是愿意在很多优秀的人中选一个优秀的,还是愿意在很多普通的人中选一个优秀的呢? 10 |    11 |   双非本科甚至是二本、三本甚至是专科的同学也有很多进入大厂的,不过比率相比于名校的低很多而已。从大厂招聘的结果上看,高学历人才的数量占据大头,那些成功进入BAT、美团,京东,网易等大厂的双非本科甚至是二本、三本甚至是专科的同学往往是因为具备丰富的项目经历或者在某个含金量比较高的竞赛比如ACM中取得了不错的成绩。**一部分学历不突出但能力出众的面试者能够进入大厂并不是说明学历不重要,而是学历的软肋能够通过其他的优势来弥补。** 所以,如果你的学校不够好而你自己又想去大厂的话,建议你可以从这几点来做:**①尽量在面试前最好有一个可以拿的出手的项目;②有实习条件的话,尽早出去实习,实习经历也会是你的简历的一个亮点(有能力在大厂实习最佳!);③参加一些含金量比较高的比赛,拿不拿得到名次没关系,重在锻炼。** 12 | 13 | 14 | ### Question2:非计算机专业的学生能学好Java后台吗?我能进大厂吗? 15 | 16 |   当然可以!现在非科班的程序员很多,很大一部分原因是互联网行业的工资比较高。我们学校外面的培训班里面90%都是非科班,我觉得他们很多人学的都还不错。另外,我的一个朋友本科是机械专业,大一开始自学安卓,技术贼溜,在我看来他比大部分本科是计算机的同学学的还要好。参考Question1的回答,即使你是非科班程序员,如果你想进入大厂的话,你也可以通过自己的其他优势来弥补。 17 | 18 |   我觉得我们不应该因为自己的专业给自己划界限或者贴标签,说实话,很多科班的同学可能并不如你,你以为科班的同学就会认真听讲吗?还不是几乎全靠自己课下自学!不过如果你是非科班的话,你想要学好,那么注定就要舍弃自己本专业的一些学习时间,这是无可厚非的。 19 | 20 |   建议非科班的同学,首先要打好计算机基础知识基础:①计算机网络、②操作系统、③数据机构与算法,我个人觉得这3个对你最重要。这些东西就像是内功,对你以后的长远发展非常有用。当然,如果你想要进大厂的话,这些知识也是一定会被问到的。另外,“一定学好数据结构与算法!一定学好数据结构与算法!一定学好数据结构与算法!”,重要的东西说3遍。 21 | 22 | 23 | 24 | ### Question3: 我没有实习经历的话找工作是不是特别艰难? 25 | 26 |   没有实习经历没关系,只要你有拿得出手的项目或者大赛经历的话,你依然有可能拿到大厂的 offer 。笔主当时找工作的时候就没有实习经历以及大赛获奖经历,单纯就是凭借自己的项目经验撑起了整个面试。 27 | 28 |   如果你既没有实习经历,又没有拿得出手的项目或者大赛经历的话,我觉得在简历关,除非你有其他特别的亮点,不然,你应该就会被刷。 29 | 30 | ### Question4: 我该如何准备面试呢?面试的注意事项有哪些呢? 31 | 32 | 下面是我总结的一些准备面试的Tips以及面试必备的注意事项: 33 | 34 | 1. **准备一份自己的自我介绍,面试的时候根据面试对象适当进行修改**(突出重点,突出自己的优势在哪里,切忌流水账); 35 | 2. **注意随身带上自己的成绩单和简历复印件;** (有的公司在面试前都会让你交一份成绩单和简历当做面试中的参考。) 36 | 3. **如果需要笔试就提前刷一些笔试题,大部分在线笔试的类型是选择题+编程题,有的还会有简答题。**(平时空闲时间多的可以刷一下笔试题目(牛客网上有很多),但是不要只刷面试题,不动手code,程序员不是为了考试而存在的。)另外,注意抓重点,因为题目太多了,但是有很多题目几乎次次遇到,像这样的题目一定要搞定。 37 | 4. **提前准备技术面试。** 搞清楚自己面试中可能涉及哪些知识点、哪些知识点是重点。面试中哪些问题会被经常问到、自己该如何回答。(强烈不推荐背题,第一:通过背这种方式你能记住多少?能记住多久?第二:背题的方式的学习很难坚持下去!) 38 | 5. **面试之前做好定向复习。** 也就是专门针对你要面试的公司来复习。比如你在面试之前可以在网上找找有没有你要面试的公司的面经。 39 | 6. **准备好自己的项目介绍。** 如果有项目的话,技术面试第一步,面试官一般都是让你自己介绍一下你的项目。你可以从下面几个方向来考虑:①对项目整体设计的一个感受(面试官可能会让你画系统的架构图);②在这个项目中你负责了什么、做了什么、担任了什么角色;③ 从这个项目中你学会了那些东西,使用到了那些技术,学会了那些新技术的使用;④项目描述中,最好可以体现自己的综合素质,比如你是如何协调项目组成员协同开发的或者在遇到某一个棘手的问题的时候你是如何解决的又或者说你在这个项目用了什么技术实现了什么功能比如:用 redis 做缓存提高访问速度和并发量、使用消息队列削峰和降流等等。 40 | 7. **面试之后记得复盘。** 面试遭遇失败是很正常的事情,所以善于总结自己的失败原因才是最重要的。如果失败,不要灰心;如果通过,切勿狂喜。 41 | 42 | 43 | **一些还算不错的 Java面试/学习相关的仓库,相信对大家准备面试一定有帮助:**[盘点一下Github上开源的Java面试/学习相关的仓库,看完弄懂薪资至少增加10k](https://mp.weixin.qq.com/s?__biz=MzU4NDQ4MzU5OA==&mid=2247484817&idx=1&sn=12f0c254a240c40c2ccab8314653216b&chksm=fd9853f0caefdae6d191e6bf085d44ab9c73f165e3323aa0362d830e420ccbfad93aa5901021&token=766994974&lang=zh_CN#rd) 44 | 45 | ### Question5: 我该自学还是报培训班呢? 46 | 47 |   我本人更加赞同自学(你要知道去了公司可没人手把手教你了,而且几乎所有的公司都对培训班出生的有偏见。为什么有偏见,你学个东西还要去培训班,说明什么,同等水平下,你的自学能力以及自律能力一定是比不上自学的人的)。但是如果,你连每天在寝室坚持学上8个小时以上都坚持不了,或者总是容易半途而废的话,我还是推荐你去培训班。观望身边同学去培训班的,大多是非计算机专业或者是没有自律能力以及自学能力非常差的人。 48 | 49 |   另外,如果自律能力不行,你也可以通过结伴学习、参加老师的项目等方式来督促自己学习。 50 | 51 |   总结:去不去培训班主要还是看自己,如果自己能坚持自学就自学,坚持不下来就去培训班。 52 | 53 | ### Question6: 没有项目经历/博客/Github开源项目怎么办? 54 | 55 |   从现在开始做! 56 | 57 |   网上有很多非常不错的项目视频,你就跟着一步一步做,不光要做,还要改进,改善。另外,如果你的老师有相关 Java 后台项目的话,你也可以主动申请参与进来。 58 | 59 |   如果有自己的博客,也算是简历上的一个亮点。建议可以在掘金、Segmentfault、CSDN等技术交流社区写博客,当然,你也可以自己搭建一个博客(采用 Hexo+Githu Pages 搭建非常简单)。写一些什么?学习笔记、实战内容、读书笔记等等都可以。 60 | 61 |   多用 Github,用好 Github,上传自己不错的项目,写好 readme 文档,在其他技术社区做好宣传。相信你也会收获一个不错的开源项目! 62 | 63 | 64 | ### Question7: 大厂到底青睐什么样的应届生? 65 | 66 |   从阿里、腾讯等大厂招聘官网对于Java后端方向/后端方向的应届实习生的要求,我们大概可以总结归纳出下面这 4 点能给简历增加很多分数: 67 | 68 | - 参加过竞赛(含金量超高的是ACM); 69 | - 对数据结构与算法非常熟练; 70 | - 参与过实际项目(比如学校网站); 71 | - 参与过某个知名的开源项目或者自己的某个开源项目很不错; 72 | 73 |   除了我上面说的这三点,在面试Java工程师的时候,下面几点也提升你的个人竞争力: 74 | 75 | - 熟悉Python、Shell、Perl等脚本语言; 76 | - 熟悉 Java 优化,JVM调优; 77 | - 熟悉 SOA 模式; 78 | - 熟悉自己所用框架的底层知识比如Spring; 79 | - 了解分布式一些常见的理论; 80 | - 具备高并发开发经验;大数据开发经验等等。 81 | 82 | -------------------------------------------------------------------------------- /docs/essential-content-for-interview/PreparingForInterview/interviewPrepare.md: -------------------------------------------------------------------------------- 1 | 不论是校招还是社招都避免不了各种面试、笔试,如何去准备这些东西就显得格外重要。不论是笔试还是面试都是有章可循的,我这个“有章可循”说的意思只是说应对技术面试是可以提前准备。 我其实特别不喜欢那种临近考试就提前背啊记啊各种题的行为,非常反对!我觉得这种方法特别极端,而且在稍有一点经验的面试官面前是根本没有用的。建议大家还是一步一个脚印踏踏实实地走。 2 | 3 | 4 | 5 | - [1 如何获取大厂面试机会?](#1-如何获取大厂面试机会) 6 | - [2 面试前的准备](#2--面试前的准备) 7 | - [2.1 准备自己的自我介绍](#21-准备自己的自我介绍) 8 | - [2.2 关于着装](#22-关于着装) 9 | - [2.3 随身带上自己的成绩单和简历](#23-随身带上自己的成绩单和简历) 10 | - [2.4 如果需要笔试就提前刷一些笔试题](#24-如果需要笔试就提前刷一些笔试题) 11 | - [2.5 花时间一些逻辑题](#25-花时间一些逻辑题) 12 | - [2.6 准备好自己的项目介绍](#26-准备好自己的项目介绍) 13 | - [2.7 提前准备技术面试](#27-提前准备技术面试) 14 | - [2.7 面试之前做好定向复习](#27-面试之前做好定向复习) 15 | - [3 面试之后复盘](#3-面试之后复盘) 16 | 17 | 18 | 19 | ## 1 如何获取大厂面试机会? 20 | 21 | **在讲如何获取大厂面试机会之前,先来给大家科普/对比一下两个校招非常常见的概念——春招和秋招。** 22 | 23 | 1. **招聘人数** :秋招多于春招 ; 24 | 2. **招聘时间** : 秋招一般7月左右开始,大概一直持续到10月底。但是大厂(如BAT)都会早开始早结束,所以一定要把握好时间。春招最佳时间为3月,次佳时间为4月,进入5月基本就不会再有春招了(金三银四)。 25 | 3. **应聘难度** :秋招略大于春招; 26 | 4. **招聘公司:** 秋招数量多,而春招数量较少,一般为秋招的补充。 27 | 28 | **综上,一般来说,秋招的含金量明显是高于春招的。** 29 | 30 | **下面我就说一下我自己知道的一些方法,不过应该也涵盖了大部分获取面试机会的方法。** 31 | 32 | 1. **关注大厂官网,随时投递简历(走流程的网申);** 33 | 2. **线下参加宣讲会,直接投递简历;** 34 | 3. **找到师兄师姐/认识的人,帮忙内推(能够让你避开网申简历筛选,笔试筛选,还是挺不错的,不过也还是需要你的简历够棒);** 35 | 4. **博客发文被看中/Github优秀开源项目作者,大厂内部人员邀请你面试;** 36 | 5. **求职类网站投递简历(不是太推荐,适合海投);** 37 | 38 | 39 | 除了这些方法,我也遇到过这样的经历:有些大公司的一些部门可能暂时没招够人,然后如果你的亲戚或者朋友刚好在这个公司,而你正好又在寻求offer,那么面试机会基本上是有了,而且这种面试的难度好像一般还普遍比其他正规面试低很多。 40 | 41 | ## 2 面试前的准备 42 | 43 | ### 2.1 准备自己的自我介绍 44 | 45 | 从HR面、技术面到高管面/部门主管面,面试官一般会让你先自我介绍一下,所以好好准备自己的自我介绍真的非常重要。网上一般建议的是准备好两份自我介绍:一份对hr说的,主要讲能突出自己的经历,会的编程技术一语带过;另一份对技术面试官说的,主要讲自己会的技术细节,项目经验,经历那些就一语带过。 46 | 47 | 我这里简单分享一下我自己的自我介绍的一个简单的模板吧: 48 | 49 | > 面试官,您好!我叫某某。大学时间我主要利用课外时间学习某某。在校期间参与过一个某某系统的开发,另外,自己学习过程中也写过很多系统比如某某系统。在学习之余,我比较喜欢通过博客整理分享自己所学知识。我现在是某某社区的认证作者,写过某某很不错的文章。另外,我获得过某某奖,我的Github上开源的某个项目已经有多少Star了。 50 | 51 | ### 2.2 关于着装 52 | 53 | 穿西装、打领带、小皮鞋?NO!NO!NO!这是互联网公司面试又不是去走红毯,所以你只需要穿的简单大方就好,不需要太正式。 54 | 55 | ### 2.3 随身带上自己的成绩单和简历 56 | 57 | 有的公司在面试前都会让你交一份成绩单和简历当做面试中的参考。 58 | 59 | ### 2.4 如果需要笔试就提前刷一些笔试题 60 | 61 | 平时空闲时间多的可以刷一下笔试题目(牛客网上有很多)。但是不要只刷面试题,不动手code,程序员不是为了考试而存在的。 62 | 63 | ### 2.5 花时间一些逻辑题 64 | 65 | 面试中发现有些公司都有逻辑题测试环节,并且都把逻辑笔试成绩作为很重要的一个参考。 66 | 67 | ### 2.6 准备好自己的项目介绍 68 | 69 | 如果有项目的话,技术面试第一步,面试官一般都是让你自己介绍一下你的项目。你可以从下面几个方向来考虑: 70 | 71 | 1. 对项目整体设计的一个感受(面试官可能会让你画系统的架构图) 72 | 2. 在这个项目中你负责了什么、做了什么、担任了什么角色 73 | 3. 从这个项目中你学会了那些东西,使用到了那些技术,学会了那些新技术的使用 74 | 4. 另外项目描述中,最好可以体现自己的综合素质,比如你是如何协调项目组成员协同开发的或者在遇到某一个棘手的问题的时候你是如何解决的又或者说你在这个项目用了什么技术实现了什么功能比如:用redis做缓存提高访问速度和并发量、使用消息队列削峰和降流等等。 75 | 76 | ### 2.7 提前准备技术面试 77 | 78 | 搞清楚自己面试中可能涉及哪些知识点、哪些知识点是重点。面试中哪些问题会被经常问到、自己该如何回答。(强烈不推荐背题,第一:通过背这种方式你能记住多少?能记住多久?第二:背题的方式的学习很难坚持下去!) 79 | 80 | ### 2.7 面试之前做好定向复习 81 | 82 | 所谓定向复习就是专门针对你要面试的公司来复习。比如你在面试之前可以在网上找找有没有你要面试的公司的面经。 83 | 84 | 举个栗子:在我面试 ThoughtWorks 的前几天我就在网上找了一些关于 ThoughtWorks 的技术面的一些文章。然后知道了 ThoughtWorks 的技术面会让我们在之前做的作业的基础上增加一个或两个功能,所以我提前一天就把我之前做的程序重新重构了一下。然后在技术面的时候,简单的改了几行代码之后写个测试就完事了。如果没有提前准备,我觉得 20 分钟我很大几率会完不成这项任务。 85 | 86 | ## 3 面试之后复盘 87 | 88 | 如果失败,不要灰心;如果通过,切勿狂喜。面试和工作实际上是两回事,可能很多面试未通过的人,工作能力比你强的多,反之亦然。我个人觉得面试也像是一场全新的征程,失败和胜利都是平常之事。所以,劝各位不要因为面试失败而灰心、丧失斗志。也不要因为面试通过而沾沾自喜,等待你的将是更美好的未来,继续加油! 89 | -------------------------------------------------------------------------------- /docs/essential-content-for-interview/PreparingForInterview/程序员的简历之道.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | - [程序员简历就该这样写](#程序员简历就该这样写) 4 | - [为什么说简历很重要?](#为什么说简历很重要) 5 | - [先从面试前来说](#先从面试前来说) 6 | - [再从面试中来说](#再从面试中来说) 7 | - [下面这几点你必须知道](#下面这几点你必须知道) 8 | - [必须了解的两大法则](#必须了解的两大法则) 9 | - [STAR法则(Situation Task Action Result)](#star法则situation-task-action-result) 10 | - [FAB 法则(Feature Advantage Benefit)](#fab-法则feature-advantage-benefit) 11 | - [项目经历怎么写?](#项目经历怎么写) 12 | - [专业技能该怎么写?](#专业技能该怎么写) 13 | - [排版注意事项](#排版注意事项) 14 | - [其他的一些小tips](#其他的一些小tips) 15 | - [推荐的工具/网站](#推荐的工具网站) 16 | 17 | 18 | 19 | # 程序员简历就该这样写 20 | 21 | 本篇文章除了教大家用Markdown如何写一份程序员专属的简历,后面还会给大家推荐一些不错的用来写Markdown简历的软件或者网站,以及如何优雅的将Markdown格式转变为PDF格式或者其他格式。 22 | 23 | 推荐大家使用Markdown语法写简历,然后再将Markdown格式转换为PDF格式后进行简历投递。 24 | 25 | 如果你对Markdown语法不太了解的话,可以花半个小时简单看一下Markdown语法说明: http://www.markdown.cn 。 26 | 27 | ## 为什么说简历很重要? 28 | 29 | 一份好的简历可以在整个申请面试以及面试过程中起到非常好的作用。 在不夸大自己能力的情况下,写出一份好的简历也是一项很棒的能力。为什么说简历很重要呢? 30 | 31 | ### 先从面试前来说 32 | 33 | - 假如你是网申,你的简历必然会经过HR的筛选,一张简历HR可能也就花费10秒钟看一下,然后HR就会决定你这一关是Fail还是Pass。 34 | - 假如你是内推,如果你的简历没有什么优势的话,就算是内推你的人再用心,也无能为力。 35 | 36 | 另外,就算你通过了筛选,后面的面试中,面试官也会根据你的简历来判断你究竟是否值得他花费很多时间去面试。 37 | 38 | 所以,简历就像是我们的一个门面一样,它在很大程度上决定了你能否进入到下一轮的面试中。 39 | 40 | ### 再从面试中来说 41 | 42 | 我发现大家比较喜欢看面经 ,这点无可厚非,但是大部分面经都没告诉你很多问题都是在特定条件下才问的。举个简单的例子:一般情况下你的简历上注明你会的东西才会被问到(Java、数据结构、网络、算法这些基础是每个人必问的),比如写了你会 redis,那面试官就很大概率会问你 redis 的一些问题。比如:redis的常见数据类型及应用场景、redis是单线程为什么还这么快、 redis 和 memcached 的区别、redis 内存淘汰机制等等。 43 | 44 | 所以,首先,你要明确的一点是:**你不会的东西就不要写在简历上**。另外,**你要考虑你该如何才能让你的亮点在简历中凸显出来**,比如:你在某某项目做了什么事情解决了什么问题(只要有项目就一定有要解决的问题)、你的某一个项目里使用了什么技术后整体性能和并发量提升了很多等等。 45 | 46 | 面试和工作是两回事,聪明的人会把面试官往自己擅长的领域领,其他人则被面试官牵着鼻子走。虽说面试和工作是两回事,但是你要想要获得自己满意的 offer ,你自身的实力必须要强。 47 | 48 | ## 下面这几点你必须知道 49 | 50 | 1. 大部分公司的HR都说我们不看重学历(骗你的!),但是如果你的学校不出众的话,很难在一堆简历中脱颖而出,除非你的简历上有特别的亮点,比如:某某大厂的实习经历、获得了某某大赛的奖等等。 51 | 2. **大部分应届生找工作的硬伤是没有工作经验或实习经历,所以如果你是应届生就不要错过秋招和春招。一旦错过,你后面就极大可能会面临社招,这个时候没有工作经验的你可能就会面临各种碰壁,导致找不到一个好的工作** 52 | 3. **写在简历上的东西一定要慎重,这是面试官大量提问的地方;** 53 | 4. **将自己的项目经历完美的展示出来非常重要。** 54 | 55 | ## 必须了解的两大法则 56 | 57 | ### STAR法则(Situation Task Action Result) 58 | 59 | - **Situation:** 事情是在什么情况下发生; 60 | - **Task::** 你是如何明确你的任务的; 61 | - **Action:** 针对这样的情况分析,你采用了什么行动方式; 62 | - **Result:** 结果怎样,在这样的情况下你学习到了什么。 63 | 64 | 简而言之,STAR法则,就是一种讲述自己故事的方式,或者说,是一个清晰、条理的作文模板。不管是什么,合理熟练运用此法则,可以轻松的对面试官描述事物的逻辑方式,表现出自己分析阐述问题的清晰性、条理性和逻辑性。 65 | 66 | ### FAB 法则(Feature Advantage Benefit) 67 | 68 | - **Feature:** 是什么; 69 | - **Advantage:** 比别人好在哪些地方; 70 | - **Benefit:** 如果雇佣你,招聘方会得到什么好处。 71 | 72 | 简单来说,这个法则主要是让你的面试官知道你的优势、招了你之后对公司有什么帮助。 73 | 74 | ## 项目经历怎么写? 75 | 76 | 简历上有一两个项目经历很正常,但是真正能把项目经历很好的展示给面试官的非常少。对于项目经历大家可以考虑从如下几点来写: 77 | 78 | 1. 对项目整体设计的一个感受 79 | 2. 在这个项目中你负责了什么、做了什么、担任了什么角色 80 | 3. 从这个项目中你学会了那些东西,使用到了那些技术,学会了那些新技术的使用 81 | 4. 另外项目描述中,最好可以体现自己的综合素质,比如你是如何协调项目组成员协同开发的或者在遇到某一个棘手的问题的时候你是如何解决的又或者说你在这个项目用了什么技术实现了什么功能比如:用redis做缓存提高访问速度和并发量、使用消息队列削峰和降流等等。 82 | 83 | ## 专业技能该怎么写? 84 | 85 | 先问一下你自己会什么,然后看看你意向的公司需要什么。一般HR可能并不太懂技术,所以他在筛选简历的时候可能就盯着你专业技能的关键词来看。对于公司有要求而你不会的技能,你可以花几天时间学习一下,然后在简历上可以写上自己了解这个技能。比如你可以这样写(下面这部分内容摘自我的简历,大家可以根据自己的情况做一些修改和完善): 86 | 87 | - 计算机网络、数据结构、算法、操作系统等课内基础知识:掌握 88 | - Java 基础知识:掌握 89 | - JVM 虚拟机(Java内存区域、虚拟机垃圾算法、虚拟垃圾收集器、JVM内存管理):掌握 90 | - 高并发、高可用、高性能系统开发:掌握 91 | - Struts2、Spring、Hibernate、Ajax、Mybatis、JQuery :掌握 92 | - SSH 整合、SSM 整合、 SOA 架构:掌握 93 | - Dubbo: 掌握 94 | - Zookeeper: 掌握 95 | - 常见消息队列: 掌握 96 | - Linux:掌握 97 | - MySQL常见优化手段:掌握 98 | - Spring Boot +Spring Cloud +Docker:了解 99 | - Hadoop 生态相关技术中的 HDFS、Storm、MapReduce、Hive、Hbase :了解 100 | - Python 基础、一些常见第三方库比如OpenCV、wxpy、wordcloud、matplotlib:熟悉 101 | 102 | ## 排版注意事项 103 | 104 | 1. 尽量简洁,不要太花里胡哨; 105 | 2. 一些技术名词不要弄错了大小写比如MySQL不要写成mysql,Java不要写成java。这个在我看来还是比较忌讳的,所以一定要注意这个细节; 106 | 3. 中文和数字英文之间加上空格的话看起来会舒服一点; 107 | 108 | ## 其他的一些小tips 109 | 110 | 1. 尽量避免主观表述,少一点语义模糊的形容词,尽量要简洁明了,逻辑结构清晰。 111 | 2. 如果自己有博客或者个人技术栈点的话,写上去会为你加分很多。 112 | 3. 如果自己的Github比较活跃的话,写上去也会为你加分很多。 113 | 4. 注意简历真实性,一定不要写自己不会的东西,或者带有欺骗性的内容 114 | 5. 项目经历建议以时间倒序排序,另外项目经历不在于多,而在于有亮点。 115 | 6. 如果内容过多的话,不需要非把内容压缩到一页,保持排版干净整洁就可以了。 116 | 7. 简历最后最好能加上:“感谢您花时间阅读我的简历,期待能有机会和您共事。”这句话,显的你会很有礼貌。 117 | 118 | ## 推荐的工具/网站 119 | 120 | - 冷熊简历(MarkDown在线简历工具,可在线预览、编辑和生成PDF): 121 | - Typora+[Java程序员简历模板](https://github.com/geekcompany/ResumeSample/blob/master/java.md) 122 | -------------------------------------------------------------------------------- /docs/essential-content-for-interview/PreparingForInterview/面试官-你有什么问题要问我.md: -------------------------------------------------------------------------------- 1 | 我还记得当时我去参加面试的时候,几乎每一场面试,特别是HR面和高管面的时候,面试官总是会在结尾问我:“问了你这么多问题了,你有什么问题问我吗?”。这个时候很多人内心就会陷入短暂的纠结中:我该问吗?不问的话面试官会不会对我影响不好?问什么问题?问这个问题会不会让面试官对我的影响不好啊? 2 | 3 | ![无奈](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-2/无奈.jpg) 4 | 5 | ### 这个问题对最终面试结果的影响到底大不大? 6 | 7 | 就技术面试而言,回答这个问题的时候,只要你不是触碰到你所面试的公司的雷区,那么我觉得这对你能不能拿到最终offer来说影响确实是不大的。我说这些并不代表你就可以直接对面试官说:“我没问题了。”,笔主当时面试的时候确实也说过挺多次“没问题要问了。”,最终也没有导致笔主被pass掉(可能是前面表现比较好,哈哈,自恋一下)。我现在回想起来,觉得自己当时做法其实挺不对的。面试本身就是一个双向选择的过程,你对这个问题的回答也会侧面反映出你对这次面试的上心程度,你的问题是否有价值,也影响了你最终的选择与公司是否选择你。 8 | 9 | 面试官在技术面试中主要考察的还是你这样个人到底有没有胜任这个工作的能力以及你是否适合公司未来的发展需要,很多公司还需要你认同它的文化,我觉得你只要不是太笨,应该不会栽在这里。除非你和另外一个人在能力上相同,但是只能在你们两个人中选一个,那么这个问题才对你能不能拿到offer至关重要。有准备总比没准备好,给面试官留一个好的影响总归是没错的。 10 | 11 | 但是,就非技术面试来说,我觉得好好回答这个问题对你最终的结果还是比较重要的。 12 | 13 | 总的来说不管是技术面试还是非技术面试,如果你想赢得公司的青睐和尊重,我觉得我们都应该重视这个问题。 14 | 15 | ### 真诚一点,不要问太 Low 的问题 16 | 17 | 回答这个问题很重要的一点就是你没有必要放低自己的姿态问一些很虚或者故意讨好面试官的问题,也不要把自己从面经上学到的东西照搬下来使用。面试官也不是傻子,特别是那种特别有经验的面试官,你是真心诚意的问问题,还是从别处照搬问题来讨好面试官,人家可能一听就听出来了。总的来说,还是要真诚。除此之外,不要问太 Low 的问题,会显得你整个人格局比较小或者说你根本没有准备(侧面反映你对这家公司不上心,既然你不上心,为什么要要你呢)。举例几个比较 Low 的问题,大家看看自己有没有问过其中的问题: 18 | 19 | - 贵公司的主要业务是什么?(面试之前自己不知道提前网上查一下吗?) 20 | - 贵公司的男女比例如何?(考虑脱单?记住你是来工作的!) 21 | - 贵公司一年搞几次外出旅游?(你是来工作的,这些娱乐活动先别放在心上!) 22 | - ...... 23 | 24 | ### 有哪些有价值的问题值得问? 25 | 26 | 针对这个问题。笔主专门找了几个专门做HR工作的小哥哥小姐姐们询问并且查阅了挺多前辈们的回答,然后结合自己的实际经历,我概括了下面几个比较适合问的问题。 27 | 28 | #### 面对HR或者其他Level比较低的面试官时 29 | 30 | 1. **能不能谈谈你作为一个公司老员工对公司的感受?** (这个问题比较容易回答,不会让面试官陷入无话可说的尴尬境地。另外,从面试官的回答中你可以加深对这个公司的了解,让你更加清楚这个公司到底是不是你想的那样或者说你是否能适应这个公司的文化。除此之外,这样的问题在某种程度上还可以拉进你与面试官的距离。) 31 | 2. **能不能问一下,你当时因为什么原因选择加入这家公司的呢或者说这家公司有哪些地方吸引你?有什么地方你觉得还不太好或者可以继续完善吗?** (类似第一个问题,都是问面试官个人对于公司的看法。) 32 | 3. **我觉得我这次表现的不是太好,你有什么建议或者评价给我吗?**(这个是我常问的。我觉得说自己表现不好只是这个语境需要这样来说,这样可以显的你比较谦虚好学上进。) 33 | 4. **接下来我会有一段空档期,有什么值得注意或者建议学习的吗?** (体现出你对工作比较上心,自助学习意识比较强。) 34 | 5. **这个岗位为什么还在招人?** (岗位真实性和价值咨询) 35 | 6. **大概什么时候能给我回复呢?** (终面的时候,如果面试官没有说的话,可以问一下) 36 | 7. ...... 37 | 38 | 39 | 40 | #### 面对部门领导 41 | 42 | 1. **部门的主要人员分配以及对应的主要工作能简单介绍一下吗?** 43 | 2. **未来如果我要加入这个团队,你对我的期望是什么?** (部门领导一般情况下是你的直属上级了,你以后和他打交道的机会应该是最多的。你问这个问题,会让他感觉你是一个对他的部门比较上心,比较有团体意识,并且愿意倾听的候选人。) 44 | 3. **公司对新入职的员工的培养机制是什么样的呢?** (正规的公司一般都有培养机制,提前问一下是对你自己的负责也会显的你比较上心) 45 | 4. **以您来看,这个岗位未来在公司内部的发展如何?** (在我看来,问这个问题也是对你自己的负责吧,谁不想发展前景更好的岗位呢?) 46 | 5. **团队现在面临的最大挑战是什么?** (这样的问题不会暴露你对公司的不了解,并且也能让你对未来工作的挑战或困难有一个提前的预期。) 47 | 48 | 49 | 50 | #### 面对Level比较高的(比如总裁,老板) 51 | 52 | 1. **贵公司的发展目标和方向是什么?** (看下公司的发展是否满足自己的期望) 53 | 2. **与同行业的竞争者相比,贵公司的核心竞争优势在什么地方?** (充分了解自己的优势和劣势) 54 | 3. **公司现在面临的最大挑战是什么?** 55 | 56 | ### 来个补充,顺便送个祝福给大家 57 | 58 | 薪酬待遇和相关福利问题一般在终面的时候(最好不要在前面几面的时候就问到这个问题),面试官会提出来或者在面试完之后以邮件的形式告知你。一般来说,如果面试官很愿意为你回答问题,对你的问题也比较上心的话,那他肯定是觉得你就是他们要招的人。 59 | 60 | 大家在面试的时候,可以根据自己对于公司或者岗位的了解程度,对上面提到的问题进行适当修饰或者修改。上面提到的一些问题只是给没有经验的朋友一个参考,如果你还有其他比较好的问题的话,那当然也更好啦! 61 | 62 | 金三银四。过了二月就到了面试高峰期或者说是黄金期。几份惊喜几份愁,愿各位能始终不忘初心!每个人都有每个人的难处。引用一句《阿甘正传》里面的台词:“生活就像一盒巧克力,你永远不知道下一块是什么味道“。 63 | 64 | ![加油!彩虹就要来了](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-2/生活就像一盒巧克力你永远不知道下一块是什么味道.JPEG) -------------------------------------------------------------------------------- /docs/essential-content-for-interview/手把手教你用Markdown写一份高质量的简历.md: -------------------------------------------------------------------------------- 1 | ## Markdown 简历模板样式一览 2 | ![](https://user-gold-cdn.xitu.io/2018/9/3/1659f91e4843bd67?w=800&h=1737&f=png&s=97357) 3 | **可以看到我把联系方式放在第一位,因为公司一般会与你联系,所以把联系方式放在第一位也是为了方便联系考虑。** 4 | 5 | ## 为什么要用 Markdown 写简历? 6 | 7 | Markdown 语法简单,易于上手。使用正确的 Markdown 语言写出来的简历不论是在排版还是格式上都比较干净,易于阅读。另外,使用 Markdown 写简历也会给面试官一种你比较专业的感觉。 8 | 9 | 除了这些,我觉得使用 Markdown 写简历可以很方便将其与PDF、HTML、PNG格式之间转换。后面我会介绍到转换方法,只需要一条命令你就可以实现 Markdown 到 PDF、HTML 与 PNG之间的无缝切换。 10 | 11 | > 下面的一些内容我在之前的一篇文章中已经提到过,这里再说一遍,最后会分享如何实现Markdown 到 PDF、HTML、PNG格式之间转换。 12 | 13 | ## 为什么说简历很重要? 14 | 15 | 假如你是网申,你的简历必然会经过HR的筛选,一张简历HR可能也就花费10秒钟看一下,然后HR就会决定你这一关是Fail还是Pass。 16 | 17 | 假如你是内推,如果你的简历没有什么优势的话,就算是内推你的人再用心,也无能为力。 18 | 19 | 另外,就算你通过了筛选,后面的面试中,面试官也会根据你的简历来判断你究竟是否值得他花费很多时间去面试。 20 | 21 | ## 写简历的两大法则 22 | 23 | 目前写简历的方式有两种普遍被认可,一种是 STAR, 一种是 FAB。 24 | 25 | **STAR法则(Situation Task Action Result):** 26 | 27 | - **Situation:** 事情是在什么情况下发生; 28 | - **Task::** 你是如何明确你的任务的; 29 | - **Action:** 针对这样的情况分析,你采用了什么行动方式; 30 | - **Result:** 结果怎样,在这样的情况下你学习到了什么。 31 | 32 | **FAB 法则(Feature Advantage Benefit):** 33 | 34 | - **Feature:** 是什么; 35 | - **Advantage:** 比别人好在哪些地方; 36 | - **Benefit:** 如果雇佣你,招聘方会得到什么好处。 37 | 38 | ## 项目经历怎么写? 39 | 简历上有一两个项目经历很正常,但是真正能把项目经历很好的展示给面试官的非常少。对于项目经历大家可以考虑从如下几点来写: 40 | 41 | 1. 对项目整体设计的一个感受 42 | 2. 在这个项目中你负责了什么、做了什么、担任了什么角色 43 | 3. 从这个项目中你学会了那些东西,使用到了那些技术,学会了那些新技术的使用 44 | 4. 另外项目描述中,最好可以体现自己的综合素质,比如你是如何协调项目组成员协同开发的或者在遇到某一个棘手的问题的时候你是如何解决的。 45 | 46 | ## 专业技能该怎么写? 47 | 先问一下你自己会什么,然后看看你意向的公司需要什么。一般HR可能并不太懂技术,所以他在筛选简历的时候可能就盯着你专业技能的关键词来看。对于公司有要求而你不会的技能,你可以花几天时间学习一下,然后在简历上可以写上自己了解这个技能。比如你可以这样写: 48 | 49 | - Dubbo:精通 50 | - Spring:精通 51 | - Docker:掌握 52 | - SOA分布式开发 :掌握 53 | - Spring Cloud:了解 54 | 55 | ## 简历模板分享 56 | 57 | **开源程序员简历模板**: [https://github.com/geekcompany/ResumeSample](https://github.com/geekcompany/ResumeSample)(包括PHP程序员简历模板、iOS程序员简历模板、Android程序员简历模板、Web前端程序员简历模板、Java程序员简历模板、C/C++程序员简历模板、NodeJS程序员简历模板、架构师简历模板以及通用程序员简历模板) 58 | 59 | **上述简历模板的改进版本:** [https://github.com/Snailclimb/Java-Guide/blob/master/面试必备/简历模板.md](https://github.com/Snailclimb/Java-Guide/blob/master/面试必备/简历模板.md) 60 | 61 | ## 其他的一些小tips 62 | 63 | 1. 尽量避免主观表述,少一点语义模糊的形容词,尽量要简洁明了,逻辑结构清晰。 64 | 2. 注意排版(不需要花花绿绿的),尽量使用Markdown语法。 65 | 3. 如果自己有博客或者个人技术栈点的话,写上去会为你加分很多。 66 | 4. 如果自己的Github比较活跃的话,写上去也会为你加分很多。 67 | 5. 注意简历真实性,一定不要写自己不会的东西,或者带有欺骗性的内容 68 | 6. 项目经历建议以时间倒序排序,另外项目经历不在于多,而在于有亮点。 69 | 7. 如果内容过多的话,不需要非把内容压缩到一页,保持排版干净整洁就可以了。 70 | 8. 简历最后最好能加上:“感谢您花时间阅读我的简历,期待能有机会和您共事。”这句话,显的你会很有礼貌。 71 | 72 | 73 | > 我们刚刚讲了很多关于如何写简历的内容并且分享了一份 Markdown 格式的简历文档。下面我们来看看如何实现 Markdown 到 HTML格式、PNG格式之间转换。 74 | ## Markdown 到 HTML格式、PNG格式之间转换 75 | 76 | 网上很难找到一个比较方便并且效果好的转换方法,最后我是通过 Visual Studio Code 的 Markdown PDF 插件完美解决了这个问题! 77 | 78 | ### 安装 Markdown PDF 插件 79 | 80 | **① 打开Visual Studio Code ,按快捷键 F1,选择安装扩展选项** 81 | 82 | ![① 打开Visual Studio Code ,按快捷键 F1,选择安装扩展选项](https://user-gold-cdn.xitu.io/2018/9/3/1659f9a44103e551?w=1366&h=688&f=png&s=104435) 83 | 84 | **② 搜索 “Markdown PDF” 插件并安装 ,然后重启** 85 | 86 | ![② 搜索 “Markdown PDF” 插件并安装 ,然后重启](https://user-gold-cdn.xitu.io/2018/9/3/1659f9dbef0d06fb?w=1280&h=420&f=png&s=70510) 87 | 88 | ### 使用方法 89 | 90 | 随便打开一份 Markdown 文件 点击F1,然后输入export即可! 91 | 92 | ![](https://user-gold-cdn.xitu.io/2018/9/3/1659fa0292906150?w=1289&h=468&f=png&s=72178) 93 | 94 | -------------------------------------------------------------------------------- /docs/essential-content-for-interview/简历模板.md: -------------------------------------------------------------------------------- 1 | # 联系方式 2 | 3 | - 手机: 4 | - Email: 5 | - 微信: 6 | 7 | # 个人信息 8 | 9 | - 姓名/性别/出生日期 10 | - 本科/xxx计算机系xxx专业/英语六级 11 | - 技术博客:[http://snailclimb.top/](http://snailclimb.top/) 12 | - 荣誉奖励:获得了什么奖(获奖时间) 13 | - Github:[https://github.com/Snailclimb ](https://github.com/Snailclimb) 14 | - Github Resume: [http://resume.github.io/?Snailclimb](http://resume.github.io/?Snailclimb) 15 | - 期望职位:Java 研发程序员/大数据工程师(Java后台开发为首选) 16 | - 期望城市:xxx城市 17 | 18 | 19 | # 项目经历 20 | 21 | ## xxx项目 22 | 23 | ### 项目描述 24 | 25 | 介绍该项目是做什么的、使用到了什么技术以及你对项目整体设计的一个感受 26 | 27 | ### 责任描述 28 | 29 | 主要可以从下面三点来写: 30 | 31 | 1. 在这个项目中你负责了什么、做了什么、担任了什么角色 32 | 2. 从这个项目中你学会了那些东西,使用到了那些技术,学会了那些新技术的使用 33 | 3. 另外项目描述中,最好可以体现自己的综合素质,比如你是如何协调项目组成员协同开发的或者在遇到某一个棘手的问题的时候你是如何解决的。 34 | 35 | # 开源项目和技术文章 36 | 37 | ## 开源项目 38 | 39 | - [Java-Guide](https://github.com/Snailclimb/Java-Guide) :一份涵盖大部分Java程序员所需要掌握的核心知识。Star:3.9K; Fork:0.9k。 40 | 41 | 42 | ## 技术文章推荐 43 | 44 | - [可能是把Java内存区域讲的最清楚的一篇文章](https://juejin.im/post/5b7d69e4e51d4538ca5730cb) 45 | - [搞定JVM垃圾回收就是这么简单](https://juejin.im/post/5b85ea54e51d4538dd08f601) 46 | - [前端&后端程序员必备的Linux基础知识](https://juejin.im/post/5b3b19856fb9a04fa42f8c71) 47 | - [可能是把Docker的概念讲的最清楚的一篇文章](https://juejin.im/post/5b260ec26fb9a00e8e4b031a) 48 | 49 | 50 | # 校园经历(可选) 51 | 52 | ## 2016-2017 53 | 54 | 担任学校社团-致深社副会长,主要负责团队每周活动的组建以及每周例会的主持。 55 | 56 | ## 2017-2018 57 | 担任学校传媒组织:“长江大学在线信息传媒”的副站长以及安卓组成员。主要负责每周例会主持、活动策划以及学校校园通APP的研发工作。 58 | 59 | 60 | # 技能清单 61 | 62 | 以下均为我熟练使用的技能 63 | 64 | - Web开发:PHP/Hack/Node 65 | - Web框架:ThinkPHP/Yaf/Yii/Lavarel/LazyPHP 66 | - 前端框架:Bootstrap/AngularJS/EmberJS/HTML5/Cocos2dJS/ionic 67 | - 前端工具:Bower/Gulp/SaSS/LeSS/PhoneGap 68 | - 数据库相关:MySQL/PgSQL/PDO/SQLite 69 | - 版本管理、文档和自动化部署工具:Svn/Git/PHPDoc/Phing/Composer 70 | - 单元测试:PHPUnit/SimpleTest/Qunit 71 | - 云和开放平台:SAE/BAE/AWS/微博开放平台/微信应用开发 72 | 73 | # 自我评价(可选) 74 | 75 | 自我发挥。切记不要过度自夸!!! 76 | 77 | 78 | ### 感谢您花时间阅读我的简历,期待能有机会和您共事。 79 | 80 | -------------------------------------------------------------------------------- /docs/essential-content-for-interview/面试必备之乐观锁与悲观锁.md: -------------------------------------------------------------------------------- 1 | 点击关注[公众号](#公众号)及时获取笔主最新更新文章,并可免费领取本文档配套的《Java面试突击》以及Java工程师必备学习资源。 2 | 3 | 4 | 5 | - [何谓悲观锁与乐观锁](#何谓悲观锁与乐观锁) 6 | - [悲观锁](#悲观锁) 7 | - [乐观锁](#乐观锁) 8 | - [两种锁的使用场景](#两种锁的使用场景) 9 | - [乐观锁常见的两种实现方式](#乐观锁常见的两种实现方式) 10 | - [1. 版本号机制](#1-版本号机制) 11 | - [2. CAS算法](#2-cas算法) 12 | - [乐观锁的缺点](#乐观锁的缺点) 13 | - [1 ABA 问题](#1-aba-问题) 14 | - [2 循环时间长开销大](#2-循环时间长开销大) 15 | - [3 只能保证一个共享变量的原子操作](#3-只能保证一个共享变量的原子操作) 16 | - [CAS与synchronized的使用情景](#cas与synchronized的使用情景) 17 | 18 | 19 | 20 | ### 何谓悲观锁与乐观锁 21 | 22 | > 乐观锁对应于生活中乐观的人总是想着事情往好的方向发展,悲观锁对应于生活中悲观的人总是想着事情往坏的方向发展。这两种人各有优缺点,不能不以场景而定说一种人好于另外一种人。 23 | 24 | #### 悲观锁 25 | 26 | 总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(**共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程**)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java中`synchronized`和`ReentrantLock`等独占锁就是悲观锁思想的实现。 27 | 28 | 29 | #### 乐观锁 30 | 31 | 总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。**乐观锁适用于多读的应用类型,这样可以提高吞吐量**,像数据库提供的类似于**write_condition机制**,其实都是提供的乐观锁。在Java中`java.util.concurrent.atomic`包下面的原子变量类就是使用了乐观锁的一种实现方式**CAS**实现的。 32 | 33 | #### 两种锁的使用场景 34 | 35 | 从上面对两种锁的介绍,我们知道两种锁各有优缺点,不可认为一种好于另一种,像**乐观锁适用于写比较少的情况下(多读场景)**,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果是多写的情况,一般会经常产生冲突,这就会导致上层应用会不断的进行retry,这样反倒是降低了性能,所以**一般多写的场景下用悲观锁就比较合适。** 36 | 37 | 38 | ### 乐观锁常见的两种实现方式 39 | 40 | > **乐观锁一般会使用版本号机制或CAS算法实现。** 41 | 42 | #### 1. 版本号机制 43 | 44 | 一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新,否则重试更新操作,直到更新成功。 45 | 46 | **举一个简单的例子:** 47 | 假设数据库中帐户信息表中有一个 version 字段,当前值为 1 ;而当前帐户余额字段( balance )为 $100 。 48 | 49 | 1. 操作员 A 此时将其读出( version=1 ),并从其帐户余额中扣除 $50( $100-$50 )。 50 | 2. 在操作员 A 操作的过程中,操作员B 也读入此用户信息( version=1 ),并从其帐户余额中扣除 $20 ( $100-$20 )。 51 | 3. 操作员 A 完成了修改工作,将数据版本号加一( version=2 ),连同帐户扣除后余额( balance=$50 ),提交至数据库更新,此时由于提交数据版本大于数据库记录当前版本,数据被更新,数据库记录 version 更新为 2 。 52 | 4. 操作员 B 完成了操作,也将版本号加一( version=2 )试图向数据库提交数据( balance=$80 ),但此时比对数据库记录版本时发现,操作员 B 提交的数据版本号为 2 ,数据库记录当前版本也为 2 ,不满足 “ 提交版本必须大于记录当前版本才能执行更新 “ 的乐观锁策略,因此,操作员 B 的提交被驳回。 53 | 54 | 这样,就避免了操作员 B 用基于 version=1 的旧数据修改的结果覆盖操作员A 的操作结果的可能。 55 | 56 | #### 2. CAS算法 57 | 58 | 即**compare and swap(比较与交换)**,是一种有名的**无锁算法**。无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步(Non-blocking Synchronization)。**CAS算法**涉及到三个操作数 59 | 60 | - 需要读写的内存值 V 61 | - 进行比较的值 A 62 | - 拟写入的新值 B 63 | 64 | 当且仅当 V 的值等于 A时,CAS通过原子方式用新值B来更新V的值,否则不会执行任何操作(比较和替换是一个原子操作)。一般情况下是一个**自旋操作**,即**不断的重试**。 65 | 66 | 关于自旋锁,大家可以看一下这篇文章,非常不错:[《 67 | 面试必备之深入理解自旋锁》](https://blog.csdn.net/qq_34337272/article/details/81252853) 68 | 69 | ### 乐观锁的缺点 70 | 71 | > ABA 问题是乐观锁一个常见的问题 72 | 73 | #### 1 ABA 问题 74 | 75 | 如果一个变量V初次读取的时候是A值,并且在准备赋值的时候检查到它仍然是A值,那我们就能说明它的值没有被其他线程修改过了吗?很明显是不能的,因为在这段时间它的值可能被改为其他值,然后又改回A,那CAS操作就会误认为它从来没有被修改过。这个问题被称为CAS操作的 **"ABA"问题。** 76 | 77 | JDK 1.5 以后的 `AtomicStampedReference 类`就提供了此种能力,其中的 `compareAndSet 方法`就是首先检查当前引用是否等于预期引用,并且当前标志是否等于预期标志,如果全部相等,则以原子方式将该引用和该标志的值设置为给定的更新值。 78 | 79 | #### 2 循环时间长开销大 80 | **自旋CAS(也就是不成功就一直循环执行直到成功)如果长时间不成功,会给CPU带来非常大的执行开销。** 如果JVM能支持处理器提供的pause指令那么效率会有一定的提升,pause指令有两个作用,第一它可以延迟流水线执行指令(de-pipeline),使CPU不会消耗过多的执行资源,延迟的时间取决于具体实现的版本,在一些处理器上延迟时间是零。第二它可以避免在退出循环的时候因内存顺序冲突(memory order violation)而引起CPU流水线被清空(CPU pipeline flush),从而提高CPU的执行效率。 81 | 82 | #### 3 只能保证一个共享变量的原子操作 83 | 84 | CAS 只对单个共享变量有效,当操作涉及跨多个共享变量时 CAS 无效。但是从 JDK 1.5开始,提供了`AtomicReference类`来保证引用对象之间的原子性,你可以把多个变量放在一个对象里来进行 CAS 操作.所以我们可以使用锁或者利用`AtomicReference类`把多个共享变量合并成一个共享变量来操作。 85 | 86 | ### CAS与synchronized的使用情景 87 | 88 | > **简单的来说CAS适用于写比较少的情况下(多读场景,冲突一般较少),synchronized适用于写比较多的情况下(多写场景,冲突一般较多)** 89 | 90 | 1. 对于资源竞争较少(线程冲突较轻)的情况,使用synchronized同步锁进行线程阻塞和唤醒切换以及用户态内核态间的切换操作额外浪费消耗cpu资源;而CAS基于硬件实现,不需要进入内核,不需要切换线程,操作自旋几率较少,因此可以获得更高的性能。 91 | 2. 对于资源竞争严重(线程冲突严重)的情况,CAS自旋的概率会比较大,从而浪费更多的CPU资源,效率低于synchronized。 92 | 93 | 补充: Java并发编程这个领域中synchronized关键字一直都是元老级的角色,很久之前很多人都会称它为 **“重量级锁”** 。但是,在JavaSE 1.6之后进行了主要包括为了减少获得锁和释放锁带来的性能消耗而引入的 **偏向锁** 和 **轻量级锁** 以及其它**各种优化**之后变得在某些情况下并不是那么重了。synchronized的底层实现主要依靠 **Lock-Free** 的队列,基本思路是 **自旋后阻塞**,**竞争切换后继续竞争锁**,**稍微牺牲了公平性,但获得了高吞吐量**。在线程冲突较少的情况下,可以获得和CAS类似的性能;而线程冲突严重的情况下,性能远高于CAS。 94 | 95 | ## 公众号 96 | 97 | 如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的公众号。 98 | 99 | **《Java面试突击》:** 由本文档衍生的专为面试而生的《Java面试突击》V2.0 PDF 版本[公众号](#公众号)后台回复 **"面试突击"** 即可免费领取! 100 | 101 | **Java工程师必备学习资源:** 一些Java工程师常用学习资源公众号后台回复关键字 **“1”** 即可免费无套路获取。 102 | 103 | ![我的公众号](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/167598cd2e17b8ec.png) 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /docs/github-trending/2018-12.md: -------------------------------------------------------------------------------- 1 | 本文数据统计于 1.1 号凌晨,由 SnailClimb 整理。 2 | 3 | ### 1. JavaGuide 4 | 5 | - **Github地址**: [https://github.com/Snailclimb/JavaGuide](https://github.com/Snailclimb/JavaGuide) 6 | - **star**: 18.2k 7 | - **介绍**: 【Java学习+面试指南】 一份涵盖大部分Java程序员所需要掌握的核心知识。 8 | 9 | ### 2. mall 10 | 11 | - **Github地址**: [https://github.com/macrozheng/mall](https://github.com/macrozheng/mall) 12 | - **star**: 3.3k 13 | - **介绍**: mall项目是一套电商系统,包括前台商城系统及后台管理系统,基于SpringBoot+MyBatis实现。 前台商城系统包含首页门户、商品推荐、商品搜索、商品展示、购物车、订单流程、会员中心、客户服务、帮助中心等模块。 后台管理系统包含商品管理、订单管理、会员管理、促销管理、运营管理、内容管理、统计报表、财务管理、权限管理、设置等模块。 14 | 15 | ### 3. advanced-java 16 | 17 | - **Github地址**:[https://github.com/doocs/advanced-java](https://github.com/doocs/advanced-java) 18 | - **star**: 3.3k 19 | - **介绍**: 互联网 Java 工程师进阶知识完全扫盲 20 | 21 | ### 4. matrix 22 | 23 | - **Github地址**:[https://github.com/Tencent/matrix](https://github.com/Tencent/matrix) 24 | - **star**: 2.5k 25 | - **介绍**: Matrix 是一款微信研发并日常使用的 APM(Application Performance Manage),当前主要运行在 Android 平台上。 Matrix 的目标是建立统一的应用性能接入框架,通过各种性能监控方案,对性能监控项的异常数据进行采集和分析,输出相应的问题分析、定位与优化建议,从而帮助开发者开发出更高质量的应用。 26 | 27 | ### 5. miaosha 28 | 29 | - **Github地址**:[https://github.com/qiurunze123/miaosha](https://github.com/qiurunze123/miaosha) 30 | - **star**: 2.4k 31 | - **介绍**: 高并发大流量如何进行秒杀架构,我对这部分知识做了一个系统的整理,写了一套系统。 32 | 33 | ### 6. arthas 34 | 35 | - **Github地址**:[https://github.com/alibaba/arthas](https://github.com/alibaba/arthas) 36 | - **star**: 8.2k 37 | - **介绍**: Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱。 38 | 39 | ### 7 spring-boot 40 | 41 | - **Github地址**: [https://github.com/spring-projects/spring-boot](https://github.com/spring-projects/spring-boot) 42 | - **star:** 32.6k 43 | - **介绍**: 虽然Spring的组件代码是轻量级的,但它的配置却是重量级的(需要大量XML配置),不过Spring Boot 让这一切成为了过去。 另外Spring Cloud也是基于Spring Boot构建的,我个人非常有必要学习一下。 44 | 45 | **关于Spring Boot官方的介绍:** 46 | 47 | > Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”…Most Spring Boot applications need very little Spring configuration.(Spring Boot可以轻松创建独立的生产级基于Spring的应用程序,只要通过 “just run”(可能是run ‘Application’或java -jar 或 tomcat 或 maven插件run 或 shell脚本)便可以运行项目。大部分Spring Boot项目只需要少量的配置即可) 48 | 49 | ### 8. tutorials 50 | 51 | - **Github地址**:[https://github.com/eugenp/tutorials](https://github.com/eugenp/tutorials) 52 | - **star**: 10k 53 | - **介绍**: 该项目是一系列小而专注的教程 - 每个教程都涵盖Java生态系统中单一且定义明确的开发领域。 当然,它们的重点是Spring Framework - Spring,Spring Boot和Spring Securiyt。 除了Spring之外,还有以下技术:核心Java,Jackson,HttpClient,Guava。 54 | 55 | ### 9. qmq 56 | 57 | - **Github地址**:[https://github.com/qunarcorp/qmq](https://github.com/qunarcorp/qmq) 58 | - **star**: 1.1k 59 | - **介绍**: QMQ是去哪儿网内部广泛使用的消息中间件,自2012年诞生以来在去哪儿网所有业务场景中广泛的应用,包括跟交易息息相关的订单场景; 也包括报价搜索等高吞吐量场景。 60 | 61 | 62 | ### 10. symphony 63 | 64 | - **Github地址**:[https://github.com/b3log/symphony](https://github.com/b3log/symphony) 65 | - **star**: 9k 66 | - **介绍**: 一款用 Java 实现的现代化社区(论坛/BBS/社交网络/博客)平台。 67 | 68 | ### 11. incubator-dubbo 69 | 70 | - **Github地址**:[https://github.com/apache/incubator-dubbo](https://github.com/apache/incubator-dubbo) 71 | - **star**: 23.6k 72 | - **介绍**: 阿里开源的一个基于Java的高性能开源RPC框架。 73 | 74 | ### 12. apollo 75 | 76 | - **Github地址**:[https://github.com/ctripcorp/apollo](https://github.com/ctripcorp/apollo) 77 | - **star**: 10k 78 | - **介绍**: Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。 79 | -------------------------------------------------------------------------------- /docs/github-trending/2019-1.md: -------------------------------------------------------------------------------- 1 | ### 1. JavaGuide 2 | 3 | - **Github地址**: [https://github.com/Snailclimb/JavaGuide](https://github.com/Snailclimb/JavaGuide) 4 | - **star**: 22.8k 5 | - **介绍**: 【Java学习+面试指南】 一份涵盖大部分Java程序员所需要掌握的核心知识。 6 | 7 | ### 2. advanced-java 8 | 9 | - **Github地址**:[https://github.com/doocs/advanced-java](https://github.com/doocs/advanced-java) 10 | - **star**: 7.9k 11 | - **介绍**: 互联网 Java 工程师进阶知识完全扫盲 12 | 13 | ### 3. fescar 14 | 15 | - **Github地址**:[https://github.com/alibaba/fescar](https://github.com/alibaba/fescar) 16 | - **star**: 4.6k 17 | - **介绍**: 具有 **高性能** 和 **易用性** 的 **微服务架构** 的 **分布式事务** 的解决方案。(特点:高性能且易于使用,旨在实现简单并快速的事务提交与回滚。 18 | 19 | ### 4. mall 20 | 21 | - **Github地址**: [https://github.com/macrozheng/mall](https://github.com/macrozheng/mall) 22 | - **star**: 5.6 k 23 | - **介绍**: mall项目是一套电商系统,包括前台商城系统及后台管理系统,基于SpringBoot+MyBatis实现。 前台商城系统包含首页门户、商品推荐、商品搜索、商品展示、购物车、订单流程、会员中心、客户服务、帮助中心等模块。 后台管理系统包含商品管理、订单管理、会员管理、促销管理、运营管理、内容管理、统计报表、财务管理、权限管理、设置等模块。 24 | 25 | ### 5. miaosha 26 | 27 | - **Github地址**:[https://github.com/qiurunze123/miaosha](https://github.com/qiurunze123/miaosha) 28 | - **star**: 4.4k 29 | - **介绍**: 高并发大流量如何进行秒杀架构,我对这部分知识做了一个系统的整理,写了一套系统。 30 | 31 | ### 6. flink 32 | 33 | - **Github地址**:[https://github.com/apache/flink](https://github.com/apache/flink) 34 | - **star**: 7.1 k 35 | - **介绍**: Apache Flink是一个开源流处理框架,具有强大的流和批处理功能。 36 | 37 | ### 7. cim 38 | 39 | - **Github地址**:[https://github.com/crossoverJie/cim](https://github.com/crossoverJie/cim) 40 | - **star**: 1.8 k 41 | - **介绍**: cim(cross IM) 适用于开发者的即时通讯系统。 42 | 43 | ### 8. symphony 44 | 45 | - **Github地址**:[https://github.com/b3log/symphony](https://github.com/b3log/symphony) 46 | - **star**: 10k 47 | - **介绍**: 一款用 Java 实现的现代化社区(论坛/BBS/社交网络/博客)平台。 48 | 49 | ### 9. spring-boot 50 | 51 | - **Github地址**: [https://github.com/spring-projects/spring-boot](https://github.com/spring-projects/spring-boot) 52 | - **star:** 32.6k 53 | - **介绍**: 虽然Spring的组件代码是轻量级的,但它的配置却是重量级的(需要大量XML配置),不过Spring Boot 让这一切成为了过去。 另外Spring Cloud也是基于Spring Boot构建的,我个人非常有必要学习一下。 54 | 55 | **关于Spring Boot官方的介绍:** 56 | 57 | > Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”…Most Spring Boot applications need very little Spring configuration.(Spring Boot可以轻松创建独立的生产级基于Spring的应用程序,只要通过 “just run”(可能是run ‘Application’或java -jar 或 tomcat 或 maven插件run 或 shell脚本)便可以运行项目。大部分Spring Boot项目只需要少量的配置即可) 58 | 59 | ### 10. arthas 60 | 61 | - **Github地址**:[https://github.com/alibaba/arthas](https://github.com/alibaba/arthas) 62 | - **star**: 9.5k 63 | - **介绍**: Arthas 是Alibaba开源的Java诊断工具。 64 | 65 | **概览:** 66 | 67 | 当你遇到以下类似问题而束手无策时,`Arthas`可以帮助你解决: 68 | 69 | 0. 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception? 70 | 1. 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了? 71 | 2. 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗? 72 | 3. 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现! 73 | 4. 是否有一个全局视角来查看系统的运行状况? 74 | 5. 有什么办法可以监控到JVM的实时运行状态? 75 | 76 | `Arthas`支持JDK 6+,支持Linux/Mac/Winodws,采用命令行交互模式,同时提供丰富的 `Tab` 自动补全功能,进一步方便进行问题的定位和诊断。 77 | -------------------------------------------------------------------------------- /docs/github-trending/2019-2.md: -------------------------------------------------------------------------------- 1 | ### 1. JavaGuide 2 | 3 | - **Github地址**: [https://github.com/Snailclimb/JavaGuide](https://github.com/Snailclimb/JavaGuide) 4 | - **Star**: 27.2k (4,437 stars this month) 5 | - **介绍**: 【Java学习+面试指南】 一份涵盖大部分Java程序员所需要掌握的核心知识。 6 | 7 | ### 2.DoraemonKit 8 | 9 | - **Github地址**: 10 | - **Star**: 5.2k (3,786 stars this month) 11 | - **介绍**: 简称 "DoKit" 。一款功能齐全的客户端( iOS 、Android )研发助手,你值得拥有。 12 | 13 | ### 3.advanced-java 14 | 15 | - **Github地址**:[https://github.com/doocs/advanced-java](https://github.com/doocs/advanced-java) 16 | - **Star**:11.2k (3,042 stars this month) 17 | - **介绍**: 互联网 Java 工程师进阶知识完全扫盲。 18 | 19 | ### 4. spring-boot-examples 20 | 21 | - **Github地址**: 22 | - **star**: 9.6 k (1,764 stars this month) 23 | - **介绍**: Spring Boot 教程、技术栈示例代码,快速简单上手教程。 24 | 25 | ### 5. mall 26 | 27 | - **Github地址**: [https://github.com/macrozheng/mall](https://github.com/macrozheng/mall) 28 | - **star**: 7.4 k (1,736 stars this month) 29 | - **介绍**: mall项目是一套电商系统,包括前台商城系统及后台管理系统,基于SpringBoot+MyBatis实现。 前台商城系统包含首页门户、商品推荐、商品搜索、商品展示、购物车、订单流程、会员中心、客户服务、帮助中心等模块。 后台管理系统包含商品管理、订单管理、会员管理、促销管理、运营管理、内容管理、统计报表、财务管理、权限管理、设置等模块。 30 | 31 | ### 6. fescar 32 | 33 | - **Github地址**:[https://github.com/alibaba/fescar](https://github.com/alibaba/fescar) 34 | - **star**: 6.0 k (1,308 stars this month) 35 | - **介绍**: 具有 **高性能** 和 **易用性** 的 **微服务架构** 的 **分布式事务** 的解决方案。(特点:高性能且易于使用,旨在实现简单并快速的事务提交与回滚。) 36 | 37 | ### 7. h4cker 38 | 39 | - **Github地址**: 40 | - **star**: 2.1 k (1,303 stars this month) 41 | - **介绍**: 该仓库主要由Omar Santos维护,包括与道德黑客/渗透测试,数字取证和事件响应(DFIR),漏洞研究,漏洞利用开发,逆向工程等相关的资源。 42 | 43 | ### 8. spring-boot 44 | 45 | - **Github地址**: [https://github.com/spring-projects/spring-boot](https://github.com/spring-projects/spring-boot) 46 | - **star:** 34.8k (1,073 stars this month) 47 | - **介绍**: 虽然Spring的组件代码是轻量级的,但它的配置却是重量级的(需要大量XML配置),不过Spring Boot 让这一切成为了过去。 另外Spring Cloud也是基于Spring Boot构建的,我个人非常有必要学习一下。 48 | 49 | **关于Spring Boot官方的介绍:** 50 | 51 | > Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”…Most Spring Boot applications need very little Spring configuration.(Spring Boot可以轻松创建独立的生产级基于Spring的应用程序,只要通过 “just run”(可能是run ‘Application’或java -jar 或 tomcat 或 maven插件run 或 shell脚本)便可以运行项目。大部分Spring Boot项目只需要少量的配置即可) 52 | 53 | ### 9. arthas 54 | 55 | - **Github地址**:[https://github.com/alibaba/arthas](https://github.com/alibaba/arthas) 56 | - **star**: 10.5 k (970 stars this month) 57 | - **介绍**: Arthas 是Alibaba开源的Java诊断工具。 58 | 59 | ### 10. tutorials 60 | 61 | - **Github地址**:[https://github.com/eugenp/tutorials](https://github.com/eugenp/tutorials) 62 | - **star**: 12.1 k (789 stars this month) 63 | - **介绍**: 该项目是一系列小而专注的教程 - 每个教程都涵盖Java生态系统中单一且定义明确的开发领域。 当然,它们的重点是Spring Framework - Spring,Spring Boot和Spring Securiyt。 除了Spring之外,还有以下技术:核心Java,Jackson,HttpClient,Guava。 64 | 65 | -------------------------------------------------------------------------------- /docs/github-trending/2019-3.md: -------------------------------------------------------------------------------- 1 | ### 1. JavaGuide 2 | 3 | - **Github 地址**: [https://github.com/Snailclimb/JavaGuide](https://github.com/Snailclimb/JavaGuide) 4 | - **Star**: 32.9k (6,196 stars this month) 5 | - **介绍**: 【Java 学习+面试指南】 一份涵盖大部分 Java 程序员所需要掌握的核心知识。 6 | 7 | ### 2.advanced-java 8 | 9 | - **Github 地址**:[https://github.com/doocs/advanced-java](https://github.com/doocs/advanced-java) 10 | - **Star**: 15.1k (4,012 stars this month) 11 | - **介绍**: 互联网 Java 工程师进阶知识完全扫盲。 12 | 13 | ### 3.spring-boot-examples 14 | 15 | - **Github 地址**:[https://github.com/ityouknow/spring-boot-examples](https://github.com/ityouknow/spring-boot-examples) 16 | - **Star**: 12.8k (3,462 stars this month) 17 | - **介绍**: Spring Boot 教程、技术栈示例代码,快速简单上手教程。 18 | 19 | ### 4. mall 20 | 21 | - **Github 地址**: [https://github.com/macrozheng/mall](https://github.com/macrozheng/mall) 22 | - **star**: 9.7 k (2,418 stars this month) 23 | - **介绍**: mall 项目是一套电商系统,包括前台商城系统及后台管理系统,基于 SpringBoot+MyBatis 实现。 前台商城系统包含首页门户、商品推荐、商品搜索、商品展示、购物车、订单流程、会员中心、客户服务、帮助中心等模块。 后台管理系统包含商品管理、订单管理、会员管理、促销管理、运营管理、内容管理、统计报表、财务管理、权限管理、设置等模块。 24 | 25 | ### 5. seata 26 | 27 | - **Github 地址** : [https://github.com/seata/seata](https://github.com/seata/seata) 28 | - **star**: 7.2 k (1359 stars this month) 29 | - **介绍**: Seata 是一种易于使用,高性能,基于 Java 的开源分布式事务解决方案。 30 | 31 | ### 6. quarkus 32 | 33 | - **Github 地址**:[https://github.com/quarkusio/quarkus](https://github.com/quarkusio/quarkus) 34 | - **star**: 12 k (1,224 stars this month) 35 | - **介绍**: Quarkus 是为 GraalVM 和 HotSpot 量身定制的 Kubernetes Native Java 框架,由最佳的 Java 库和标准精心打造而成。Quarkus 的目标是使 Java 成为 Kubernetes 和无服务器环境中的领先平台,同时为开发人员提供统一的反应式和命令式编程模型,以优化地满足更广泛的分布式应用程序架构。 36 | 37 | ### 7. arthas 38 | 39 | - **Github 地址**:[https://github.com/alibaba/arthas](https://github.com/alibaba/arthas) 40 | - **star**: 11.6 k (1,199 stars this month) 41 | - **介绍**: Arthas 是 Alibaba 开源的 Java 诊断工具。 42 | 43 | ### 8.DoraemonKit 44 | 45 | - **Github 地址**: 46 | - **Star**: 6.2k (1,177 stars this month) 47 | - **介绍**: 简称 "DoKit" 。一款功能齐全的客户端( iOS 、Android )研发助手,你值得拥有。 48 | 49 | ### 9.elasticsearch 50 | 51 | - **Github 地址** [https://github.com/elastic/elasticsearch](https://github.com/elastic/elasticsearch) 52 | - **Star**: 39.7k (1,069 stars this month) 53 | - **介绍**: 开源,分布式,RESTful 搜索引擎。 54 | 55 | ### 10. tutorials 56 | 57 | - **Github 地址**:[https://github.com/eugenp/tutorials](https://github.com/eugenp/tutorials) 58 | - **star**: 13 k (998 stars this month) 59 | - **介绍**: 该项目是一系列小而专注的教程 - 每个教程都涵盖 Java 生态系统中单一且定义明确的开发领域。 当然,它们的重点是 Spring Framework - Spring,Spring Boot 和 Spring Securiyt。 除了 Spring 之外,还有以下技术:核心 Java,Jackson,HttpClient,Guava。 60 | 61 | -------------------------------------------------------------------------------- /docs/github-trending/2019-4.md: -------------------------------------------------------------------------------- 1 | 以下涉及到的数据统计与 2019 年 5 月 1 日 12 点,数据来源: 。 2 | 3 | 下面的内容从 Java 学习文档到最热门的框架再到热门的工具应有尽有,比如下面推荐到的开源项目 Hutool 就是近期比较热门的项目之一,它是 Java 工具包,能够帮助我们简化代码!我觉得下面这些项目对于学习 Java 的朋友还是很有帮助的! 4 | 5 | 6 | ### 1. JavaGuide 7 | 8 | - **Github 地址**: [https://github.com/Snailclimb/JavaGuide](https://github.com/Snailclimb/JavaGuide) 9 | - **Star**: 37.9k (5,660 stars this month) 10 | - **介绍**: 【Java 学习+面试指南】 一份涵盖大部分 Java 程序员所需要掌握的核心知识。 11 | 12 | ### 2. advanced-java 13 | 14 | - **Github 地址**:[https://github.com/doocs/advanced-java](https://github.com/doocs/advanced-java) 15 | - **Star**: 15.1k (4,654 stars this month) 16 | - **介绍**: 互联网 Java 工程师进阶知识完全扫盲。 17 | 18 | ### 3. CS-Notes 19 | 20 | - **Github 地址**: 21 | - **Star**: 59.2k (4,012 stars this month) 22 | - **介绍**: 技术面试必备基础知识。 23 | 24 | ### 4. ghidra 25 | 26 | - **Github 地址**: 27 | - **Star**: 15.0k (2,995 stars this month) 28 | - **介绍**: Ghidra是一个软件逆向工程(SRE)框架。 29 | 30 | ### 5. mall 31 | 32 | - **Github 地址**: [https://github.com/macrozheng/mall](https://github.com/macrozheng/mall) 33 | - **star**: 11.6 k (2,100 stars this month) 34 | - **介绍**: mall 项目是一套电商系统,包括前台商城系统及后台管理系统,基于 SpringBoot+MyBatis 实现。 前台商城系统包含首页门户、商品推荐、商品搜索、商品展示、购物车、订单流程、会员中心、客户服务、帮助中心等模块。 后台管理系统包含商品管理、订单管理、会员管理、促销管理、运营管理、内容管理、统计报表、财务管理、权限管理、设置等模块。 35 | 36 | ### 6. ZXBlog 37 | 38 | - **Github 地址**: 39 | - **star**: 2.1 k (2,086 stars this month) 40 | - **介绍**: 记录各种学习笔记(算法、Java、数据库、并发......)。 41 | 42 | ### 7.DoraemonKit 43 | 44 | - **Github地址**: 45 | - **Star**: 7.6k (1,541 stars this month) 46 | - **介绍**: 简称 "DoKit" 。一款功能齐全的客户端( iOS 、Android )研发助手,你值得拥有。 47 | 48 | ### 8. spring-boot 49 | 50 | - **Github地址**: [https://github.com/spring-projects/spring-boot](https://github.com/spring-projects/spring-boot) 51 | - **star:** 37.3k (1,489 stars this month) 52 | - **介绍**: 虽然Spring的组件代码是轻量级的,但它的配置却是重量级的(需要大量XML配置),不过Spring Boot 让这一切成为了过去。 另外Spring Cloud也是基于Spring Boot构建的,我个人非常有必要学习一下。 53 | 54 | **Spring Boot官方的介绍:** 55 | 56 | > Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”…Most Spring Boot applications need very little Spring configuration.(Spring Boot可以轻松创建独立的生产级基于Spring的应用程序,只要通过 “just run”(可能是run ‘Application’或java -jar 或 tomcat 或 maven插件run 或 shell脚本)便可以运行项目。大部分Spring Boot项目只需要少量的配置即可) 57 | 58 | ### 9. spring-boot-examples 59 | 60 | - **Github 地址**:[https://github.com/ityouknow/spring-boot-examples](https://github.com/ityouknow/spring-boot-examples) 61 | - **Star**: 12.8k (1,453 stars this month) 62 | - **介绍**: Spring Boot 教程、技术栈示例代码,快速简单上手教程。 63 | 64 | ### 10. seata 65 | 66 | - **Github 地址** : [https://github.com/seata/seata](https://github.com/seata/seata) 67 | - **star**: 8.4 k (1441 stars this month) 68 | - **介绍**: Seata 是一种易于使用,高性能,基于 Java 的开源分布式事务解决方案。 69 | 70 | ### 11. litemall 71 | 72 | - **Github 地址**:[https://github.com/ityouknow/spring-boot-examples](https://github.com/ityouknow/spring-boot-examples) 73 | - **Star**: 6.0k (1,427 stars this month) 74 | - **介绍**: 又一个小商城。litemall = Spring Boot后端 + Vue管理员前端 + 微信小程序用户前端 + Vue用户移动端。 75 | 76 | ### 12. skywalking 77 | 78 | - **Github 地址**: 79 | - **Star**: 8.0k (1,381 stars this month) 80 | - **介绍**: 针对分布式系统的应用性能监控,尤其是针对微服务、云原生和面向容器的分布式系统架构。 81 | 82 | ### 13. elasticsearch 83 | 84 | - **Github 地址** [https://github.com/elastic/elasticsearch](https://github.com/elastic/elasticsearch) 85 | - **Star**: 4.0k (1,068stars this month) 86 | - **介绍**: 开源,分布式,RESTful 搜索引擎。 87 | 88 | ### 14. arthas 89 | 90 | - **Github地址**:[https://github.com/alibaba/arthas](https://github.com/alibaba/arthas) 91 | - **star**: 12.6 k (1,080 stars this month) 92 | - **介绍**: Arthas 是Alibaba开源的Java诊断工具。 93 | 94 | ### 15. hutool 95 | 96 | - **Github地址**: 97 | - **star**: 4.5 k (1,031 stars this month) 98 | - **介绍**: Hutool是一个Java工具包,也只是一个工具包,它帮助我们简化每一行代码,减少每一个方法,让Java语言也可以“甜甜的”。Hutool最初是我项目中“util”包的一个整理,后来慢慢积累并加入更多非业务相关功能,并广泛学习其它开源项目精髓,经过自己整理修改,最终形成丰富的开源工具集。官网: 。 -------------------------------------------------------------------------------- /docs/github-trending/2019-5.md: -------------------------------------------------------------------------------- 1 | 以下涉及到的数据统计与 2019 年 6 月 1 日 18 点,数据来源: 。下面推荐的内容从 Java 学习文档到最热门的框架再到热门的工具应有尽有,建议收藏+在看! 2 | 3 | ### 1.LeetCodeAnimation 4 | 5 | - **Github 地址**: 6 | - **Star**: 29.0k (11,492 stars this month) 7 | - **介绍**: Demonstrate all the questions on LeetCode in the form of animation.(用动画的形式呈现解LeetCode题目的思路)。 8 | 9 | ### 2.CS-Notes 10 | 11 | - **Github 地址**: 12 | - **Star**: 64.4k (5513 stars this month) 13 | - **介绍**: 技术面试必备基础知识、Leetcode 题解、后端面试、Java 面试、春招、秋招、操作系统、计算机网络、系统设计。 14 | 15 | ### 3.JavaGuide 16 | 17 | - **Github 地址**: 18 | - **Star**: 42.0k (4,442 stars this month) 19 | - **介绍**: 【Java 学习+面试指南】 一份涵盖大部分 Java 程序员所需要掌握的核心知识。 20 | 21 | ### 4.mall 22 | 23 | - **Github 地址**: [https://github.com/macrozheng/mall](https://github.com/macrozheng/mall) 24 | - **star**: 14.6 k (3,086 stars this month) 25 | - **介绍**: mall 项目是一套电商系统,包括前台商城系统及后台管理系统,基于 SpringBoot+MyBatis 实现。 前台商城系统包含首页门户、商品推荐、商品搜索、商品展示、购物车、订单流程、会员中心、客户服务、帮助中心等模块。 后台管理系统包含商品管理、订单管理、会员管理、促销管理、运营管理、内容管理、统计报表、财务管理、权限管理、设置等模块。 26 | 27 | ### 5.advanced-java 28 | 29 | - **Github 地址**:[https://github.com/doocs/advanced-java](https://github.com/doocs/advanced-java) 30 | - **Star**: 20.8k (2,394 stars this month) 31 | - **介绍**: 互联网 Java 工程师进阶知识完全扫盲。 32 | 33 | ### 6.spring-boot 34 | 35 | - **Github地址**: [https://github.com/spring-projects/spring-boot](https://github.com/spring-projects/spring-boot) 36 | - **star:** 38.5k (1,339 stars this month) 37 | - **介绍**: 虽然Spring的组件代码是轻量级的,但它的配置却是重量级的(需要大量XML配置),不过Spring Boot 让这一切成为了过去。 另外Spring Cloud也是基于Spring Boot构建的,我个人非常有必要学习一下。 38 | 39 | **Spring Boot官方的介绍:** 40 | 41 | > Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”…Most Spring Boot applications need very little Spring configuration.(Spring Boot可以轻松创建独立的生产级基于Spring的应用程序,只要通过 “just run”(可能是run ‘Application’或java -jar 或 tomcat 或 maven插件run 或 shell脚本)便可以运行项目。大部分Spring Boot项目只需要少量的配置即可) 42 | 43 | ### 7. Java 44 | 45 | - **Github 地址**: 46 | - **Star**:14.3k (1,334 stars this month) 47 | - **介绍**: All Algorithms implemented in Java。 48 | 49 | ### 8.server 50 | 51 | - **Github 地址**: 52 | - **star**: 2.2 k (1,275 stars this month) 53 | - **介绍**: 全开源即时通讯(IM)系统。 54 | 55 | ### 9.litemall 56 | 57 | - **Github 地址**: 58 | - **Star**: 7.1k (1,114 stars this month) 59 | - **介绍**: 又一个小商城。litemall = Spring Boot后端 + Vue管理员前端 + 微信小程序用户前端 + Vue用户移动端。 60 | 61 | ### 10.Linkage-RecyclerView 62 | 63 | - **Github 地址**: 64 | - **Star**: 10.0k (1,093 stars this month) 65 | - **介绍**: 即使不用饿了么订餐,也请务必收藏好该库!🔥 一行代码即可接入,二级联动订餐列表 - Even if you don't order food by PrubHub, be sure to collect this library, please! 🔥 This secondary linkage list widget can be accessed by only one line of code. Supporting by RecyclerView & AndroidX. 66 | 67 | ### 11.toBeTopJavaer 68 | 69 | - **Github 地址** : 70 | - **Star**: 3.3k (1,007 stars this month) 71 | - **介绍**: To Be Top Javaer - Java工程师成神之路 72 | 73 | ### 12.elasticsearch 74 | 75 | - **Github 地址** : [https://github.com/elastic/elasticsearch](https://github.com/elastic/elasticsearch) 76 | - **Star**: 48.0k (968 stars this month) 77 | - **介绍**: 开源,分布式,RESTful 搜索引擎。 78 | 79 | ### 13.java-design-patterns 80 | 81 | - **Github 地址** : 82 | - **Star**: 41.5k (955 stars this month) 83 | - **介绍**: Design patterns implemented in Java。 84 | 85 | ### 14.apollo 86 | 87 | - **Github 地址** : 88 | - **Star**: 14.5k (927 stars this month) 89 | - **介绍**: Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。 90 | 91 | ### 15.arthas 92 | 93 | - **Github地址**:[https://github.com/alibaba/arthas](https://github.com/alibaba/arthas) 94 | - **star**: 13.5 k (933 stars this month) 95 | - **介绍**: Arthas 是Alibaba开源的Java诊断工具。 96 | 97 | ### 16.dubbo 98 | 99 | - **Github地址**: 100 | - **star**: 26.9 k (769 stars this month) 101 | - **介绍**: Apache Dubbo是一个基于Java的高性能开源RPC框架。 102 | 103 | ### 17.DoraemonKit 104 | 105 | - **Github地址**: 106 | - **Star**: 8.5k (909 stars this month) 107 | - **介绍**: 简称 "DoKit" 。一款功能齐全的客户端( iOS 、Android )研发助手,你值得拥有。 108 | 109 | ### 18.halo 110 | 111 | - **Github地址**: 112 | - **Star**: 4.1k (829 stars this month) 113 | - **介绍**: Halo 可能是最好的 Java 博客系统。 114 | 115 | ### 19.seata 116 | 117 | - **Github 地址** : [https://github.com/seata/seata](https://github.com/seata/seata) 118 | - **star**: 9.2 k (776 stars this month) 119 | - **介绍**: Seata 是一种易于使用,高性能,基于 Java 的开源分布式事务解决方案。 120 | 121 | ### 20.hutool 122 | 123 | - **Github地址**: 124 | - **star**: 5,3 k (812 stars this month) 125 | - **介绍**: Hutool是一个Java工具包,也只是一个工具包,它帮助我们简化每一行代码,减少每一个方法,让Java语言也可以“甜甜的”。Hutool最初是我项目中“util”包的一个整理,后来慢慢积累并加入更多非业务相关功能,并广泛学习其它开源项目精髓,经过自己整理修改,最终形成丰富的开源工具集。官网: 。 -------------------------------------------------------------------------------- /docs/github-trending/2019-6.md: -------------------------------------------------------------------------------- 1 | ### 1.CS-Notes 2 | 3 | - **Github 地址**:https://github.com/CyC2018/CS-Notes 4 | - **Star**: 69.8k 5 | - **介绍**: 技术面试必备基础知识、Leetcode 题解、后端面试、Java 面试、春招、秋招、操作系统、计算机网络、系统设计。 6 | 7 | ### 2.toBeTopJavaer 8 | 9 | - **Github 地址:**[https://github.com/hollischuang/toBeTopJavaer](https://github.com/hollischuang/toBeTopJavaer) 10 | - **Star**: 4.7k 11 | - **介绍**: To Be Top Javaer - Java工程师成神之路。 12 | 13 | ### 3.p3c 14 | 15 | - **Github 地址:** [https://github.com/alibaba/p3c](https://github.com/alibaba/p3c) 16 | - **Star**: 16.6k 17 | - **介绍**: Alibaba Java Coding Guidelines pmd implements and IDE plugin。Eclipse 和 IDEA 上都有该插件,推荐使用! 18 | 19 | ### 4.SpringCloudLearning 20 | 21 | - **Github 地址:** [https://github.com/forezp/SpringCloudLearning](https://github.com/forezp/SpringCloudLearning) 22 | - **Star**: 8.7k 23 | - **介绍**: 史上最简单的Spring Cloud教程源码。 24 | 25 | ### 5.dubbo 26 | 27 | - **Github地址**: 28 | - **star**: 27.6 k 29 | - **介绍**: Apache Dubbo是一个基于Java的高性能开源RPC框架。 30 | 31 | ### 6.jeecg-boot 32 | 33 | - **Github地址**: [https://github.com/zhangdaiscott/jeecg-boot](https://github.com/zhangdaiscott/jeecg-boot) 34 | - **star**: 3.3 k 35 | - **介绍**: 一款基于代码生成器的JAVA快速开发平台!全新架构前后端分离:SpringBoot 2.x,Ant Design&Vue,Mybatis,Shiro,JWT。强大的代码生成器让前后端代码一键生成,无需写任何代码,绝对是全栈开发福音!! JeecgBoot的宗旨是提高UI能力的同时,降低前后分离的开发成本,JeecgBoot还独创在线开发模式,No代码概念,一系列在线智能开发:在线配置表单、在线配置报表、在线设计流程等等。 36 | 37 | ### 7.advanced-java 38 | 39 | - **Github 地址**:[https://github.com/doocs/advanced-java](https://github.com/doocs/advanced-java) 40 | - **Star**: 24.2k 41 | - **介绍**: 互联网 Java 工程师进阶知识完全扫盲:涵盖高并发、分布式、高可用、微服务等领域知识,后端同学必看,前端同学也可学习。 42 | 43 | ### 8.FEBS-Shiro 44 | 45 | - **Github 地址**:[https://github.com/wuyouzhuguli/FEBS-Shiro](https://github.com/wuyouzhuguli/FEBS-Shiro) 46 | - **Star**: 2.6k 47 | - **介绍**: Spring Boot 2.1.3,Shiro1.4.0 & Layui 2.5.4 权限管理系统。预览地址:http://49.234.20.223:8080/login。 48 | 49 | ### 9.SpringAll 50 | 51 | - **Github 地址**: [https://github.com/wuyouzhuguli/SpringAll](https://github.com/wuyouzhuguli/SpringAll) 52 | - **Star**: 5.4k 53 | - **介绍**: 循序渐进,学习Spring Boot、Spring Boot & Shiro、Spring Cloud、Spring Security & Spring Security OAuth2,博客Spring系列源码。 54 | 55 | ### 10.JavaGuide 56 | 57 | - **Github 地址**: 58 | - **Star**: 47.2k 59 | - **介绍**: 【Java 学习+面试指南】 一份涵盖大部分 Java 程序员所需要掌握的核心知识。 60 | 61 | ### 11.vhr 62 | 63 | - **Github 地址**:[https://github.com/lenve/vhr](https://github.com/lenve/vhr) 64 | - **Star**: 4.9k 65 | - **介绍**: 微人事是一个前后端分离的人力资源管理系统,项目采用SpringBoot+Vue开发。 66 | 67 | ### 12. tutorials 68 | 69 | - **Github 地址**:[https://github.com/eugenp/tutorials](https://github.com/eugenp/tutorials) 70 | - **star**: 15.4 k 71 | - **介绍**: 该项目是一系列小而专注的教程 - 每个教程都涵盖 Java 生态系统中单一且定义明确的开发领域。 当然,它们的重点是 Spring Framework - Spring,Spring Boot 和 Spring Securiyt。 除了 Spring 之外,还有以下技术:核心 Java,Jackson,HttpClient,Guava。 72 | 73 | ### 13.EasyScheduler 74 | 75 | - **Github 地址**:[https://github.com/analysys/EasyScheduler](https://github.com/analysys/EasyScheduler) 76 | - **star**: 1.1 k 77 | - **介绍**: Easy Scheduler是一个分布式工作流任务调度系统,主要解决“复杂任务依赖但无法直接监控任务健康状态”的问题。Easy Scheduler以DAG方式组装任务,可以实时监控任务的运行状态。同时,它支持重试,重新运行等操作... 。https://analysys.github.io/easyscheduler_docs_cn/ 78 | 79 | ### 14.thingsboard 80 | 81 | - **Github 地址**:[https://github.com/thingsboard/thingsboard](https://github.com/thingsboard/thingsboard) 82 | - **star**: 3.7 k 83 | - **介绍**: 开源物联网平台 - 设备管理,数据收集,处理和可视化。 [https://thingsboard.io](https://thingsboard.io/) 84 | 85 | ### 15.mall-learning 86 | 87 | - **Github 地址**: [https://github.com/macrozheng/mall-learning](https://github.com/macrozheng/mall-learning) 88 | - **star**: 0.6 k 89 | - **介绍**: mall学习教程,架构、业务、技术要点全方位解析。mall项目(16k+star)是一套电商系统,使用现阶段主流技术实现。 涵盖了SpringBoot2.1.3、MyBatis3.4.6、Elasticsearch6.2.2、RabbitMQ3.7.15、Redis3.2、Mongodb3.2、Mysql5.7等技术,采用Docker容器化部署。 https://github.com/macrozheng/mall 90 | 91 | ### 16. flink 92 | 93 | - **Github地址**:[https://github.com/apache/flink](https://github.com/apache/flink) 94 | - **star**: 9.3 k 95 | - **介绍**: Apache Flink是一个开源流处理框架,具有强大的流和批处理功能。 96 | 97 | ### 17.spring-cloud-kubernetes 98 | 99 | - **Github地址**:[https://github.com/spring-cloud/spring-cloud-kubernetes](https://github.com/spring-cloud/spring-cloud-kubernetes) 100 | - **star**: 1.4 k 101 | - **介绍**: Kubernetes 集成 Spring Cloud Discovery Client, Configuration, etc... 102 | 103 | ### 18.springboot-learning-example 104 | 105 | - **Github地址**:[https://github.com/JeffLi1993/springboot-learning-example](https://github.com/JeffLi1993/springboot-learning-example) 106 | - **star**: 10.0 k 107 | - **介绍**: spring boot 实践学习案例,是 spring boot 初学者及核心技术巩固的最佳实践。 108 | 109 | ### 19.canal 110 | 111 | - **Github地址**:[https://github.com/alibaba/canal](https://github.com/alibaba/canal) 112 | - **star**: 9.3 k 113 | - **介绍**: 阿里巴巴 MySQL binlog 增量订阅&消费组件。 114 | 115 | ### 20.react-native-device-info 116 | 117 | - **Github地址**:[https://github.com/react-native-community/react-native-device-info](https://github.com/react-native-community/react-native-device-info) 118 | - **star**: 4.0 k 119 | - **介绍**: React Native iOS和Android的设备信息。 -------------------------------------------------------------------------------- /docs/github-trending/JavaGithubTrending.md: -------------------------------------------------------------------------------- 1 | - [2018 年 12 月](https://github.com/Snailclimb/JavaGuide/blob/master/docs/github-trending/2018-12.md) 2 | - [2019 年 1 月](https://github.com/Snailclimb/JavaGuide/blob/master/docs/github-trending/2019-1.md) 3 | - [2019 年 2 月](https://github.com/Snailclimb/JavaGuide/blob/master/docs/github-trending/2019-2.md) 4 | - [2019 年 3 月](https://github.com/Snailclimb/JavaGuide/blob/master/docs/github-trending/2019-3.md) 5 | - [2019 年 4 月](https://github.com/Snailclimb/JavaGuide/blob/master/docs/github-trending/2019-4.md) 6 | - [2019 年 5 月](https://github.com/Snailclimb/JavaGuide/blob/master/docs/github-trending/2019-5.md) 7 | - [2019 年 6 月](https://github.com/Snailclimb/JavaGuide/blob/master/docs/github-trending/2019-6.md) 8 | 9 | -------------------------------------------------------------------------------- /docs/java/Java程序设计题.md: -------------------------------------------------------------------------------- 1 | ## 泛型的实际应用 2 | 3 | ### 实现最小值函数 4 | 5 | 自己设计一个泛型的获取数组最小值的函数.并且这个方法只能接受Number的子类并且实现了Comparable接口。 6 | 7 | ```java 8 | //注意:Number并没有实现Comparable 9 | private static > T min(T[] values) { 10 | if (values == null || values.length == 0) return null; 11 | T min = values[0]; 12 | for (int i = 1; i < values.length; i++) { 13 | if (min.compareTo(values[i]) > 0) min = values[i]; 14 | } 15 | return min; 16 | } 17 | ``` 18 | 19 | 测试: 20 | 21 | ```java 22 | int minInteger = min(new Integer[]{1, 2, 3});//result:1 23 | double minDouble = min(new Double[]{1.2, 2.2, -1d});//result:-1d 24 | String typeError = min(new String[]{"1","3"});//报错 25 | ``` 26 | 27 | ## 数据结构 28 | 29 | ### 使用数组实现栈 30 | 31 | **自己实现一个栈,要求这个栈具有`push()`、`pop()`(返回栈顶元素并出栈)、`peek()` (返回栈顶元素不出栈)、`isEmpty()`、`size()`这些基本的方法。** 32 | 33 | 提示:每次入栈之前先判断栈的容量是否够用,如果不够用就用`Arrays.copyOf()`进行扩容; 34 | 35 | ```java 36 | public class MyStack { 37 | private int[] storage;//存放栈中元素的数组 38 | private int capacity;//栈的容量 39 | private int count;//栈中元素数量 40 | private static final int GROW_FACTOR = 2; 41 | 42 | //TODO:不带初始容量的构造方法。默认容量为8 43 | public MyStack() { 44 | this.capacity = 8; 45 | this.storage=new int[8]; 46 | this.count = 0; 47 | } 48 | 49 | //TODO:带初始容量的构造方法 50 | public MyStack(int initialCapacity) { 51 | if (initialCapacity < 1) 52 | throw new IllegalArgumentException("Capacity too small."); 53 | 54 | this.capacity = initialCapacity; 55 | this.storage = new int[initialCapacity]; 56 | this.count = 0; 57 | } 58 | 59 | //TODO:入栈 60 | public void push(int value) { 61 | if (count == capacity) { 62 | ensureCapacity(); 63 | } 64 | storage[count++] = value; 65 | } 66 | 67 | //TODO:确保容量大小 68 | private void ensureCapacity() { 69 | int newCapacity = capacity * GROW_FACTOR; 70 | storage = Arrays.copyOf(storage, newCapacity); 71 | capacity = newCapacity; 72 | } 73 | 74 | //TODO:返回栈顶元素并出栈 75 | private int pop() { 76 | count--; 77 | if (count == -1) 78 | throw new IllegalArgumentException("Stack is empty."); 79 | 80 | return storage[count]; 81 | } 82 | 83 | //TODO:返回栈顶元素不出栈 84 | private int peek() { 85 | if (count == 0){ 86 | throw new IllegalArgumentException("Stack is empty."); 87 | }else { 88 | return storage[count-1]; 89 | } 90 | } 91 | 92 | //TODO:判断栈是否为空 93 | private boolean isEmpty() { 94 | return count == 0; 95 | } 96 | 97 | //TODO:返回栈中元素的个数 98 | private int size() { 99 | return count; 100 | } 101 | 102 | } 103 | 104 | ``` 105 | 106 | 验证 107 | 108 | ```java 109 | MyStack myStack = new MyStack(3); 110 | myStack.push(1); 111 | myStack.push(2); 112 | myStack.push(3); 113 | myStack.push(4); 114 | myStack.push(5); 115 | myStack.push(6); 116 | myStack.push(7); 117 | myStack.push(8); 118 | System.out.println(myStack.peek());//8 119 | System.out.println(myStack.size());//8 120 | for (int i = 0; i < 8; i++) { 121 | System.out.println(myStack.pop()); 122 | } 123 | System.out.println(myStack.isEmpty());//true 124 | myStack.pop();//报错:java.lang.IllegalArgumentException: Stack is empty. 125 | ``` -------------------------------------------------------------------------------- /docs/java/Java编程规范.md: -------------------------------------------------------------------------------- 1 | 讲真的,下面推荐的文章或者资源建议阅读 3 遍以上。 2 | 3 | ### 团队 4 | 5 | - **阿里巴巴Java开发手册(详尽版)** 6 | - **Google Java编程风格指南:** 7 | 8 | ### 个人 9 | 10 | - **程序员你为什么这么累:** 11 | 12 | ### 如何写出优雅的 Java 代码 13 | 14 | 1. 使用 IntelliJ IDEA 作为您的集成开发环境 (IDE) 15 | 1. 使用 JDK 8 或更高版本 16 | 1. 使用 Maven/Gradle 17 | 1. 使用 Lombok 18 | 1. 编写单元测试 19 | 1. 重构:常见,但也很慢 20 | 1. 注意代码规范 21 | 1. 定期联络客户,以获取他们的反馈 22 | 23 | 上述建议的详细内容:[八点建议助您写出优雅的Java代码](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485140&idx=1&sn=ecaeace613474f1859aaeed0282ae680&chksm=cea2491ff9d5c00982ffaece847ce1aead89fdb3fe190752d9837c075c79fc95db5940992c56&token=1328169465&lang=zh_CN&scene=21#wechat_redirect)。 24 | 25 | 更多代码优化相关内容推荐: 26 | 27 | - [业务复杂=if else?刚来的大神竟然用策略+工厂彻底干掉了他们!](https://juejin.im/post/5dad23685188251d2c4ea2b6) 28 | - [一些不错的 Java 实践!推荐阅读3遍以上!](http://lrwinx.github.io/2017/03/04/%E7%BB%86%E6%80%9D%E6%9E%81%E6%81%90-%E4%BD%A0%E7%9C%9F%E7%9A%84%E4%BC%9A%E5%86%99java%E5%90%97/) 29 | - [[解锁新姿势] 兄dei,你代码需要优化了](https://juejin.im/post/5dafbc02e51d4524a0060bdd) 30 | - [消灭 Java 代码的“坏味道”](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485599&idx=1&sn=d83ff4e6b1ee951a0a33508a10980ea3&chksm=cea24754f9d5ce426d18b435a8c373ddc580c06c7d6a45cc51377361729c31c7301f1bbc3b78&token=1328169465&lang=zh_CN#rd) -------------------------------------------------------------------------------- /docs/java/Multithread/ThredLocal.md: -------------------------------------------------------------------------------- 1 | [ThreadLocal造成OOM内存溢出案例演示与原理分析](https://blog.csdn.net/xlgen157387/article/details/78298840) 2 | 3 | [深入理解 Java 之 ThreadLocal 工作原理]() 4 | 5 | ## ThreadLocal 6 | 7 | ### ThreadLocal简介 8 | 9 | 通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。**如果想实现每一个线程都有自己的专属本地变量该如何解决呢?** JDK中提供的`ThreadLocal`类正是为了解决这样的问题。 **`ThreadLocal`类主要解决的就是让每个线程绑定自己的值,可以将`ThreadLocal`类形象的比喻成存放数据的盒子,盒子中可以存储每个线程的私有数据。** 10 | 11 | **如果你创建了一个`ThreadLocal`变量,那么访问这个变量的每个线程都会有这个变量的本地副本,这也是`ThreadLocal`变量名的由来。他们可以使用 `get()` 和 `set()` 方法来获取默认值或将其值更改为当前线程所存的副本的值,从而避免了线程安全问题。** 12 | 13 | 再举个简单的例子: 14 | 15 | 比如有两个人去宝屋收集宝物,这两个共用一个袋子的话肯定会产生争执,但是给他们两个人每个人分配一个袋子的话就不会出现这样的问题。如果把这两个人比作线程的话,那么ThreadLocal就是用来这两个线程竞争的。 16 | 17 | ### ThreadLocal示例 18 | 19 | 相信看了上面的解释,大家已经搞懂 ThreadLocal 类是个什么东西了。 20 | 21 | ```java 22 | import java.text.SimpleDateFormat; 23 | import java.util.Random; 24 | 25 | public class ThreadLocalExample implements Runnable{ 26 | 27 | // SimpleDateFormat 不是线程安全的,所以每个线程都要有自己独立的副本 28 | private static final ThreadLocal formatter = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMdd HHmm")); 29 | 30 | public static void main(String[] args) throws InterruptedException { 31 | ThreadLocalExample obj = new ThreadLocalExample(); 32 | for(int i=0 ; i<10; i++){ 33 | Thread t = new Thread(obj, ""+i); 34 | Thread.sleep(new Random().nextInt(1000)); 35 | t.start(); 36 | } 37 | } 38 | 39 | @Override 40 | public void run() { 41 | System.out.println("Thread Name= "+Thread.currentThread().getName()+" default Formatter = "+formatter.get().toPattern()); 42 | try { 43 | Thread.sleep(new Random().nextInt(1000)); 44 | } catch (InterruptedException e) { 45 | e.printStackTrace(); 46 | } 47 | //formatter pattern is changed here by thread, but it won't reflect to other threads 48 | formatter.set(new SimpleDateFormat()); 49 | 50 | System.out.println("Thread Name= "+Thread.currentThread().getName()+" formatter = "+formatter.get().toPattern()); 51 | } 52 | 53 | } 54 | 55 | ``` 56 | 57 | Output: 58 | 59 | ``` 60 | Thread Name= 0 default Formatter = yyyyMMdd HHmm 61 | Thread Name= 0 formatter = yy-M-d ah:mm 62 | Thread Name= 1 default Formatter = yyyyMMdd HHmm 63 | Thread Name= 2 default Formatter = yyyyMMdd HHmm 64 | Thread Name= 1 formatter = yy-M-d ah:mm 65 | Thread Name= 3 default Formatter = yyyyMMdd HHmm 66 | Thread Name= 2 formatter = yy-M-d ah:mm 67 | Thread Name= 4 default Formatter = yyyyMMdd HHmm 68 | Thread Name= 3 formatter = yy-M-d ah:mm 69 | Thread Name= 4 formatter = yy-M-d ah:mm 70 | Thread Name= 5 default Formatter = yyyyMMdd HHmm 71 | Thread Name= 5 formatter = yy-M-d ah:mm 72 | Thread Name= 6 default Formatter = yyyyMMdd HHmm 73 | Thread Name= 6 formatter = yy-M-d ah:mm 74 | Thread Name= 7 default Formatter = yyyyMMdd HHmm 75 | Thread Name= 7 formatter = yy-M-d ah:mm 76 | Thread Name= 8 default Formatter = yyyyMMdd HHmm 77 | Thread Name= 9 default Formatter = yyyyMMdd HHmm 78 | Thread Name= 8 formatter = yy-M-d ah:mm 79 | Thread Name= 9 formatter = yy-M-d ah:mm 80 | ``` 81 | 82 | 从输出中可以看出,Thread-0已经改变了formatter的值,但仍然是thread-2默认格式化程序与初始化值相同,其他线程也一样。 83 | 84 | 上面有一段代码用到了创建 `ThreadLocal` 变量的那段代码用到了 Java8 的知识,它等于下面这段代码,如果你写了下面这段代码的话,IDEA会提示你转换为Java8的格式(IDEA真的不错!)。因为ThreadLocal类在Java 8中扩展,使用一个新的方法`withInitial()`,将Supplier功能接口作为参数。 85 | 86 | ```java 87 | private static final ThreadLocal formatter = new ThreadLocal(){ 88 | @Override 89 | protected SimpleDateFormat initialValue() 90 | { 91 | return new SimpleDateFormat("yyyyMMdd HHmm"); 92 | } 93 | }; 94 | ``` 95 | 96 | ### ThreadLocal原理 97 | 98 | 从 `Thread`类源代码入手。 99 | 100 | ```java 101 | public class Thread implements Runnable { 102 | ...... 103 | //与此线程有关的ThreadLocal值。由ThreadLocal类维护 104 | ThreadLocal.ThreadLocalMap threadLocals = null; 105 | 106 | //与此线程有关的InheritableThreadLocal值。由InheritableThreadLocal类维护 107 | ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; 108 | ...... 109 | } 110 | ``` 111 | 112 | 从上面`Thread`类 源代码可以看出`Thread` 类中有一个 `threadLocals` 和 一个 `inheritableThreadLocals` 变量,它们都是 `ThreadLocalMap` 类型的变量,我们可以把 `ThreadLocalMap` 理解为`ThreadLocal` 类实现的定制化的 `HashMap`。默认情况下这两个变量都是null,只有当前线程调用 `ThreadLocal` 类的 `set`或`get`方法时才创建它们,实际上调用这两个方法的时候,我们调用的是`ThreadLocalMap`类对应的 `get()`、`set() `方法。 113 | 114 | `ThreadLocal`类的`set()`方法 115 | 116 | ```java 117 | public void set(T value) { 118 | Thread t = Thread.currentThread(); 119 | ThreadLocalMap map = getMap(t); 120 | if (map != null) 121 | map.set(this, value); 122 | else 123 | createMap(t, value); 124 | } 125 | ThreadLocalMap getMap(Thread t) { 126 | return t.threadLocals; 127 | } 128 | ``` 129 | 130 | 通过上面这些内容,我们足以通过猜测得出结论:**最终的变量是放在了当前线程的 `ThreadLocalMap` 中,并不是存在 `ThreadLocal` 上,ThreadLocal 可以理解为只是ThreadLocalMap的封装,传递了变量值。** 131 | 132 | **每个Thread中都具备一个ThreadLocalMap,而ThreadLocalMap可以存储以ThreadLocal为key的键值对。** 比如我们在同一个线程中声明了两个 `ThreadLocal` 对象的话,会使用 `Thread`内部都是使用仅有那个`ThreadLocalMap` 存放数据的,`ThreadLocalMap`的 key 就是 `ThreadLocal`对象,value 就是 `ThreadLocal` 对象调用`set`方法设置的值。`ThreadLocal` 是 map结构是为了让每个线程可以关联多个 `ThreadLocal`变量。这也就解释了ThreadLocal声明的变量为什么在每一个线程都有自己的专属本地变量。 133 | 134 | ```java 135 | public class Thread implements Runnable { 136 | ...... 137 | //与此线程有关的ThreadLocal值。由ThreadLocal类维护 138 | ThreadLocal.ThreadLocalMap threadLocals = null; 139 | 140 | //与此线程有关的InheritableThreadLocal值。由InheritableThreadLocal类维护 141 | ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; 142 | ...... 143 | } 144 | ``` 145 | 146 | `ThreadLocalMap`是`ThreadLocal`的静态内部类。 147 | 148 | ![ThreadLocal内部类](https://ws1.sinaimg.cn/large/006rNwoDgy1g2f47u9li2j30ka08cq43.jpg) 149 | 150 | ### ThreadLocal 内存泄露问题 151 | 152 | `ThreadLocalMap` 中使用的 key 为 `ThreadLocal` 的弱引用,而 value 是强引用。所以,如果 `ThreadLocal` 没有被外部强引用的情况下,在垃圾回收的时候会 key 会被清理掉,而 value 不会被清理掉。这样一来,`ThreadLocalMap` 中就会出现key为null的Entry。假如我们不做任何措施的话,value 永远无法被GC 回收,这个时候就可能会产生内存泄露。ThreadLocalMap实现中已经考虑了这种情况,在调用 `set()`、`get()`、`remove()` 方法的时候,会清理掉 key 为 null 的记录。使用完 `ThreadLocal`方法后 最好手动调用`remove()`方法 153 | 154 | ```java 155 | static class Entry extends WeakReference> { 156 | /** The value associated with this ThreadLocal. */ 157 | Object value; 158 | 159 | Entry(ThreadLocal k, Object v) { 160 | super(k); 161 | value = v; 162 | } 163 | } 164 | ``` 165 | 166 | **弱引用介绍:** 167 | 168 | > 如果一个对象只具有弱引用,那就类似于**可有可无的生活用品**。弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它 所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程, 因此不一定会很快发现那些只具有弱引用的对象。 169 | > 170 | > 弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。 -------------------------------------------------------------------------------- /docs/java/What's New in JDK8/Java8foreach指南.md: -------------------------------------------------------------------------------- 1 | > 本文由 JavaGuide 翻译,原文地址:https://www.baeldung.com/foreach-java 2 | 3 | ## 1 概述 4 | 5 | 在Java 8中引入的*forEach*循环为程序员提供了一种新的,简洁而有趣的迭代集合的方式。 6 | 7 | 在本文中,我们将看到如何将*forEach*与集合*一起*使用,它采用何种参数以及此循环与增强的*for*循环的不同之处。 8 | 9 | ## 2 基础知识 10 | 11 | ```Java 12 | public interface Collection extends Iterable 13 | ``` 14 | 15 | Collection 接口实现了 Iterable 接口,而 Iterable 接口在 Java 8开始具有一个新的 API: 16 | 17 | ```java 18 | void forEach(Consumer action)//对 Iterable的每个元素执行给定的操作,直到所有元素都被处理或动作引发异常。 19 | ``` 20 | 21 | 使用*forEach*,我们可以迭代一个集合并对每个元素执行给定的操作,就像任何其他*迭代器一样。* 22 | 23 | 例如,迭代和打印字符串集合*的*for循环版本: 24 | 25 | ```java 26 | for (String name : names) { 27 | System.out.println(name); 28 | } 29 | ``` 30 | 31 | 我们可以使用*forEach*写这个 : 32 | 33 | ```java 34 | names.forEach(name -> { 35 | System.out.println(name); 36 | }); 37 | ``` 38 | 39 | ## 3.使用forEach方法 40 | 41 | ### 3.1 匿名类 42 | 43 | 我们使用 *forEach*迭代集合并对每个元素执行特定操作。**要执行的操作包含在实现Consumer接口的类中,并作为参数传递给forEach 。** 44 | 45 | 所述*消费者*接口是一个功能接口(具有单个抽象方法的接口)。它接受输入并且不返回任何结果。 46 | 47 | Consumer 接口定义如下: 48 | 49 | ```java 50 | @FunctionalInterface 51 | public interface Consumer { 52 | void accept(T t); 53 | } 54 | ``` 55 | 任何实现,例如,只是打印字符串的消费者: 56 | 57 | ```java 58 | Consumer printConsumer = new Consumer() { 59 | public void accept(String name) { 60 | System.out.println(name); 61 | }; 62 | }; 63 | ``` 64 | 65 | 可以作为参数传递给*forEach*: 66 | 67 | ```java 68 | names.forEach(printConsumer); 69 | ``` 70 | 71 | 但这不是通过消费者和使用*forEach* API 创建操作的唯一方法。让我们看看我们将使用*forEach*方法的另外2种最流行的方式: 72 | 73 | ### 3.2 Lambda表达式 74 | 75 | Java 8功能接口的主要优点是我们可以使用Lambda表达式来实例化它们,并避免使用庞大的匿名类实现。 76 | 77 | 由于 Consumer 接口属于函数式接口,我们可以通过以下形式在Lambda中表达它: 78 | 79 | ```java 80 | (argument) -> { body } 81 | name -> System.out.println(name) 82 | names.forEach(name -> System.out.println(name)); 83 | ``` 84 | 85 | ### 3.3 方法参考 86 | 87 | 我们可以使用方法引用语法而不是普通的Lambda语法,其中已存在一个方法来对类执行操作: 88 | 89 | ```java 90 | names.forEach(System.out::println); 91 | ``` 92 | 93 | ## 4.forEach在集合中的使用 94 | 95 | ### 4.1.迭代集合 96 | 97 | **任何类型Collection的可迭代 - 列表,集合,队列 等都具有使用forEach的相同语法。** 98 | 99 | 因此,正如我们已经看到的,迭代列表的元素: 100 | 101 | ```java 102 | List names = Arrays.asList("Larry", "Steve", "James"); 103 | 104 | names.forEach(System.out::println); 105 | ``` 106 | 107 | 同样对于一组: 108 | 109 | ```java 110 | Set uniqueNames = new HashSet<>(Arrays.asList("Larry", "Steve", "James")); 111 | 112 | uniqueNames.forEach(System.out::println); 113 | ``` 114 | 115 | 或者让我们说一个*队列*也是一个*集合*: 116 | 117 | ```java 118 | Queue namesQueue = new ArrayDeque<>(Arrays.asList("Larry", "Steve", "James")); 119 | 120 | namesQueue.forEach(System.out::println); 121 | ``` 122 | 123 | ### 4.2.迭代Map - 使用Map的forEach 124 | 125 | Map没有实现Iterable接口,但它**提供了自己的forEach 变体,它接受BiConsumer**。* 126 | 127 | ```java 128 | Map namesMap = new HashMap<>(); 129 | namesMap.put(1, "Larry"); 130 | namesMap.put(2, "Steve"); 131 | namesMap.put(3, "James"); 132 | namesMap.forEach((key, value) -> System.out.println(key + " " + value)); 133 | ``` 134 | 135 | ### 4.3.迭代一个Map - 通过迭代entrySet 136 | 137 | ```java 138 | namesMap.entrySet().forEach(entry -> System.out.println(entry.getKey() + " " + entry.getValue())); 139 | ``` -------------------------------------------------------------------------------- /docs/java/What's New in JDK8/Java8教程推荐.md: -------------------------------------------------------------------------------- 1 | ### 书籍 2 | 3 | - **《Java8 In Action》** 4 | - **《写给大忙人看的Java SE 8》** 5 | 6 | 上述书籍的PDF版本见 https://shimo.im/docs/CPB0PK05rP4CFmI2/ 中的 “Java 书籍推荐”。 7 | 8 | ### 开源文档 9 | 10 | - **【译】Java 8 简明教程**: 11 | - **30 seconds of java8:** 12 | 13 | ### 视频 14 | 15 | - **尚硅谷 Java 8 新特性** 16 | 17 | 视频资源见: https://shimo.im/docs/CPB0PK05rP4CFmI2/ 。 18 | 19 | -------------------------------------------------------------------------------- /docs/java/jvm/GC调优参数.md: -------------------------------------------------------------------------------- 1 | > 原文地址: https://juejin.im/post/5c94a123f265da610916081f。 2 | 3 | ## JVM 配置常用参数 4 | 5 | 1. 堆参数; 6 | 2. 回收器参数; 7 | 3. 项目中常用配置; 8 | 4. 常用组合; 9 | 10 | ### 堆参数 11 | 12 | ![img](https://ask.qcloudimg.com/http-save/yehe-1130324/975rk4d0wx.jpeg?imageView2/2/w/1620) 13 | 14 | ### 回收器参数 15 | 16 | ![img](https://ask.qcloudimg.com/http-save/yehe-1130324/34nzellt71.jpeg?imageView2/2/w/1620) 17 | 18 | 如上表所示,目前**主要有串行、并行和并发三种**,对于大内存的应用而言,串行的性能太低,因此使用到的主要是并行和并发两种。并行和并发 GC 的策略通过 `UseParallelGC `和` UseConcMarkSweepGC` 来指定,还有一些细节的配置参数用来配置策略的执行方式。例如:`XX:ParallelGCThreads`, `XX:CMSInitiatingOccupancyFraction` 等。 通常:Young 区对象回收只可选择并行(耗时间),Old 区选择并发(耗 CPU)。 19 | 20 | ### 项目中常用配置 21 | 22 | > 备注:在Java8中永久代的参数`-XX:PermSize` 和`-XX:MaxPermSize`已经失效。 23 | 24 | ![img](https://ask.qcloudimg.com/http-save/yehe-1130324/urw285pczz.jpeg?imageView2/2/w/1620) 25 | 26 | ### 常用组合 27 | 28 | ![img](https://ask.qcloudimg.com/http-save/yehe-1130324/ff8ues5crb.jpeg?imageView2/2/w/1620) 29 | 30 | ## 常用 GC 调优策略 31 | 32 | 1. GC 调优原则; 33 | 2. GC 调优目的; 34 | 3. GC 调优策略; 35 | 36 | ### GC 调优原则 37 | 38 | 在调优之前,我们需要记住下面的原则: 39 | 40 | > 多数的 Java 应用不需要在服务器上进行 GC 优化; 多数导致 GC 问题的 Java 应用,都不是因为我们参数设置错误,而是代码问题; 在应用上线之前,先考虑将机器的 JVM 参数设置到最优(最适合); 减少创建对象的数量; 减少使用全局变量和大对象; GC 优化是到最后不得已才采用的手段; 在实际使用中,分析 GC 情况优化代码比优化 GC 参数要多得多。 41 | 42 | ### GC 调优目的 43 | 44 | 将转移到老年代的对象数量降低到最小; 减少 GC 的执行时间。 45 | 46 | ### GC 调优策略 47 | 48 | **策略 1:**将新对象预留在新生代,由于 Full GC 的成本远高于 Minor GC,因此尽可能将对象分配在新生代是明智的做法,实际项目中根据 GC 日志分析新生代空间大小分配是否合理,适当通过“-Xmn”命令调节新生代大小,最大限度降低新对象直接进入老年代的情况。 49 | 50 | **策略 2:**大对象进入老年代,虽然大部分情况下,将对象分配在新生代是合理的。但是对于大对象这种做法却值得商榷,大对象如果首次在新生代分配可能会出现空间不足导致很多年龄不够的小对象被分配的老年代,破坏新生代的对象结构,可能会出现频繁的 full gc。因此,对于大对象,可以设置直接进入老年代(当然短命的大对象对于垃圾回收来说简直就是噩梦)。`-XX:PretenureSizeThreshold` 可以设置直接进入老年代的对象大小。 51 | 52 | **策略 3:**合理设置进入老年代对象的年龄,`-XX:MaxTenuringThreshold` 设置对象进入老年代的年龄大小,减少老年代的内存占用,降低 full gc 发生的频率。 53 | 54 | **策略 4:**设置稳定的堆大小,堆大小设置有两个参数:`-Xms` 初始化堆大小,`-Xmx` 最大堆大小。 55 | 56 | **策略5:**注意: 如果满足下面的指标,**则一般不需要进行 GC 优化:** 57 | 58 | > MinorGC 执行时间不到50ms; Minor GC 执行不频繁,约10秒一次; Full GC 执行时间不到1s; Full GC 执行频率不算频繁,不低于10分钟1次。 -------------------------------------------------------------------------------- /docs/java/jvm/jvm 知识点汇总.md: -------------------------------------------------------------------------------- 1 | 2 | 无论什么级别的Java从业者,JVM都是进阶时必须迈过的坎。不管是工作还是面试中,JVM都是必考题。如果不懂JVM的话,薪酬会非常吃亏(近70%的面试者挂在JVM上了)。 3 | 4 | 5 | 掌握了JVM机制,就等于学会了深层次解决问题的方法。对于Java开发者而言,只有熟悉底层虚拟机的运行机制,才能通过JVM日志深入到字节码的层次去分析排查问题,发现隐性的系统缺陷,进而提升系统性能。 6 | 7 | 8 | 一些技术人员开发工具用得很熟练,触及JVM问题时却是模棱两可,甚至连内存模型和内存区域,HotSpot和JVM规范,都混淆不清。工作很长时间,在生产时还在用缺省参数来直接启动,以致系统运行时出现性能、稳定性等问题时束手无措,不知该如何追踪排查。久而久之,这对自己的职业成长是极为不利的。 9 | 10 | 11 | 掌握JVM,是深入Java技术栈的必经之路。 12 | 13 | ![jv.png](https://i.loli.net/2019/09/10/HsJXU8S4oVtCTM7.png) 14 | -------------------------------------------------------------------------------- /docs/java/jvm/最重要的JVM参数指南.md: -------------------------------------------------------------------------------- 1 | > 本文由 JavaGuide 翻译自 https://www.baeldung.com/jvm-parameters,并对文章进行了大量的完善补充。翻译不易,如需转载请注明出处为: 作者: 。 2 | 3 | ## 1.概述 4 | 5 | 在本篇文章中,你将掌握最常用的 JVM 参数配置。如果对于下面提到了一些概念比如堆、 6 | 7 | ## 2.堆内存相关 8 | 9 | >Java 虚拟机所管理的内存中最大的一块,Java 堆是所有线程共享的一块内存区域,在虚拟机启动时创建。**此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例以及数组都在这里分配内存。** 10 | > 11 | 12 | ### 2.1.显式指定堆内存`–Xms`和`-Xmx` 13 | 14 | 与性能有关的最常见实践之一是根据应用程序要求初始化堆内存。如果我们需要指定最小和最大堆大小(推荐显示指定大小),以下参数可以帮助你实现: 15 | 16 | ``` 17 | -Xms[unit] 18 | -Xmx[unit] 19 | ``` 20 | 21 | - **heap size** 表示要初始化内存的具体大小。 22 | - **unit** 表示要初始化内存的单位。单位为***“ g”*** (GB) 、***“ m”***(MB)、***“ k”***(KB)。 23 | 24 | 举个栗子🌰,如果我们要为JVM分配最小2 GB和最大5 GB的堆内存大小,我们的参数应该这样来写: 25 | 26 | ``` 27 | -Xms2G -Xmx5G 28 | ``` 29 | 30 | ### 2.2.显式新生代内存(Young Ceneration) 31 | 32 | 根据[Oracle官方文档](https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/sizing.html),在堆总可用内存配置完成之后,第二大影响因素是为 `Young Generation` 在堆内存所占的比例。默认情况下,YG 的最小大小为 1310 *MB*,最大大小为*无限制*。 33 | 34 | 一共有两种指定 新生代内存(Young Ceneration)大小的方法: 35 | 36 | **1.通过`-XX:NewSize`和`-XX:MaxNewSize`指定** 37 | 38 | ``` 39 | -XX:NewSize=[unit] 40 | -XX:MaxNewSize=[unit] 41 | ``` 42 | 43 | 举个栗子🌰,如果我们要为 新生代分配 最小256m 的内存,最大 1024m的内存我们的参数应该这样来写: 44 | 45 | ``` 46 | -XX:NewSize=256m 47 | -XX:MaxNewSize=1024m 48 | ``` 49 | 50 | **2.通过`-Xmn[unit] `指定** 51 | 52 | 举个栗子🌰,如果我们要为 新生代分配256m的内存(NewSize与MaxNewSize设为一致),我们的参数应该这样来写: 53 | 54 | ``` 55 | -Xmn256m 56 | ``` 57 | 58 | GC 调优策略中很重要的一条经验总结是这样说的: 59 | 60 | > 将新对象预留在新生代,由于 Full GC 的成本远高于 Minor GC,因此尽可能将对象分配在新生代是明智的做法,实际项目中根据 GC 日志分析新生代空间大小分配是否合理,适当通过“-Xmn”命令调节新生代大小,最大限度降低新对象直接进入老年代的情况。 61 | 62 | 另外,你还可以通过**`-XX:NewRatio=`**来设置新生代和老年代内存的比值。 63 | 64 | 比如下面的参数就是设置新生代(包括Eden和两个Survivor区)与老年代的比值为1。也就是说:新生代与老年代所占比值为1:1,新生代占整个堆栈的 1/2。 65 | 66 | ``` 67 | -XX:NewRatio=1 68 | ``` 69 | 70 | ### 2.3.显示指定永久代/元空间的大小 71 | 72 | **从Java 8开始,如果我们没有指定 Metaspace 的大小,随着更多类的创建,虚拟机会耗尽所有可用的系统内存(永久代并不会出现这种情况)。** 73 | 74 | JDK 1.8 之前永久代还没被彻底移除的时候通常通过下面这些参数来调节方法区大小 75 | 76 | ```java 77 | -XX:PermSize=N //方法区 (永久代) 初始大小 78 | -XX:MaxPermSize=N //方法区 (永久代) 最大大小,超过这个值将会抛出 OutOfMemoryError 异常:java.lang.OutOfMemoryError: PermGen 79 | ``` 80 | 81 | 相对而言,垃圾收集行为在这个区域是比较少出现的,但并非数据进入方法区后就“永久存在”了。 82 | 83 | **JDK 1.8 的时候,方法区(HotSpot 的永久代)被彻底移除了(JDK1.7 就已经开始了),取而代之是元空间,元空间使用的是直接内存。** 84 | 85 | 下面是一些常用参数: 86 | 87 | ```java 88 | -XX:MetaspaceSize=N //设置 Metaspace 的初始(和最小大小) 89 | -XX:MaxMetaspaceSize=N //设置 Metaspace 的最大大小,如果不指定大小的话,随着更多类的创建,虚拟机会耗尽所有可用的系统内存。 90 | ``` 91 | 92 | ## 3.垃圾收集相关 93 | 94 | ### 3.1.垃圾回收器 95 | 96 | 为了提高应用程序的稳定性,选择正确的[垃圾收集](http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html)算法至关重要。 97 | 98 | JVM具有四种类型的*GC*实现: 99 | 100 | - 串行垃圾收集器 101 | - 并行垃圾收集器 102 | - CMS垃圾收集器 103 | - G1垃圾收集器 104 | 105 | 可以使用以下参数声明这些实现: 106 | 107 | ``` 108 | -XX:+UseSerialGC 109 | -XX:+UseParallelGC 110 | -XX:+USeParNewGC 111 | -XX:+UseG1GC 112 | ``` 113 | 114 | 有关*垃圾回收*实施的更多详细信息,请参见[此处](https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/jvm/JVM%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6.md)。 115 | 116 | ### 3.2.GC记录 117 | 118 | 为了严格监控应用程序的运行状况,我们应该始终检查JVM的*垃圾回收*性能。最简单的方法是以人类可读的格式记录*GC*活动。 119 | 120 | 使用以下参数,我们可以记录*GC*活动: 121 | 122 | ``` 123 | -XX:+UseGCLogFileRotation 124 | -XX:NumberOfGCLogFiles=< number of log files > 125 | -XX:GCLogFileSize=< file size >[ unit ] 126 | -Xloggc:/path/to/gc.log 127 | ``` 128 | 129 | 130 | 131 | ## 推荐阅读 132 | 133 | - [CMS GC 默认新生代是多大?](https://www.jianshu.com/p/832fc4d4cb53) 134 | - [CMS GC启动参数优化配置](https://www.cnblogs.com/hongdada/p/10277782.html) 135 | - [从实际案例聊聊Java应用的GC优化-美团技术团队](https://tech.meituan.com/2017/12/29/jvm-optimize.html) 136 | - [JVM性能调优详解](https://www.choupangxia.com/2019/11/11/interview-jvm-gc-08/) (2019-11-11) 137 | - [JVM参数使用手册](https://segmentfault.com/a/1190000010603813) -------------------------------------------------------------------------------- /docs/java/jvm/类加载器.md: -------------------------------------------------------------------------------- 1 | 点击关注[公众号](#公众号)及时获取笔主最新更新文章,并可免费领取本文档配套的《Java面试突击》以及Java工程师必备学习资源。 2 | 3 | 4 | 5 | - [回顾一下类加载过程](#回顾一下类加载过程) 6 | - [类加载器总结](#类加载器总结) 7 | - [双亲委派模型](#双亲委派模型) 8 | - [双亲委派模型介绍](#双亲委派模型介绍) 9 | - [双亲委派模型实现源码分析](#双亲委派模型实现源码分析) 10 | - [双亲委派模型的好处](#双亲委派模型的好处) 11 | - [如果我们不想要双亲委派模型怎么办?](#如果我们不想要双亲委派模型怎么办) 12 | - [自定义类加载器](#自定义类加载器) 13 | - [推荐](#推荐) 14 | 15 | 16 | 17 | > 公众号JavaGuide 后台回复关键字“1”,免费获取JavaGuide配套的Java工程师必备学习资源(文末有公众号二维码)。 18 | 19 | ## 回顾一下类加载过程 20 | 21 | 类加载过程:**加载->连接->初始化**。连接过程又可分为三步:**验证->准备->解析**。 22 | 23 | ![类加载过程](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/类加载过程.png) 24 | 25 | 一个非数组类的加载阶段(加载阶段获取类的二进制字节流的动作)是可控性最强的阶段,这一步我们可以去完成还可以自定义类加载器去控制字节流的获取方式(重写一个类加载器的 `loadClass()` 方法)。数组类型不通过类加载器创建,它由 Java 虚拟机直接创建。 26 | 27 | 所有的类都由类加载器加载,加载的作用就是将 .class文件加载到内存。 28 | 29 | ## 类加载器总结 30 | 31 | JVM 中内置了三个重要的 ClassLoader,除了 BootstrapClassLoader 其他类加载器均由 Java 实现且全部继承自`java.lang.ClassLoader`: 32 | 33 | 1. **BootstrapClassLoader(启动类加载器)** :最顶层的加载类,由C++实现,负责加载 `%JAVA_HOME%/lib`目录下的jar包和类或者或被 `-Xbootclasspath`参数指定的路径中的所有类。 34 | 2. **ExtensionClassLoader(扩展类加载器)** :主要负责加载目录 `%JRE_HOME%/lib/ext` 目录下的jar包和类,或被 `java.ext.dirs` 系统变量所指定的路径下的jar包。 35 | 3. **AppClassLoader(应用程序类加载器)** :面向我们用户的加载器,负责加载当前应用classpath下的所有jar包和类。 36 | 37 | ## 双亲委派模型 38 | 39 | ### 双亲委派模型介绍 40 | 41 | 每一个类都有一个对应它的类加载器。系统中的 ClassLoder 在协同工作的时候会默认使用 **双亲委派模型** 。即在类加载的时候,系统会首先判断当前类是否被加载过。已经被加载的类会直接返回,否则才会尝试加载。加载的时候,首先会把该请求委派该父类加载器的 `loadClass()` 处理,因此所有的请求最终都应该传送到顶层的启动类加载器 `BootstrapClassLoader` 中。当父类加载器无法处理时,才由自己来处理。当父类加载器为null时,会使用启动类加载器 `BootstrapClassLoader` 作为父类加载器。 42 | 43 | ![ClassLoader](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/classloader_WPS图片.png) 44 | 45 | 每个类加载都有一个父类加载器,我们通过下面的程序来验证。 46 | 47 | ```java 48 | public class ClassLoaderDemo { 49 | public static void main(String[] args) { 50 | System.out.println("ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader()); 51 | System.out.println("The Parent of ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader().getParent()); 52 | System.out.println("The GrandParent of ClassLodarDemo's ClassLoader is " + ClassLoaderDemo.class.getClassLoader().getParent().getParent()); 53 | } 54 | } 55 | ``` 56 | 57 | Output 58 | 59 | ``` 60 | ClassLodarDemo's ClassLoader is sun.misc.Launcher$AppClassLoader@18b4aac2 61 | The Parent of ClassLodarDemo's ClassLoader is sun.misc.Launcher$ExtClassLoader@1b6d3586 62 | The GrandParent of ClassLodarDemo's ClassLoader is null 63 | ``` 64 | 65 | `AppClassLoader`的父类加载器为`ExtClassLoader` 66 | `ExtClassLoader`的父类加载器为null,**null并不代表`ExtClassLoader`没有父类加载器,而是 `BootstrapClassLoader`** 。 67 | 68 | 其实这个双亲翻译的容易让别人误解,我们一般理解的双亲都是父母,这里的双亲更多地表达的是“父母这一辈”的人而已,并不是说真的有一个 Mother ClassLoader 和一个 Father ClassLoader 。另外,类加载器之间的“父子”关系也不是通过继承来体现的,是由“优先级”来决定。官方API文档对这部分的描述如下: 69 | 70 | >The Java platform uses a delegation model for loading classes. **The basic idea is that every class loader has a "parent" class loader.** When loading a class, a class loader first "delegates" the search for the class to its parent class loader before attempting to find the class itself. 71 | 72 | ### 双亲委派模型实现源码分析 73 | 74 | 双亲委派模型的实现代码非常简单,逻辑非常清晰,都集中在 `java.lang.ClassLoader` 的 `loadClass()` 中,相关代码如下所示。 75 | 76 | ```java 77 | private final ClassLoader parent; 78 | protected Class loadClass(String name, boolean resolve) 79 | throws ClassNotFoundException 80 | { 81 | synchronized (getClassLoadingLock(name)) { 82 | // 首先,检查请求的类是否已经被加载过 83 | Class c = findLoadedClass(name); 84 | if (c == null) { 85 | long t0 = System.nanoTime(); 86 | try { 87 | if (parent != null) {//父加载器不为空,调用父加载器loadClass()方法处理 88 | c = parent.loadClass(name, false); 89 | } else {//父加载器为空,使用启动类加载器 BootstrapClassLoader 加载 90 | c = findBootstrapClassOrNull(name); 91 | } 92 | } catch (ClassNotFoundException e) { 93 | //抛出异常说明父类加载器无法完成加载请求 94 | } 95 | 96 | if (c == null) { 97 | long t1 = System.nanoTime(); 98 | //自己尝试加载 99 | c = findClass(name); 100 | 101 | // this is the defining class loader; record the stats 102 | sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); 103 | sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); 104 | sun.misc.PerfCounter.getFindClasses().increment(); 105 | } 106 | } 107 | if (resolve) { 108 | resolveClass(c); 109 | } 110 | return c; 111 | } 112 | } 113 | ``` 114 | 115 | ### 双亲委派模型的好处 116 | 117 | 双亲委派模型保证了Java程序的稳定运行,可以避免类的重复加载(JVM 区分不同类的方式不仅仅根据类名,相同的类文件被不同的类加载器加载产生的是两个不同的类),也保证了 Java 的核心 API 不被篡改。如果没有使用双亲委派模型,而是每个类加载器加载自己的话就会出现一些问题,比如我们编写一个称为 `java.lang.Object` 类的话,那么程序运行的时候,系统就会出现多个不同的 `Object` 类。 118 | 119 | ### 如果我们不想用双亲委派模型怎么办? 120 | 121 | 为了避免双亲委托机制,我们可以自己定义一个类加载器,然后重写 `loadClass()` 即可。 122 | 123 | ## 自定义类加载器 124 | 125 | 除了 `BootstrapClassLoader` 其他类加载器均由 Java 实现且全部继承自`java.lang.ClassLoader`。如果我们要自定义自己的类加载器,很明显需要继承 `ClassLoader`。 126 | 127 | ## 推荐阅读 128 | 129 | - 130 | - 131 | - 132 | 133 | ### 公众号 134 | 135 | 如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的公众号。 136 | 137 | **《Java面试突击》:** 由本文档衍生的专为面试而生的《Java面试突击》V2.0 PDF 版本[公众号](#公众号)后台回复 **"Java面试突击"** 即可免费领取! 138 | 139 | **Java工程师必备学习资源:** 一些Java工程师常用学习资源[公众号](#公众号)后台回复关键字 **“1”** 即可免费无套路获取。 140 | 141 | ![我的公众号](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/167598cd2e17b8ec.png) 142 | 143 | -------------------------------------------------------------------------------- /docs/java/jvm/类加载过程.md: -------------------------------------------------------------------------------- 1 | 点击关注[公众号](#公众号)及时获取笔主最新更新文章,并可免费领取本文档配套的《Java面试突击》以及Java工程师必备学习资源。 2 | 3 | 4 | 5 | - [类加载过程](#类加载过程) 6 | - [加载](#加载) 7 | - [验证](#验证) 8 | - [准备](#准备) 9 | - [解析](#解析) 10 | - [初始化](#初始化) 11 | 12 | 13 | 14 | > 公众号JavaGuide 后台回复关键字“1”,免费获取JavaGuide配套的Java工程师必备学习资源(文末有公众号二维码)。 15 | 16 | # 类加载过程 17 | 18 | Class 文件需要加载到虚拟机中之后才能运行和使用,那么虚拟机是如何加载这些 Class 文件呢? 19 | 20 | 系统加载 Class 类型的文件主要三步:**加载->连接->初始化**。连接过程又可分为三步:**验证->准备->解析**。 21 | 22 | ![类加载过程](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/类加载过程.png) 23 | 24 | ## 加载 25 | 26 | 类加载过程的第一步,主要完成下面3件事情: 27 | 28 | 1. 通过全类名获取定义此类的二进制字节流 29 | 2. 将字节流所代表的静态存储结构转换为方法区的运行时数据结构 30 | 3. 在内存中生成一个代表该类的 Class 对象,作为方法区这些数据的访问入口 31 | 32 | 虚拟机规范多上面这3点并不具体,因此是非常灵活的。比如:"通过全类名获取定义此类的二进制字节流" 并没有指明具体从哪里获取、怎样获取。比如:比较常见的就是从 ZIP 包中读取(日后出现的JAR、EAR、WAR格式的基础)、其他文件生成(典型应用就是JSP)等等。 33 | 34 | **一个非数组类的加载阶段(加载阶段获取类的二进制字节流的动作)是可控性最强的阶段,这一步我们可以去完成还可以自定义类加载器去控制字节流的获取方式(重写一个类加载器的 `loadClass()` 方法)。数组类型不通过类加载器创建,它由 Java 虚拟机直接创建。** 35 | 36 | 类加载器、双亲委派模型也是非常重要的知识点,这部分内容会在后面的文章中单独介绍到。 37 | 38 | 加载阶段和连接阶段的部分内容是交叉进行的,加载阶段尚未结束,连接阶段可能就已经开始了。 39 | 40 | ## 验证 41 | 42 | ![验证阶段示意图](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/验证阶段.png) 43 | 44 | ## 准备 45 | 46 | **准备阶段是正式为类变量分配内存并设置类变量初始值的阶段**,这些内存都将在方法区中分配。对于该阶段有以下几点需要注意: 47 | 48 | 1. 这时候进行内存分配的仅包括类变量(static),而不包括实例变量,实例变量会在对象实例化时随着对象一块分配在 Java 堆中。 49 | 2. 这里所设置的初始值"通常情况"下是数据类型默认的零值(如0、0L、null、false等),比如我们定义了`public static int value=111` ,那么 value 变量在准备阶段的初始值就是 0 而不是111(初始化阶段才会赋值)。特殊情况:比如给 value 变量加上了 fianl 关键字`public static final int value=111` ,那么准备阶段 value 的值就被赋值为 111。 50 | 51 | **基本数据类型的零值:** 52 | 53 | ![基本数据类型的零值](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/基本数据类型的零值.png) 54 | 55 | ## 解析 56 | 57 | 解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。解析动作主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用限定符7类符号引用进行。 58 | 59 | 符号引用就是一组符号来描述目标,可以是任何字面量。**直接引用**就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄。在程序实际运行时,只有符号引用是不够的,举个例子:在程序执行方法时,系统需要明确知道这个方法所在的位置。Java 虚拟机为每个类都准备了一张方法表来存放类中所有的方法。当需要调用一个类的方法的时候,只要知道这个方法在方发表中的偏移量就可以直接调用该方法了。通过解析操作符号引用就可以直接转变为目标方法在类中方法表的位置,从而使得方法可以被调用。 60 | 61 | 综上,解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程,也就是得到类或者字段、方法在内存中的指针或者偏移量。 62 | 63 | ## 初始化 64 | 65 | 初始化是类加载的最后一步,也是真正执行类中定义的 Java 程序代码(字节码),初始化阶段是执行类构造器 ` ()`方法的过程。 66 | 67 | 对于`()` 方法的调用,虚拟机会自己确保其在多线程环境中的安全性。因为 `()` 方法是带锁线程安全,所以在多线程环境下进行类初始化的话可能会引起死锁,并且这种死锁很难被发现。 68 | 69 | 对于初始化阶段,虚拟机严格规范了有且只有5种情况下,必须对类进行初始化: 70 | 71 | 1. 当遇到 new 、 getstatic、putstatic或invokestatic 这4条直接码指令时,比如 new 一个类,读取一个静态字段(未被 final 修饰)、或调用一个类的静态方法时。 72 | 2. 使用 `java.lang.reflect` 包的方法对类进行反射调用时 ,如果类没初始化,需要触发其初始化。 73 | 3. 初始化一个类,如果其父类还未初始化,则先触发该父类的初始化。 74 | 4. 当虚拟机启动时,用户需要定义一个要执行的主类 (包含 main 方法的那个类),虚拟机会先初始化这个类。 75 | 5. 当使用 JDK1.7 的动态动态语言时,如果一个 MethodHandle 实例的最后解析结构为 REF_getStatic、REF_putStatic、REF_invokeStatic、的方法句柄,并且这个句柄没有初始化,则需要先触发器初始化。 76 | 77 | **参考** 78 | 79 | - 《深入理解Java虚拟机》 80 | - 《实战Java虚拟机》 81 | - 82 | 83 | ## 公众号 84 | 85 | 如果大家想要实时关注我更新的文章以及分享的干货的话,可以关注我的公众号。 86 | 87 | **《Java面试突击》:** 由本文档衍生的专为面试而生的《Java面试突击》V2.0 PDF 版本[公众号](#公众号)后台回复 **"Java面试突击"** 即可免费领取! 88 | 89 | **Java工程师必备学习资源:** 一些Java工程师常用学习资源[公众号](#公众号)后台回复关键字 **“1”** 即可免费无套路获取。 90 | 91 | ![我的公众号](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/167598cd2e17b8ec.png) 92 | -------------------------------------------------------------------------------- /docs/java/多线程系列.md: -------------------------------------------------------------------------------- 1 | > ## 多线程系列文章 2 | 下列文章,我都更新在了我的博客专栏:[Java并发编程指南](https://blog.csdn.net/column/details/20860.html)。 3 | 4 | 1. [Java多线程学习(一)Java多线程入门](http://blog.csdn.net/qq_34337272/article/details/79640870) 5 | 2. [Java多线程学习(二)synchronized关键字(1)](http://blog.csdn.net/qq_34337272/article/details/79655194) 6 | 3. [Java多线程学习(二)synchronized关键字(2)](http://blog.csdn.net/qq_34337272/article/details/79670775) 7 | 4. [Java多线程学习(三)volatile关键字](http://blog.csdn.net/qq_34337272/article/details/79680771) 8 | 5. [Java多线程学习(四)等待/通知(wait/notify)机制](http://blog.csdn.net/qq_34337272/article/details/79690279) 9 | 10 | 6. [Java多线程学习(五)线程间通信知识点补充](http://blog.csdn.net/qq_34337272/article/details/79694226) 11 | 7. [Java多线程学习(六)Lock锁的使用](http://blog.csdn.net/qq_34337272/article/details/79714196) 12 | 8. [Java多线程学习(七)并发编程中一些问题](https://blog.csdn.net/qq_34337272/article/details/79844051) 13 | 9. [Java多线程学习(八)线程池与Executor 框架](https://blog.csdn.net/qq_34337272/article/details/79959271) 14 | 15 | 16 | > ## 多线程系列文章重要知识点与思维导图 17 | 18 | ### Java多线程学习(一)Java多线程入门 19 | 20 | ![](https://user-gold-cdn.xitu.io/2018/8/4/16504e0cb6bac32e?w=758&h=772&f=jpeg&s=247210) 21 | 22 | ### Java多线程学习(二)synchronized关键字(1) 23 | ![](https://user-gold-cdn.xitu.io/2018/8/4/16504e245ceb3ea9?w=1028&h=490&f=jpeg&s=203811) 24 | 25 | 注意:**可重入锁的概念**。 26 | 27 | 另外要注意:**synchronized取得的锁都是对象锁,而不是把一段代码或方法当做锁。** 如果多个线程访问的是同一个对象,哪个线程先执行带synchronized关键字的方法,则哪个线程就持有该方法,那么其他线程只能呈等待状态。如果多个线程访问的是多个对象则不一定,因为多个对象会产生多个锁。 28 | 29 | ### Java多线程学习(二)synchronized关键字(2) 30 | 31 | ![思维导图](https://user-gold-cdn.xitu.io/2018/8/4/16504e3d98213324?w=1448&h=439&f=jpeg&s=245012) 32 | 33 | **注意:** 34 | 35 | - 其他线程执行对象中**synchronized同步方法**(上一节我们介绍过,需要回顾的可以看上一节的文章)和**synchronized(this)代码块**时呈现同步效果; 36 | - **如果两个线程使用了同一个“对象监视器”(synchronized(object)),运行结果同步,否则不同步**. 37 | 38 | **synchronized关键字加到static静态方法**和**synchronized(class)代码块**上都是是给**Class类**上锁,而**synchronized关键字加到非static静态方法**上是给**对象**上锁。 39 | 40 | 数据类型String的常量池属性:**在Jvm中具有String常量池缓存的功能** 41 | 42 | ### Java多线程学习(三)volatile关键字 43 | 44 | ![volatile关键字](https://user-gold-cdn.xitu.io/2018/8/4/16504e4ab69d8d58) 45 | **注意:** 46 | 47 | **synchronized关键字**和**volatile关键字**比较 48 | 49 | ### Java多线程学习(四)等待/通知(wait/notify)机制 50 | 51 | ![本节思维导图](https://user-gold-cdn.xitu.io/2018/3/25/1625d2a9188ec021?w=1254&h=452&f=jpeg&s=229471) 52 | 53 | ### Java多线程学习(五)线程间通信知识点补充 54 | 55 | ![本节思维导图](https://user-gold-cdn.xitu.io/2018/8/4/16504e618d6886c5?w=1146&h=427&f=jpeg&s=220573) 56 | **注意:** ThreadLocal类主要解决的就是让每个线程绑定自己的值,可以将ThreadLocal类形象的比喻成存放数据的盒子,盒子中可以存储每个线程的私有数据。 57 | 58 | ### Java多线程学习(六)Lock锁的使用 59 | 60 | ![本节思维导图](https://user-gold-cdn.xitu.io/2018/3/27/1626755a8e9a8774?w=1197&h=571&f=jpeg&s=258439) 61 | 62 | ### Java多线程学习(七)并发编程中一些问题 63 | 64 | ![思维导图](https://user-gold-cdn.xitu.io/2018/4/7/162a01b71ebc4842?w=1067&h=517&f=png&s=36857) 65 | 66 | ### Java多线程学习(八)线程池与Executor 框架 67 | 68 | ![](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-12-14/86510659.jpg) 69 | 70 | -------------------------------------------------------------------------------- /docs/network/HTTPS中的TLS.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | - [1. SSL 与 TLS](#1-ssl-%E4%B8%8E-tls) 4 | - [2. 从网络协议的角度理解 HTTPS](#2-%E4%BB%8E%E7%BD%91%E7%BB%9C%E5%8D%8F%E8%AE%AE%E7%9A%84%E8%A7%92%E5%BA%A6%E7%90%86%E8%A7%A3-https) 5 | - [3. 从密码学的角度理解 HTTPS](#3-%E4%BB%8E%E5%AF%86%E7%A0%81%E5%AD%A6%E7%9A%84%E8%A7%92%E5%BA%A6%E7%90%86%E8%A7%A3-https) 6 | - [3.1. TLS 工作流程](#31-tls-%E5%B7%A5%E4%BD%9C%E6%B5%81%E7%A8%8B) 7 | - [3.2. 密码基础](#32-%E5%AF%86%E7%A0%81%E5%9F%BA%E7%A1%80) 8 | - [3.2.1. 伪随机数生成器](#321-%E4%BC%AA%E9%9A%8F%E6%9C%BA%E6%95%B0%E7%94%9F%E6%88%90%E5%99%A8) 9 | - [3.2.2. 消息认证码](#322-%E6%B6%88%E6%81%AF%E8%AE%A4%E8%AF%81%E7%A0%81) 10 | - [3.2.3. 数字签名](#323-%E6%95%B0%E5%AD%97%E7%AD%BE%E5%90%8D) 11 | - [3.2.4. 公钥密码](#324-%E5%85%AC%E9%92%A5%E5%AF%86%E7%A0%81) 12 | - [3.2.5. 证书](#325-%E8%AF%81%E4%B9%A6) 13 | - [3.2.6. 密码小结](#326-%E5%AF%86%E7%A0%81%E5%B0%8F%E7%BB%93) 14 | - [3.3. TLS 使用的密码技术](#33-tls-%E4%BD%BF%E7%94%A8%E7%9A%84%E5%AF%86%E7%A0%81%E6%8A%80%E6%9C%AF) 15 | - [3.4. TLS 总结](#34-tls-%E6%80%BB%E7%BB%93) 16 | - [4. RSA 简单示例](#4-rsa-%E7%AE%80%E5%8D%95%E7%A4%BA%E4%BE%8B) 17 | - [5. 参考](#5-%E5%8F%82%E8%80%83) 18 | 19 | 20 | 21 | # 1. SSL 与 TLS 22 | 23 | SSL:(Secure Socket Layer) 安全套接层,于 1994 年由网景公司设计,并于 1995 年发布了 3.0 版本 24 | TLS:(Transport Layer Security)传输层安全性协议,是 IETF 在 SSL3.0 的基础上设计的协议 25 | 以下全部使用 TLS 来表示 26 | 27 | # 2. 从网络协议的角度理解 HTTPS 28 | 29 | ![此图并不准确][1] 30 | HTTP:HyperText Transfer Protocol 超文本传输协议 31 | HTTPS:Hypertext Transfer Protocol Secure 超文本传输安全协议 32 | TLS:位于 HTTP 和 TCP 之间的协议,其内部有 TLS握手协议、TLS记录协议 33 | HTTPS 经由 HTTP 进行通信,但利用 TLS 来保证安全,即 HTTPS = HTTP + TLS 34 | 35 | # 3. 从密码学的角度理解 HTTPS 36 | 37 | HTTPS 使用 TLS 保证安全,这里的“安全”分两部分,一是传输内容加密、二是服务端的身份认证 38 | 39 | ## 3.1. TLS 工作流程 40 | 41 | ![此图并不准确][2] 42 | 此为服务端单向认证,还有客户端/服务端双向认证,流程类似,只不过客户端也有自己的证书,并发送给服务器进行验证 43 | 44 | ## 3.2. 密码基础 45 | 46 | ### 3.2.1. 伪随机数生成器 47 | 48 | 为什么叫伪随机数,因为没有真正意义上的随机数,具体可以参考 Random/TheadLocalRandom 49 | 它的主要作用在于生成对称密码的秘钥、用于公钥密码生成秘钥对 50 | 51 | ### 3.2.2. 消息认证码 52 | 53 | 消息认证码主要用于验证消息的完整性与消息的认证,其中消息的认证指“消息来自正确的发送者” 54 | 55 | >消息认证码用于验证和认证,而不是加密 56 | 57 | ![消息认证码过程][3] 58 | 59 | 1. 发送者与接收者事先共享秘钥 60 | 2. 发送者根据发送消息计算 MAC 值 61 | 3. 发送者发送消息和 MAC 值 62 | 4. 接收者根据接收到的消息计算 MAC 值 63 | 5. 接收者根据自己计算的 MAC 值与收到的 MAC 对比 64 | 6. 如果对比成功,说明消息完整,并来自与正确的发送者 65 | 66 | ### 3.2.3. 数字签名 67 | 68 | 消息认证码的缺点在于**无法防止否认**,因为共享秘钥被 client、server 两端拥有,server 可以伪造 client 发送给自己的消息(自己给自己发送消息),为了解决这个问题,我们需要它们有各自的秘钥不被第二个知晓(这样也解决了共享秘钥的配送问题) 69 | 70 | ![数字签名过程][4] 71 | 72 | >数字签名和消息认证码都**不是为了加密** 73 | >可以将单向散列函数获取散列值的过程理解为使用 md5 摘要算法获取摘要的过程 74 | 75 | 使用自己的私钥对自己所认可的消息生成一个该消息专属的签名,这就是数字签名,表明我承认该消息来自自己 76 | 注意:**私钥用于加签,公钥用于解签,每个人都可以解签,查看消息的归属人** 77 | 78 | ### 3.2.4. 公钥密码 79 | 80 | 公钥密码也叫非对称密码,由公钥和私钥组成,它是最开始是为了解决秘钥的配送传输安全问题,即,我们不配送私钥,只配送公钥,私钥由本人保管 81 | 它与数字签名相反,公钥密码的私钥用于解密、公钥用于加密,每个人都可以用别人的公钥加密,但只有对应的私钥才能解开密文 82 | client:明文 + 公钥 = 密文 83 | server:密文 + 私钥 = 明文 84 | 注意:**公钥用于加密,私钥用于解密,只有私钥的归属者,才能查看消息的真正内容** 85 | 86 | ### 3.2.5. 证书 87 | 88 | 证书:全称公钥证书(Public-Key Certificate, PKC),里面保存着归属者的基本信息,以及证书过期时间、归属者的公钥,并由认证机构(Certification Authority, **CA**)施加数字签名,表明,某个认证机构认定该公钥的确属于此人 89 | 90 | >想象这个场景:你想在支付宝页面交易,你需要支付宝的公钥进行加密通信,于是你从百度上搜索关键字“支付宝公钥”,你获得了支什宝的公钥,这个时候,支什宝通过中间人攻击,让你访问到了他们支什宝的页面,最后你在这个支什宝页面完美的使用了支什宝的公钥完成了与支什宝的交易 91 | >![证书过程][5] 92 | 93 | 在上面的场景中,你可以理解支付宝证书就是由支付宝的公钥、和给支付宝颁发证书的企业的数字签名组成 94 | 任何人都可以给自己或别人的公钥添加自己的数字签名,表明:我拿我的尊严担保,我的公钥/别人的公钥是真的,至于信不信那是另一回事了 95 | 96 | ### 3.2.6. 密码小结 97 | 98 | | 密码 | 作用 | 组成 | 99 | | :-- | :-- | :-- | 100 | | 消息认证码 | 确认消息的完整、并对消息的来源认证 | 共享秘钥+消息的散列值 | 101 | | 数字签名 | 对消息的散列值签名 | 公钥+私钥+消息的散列值 | 102 | | 公钥密码 | 解决秘钥的配送问题 | 公钥+私钥+消息 | 103 | | 证书 | 解决公钥的归属问题 | 公钥密码中的公钥+数字签名 | 104 | 105 | ## 3.3. TLS 使用的密码技术 106 | 107 | 1. 伪随机数生成器:秘钥生成随机性,更难被猜测 108 | 2. 对称密码:对称密码使用的秘钥就是由伪随机数生成,相较于非对称密码,效率更高 109 | 3. 消息认证码:保证消息信息的完整性、以及验证消息信息的来源 110 | 4. 公钥密码:证书技术使用的就是公钥密码 111 | 5. 数字签名:验证证书的签名,确定由真实的某个 CA 颁发 112 | 6. 证书:解决公钥的真实归属问题,降低中间人攻击概率 113 | 114 | ## 3.4. TLS 总结 115 | 116 | TLS 是一系列密码工具的框架,作为框架,它也是非常的灵活,体现在每个工具套件它都可以替换,即:客户端与服务端之间协商密码套件,从而更难的被攻破,例如使用不同方式的对称密码,或者公钥密码、数字签名生成方式、单向散列函数技术的替换等 117 | 118 | # 4. RSA 简单示例 119 | 120 | RSA 是一种公钥密码算法,我们简单的走一遍它的加密解密过程 121 | 加密算法:密文 = (明文^E) mod N,其中公钥为{E,N},即”求明文的E次方的对 N 的余数“ 122 | 解密算法:明文 = (密文^D) mod N,其中秘钥为{D,N},即”求密文的D次方的对 N 的余数“ 123 | 例:我们已知公钥为{5,323},私钥为{29,323},明文为300,请写出加密和解密的过程: 124 | >加密:密文 = 123 ^ 5 mod 323 = 225 125 | >解密:明文 = 225 ^ 29 mod 323 = [[(225 ^ 5) mod 323] * [(225 ^ 5) mod 323] * [(225 ^ 5) mod 323] * [(225 ^ 5) mod 323] * [(225 ^ 5) mod 323] * [(225 ^ 4) mod 323]] mod 323 = (4 * 4 * 4 * 4 * 4 * 290) mod 323 = 123 126 | 127 | # 5. 参考 128 | 129 | 1. SSL加密发生在哪里: 130 | 2. TLS工作流程: 131 | 3. 《图解密码技术》: 豆瓣评分 9.5 132 | 133 | [1]: https://leran2deeplearnjavawebtech.oss-cn-beijing.aliyuncs.com/somephoto/%E4%B8%83%E5%B1%82.png 134 | [2]: https://leran2deeplearnjavawebtech.oss-cn-beijing.aliyuncs.com/somephoto/tls%E6%B5%81%E7%A8%8B.png 135 | [3]: https://leran2deeplearnjavawebtech.oss-cn-beijing.aliyuncs.com/somephoto/%E6%B6%88%E6%81%AF%E8%AE%A4%E8%AF%81%E7%A0%81%E8%BF%87%E7%A8%8B.png 136 | [4]: https://leran2deeplearnjavawebtech.oss-cn-beijing.aliyuncs.com/somephoto/%E6%95%B0%E5%AD%97%E7%AD%BE%E5%90%8D%E8%BF%87%E7%A8%8B.png 137 | [5]: https://leran2deeplearnjavawebtech.oss-cn-beijing.aliyuncs.com/somephoto/dns%E4%B8%AD%E9%97%B4%E4%BA%BA%E6%94%BB%E5%87%BB.png -------------------------------------------------------------------------------- /docs/questions/java-learning-website-blog.md: -------------------------------------------------------------------------------- 1 | ## 推荐两个视频学习网站 2 | 3 | ### 慕课网 4 | 5 | 第一个推荐的学习网站应该是慕课网(慕课网私聊我打钱哈!),在我初学的时候,这个网站对我的帮助挺大的,里面有很多免费的课程,也有很多付费的课程。如果你没有特殊的需求,一般免费课程就够自己学的了。 6 | 7 | ![慕课网](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/慕课网-java.png) 8 | 9 | ### 哔哩哔哩 10 | 11 | 想不到弹幕追番/原创视频小站也被推荐了吧!不得不说哔哩哔哩上面的学习资源还是很多的,现在有很多年轻人都在上面学习呢!哈哈哈 大部分年轻人最爱的小破站可是受到过央视表扬的。被誉为年轻人学习的首要阵地,哔哩哔哩干杯! 12 | 13 | 不过在哔哩哔哩上面越靠前的视频就是最好的视频或者说最适合你的视频,也是要筛选一下的。 14 | 15 | ![哔哩哔哩](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/哔哩哔哩-java.png) 16 | 17 | ### 极客时间 18 | 19 | 主打付费学习的一个付费学习社区(极客时间私聊我打钱哈!)。不过课程的质量大部分都挺高的,我自己也看了里面很多的课程,并且很多课程都是 Java 领域大佬级别的人物将的。 20 | 21 | ![极客时间-java](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/极客时间-java.png) 22 | 23 | ## 推荐一些文字类型学习网站/博客 24 | 25 | ### Github 26 | 27 | 最牛逼的程序员交流网站!!!没有之一。一定要多逛逛!上面有很多好东西,比如我搜索 Java(它竟然给我返回贼多 javascript 的项目,啥意思???) 28 | 29 | ![Github-Java](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-11/github-java.jpg) 30 | 31 | 比如我搜索女装,emm....然后就出来了这些东西,捂住眼睛,不敢看! 32 | 33 | ![Github-女装](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-11/githb-女装.jpg) 34 | 35 | ### 菜鸟教程 36 | 37 | 对于新手入门来说很不错的网站,大部分教程都是针对的入门级别。优点是网站教程内容比较完善并且内容质量也是有保障的。 38 | 39 | ![菜鸟教程](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/菜鸟教程-java.png) 40 | 41 | ### w3cschool 42 | 43 | 和菜鸟教程类似的一个网站,里面的教程也很齐全。 44 | 45 | ![w3cschool](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/w3cschool-java.png) 46 | 47 | ### Stackoverflow 48 | 49 | **Stack Overflow**是一个程序设计领域的问答网站,网站允许注册用户提出或回答问题。和知乎很像,重大的一点不同是 Stack Overflow 可以对问题进行打分。 50 | 51 | ![Stackoverflow-Java](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-11/stackoverflow-java.jpg) 52 | 53 | ### leetcode 54 | 55 | 网站地址:https://leetcode-cn.com/ 56 | 57 | 工作之余没事去刷个算法题,岂不是美滋滋。 58 | 59 | ![leetcode](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-11/leetcode.jpg) 60 | 61 | ### 一些不错的技术交流社区推荐 62 | 63 | 1. **掘金**:[https://juejin.im/](https://juejin.im/ "https://juejin.im/") 。 64 | 2. **segmentfault** : [https://segmentfault.com/](https://segmentfault.com/ "https://segmentfault.com/") 65 | 3. **博客园** : [https://www.cnblogs.com/](https://www.cnblogs.com/ "https://www.cnblogs.com/") 66 | 4. **慕课网手记** :[https://www.imooc.com/article](https://www.imooc.com/article "https://www.imooc.com/article") 67 | 5. **知乎** :[https://www.zhihu.com/](https://www.zhihu.com/ "https://www.zhihu.com/") 68 | 69 | ### 一些不错的博客/Github 推荐 70 | 71 | - SnailClimb 的 Github :[https://github.com/Snailclimb](https://github.com/Snailclimb "https://github.com/Snailclimb") 。(自荐一波哈!主要专注在 Java 基础和进阶、Spring、Spiring Boot、Java 面试这方面。) 72 | - 徐靖峰个人博客 :[https://www.cnkirito.moe/](https://www.cnkirito.moe/ "https://www.cnkirito.moe/")(探讨 Java 生态的知识点,内容覆盖分布式服务治理、微服务、性能调优、各类源码分析) 73 | - 田小波:[http://www.tianxiaobo.com/](http://www.tianxiaobo.com/ "http://www.tianxiaobo.com/") (Java 、Spring 、MyBatis 、Dubbo) 74 | - 周立的博客: [http://www.itmuch.com/](http://www.itmuch.com/ "http://www.itmuch.com/")(Spring Cloud、Docker、Kubernetes,及其相关生态的技术) 75 | - Hollis: [https://www.hollischuang.com/](https://www.hollischuang.com/ "https://www.hollischuang.com/") (Java 后端) 76 | - 方志朋的专栏 : [https://www.fangzhipeng.com/](https://www.fangzhipeng.com/ "https://www.fangzhipeng.com/") (Java 面试 Java 并发 openresty kubernetes Docker 故事 ) 77 | - 纯洁的微笑 : [http://www.ityouknow.com/](http://www.ityouknow.com/ "http://www.ityouknow.com/") (Java、SpringBoot、Spring Cloud) 78 | - 芋道源码: [http://www.iocoder.cn/](http://www.iocoder.cn/ "http://www.iocoder.cn/") (专注源码)。 79 | - 欢迎自荐 80 | - ...... -------------------------------------------------------------------------------- /docs/questions/java-training-4-month.md: -------------------------------------------------------------------------------- 1 | 问题描述: 2 | 3 | > 最近在北京华软科技公司看到一个招聘,去咨询了人事部,他说培训四个月就能上岗,并且不要学费,上岗后再每还1000元,还一年,这个可靠吗?本人高中毕业,四个月能学会吗?谢谢了!!! 4 | 5 | 下面是正文: 6 | 7 | 一般说不要学费,上岗后每月再还1000元这种十有八九都不靠谱,就算你把合同看的再仔细,别人也总有各种办法去刁难你。 8 | 9 | 另外,目前的互联网行业已经完全不是它刚开始盛行的样子了。在互联网爆火🔥的初期,你可能会简单用一下语言就能找到一个不错的工作。那时候,即使是没有学历支撑直接从培训班出来的基本也都找到了还算是不错的工作。但是,现在已经完全不一样了。我觉得主要可以从以下几个方面讲: 10 | 11 | 1. **没有学历支撑,直接从培训班出来的找工作会很难,甚至找不到**; 12 | 2. **面试的难度可以说一年比一年难,学的人越来越多,和你竞争的也越来越多,特别是像面试阿里、腾讯、字节跳动这样的大厂,你可能要和更多人去竞争。“面试造火箭,入职拎螺丝”想想也是正常,毕竟这么多人去竞争那少数的 offer,如果不难点的话,区分度就没那么明显了**; 13 | 3. 学习计算机专业的越来越多,和你竞争的也越来越多,需求就那么一些,人多了之后,平均工资水平以后应该不会和其他行业差别这么大。但是,我个人感觉技术厉害的还是会很吃香。只是,普通的程序员的工资可能比不上前几年了。 14 | 15 | **养成一个学习习惯和编程习惯真的太重要了,一个好习惯的养成真的对后面的学习有很大帮助。** 说实话我自己当初在这方面吃了不少亏,很多比较好的习惯我也是后面自己才慢慢发现,所以这里想着重给大家说一下有哪些好的学习和编程习惯。另外,**不要在意自己会多少框架,真的没有一点用!** 16 | 17 | 下面是一些我觉得还不错的编程好习惯,希望对大家有帮助。 18 | 19 | ## 编程好习惯推荐 20 | 21 | > **下面这些我都总结在了 Github 上,更多内容可以通过这个链接查看:** https://github.com/Snailclimb/programmer-advancement 。 22 | 23 | ### 正确提问 24 | 25 | 我们平时任何时候都离不开提问特别是初学的时候,但是真正知道如何正确的提问的人很少。问别人问题前不要来一句“在吗”,你说你问了在吗我是回复好还是不回复好呢 ?不要让别人给你发 32 位的JDK,除非你是喜欢那个人。 26 | 27 | 更多关于如何提问的内容,详见 github 上开源版『提问的智慧』 ,抽时间看一下,我想看完之后应该会有很多收获。 28 | 29 | 更多内容可以查看我的这篇原创文章:[如何提问](docs/how-to-ask.md) 30 | 31 | ### 健康生活 32 | 33 | 我一直觉得这一方面是最重要的,我想很多人和我一样会无意识间忽略它,等到真的身体不舒服了,你才开始意识到健康生活的重要性。 34 | 35 | 1. 除非万不得已,不要熬夜了。熬夜的危害就不用多说了,秃头加内分泌失调,你懂得! 36 | 2. 看电脑45分钟之后,起来走5分钟,看看远方放松一下。不要觉得这5分钟浪费时间,相反,这5分钟可能为你带来更大的效率提升。 37 | 3. 可以考虑买一个电脑架子,保护好自己脊椎的同时,办公体验也会提升很多。 38 | 4. 可以下载一个护眼宝,感觉可以护眼模式挺棒的,非常适合我们这种需要经常盯着电脑的人使用,强烈安利。 39 | 40 | ### 高效搜索 41 | 42 | 尽量用 google 查找技术资料以及自己在学习中遇到的一些问题。 43 | 44 | ### 解决 bug 45 | 46 | 程序遇到问题先在 stackoverflow 找找,大部分别人已经遇到过了。如果上面没有的话,再考虑其他解决办法。实在解决不了的话,再去问你觉得有能力帮你解决的人(注意描述好自己的问题,不要随便截一个Bug 图)。 47 | 48 | ### 善于总结 49 | 50 | 学习完任何一门知识后,你可能当时看视频感觉老师讲的挺容易懂的。但是,过几天后你发现你忘的一干二净,别人问你一个类似的问题,你一点思路都没有。所以,我推荐你学完一门知识后不光要及时复习,还要做好总结,让知识形成一个体系。另外,你可以假想自己要给别人讲这个知识点,你能不能把这个知识点讲清楚呢?如果不能,说明你对这个知识点还没有彻底了解。这也就是人们经常说的费曼学习技巧。 51 | 52 | 总结的方式: 53 | 54 | 1. 有道云笔记、OneNote......这类专门用来记录笔记的软件上; 55 | 2. 思维导图; 56 | 3. 通过写博客输出。可以考虑自己搭建一个博客(hexo+GithubPages非常简单),你也可以在简书、掘金......等等技术交流社区写博客。Markdown 格式参考: 中文文案排版指北: 57 | 58 | ### 写博客 59 | 60 | 写博客有哪些好处: 61 | 62 | 1. 对知识有更加深的认识,让自己的知识体系更加完整; 63 | 2. 督促自己学习; 64 | 3. 可能会带来不错的经济收入; 65 | 4. 提升个人影响力; 66 | 5. 拥有更多机会; 67 | 6. ...... 68 | 69 | **总的来说,写博客是一件利己利彼的事情。你可能会从中收获到很多东西,你写的东西也可能对别人也有很大的帮助。但是,写博客还是比较耗费自己时间的,你需要和工作做好权衡。** 70 | 71 | **分享是一种美德,任何行业都不是靠单打独斗的,写博客、写好博客是一个程序员很好的习惯。我为人人,人人为我!** 72 | 73 | 更多内容可以查看我的这篇原创文章:[我为什么推荐你写博客?](./docs/我为什么推荐你写博客.md) 74 | 75 | ### 多用 Github 76 | 77 | 没事多去Github转转,如果有能力可以参与到一些开源项目中。多看看别人开源的优秀项目,看看别人的代码和设计思路,看的多了,你的编程思想也会慢慢得到提升。除了这些优秀的开源项目之外,Github上面还有很多不错的开源文档、开源资料什么的,我觉得对我们平时学习都挺有帮助。Github用得好还能装一下,毕竟人家还是一个全英文网站,咳咳咳。 78 | 79 | ### 实践 80 | 81 | 多去实践,将学到的东西运用到实际项目中去。很多人都找我抱怨过没有实际项目让自己去做,怎么能有项目经验呢?如果实在没有实际项目让你去做,我觉得你可以通过下面几种方式: 82 | 83 | 1. 在网上找一个符合自己能力与找工作需求的实战项目视频或者博客跟着老师一起做。做的过程中,你要有自己的思考,不要浅尝辄止,对于很多知识点,别人的讲解可能只是满足项目就够了,你自己想多点知识的话,对于重要的知识点就要自己学会去往深出学。 84 | 2. Github或者码云上面有很多实战类别项目,你可以选择一个来研究,为了让自己对这个项目更加理解,在理解原有代码的基础上,你可以对原有项目进行改进或者增加功能。 85 | 3. 自己动手去做一个自己想完成的东西,遇到不会的东西就临时去学,现学现卖。 86 | 87 | ### 注意代码规范 88 | 89 | 从学习编程的第一天起就要养成不错的编码习惯,包、类、方法的命名这些是最基本的。 90 | 91 | 推荐阅读: 92 | 93 | - 阿里巴巴Java开发手册(详尽版)[https://github.com/alibaba/p3c/blob/master/阿里巴巴Java开发手册(详尽版).pdf](https://github.com/alibaba/p3c/blob/master/%E9%98%BF%E9%87%8C%E5%B7%B4%E5%B7%B4Java%E5%BC%80%E5%8F%91%E6%89%8B%E5%86%8C%EF%BC%88%E8%AF%A6%E5%B0%BD%E7%89%88%EF%BC%89.pdf) 94 | - Google Java编程风格指南: 95 | - Effective Java第三版中文版: 96 | 97 | ### 沟通能力 98 | 99 | 程序员也离不开沟通。你可能需要与客户交流需求,还要和同事交流项目问题,还有可能定期需要向领导汇报项目进展情况。所以,我觉得不错的沟通能力也是一个优秀的程序员应该有的基本素质。 100 | 101 | ## 学习方法和学习路线推荐 102 | 103 | 推荐查看我的这篇文章[《可能是最适合你的Java学习方法和路线推荐》](https://github.com/Snailclimb/JavaGuide/blob/master/docs/questions/java-learning-path-and-methods.md),文中提到的学习路线以及方法是笔主根据个人学习经历总结改进后得出,我相信照着这条学习路线来你的学习效率会非常高。 104 | 105 | -------------------------------------------------------------------------------- /docs/system-design/authority-certification/JWT-advantages-and-disadvantages.md: -------------------------------------------------------------------------------- 1 | # JWT 身份认证优缺点分析以及常见问题解决方案 2 | 3 | 之前分享了一个使用 Spring Security 实现 JWT 身份认证的 Demo,文章地址:[适合初学者入门 Spring Security With JWT 的 Demo](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485622&idx=1&sn=e9750ed63c47457ba1896db8dfceac6a&chksm=cea2477df9d5ce6b7af20e582c6c60b7408a6459b05b849394c45f04664d1651510bdee029f7&token=684071313&lang=zh_CN&scene=21#wechat_redirect)。 Demo 非常简单,没有介绍到 JWT 存在的一些问题。所以,单独抽了一篇文章出来介绍。为了完成这篇文章,我查阅了很多资料和文献,我觉得应该对大家有帮助。 4 | 5 | 相关阅读: 6 | 7 | - [《一问带你区分清楚Authentication,Authorization以及Cookie、Session、Token》](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485626&idx=1&sn=3247aa9000693dd692de8a04ccffeec1&chksm=cea24771f9d5ce675ea0203633a95b68bfe412dc6a9d05f22d221161147b76161d1b470d54b3&token=684071313&lang=zh_CN&scene=21#wechat_redirect) 8 | - [适合初学者入门 Spring Security With JWT 的 Demo](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485622&idx=1&sn=e9750ed63c47457ba1896db8dfceac6a&chksm=cea2477df9d5ce6b7af20e582c6c60b7408a6459b05b849394c45f04664d1651510bdee029f7&token=684071313&lang=zh_CN&scene=21#wechat_redirect) 9 | - [Spring Boot 使用 JWT 进行身份和权限验证](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485640&idx=1&sn=0ff147808318d53b371f16bb730c96ef&chksm=cea24703f9d5ce156ba67662f6f3f482330e8e6ebd9d44c61bf623083e9b941d8a180db6b0ea&token=1533246333&lang=zh_CN#rd) 10 | 11 | ## Token 认证的优势 12 | 13 | 相比于 Session 认证的方式来说,使用 token 进行身份认证主要有下面三个优势: 14 | 15 | ### 1.无状态 16 | 17 | token 自身包含了身份验证所需要的所有信息,使得我们的服务器不需要存储 Session 信息,这显然增加了系统的可用性和伸缩性,大大减轻了服务端的压力。但是,也正是由于 token 的无状态,也导致了它最大的缺点:当后端在token 有效期内废弃一个 token 或者更改它的权限的话,不会立即生效,一般需要等到有效期过后才可以。另外,当用户 Logout 的话,token 也还有效。除非,我们在后端增加额外的处理逻辑。 18 | 19 | ### 2.有效避免了CSRF 攻击 20 | 21 | **CSRF(Cross Site Request Forgery)**一般被翻译为 **跨站请求伪造**,属于网络攻击领域范围。相比于 SQL 脚本注入、XSS等等安全攻击方式,CSRF 的知名度并没有它们高。但是,它的确是每个系统都要考虑的安全隐患,就连技术帝国 Google 的 Gmail 在早些年也被曝出过存在 CSRF 漏洞,这给 Gmail 的用户造成了很大的损失。 22 | 23 | 那么究竟什么是 **跨站请求伪造** 呢?说简单用你的身份去发送一些对你不友好的请求。举个简单的例子: 24 | 25 | 小壮登录了某网上银行,他来到了网上银行的帖子区,看到一个帖子下面有一个链接写着“科学理财,年盈利率过万”,小壮好奇的点开了这个链接,结果发现自己的账户少了10000元。这是这么回事呢?原来黑客在链接中藏了一个请求,这个请求直接利用小壮的身份给银行发送了一个转账请求,也就是通过你的 Cookie 向银行发出请求。 26 | 27 | ```html 28 | 科学理财,年盈利率过万 29 | ``` 30 | 31 | 导致这个问题很大的原因就是: Session 认证中 Cookie 中的 session_id 是由浏览器发送到服务端的,借助这个特性,攻击者就可以通过让用户误点攻击链接,达到攻击效果。 32 | 33 | **那为什么 token 不会存在这种问题呢?** 34 | 35 | 我是这样理解的:一般情况下我们使用 JWT 的话,在我们登录成功获得 token 之后,一般会选择存放在 local storage 中。然后我们在前端通过某些方式会给每个发到后端的请求加上这个 token,这样就不会出现 CSRF 漏洞的问题。因为,即使有个你点击了非法链接发送了请求到服务端,这个非法请求是不会携带 token 的,所以这个请求将是非法的。 36 | 37 | 但是这样会存在 XSS 攻击中被盗的风险,为了避免 XSS 攻击,你可以选择将 token 存储在标记为`httpOnly` 的cookie 中。但是,这样又导致了你必须自己提供CSRF保护。 38 | 39 | 具体采用上面哪两种方式存储 token 呢,大部分情况下存放在 local storage 下都是最好的选择,某些情况下可能需要存放在标记为`httpOnly` 的cookie 中会更好。 40 | 41 | ### 3.适合移动端应用 42 | 43 | 使用 Session 进行身份认证的话,需要保存一份信息在服务器端,而且这种方式会依赖到 Cookie(需要 Cookie 保存 SessionId),所以不适合移动端。 44 | 45 | 但是,使用 token 进行身份认证就不会存在这种问题,因为只要 token 可以被客户端存储就能够使用,而且 token 还可以跨语言使用。 46 | 47 | ### 4.单点登录友好 48 | 49 | 使用 Session 进行身份认证的话,实现单点登录,需要我们把用户的 Session 信息保存在一台电脑上,并且还会遇到常见的 Cookie 跨域的问题。但是,使用 token 进行认证的话, token 被保存在客户端,不会存在这些问题。 50 | 51 | ## Token 认证常见问题以及解决办法 52 | 53 | ### 1.注销登录等场景下 token 还有效 54 | 55 | 与之类似的具体相关场景有: 56 | 57 | 1. 退出登录; 58 | 2. 修改密码; 59 | 3. 服务端修改了某个用户具有的权限或者角色; 60 | 4. 用户的帐户被删除/暂停。 61 | 5. 用户由管理员注销; 62 | 63 | 这个问题不存在于 Session 认证方式中,因为在 Session 认证方式中,遇到这种情况的话服务端删除对应的 Session 记录即可。但是,使用 token 认证的方式就不好解决了。我们也说过了,token 一旦派发出去,如果后端不增加其他逻辑的话,它在失效之前都是有效的。那么,我们如何解决这个问题呢?查阅了很多资料,总结了下面几种方案: 64 | 65 | - **将 token 存入内存数据库**:将 token 存入 DB 中,redis 内存数据库在这里是是不错的选择。如果需要让某个 token 失效就直接从 redis 中删除这个 token 即可。但是,这样会导致每次使用 token 发送请求都要先从 DB 中查询 token 是否存在的步骤,而且违背了 JWT 的无状态原则。 66 | - **黑名单机制**:和上面的方式类似,使用内存数据库比如 redis 维护一个黑名单,如果想让某个 token 失效的话就直接将这个 token 加入到 **黑名单** 即可。然后,每次使用 token 进行请求的话都会先判断这个 token 是否存在于黑名单中。 67 | - **修改密钥 (Secret)** : 我们为每个用户都创建一个专属密钥,如果我们想让某个 token 失效,我们直接修改对应用户的密钥即可。但是,这样相比于前两种引入内存数据库带来了危害更大,比如:1⃣️如果服务是分布式的,则每次发出新的 token 时都必须在多台机器同步密钥。为此,你需要将必须将机密存储在数据库或其他外部服务中,这样和 Session 认证就没太大区别了。2⃣️如果用户同时在两个浏览器打开系统,或者在手机端也打开了系统,如果它从一个地方将账号退出,那么其他地方都要重新进行登录,这是不可取的。 68 | - **保持令牌的有效期限短并经常轮换** :很简单的一种方式。但是,会导致用户登录状态不会被持久记录,而且需要用户经常登录。 69 | 70 | 对于修改密码后 token 还有效问题的解决还是比较容易的,说一种我觉得比较好的方式:**使用用户的密码的哈希值对 token 进行签名。因此,如果密码更改,则任何先前的令牌将自动无法验证。** 71 | 72 | ### 2.token 的续签问题 73 | 74 | token 有效期一般都建议设置的不太长,那么 token 过期后如何认证,如何实现动态刷新 token,避免用户经常需要重新登录? 75 | 76 | 我们先来看看在 Session 认证中一般的做法:**假如 session 的有效期30分钟,如果 30 分钟内用户有访问,就把 session 有效期被延长30分钟。** 77 | 78 | 1. **类似于 Session 认证中的做法**:这种方案满足于大部分场景。假设服务端给的 token 有效期设置为30分钟,服务端每次进行校验时,如果发现 token 的有效期马上快过期了,服务端就重新生成 token 给客户端。客户端每次请求都检查新旧token,如果不一致,则更新本地的token。这种做法的问题是仅仅在快过期的时候请求才会更新 token ,对客户端不是很友好。 79 | 2. **每次请求都返回新 token** :这种方案的的思路很简单,但是,很明显,开销会比较大。 80 | 3. **token 有效期设置到半夜** :这种方案是一种折衷的方案,保证了大部分用户白天可以正常登录,适用于对安全性要求不高的系统。 81 | 4. **用户登录返回两个 token** :第一个是 acessToken ,它的过期时间 token 本身的过期时间比如半个小时,另外一个是 refreshToken 它的过期时间更长一点比如为1天。客户端登录后,将 accessToken和refreshToken 保存在本地,每次访问将 accessToken 传给服务端。服务端校验 accessToken 的有效性,如果过期的话,就将 refreshToken 传给服务端。如果有效,服务端就生成新的 accessToken 给客户端。否则,客户端就重新登录即可。该方案的不足是:1⃣️需要客户端来配合;2⃣️用户注销的时候需要同时保证两个 token 都无效;3⃣️重新请求获取 token 的过程中会有短暂 token 不可用的情况(可以通过在客户端设置定时器,当accessToken 快过期的时候,提前去通过 refreshToken 获取新的accessToken)。 82 | 83 | ## 总结 84 | 85 | JWT 最适合的场景是不需要服务端保存用户状态的场景,比如如果考虑到 token 注销和 token 续签的场景话,没有特别好的解决方案,大部分解决方案都给 token 加上了状态,这就有点类似 Session 认证了。 86 | 87 | ## Reference 88 | 89 | - [JWT 超详细分析](https://learnku.com/articles/17883?order_by=vote_count&) 90 | - https://medium.com/devgorilla/how-to-log-out-when-using-jwt-a8c7823e8a6 91 | - https://medium.com/@agungsantoso/csrf-protection-with-json-web-tokens-83e0f2fcbcc 92 | - [Invalidating JSON Web Tokens](https://stackoverflow.com/questions/21978658/invalidating-json-web-tokens) 93 | 94 | -------------------------------------------------------------------------------- /docs/system-design/authority-certification/basis-of-authority-certification.md: -------------------------------------------------------------------------------- 1 | ## 1. 认证 (Authentication) 和授权 (Authorization)的区别是什么? 2 | 3 | 这是一个绝大多数人都会混淆的问题。首先先从读音上来认识这两个名词,很多人都会把它俩的读音搞混,所以我建议你先先去查一查这两个单词到底该怎么读,他们的具体含义是什么。 4 | 5 | 说简单点就是: 6 | 7 | - **认证 (Authentication):** 你是谁。 8 | - **授权 (Authorization):** 你有权限干什么。 9 | 10 | 稍微正式点(啰嗦点)的说法就是: 11 | 12 | - **Authentication(认证)** 是验证您的身份的凭据(例如用户名/用户ID和密码),通过这个凭据,系统得以知道你就是你,也就是说系统存在你这个用户。所以,Authentication 被称为身份/用户验证。 13 | - **Authorization(授权)** 发生在 **Authentication(认证)** 之后。授权嘛,光看意思大家应该就明白,它主要掌管我们访问系统的权限。比如有些特定资源只能具有特定权限的人才能访问比如admin,有些对系统资源操作比如删除、添加、更新只能特定人才具有。 14 | 15 | 这两个一般在我们的系统中被结合在一起使用,目的就是为了保护我们系统的安全性。 16 | 17 | ## 2. 什么是Cookie ? Cookie的作用是什么?如何在服务端使用 Cookie ? 18 | 19 | ### 2.1 什么是Cookie ? Cookie的作用是什么? 20 | 21 | Cookie 和 Session都是用来跟踪浏览器用户身份的会话方式,但是两者的应用场景不太一样。 22 | 23 | 维基百科是这样定义 Cookie 的:Cookies是某些网站为了辨别用户身份而储存在用户本地终端上的数据(通常经过加密)。简单来说: **Cookie 存放在客户端,一般用来保存用户信息**。 24 | 25 | 下面是 Cookie 的一些应用案例: 26 | 27 | 1. 我们在 Cookie 中保存已经登录过得用户信息,下次访问网站的时候页面可以自动帮你登录的一些基本信息给填了。除此之外,Cookie 还能保存用户首选项,主题和其他设置信息。 28 | 2. 使用Cookie 保存 session 或者 token ,向后端发送请求的时候带上 Cookie,这样后端就能取到session或者token了。这样就能记录用户当前的状态了,因为 HTTP 协议是无状态的。 29 | 3. Cookie 还可以用来记录和分析用户行为。举个简单的例子你在网上购物的时候,因为HTTP协议是没有状态的,如果服务器想要获取你在某个页面的停留状态或者看了哪些商品,一种常用的实现方式就是将这些信息存放在Cookie 30 | 31 | ### 2.2 如何能在 服务端使用 Cookie 呢? 32 | 33 | 这部分内容参考:https://attacomsian.com/blog/cookies-spring-boot,更多如何在Spring Boot中使用Cookie 的内容可以查看这篇文章。 34 | 35 | **1)设置cookie返回给客户端** 36 | 37 | ```java 38 | @GetMapping("/change-username") 39 | public String setCookie(HttpServletResponse response) { 40 | // 创建一个 cookie 41 | Cookie cookie = new Cookie("username", "Jovan"); 42 | //设置 cookie过期时间 43 | cookie.setMaxAge(7 * 24 * 60 * 60); // expires in 7 days 44 | //添加到 response 中 45 | response.addCookie(cookie); 46 | 47 | return "Username is changed!"; 48 | } 49 | ``` 50 | 51 | **2) 使用Spring框架提供的`@CookieValue`注解获取特定的 cookie的值** 52 | 53 | ```java 54 | @GetMapping("/") 55 | public String readCookie(@CookieValue(value = "username", defaultValue = "Atta") String username) { 56 | return "Hey! My username is " + username; 57 | } 58 | ``` 59 | 60 | **3) 读取所有的 Cookie 值** 61 | 62 | ```java 63 | @GetMapping("/all-cookies") 64 | public String readAllCookies(HttpServletRequest request) { 65 | 66 | Cookie[] cookies = request.getCookies(); 67 | if (cookies != null) { 68 | return Arrays.stream(cookies) 69 | .map(c -> c.getName() + "=" + c.getValue()).collect(Collectors.joining(", ")); 70 | } 71 | 72 | return "No cookies"; 73 | } 74 | ``` 75 | 76 | ## 3. Cookie 和 Session 有什么区别?如何使用Session进行身份验证? 77 | 78 | **Session 的主要作用就是通过服务端记录用户的状态。** 典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为 HTTP 协议是无状态的。服务端给特定的用户创建特定的 Session 之后就可以标识这个用户并且跟踪这个用户了。 79 | 80 | **Cookie 数据保存在客户端(浏览器端),Session 数据保存在服务器端。相对来说 Session 安全性更高。如果使用 Cookie 的一些敏感信息不要写入 Cookie 中,最好能将 Cookie 信息加密然后使用到的时候再去服务器端解密。** 81 | 82 | **那么,如何使用Session进行身份验证?** 83 | 84 | 很多时候我们都是通过 SessionID 来实现特定的用户,SessionID 一般会选择存放在 Redis 中。举个例子:用户成功登陆系统,然后返回给客户端具有 SessionID 的 Cookie,当用户向后端发起请求的时候会把 SessionID 带上,这样后端就知道你的身份状态了。关于这种认证方式更详细的过程如下: 85 | 86 | ![Session Based Authentication flow](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/Session-Based-Authentication-flow.png) 87 | 88 | 1. 用户向服务器发送用户名和密码用于登陆系统。 89 | 2. 服务器验证通过后,服务器为用户创建一个 Session,并将 Session信息存储 起来。 90 | 3. 服务器向用户返回一个 SessionID,写入用户的 Cookie。 91 | 4. 当用户保持登录状态时,Cookie 将与每个后续请求一起被发送出去。 92 | 5. 服务器可以将存储在 Cookie 上的 Session ID 与存储在内存中或者数据库中的 Session 信息进行比较,以验证用户的身份,返回给用户客户端响应信息的时候会附带用户当前的状态。 93 | 94 | 另外,Spring Session提供了一种跨多个应用程序或实例管理用户会话信息的机制。如果想详细了解可以查看下面几篇很不错的文章: 95 | 96 | - [Getting Started with Spring Session](https://codeboje.de/spring-session-tutorial/) 97 | - [Guide to Spring Session](https://www.baeldung.com/spring-session) 98 | - [Sticky Sessions with Spring Session & Redis](https://medium.com/@gvnix/sticky-sessions-with-spring-session-redis-bdc6f7438cc3) 99 | 100 | ## 4. 什么是 Token?什么是 JWT?如何基于Token进行身份验证? 101 | 102 | 我们在上一个问题中探讨了使用 Session 来鉴别用户的身份,并且给出了几个 Spring Session 的案例分享。 我们知道 Session 信息需要保存一份在服务器端。这种方式会带来一些麻烦,比如需要我们保证保存 Session 信息服务器的可用性、不适合移动端(依赖Cookie)等等。 103 | 104 | 有没有一种不需要自己存放 Session 信息就能实现身份验证的方式呢?使用 Token 即可!JWT (JSON Web Token) 就是这种方式的实现,通过这种方式服务器端就不需要保存 Session 数据了,只用在客户端保存服务端返回给客户的 Token 就可以了,扩展性得到提升。 105 | 106 | **JWT 本质上就一段签名的 JSON 格式的数据。由于它是带有签名的,因此接收者便可以验证它的真实性。** 107 | 108 | 下面是 [RFC 7519](https://tools.ietf.org/html/rfc7519) 对 JWT 做的较为正式的定义。 109 | 110 | > JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted. ——[JSON Web Token (JWT)](https://tools.ietf.org/html/rfc7519) 111 | 112 | JWT 由 3 部分构成: 113 | 114 | 1. Header :描述 JWT 的元数据。定义了生成签名的算法以及 Token 的类型。 115 | 2. Payload(负载):用来存放实际需要传递的数据 116 | 3. Signature(签名):服务器通过`Payload`、`Header`和一个密钥(`secret`)使用 Header 里面指定的签名算法(默认是 HMAC SHA256)生成。 117 | 118 | 在基于 Token 进行身份验证的的应用程序中,服务器通过`Payload`、`Header`和一个密钥(`secret`)创建令牌(`Token`)并将 `Token` 发送给客户端,客户端将 `Token` 保存在 Cookie 或者 localStorage 里面,以后客户端发出的所有请求都会携带这个令牌。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP Header 的 Authorization字段中:` Authorization: Bearer Token`。 119 | 120 | ![Token Based Authentication flow](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/Token-Based-Authentication.png) 121 | 122 | 1. 用户向服务器发送用户名和密码用于登陆系统。 123 | 2. 身份验证服务响应并返回了签名的 JWT,上面包含了用户是谁的内容。 124 | 3. 用户以后每次向后端发请求都在Header中带上 JWT。 125 | 4. 服务端检查 JWT 并从中获取用户相关信息。 126 | 127 | 128 | 推荐阅读: 129 | 130 | - [JWT (JSON Web Tokens) Are Better Than Session Cookies](https://dzone.com/articles/jwtjson-web-tokens-are-better-than-session-cookies) 131 | - [JSON Web Tokens (JWT) 与 Sessions](https://juejin.im/entry/577b7b56a3413100618c2938) 132 | - [JSON Web Token 入门教程](https://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html) 133 | - [彻底理解Cookie,Session,Token](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247485603&idx=1&sn=c8d324f44d6102e7b44554733da10bb7&chksm=cea24768f9d5ce7efe7291ddabce02b68db34073c7e7d9a7dc9a7f01c5a80cebe33ac75248df&token=844918801&lang=zh_CN#rd) 134 | 135 | ## 5 什么是OAuth 2.0? 136 | 137 | OAuth 是一个行业的标准授权协议,主要用来授权第三方应用获取有限的权限。而 OAuth 2.0是对 OAuth 1.0 的完全重新设计,OAuth 2.0更快,更容易实现,OAuth 1.0 已经被废弃。详情请见:[rfc6749](https://tools.ietf.org/html/rfc6749)。 138 | 139 | 实际上它就是一种授权机制,它的最终目的是为第三方应用颁发一个有时效性的令牌 token,使得第三方应用能够通过该令牌获取相关的资源。 140 | 141 | OAuth 2.0 比较常用的场景就是第三方登录,当你的网站接入了第三方登录的时候一般就是使用的 OAuth 2.0 协议。 142 | 143 | **推荐阅读:** 144 | 145 | - [OAuth 2.0 的一个简单解释](http://www.ruanyifeng.com/blog/2019/04/oauth_design.html) 146 | - [10 分钟理解什么是 OAuth 2.0 协议](https://deepzz.com/post/what-is-oauth2-protocol.html) 147 | - [OAuth 2.0 的四种方式](http://www.ruanyifeng.com/blog/2019/04/oauth-grant-types.html) 148 | - [GitHub OAuth 第三方登录示例教程](http://www.ruanyifeng.com/blog/2019/04/github-oauth.html) 149 | 150 | ## 参考 151 | 152 | - https://medium.com/@sherryhsu/session-vs-token-based-authentication-11a6c5ac45e4 153 | - https://www.varonis.com/blog/what-is-oauth/ 154 | - https://tools.ietf.org/html/rfc6749 155 | -------------------------------------------------------------------------------- /docs/system-design/data-communication/summary.md: -------------------------------------------------------------------------------- 1 | > ## RPC 2 | 3 | **RPC(Remote Procedure Call)—远程过程调用** ,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发分布式程序就像开发本地程序一样简单。 4 | 5 | **RPC采用客户端(服务调用方)/服务器端(服务提供方)模式,** 都运行在自己的JVM中。客户端只需要引入要使用的接口,接口的实现和运行都在服务器端。RPC主要依赖的技术包括序列化、反序列化和数据传输协议,这是一种定义与实现相分离的设计。 6 | 7 | **目前Java使用比较多的RPC方案主要有RMI(JDK自带)、Hessian、Dubbo以及Thrift等。** 8 | 9 | **注意: RPC主要指内部服务之间的调用,RESTful也可以用于内部服务之间的调用,但其主要用途还在于外部系统提供服务,因此没有将其包含在本知识点内。** 10 | 11 | ### 常见RPC框架: 12 | 13 | - **RMI(JDK自带):** JDK自带的RPC 14 | 15 | 详细内容可以参考:[从懵逼到恍然大悟之Java中RMI的使用](https://blog.csdn.net/lmy86263/article/details/72594760) 16 | 17 | - **Dubbo:** Dubbo是 阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成。 18 | 19 | 详细内容可以参考: 20 | 21 | - [ 高性能优秀的服务框架-dubbo介绍](https://blog.csdn.net/qq_34337272/article/details/79862899) 22 | 23 | - [Dubbo是什么?能做什么?](https://blog.csdn.net/houshaolin/article/details/76408399) 24 | 25 | 26 | - **Hessian:** Hessian是一个轻量级的remotingonhttp工具,使用简单的方法提供了RMI的功能。 相比WebService,Hessian更简单、快捷。采用的是二进制RPC协议,因为采用的是二进制协议,所以它很适合于发送二进制数据。 27 | 28 | 详细内容可以参考: [Hessian的使用以及理解](https://blog.csdn.net/sunwei_pyw/article/details/74002351) 29 | 30 | - **Thrift:** Apache Thrift是Facebook开源的跨语言的RPC通信框架,目前已经捐献给Apache基金会管理,由于其跨语言特性和出色的性能,在很多互联网公司得到应用,有能力的公司甚至会基于thrift研发一套分布式服务框架,增加诸如服务注册、服务发现等功能。 31 | 32 | 33 | 详细内容可以参考: [【Java】分布式RPC通信框架Apache Thrift 使用总结](https://www.cnblogs.com/zeze/p/8628585.html) 34 | 35 | ### 如何进行选择: 36 | 37 | - **是否允许代码侵入:** 即需要依赖相应的代码生成器生成代码,比如Thrift。 38 | - **是否需要长连接获取高性能:** 如果对于性能需求较高的haul,那么可以果断选择基于TCP的Thrift、Dubbo。 39 | - **是否需要跨越网段、跨越防火墙:** 这种情况一般选择基于HTTP协议的Hessian和Thrift的HTTP Transport。 40 | 41 | 此外,Google推出的基于HTTP2.0的gRPC框架也开始得到应用,其序列化协议基于Protobuf,网络框架使用的是Netty4,但是其需要生成代码,可扩展性也比较差。 42 | 43 | > ## 消息中间件 44 | 45 | **消息中间件,也可以叫做中央消息队列或者是消息队列(区别于本地消息队列,本地消息队列指的是JVM内的队列实现)**,是一种独立的队列系统,消息中间件经常用来解决内部服务之间的 **异步调用问题** 。请求服务方把请求队列放到队列中即可返回,然后等待服务提供方去队列中获取请求进行处理,之后通过回调等机制把结果返回给请求服务方。 46 | 47 | 异步调用只是消息中间件一个非常常见的应用场景。此外,常用的消息队列应用场景还有如下几个: 48 | - **解耦 :** 一个业务的非核心流程需要依赖其他系统,但结果并不重要,有通知即可。 49 | - **最终一致性 :** 指的是两个系统的状态保持一致,可以有一定的延迟,只要最终达到一致性即可。经常用在解决分布式事务上。 50 | - **广播 :** 消息队列最基本的功能。生产者只负责生产消息,订阅者接收消息。 51 | - **错峰和流控** 52 | 53 | 54 | 具体可以参考: 55 | 56 | [《消息队列深入解析》](https://blog.csdn.net/qq_34337272/article/details/80029918) 57 | 58 | 当前使用较多的消息队列有ActiveMQ(性能差,不推荐使用)、RabbitMQ、RocketMQ、Kafka等等,我们之前提到的redis数据库也可以实现消息队列,不过不推荐,redis本身设计就不是用来做消息队列的。 59 | 60 | - **ActiveMQ:** ActiveMQ是Apache出品,最流行的,能力强劲的开源消息总线。ActiveMQ是一个完全支持JMS1.1和J2EE 1.4规范的JMSProvider实现,尽管JMS规范出台已经是很久的事情了,但是JMS在当今的J2EE应用中间仍然扮演着特殊的地位。 61 | 62 | 具体可以参考: 63 | 64 | [《消息队列ActiveMQ的使用详解》](https://blog.csdn.net/qq_34337272/article/details/80031702) 65 | 66 | - **RabbitMQ:** RabbitMQ 是一个由 Erlang 语言开发的 AMQP 的开源实现。RabbitMQ 最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗 67 | > AMQP :Advanced Message Queue,高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。 68 | 69 | 70 | 具体可以参考: 71 | 72 | [《消息队列之 RabbitMQ》](https://www.jianshu.com/p/79ca08116d57) 73 | 74 | - **RocketMQ:** 75 | 76 | 具体可以参考: 77 | 78 | [《RocketMQ 实战之快速入门》](https://www.jianshu.com/p/824066d70da8) 79 | 80 | [《十分钟入门RocketMQ》](http://jm.taobao.org/2017/01/12/rocketmq-quick-start-in-10-minutes/) (阿里中间件团队博客) 81 | 82 | 83 | - **Kafka**:Kafka是一个分布式的、可分区的、可复制的、基于发布/订阅的消息系统(现在官方的描述是“一个分布式流平台”),Kafka主要用于大数据领域,当然在分布式系统中也有应用。目前市面上流行的消息队列RocketMQ就是阿里借鉴Kafka的原理、用Java开发而得。 84 | 85 | 具体可以参考: 86 | 87 | [《Kafka应用场景》](http://book.51cto.com/art/201801/565244.htm) 88 | 89 | [《初谈Kafka》](https://mp.weixin.qq.com/s?__biz=MzU4NDQ4MzU5OA==&mid=2247484106&idx=1&sn=aa1999895d009d91eb3692a3e6429d18&chksm=fd9854abcaefddbd1101ca5dc2c7c783d7171320d6300d9b2d8e68b7ef8abd2b02ea03e03600#rd) 90 | 91 | **推荐阅读:** 92 | 93 | [《Kafka、RabbitMQ、RocketMQ等消息中间件的对比 —— 消息发送性能和区别》](https://mp.weixin.qq.com/s?__biz=MzU5OTMyODAyNg==&mid=2247484721&idx=1&sn=11e4e29886e581dd328311d308ccc068&chksm=feb7d144c9c058529465b02a4e26a25ef76b60be8984ace9e4a0f5d3d98ca52e014ecb73b061&scene=21#wechat_redirect) 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /docs/system-design/data-communication/why-use-rpc.md: -------------------------------------------------------------------------------- 1 | ## 什么是 RPC?RPC原理是什么? 2 | 3 | ### **什么是 RPC?** 4 | 5 | RPC(Remote Procedure Call)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。比如两个不同的服务 A、B 部署在两台不同的机器上,那么服务 A 如果想要调用服务 B 中的某个方法该怎么办呢?使用 HTTP请求 当然可以,但是可能会比较慢而且一些优化做的并不好。 RPC 的出现就是为了解决这个问题。 6 | 7 | ### **RPC原理是什么?** 8 | 9 | 我这里这是简单的提一下,详细内容可以查看下面这篇文章: 10 | 11 | http://www.importnew.com/22003.html 12 | 13 | ![RPC原理图](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-12-6/37345851.jpg) 14 | 15 | 1. 服务消费方(client)调用以本地调用方式调用服务; 16 | 2. client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体; 17 | 3. client stub找到服务地址,并将消息发送到服务端; 18 | 4. server stub收到消息后进行解码; 19 | 5. server stub根据解码结果调用本地的服务; 20 | 6. 本地服务执行并将结果返回给server stub; 21 | 7. server stub将返回结果打包成消息并发送至消费方; 22 | 8. client stub接收到消息,并进行解码; 23 | 9. 服务消费方得到最终结果。 24 | 25 | 下面再贴一个网上的时序图: 26 | 27 | ![RPC原理时序图](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-12-6/32527396.jpg) 28 | 29 | ### RPC 解决了什么问题? 30 | 31 | 从上面对 RPC 介绍的内容中,概括来讲RPC 主要解决了:**让分布式或者微服务系统中不同服务之间的调用像本地调用一样简单。** 32 | 33 | ### 常见的 RPC 框架总结? 34 | 35 | - **RMI(JDK自带):** JDK自带的RPC,有很多局限性,不推荐使用。 36 | - **Dubbo:** Dubbo是 阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成。目前 Dubbo 已经成为 Spring Cloud Alibaba 中的官方组件。 37 | - **gRPC** :gRPC是可以在任何环境中运行的现代开源高性能RPC框架。它可以通过可插拔的支持来有效地连接数据中心内和跨数据中心的服务,以实现负载平衡,跟踪,运行状况检查和身份验证。它也适用于分布式计算的最后一英里,以将设备,移动应用程序和浏览器连接到后端服务。 38 | 39 | - **Hessian:** Hessian是一个轻量级的remotingonhttp工具,使用简单的方法提供了RMI的功能。 相比WebService,Hessian更简单、快捷。采用的是二进制RPC协议,因为采用的是二进制协议,所以它很适合于发送二进制数据。 40 | - **Thrift:** Apache Thrift是Facebook开源的跨语言的RPC通信框架,目前已经捐献给Apache基金会管理,由于其跨语言特性和出色的性能,在很多互联网公司得到应用,有能力的公司甚至会基于thrift研发一套分布式服务框架,增加诸如服务注册、服务发现等功能。 41 | 42 | ## 既有 HTTP ,为啥用 RPC 进行服务调用? 43 | 44 | ###RPC 只是一种设计而已 45 | 46 | RPC 只是一种概念、一种设计,就是为了解决 **不同服务之间的调用问题**, 它一般会包含有 **传输协议** 和 **序列化协议** 这两个。 47 | 48 | 实现 RPC 的可以传输协议可以直接建立在 TCP 之上,也可以建立在 HTTP 协议之上。**大部分 RPC 框架都是使用的 TCP 连接(gRPC使用了HTTP2)。** 49 | 50 | ### HTTP 和 TCP 51 | 52 | **可能现在很多对计算机网络不太熟悉的朋友已经被搞蒙了,要想真正搞懂,还需要来简单复习一下计算机网络基础知识:** 53 | 54 | > 我们通常谈计算机网络的五层协议的体系结构是指:应用层、传输层、网络层、数据链路层、物理层。 55 | > 56 | > **应用层(application-layer)的任务是通过应用进程间的交互来完成特定网络应用。**HTTP 属于应用层协议,它会基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。HTTP协议工作于客户端-服务端架构为上。浏览器作为HTTP客户端通过 URL 向HTTP服务端即WEB服务器发送所有请求。Web服务器根据接收到的请求后,向客户端发送响应信息。HTTP协议建立在 TCP 协议之上。 57 | > 58 | > **运输层(transport layer)的主要任务就是负责向两台主机进程之间的通信提供通用的数据传输服务**。TCP是传输层协议,主要解决数据如何在网络中传输。相比于UDP,**TCP** 提供的是**面向连接**的,**可靠的**数据传输服务。 59 | 60 | **主要关键就在 HTTP 使用的 TCP 协议,和我们自定义的 TCP 协议在报文上的区别。** 61 | 62 | **http1.1协议的 TCP 报文包含太多在传输过程中可能无用的信息:** 63 | 64 | ``` 65 | HTTP/1.0 200 OK 66 | Content-Type: text/plain 67 | Content-Length: 137582 68 | Expires: Thu, 05 Dec 1997 16:00:00 GMT 69 | Last-Modified: Wed, 5 August 1996 15:55:28 GMT 70 | Server: Apache 0.84 71 | 72 | 73 | Hello World 74 | 75 | ``` 76 | 77 | **使用自定义 TCP 协议进行传输就会避免上面这个问题,极大地减轻了传输数据的开销。** 78 | 这也就是为什么通常会采用自定义 TCP 协议的 RPC 79 | 来进行进行服务调用的真正原因。除此之外,成熟的 RPC 80 | 框架还提供好了“服务自动注册与发现”、"智能负载均衡"、“可视化的服务治理和运维”、“运行期流量调度”等等功能,这些也算是选择 81 | RPC 进行服务注册和发现的一方面原因吧! 82 | 83 | **相关阅读:** 84 | 85 | - http://www.ruanyifeng.com/blog/2016/08/http.html (HTTP 协议入门- 阮一峰) 86 | 87 | ### 一个常见的错误观点 88 | 89 | 很多文章中还会提到说 HTTP 协议相较于自定义 TCP 报文协议,增加的开销在于连接的建立与断开,但是这个观点已经被否认,下面截取自知乎中一个回答,原回答地址:https://www.zhihu.com/question/41609070/answer/191965937。 90 | 91 | >首先要否认一点 HTTP 协议相较于自定义 TCP 报文协议,增加的开销在于连接的建立与断开。HTTP 协议是支持连接池复用的,也就是建立一定数量的连接不断开,并不会频繁的创建和销毁连接。二一要说的是 HTTP 也可以使用 Protobuf 这种二进制编码协议对内容进行编码,因此二者最大的区别还是在传输协议上。 92 | 93 | ### 题外话 94 | 95 | 除此之外,还需要注意的一点是 Spring Cloud Netflix 并没有使用 RPC 96 | 框架来进行不同服务之间的调用,而是使用 HTTP 协议进行调用的,速度虽然不比 RPC 97 | ,但是使用 HTTP 协议也会带来其他很多好处(这一点,可以自行查阅相关资料了解)。 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /docs/system-design/framework/ZooKeeper数据模型和常见命令.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | - [ZooKeeper 数据模型](#zookeeper-数据模型) 4 | - [ZNode\(数据节点\)的结构](#znode数据节点的结构) 5 | - [测试 ZooKeeper 中的常见操作](#测试-zookeeper-中的常见操作) 6 | - [连接 ZooKeeper 服务](#连接-zookeeper-服务) 7 | - [查看常用命令\(help 命令\)](#查看常用命令help-命令) 8 | - [创建节点\(create 命令\)](#创建节点create-命令) 9 | - [更新节点数据内容\(set 命令\)](#更新节点数据内容set-命令) 10 | - [获取节点的数据\(get 命令\)](#获取节点的数据get-命令) 11 | - [查看某个目录下的子节点\(ls 命令\)](#查看某个目录下的子节点ls-命令) 12 | - [查看节点状态\(stat 命令\)](#查看节点状态stat-命令) 13 | - [查看节点信息和状态\(ls2 命令\)](#查看节点信息和状态ls2-命令) 14 | - [删除节点\(delete 命令\)](#删除节点delete-命令) 15 | - [参考](#参考) 16 | 17 | 18 | 19 | > 看本文之前如果你没有安装 ZooKeeper 的话,可以参考这篇文章:[《使用 SpringBoot+Dubbo 搭建一个简单分布式服务》](https://github.com/Snailclimb/springboot-integration-examples/blob/master/md/springboot-dubbo.md) 的 “开始实战 1 :zookeeper 环境安装搭建” 这部分进行安装(Centos7.4 环境下)。如果你想对 ZooKeeper 有一个整体了解的话,可以参考这篇文章:[《可能是把 ZooKeeper 概念讲的最清楚的一篇文章》](https://github.com/Snailclimb/JavaGuide/blob/master/%E4%B8%BB%E6%B5%81%E6%A1%86%E6%9E%B6/ZooKeeper.md) 20 | 21 | ### ZooKeeper 数据模型 22 | 23 | ZNode(数据节点)是 ZooKeeper 中数据的最小单元,每个ZNode上都可以保存数据,同时还是可以有子节点(这就像树结构一样,如下图所示)。可以看出,节点路径标识方式和Unix文件 24 | 系统路径非常相似,都是由一系列使用斜杠"/"进行分割的路径表示,开发人员可以向这个节点中写人数据,也可以在节点下面创建子节点。这些操作我们后面都会介绍到。 25 | ![ZooKeeper 数据模型](https://images.gitbook.cn/95a192b0-1c56-11e9-9a8e-f3b01b1ea9aa) 26 | 27 | 提到 ZooKeeper 数据模型,还有一个不得不得提的东西就是 **事务 ID** 。事务的ACID(Atomic:原子性;Consistency:一致性;Isolation:隔离性;Durability:持久性)四大特性我在这里就不多说了,相信大家也已经挺腻了。 28 | 29 | 在Zookeeper中,事务是指能够改变 ZooKeeper 服务器状态的操作,我们也称之为事务操作或更新操作,一般包括数据节点创建与删除、数据节点内容更新和客户端会话创建与失效等操作。**对于每一个事务请求,ZooKeeper 都会为其分配一个全局唯一的事务ID,用 ZXID 来表示**,通常是一个64位的数字。每一个ZXID对应一次更新操作,**从这些 ZXID 中可以间接地识别出Zookeeper处理这些更新操作请求的全局顺序**。 30 | 31 | ### ZNode(数据节点)的结构 32 | 33 | 每个 ZNode 由2部分组成: 34 | 35 | - stat:状态信息 36 | - data:数据内容 37 | 38 | 如下所示,我通过 get 命令来获取 根目录下的 dubbo 节点的内容。(get 命令在下面会介绍到) 39 | 40 | ```shell 41 | [zk: 127.0.0.1:2181(CONNECTED) 6] get /dubbo 42 | # 该数据节点关联的数据内容为空 43 | null 44 | # 下面是该数据节点的一些状态信息,其实就是 Stat 对象的格式化输出 45 | cZxid = 0x2 46 | ctime = Tue Nov 27 11:05:34 CST 2018 47 | mZxid = 0x2 48 | mtime = Tue Nov 27 11:05:34 CST 2018 49 | pZxid = 0x3 50 | cversion = 1 51 | dataVersion = 0 52 | aclVersion = 0 53 | ephemeralOwner = 0x0 54 | dataLength = 0 55 | numChildren = 1 56 | 57 | ``` 58 | 这些状态信息其实就是 Stat 对象的格式化输出。Stat 类中包含了一个数据节点的所有状态信息的字段,包括事务ID、版本信息和子节点个数等,如下图所示(图源:《从Paxos到Zookeeper 分布式一致性原理与实践》,下面会介绍通过 stat 命令查看数据节点的状态)。 59 | 60 | **Stat 类:** 61 | 62 | ![Stat 类](https://images.gitbook.cn/a841e740-1c55-11e9-b5b7-abf0ec0c666a) 63 | 64 | 关于数据节点的状态信息说明(也就是对Stat 类中的各字段进行说明),可以参考下图(图源:《从Paxos到Zookeeper 分布式一致性原理与实践》)。 65 | 66 | ![数据节点的状态信息说明](https://images.gitbook.cn/f44d8630-1c55-11e9-b5b7-abf0ec0c666a) 67 | 68 | ### 测试 ZooKeeper 中的常见操作 69 | 70 | 71 | #### 连接 ZooKeeper 服务 72 | 73 | 进入安装 ZooKeeper文件夹的 bin 目录下执行下面的命令连接 ZooKeeper 服务(Linux环境下)(连接之前首选要确定你的 ZooKeeper 服务已经启动成功)。 74 | 75 | ```shell 76 | ./zkCli.sh -server 127.0.0.1:2181 77 | ``` 78 | ![连接 ZooKeeper 服务](https://images.gitbook.cn/153b84c0-1c59-11e9-9a8e-f3b01b1ea9aa) 79 | 80 | 从上图可以看出控制台打印出了很多信息,包括我们的主机名称、JDK 版本、操作系统等等。如果你成功看到这些信息,说明你成功连接到 ZooKeeper 服务。 81 | 82 | #### 查看常用命令(help 命令) 83 | 84 | help 命令查看 zookeeper 常用命令 85 | 86 | ![help 命令](https://images.gitbook.cn/091db640-1c59-11e9-b5b7-abf0ec0c666a) 87 | 88 | #### 创建节点(create 命令) 89 | 90 | 通过 create 命令在根目录创建了node1节点,与它关联的字符串是"node1" 91 | 92 | ```shell 93 | [zk: 127.0.0.1:2181(CONNECTED) 34] create /node1 “node1” 94 | ``` 95 | 通过 create 命令在根目录创建了node1节点,与它关联的内容是数字 123 96 | 97 | ```shell 98 | [zk: 127.0.0.1:2181(CONNECTED) 1] create /node1/node1.1 123 99 | Created /node1/node1.1 100 | ``` 101 | 102 | #### 更新节点数据内容(set 命令) 103 | 104 | ```shell 105 | [zk: 127.0.0.1:2181(CONNECTED) 11] set /node1 "set node1" 106 | ``` 107 | 108 | #### 获取节点的数据(get 命令) 109 | 110 | get 命令可以获取指定节点的数据内容和节点的状态,可以看出我们通过set 命令已经将节点数据内容改为 "set node1"。 111 | 112 | ```shell 113 | set node1 114 | cZxid = 0x47 115 | ctime = Sun Jan 20 10:22:59 CST 2019 116 | mZxid = 0x4b 117 | mtime = Sun Jan 20 10:41:10 CST 2019 118 | pZxid = 0x4a 119 | cversion = 1 120 | dataVersion = 1 121 | aclVersion = 0 122 | ephemeralOwner = 0x0 123 | dataLength = 9 124 | numChildren = 1 125 | 126 | ``` 127 | 128 | #### 查看某个目录下的子节点(ls 命令) 129 | 130 | 通过 ls 命令查看根目录下的节点 131 | 132 | ```shell 133 | [zk: 127.0.0.1:2181(CONNECTED) 37] ls / 134 | [dubbo, zookeeper, node1] 135 | ``` 136 | 通过 ls 命令查看 node1 目录下的节点 137 | 138 | ```shell 139 | [zk: 127.0.0.1:2181(CONNECTED) 5] ls /node1 140 | [node1.1] 141 | ``` 142 | zookeeper 中的 ls 命令和 linux 命令中的 ls 类似, 这个命令将列出绝对路径path下的所有子节点信息(列出1级,并不递归) 143 | 144 | #### 查看节点状态(stat 命令) 145 | 146 | 通过 stat 命令查看节点状态 147 | 148 | ```shell 149 | [zk: 127.0.0.1:2181(CONNECTED) 10] stat /node1 150 | cZxid = 0x47 151 | ctime = Sun Jan 20 10:22:59 CST 2019 152 | mZxid = 0x47 153 | mtime = Sun Jan 20 10:22:59 CST 2019 154 | pZxid = 0x4a 155 | cversion = 1 156 | dataVersion = 0 157 | aclVersion = 0 158 | ephemeralOwner = 0x0 159 | dataLength = 11 160 | numChildren = 1 161 | ``` 162 | 上面显示的一些信息比如cversion、aclVersion、numChildren等等,我在上面 “ZNode(数据节点)的结构” 这部分已经介绍到。 163 | 164 | #### 查看节点信息和状态(ls2 命令) 165 | 166 | 167 | ls2 命令更像是 ls 命令和 stat 命令的结合。ls2 命令返回的信息包括2部分:子节点列表 + 当前节点的stat信息。 168 | 169 | ```shell 170 | [zk: 127.0.0.1:2181(CONNECTED) 7] ls2 /node1 171 | [node1.1] 172 | cZxid = 0x47 173 | ctime = Sun Jan 20 10:22:59 CST 2019 174 | mZxid = 0x47 175 | mtime = Sun Jan 20 10:22:59 CST 2019 176 | pZxid = 0x4a 177 | cversion = 1 178 | dataVersion = 0 179 | aclVersion = 0 180 | ephemeralOwner = 0x0 181 | dataLength = 11 182 | numChildren = 1 183 | 184 | ``` 185 | 186 | #### 删除节点(delete 命令) 187 | 188 | 这个命令很简单,但是需要注意的一点是如果你要删除某一个节点,那么这个节点必须无子节点才行。 189 | 190 | ```shell 191 | [zk: 127.0.0.1:2181(CONNECTED) 3] delete /node1/node1.1 192 | ``` 193 | 194 | 在后面我会介绍到 Java 客户端 API的使用以及开源 Zookeeper 客户端 ZkClient 和 Curator 的使用。 195 | 196 | 197 | ### 参考 198 | 199 | - 《从Paxos到Zookeeper 分布式一致性原理与实践》 200 | 201 | -------------------------------------------------------------------------------- /docs/system-design/framework/spring/Spring.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Spring相关教程/资料 4 | 5 | ### 官网相关 6 | 7 | - [Spring官网](https://spring.io/)、[Spring系列主要项目](https://spring.io/projects)、[Spring官网指南](https://spring.io/guides)、[官方文档](https://spring.io/docs/reference) 8 | - [spring-framework-reference](https://docs.spring.io/spring/docs/5.0.14.RELEASE/spring-framework-reference/index.html) 9 | - [Spring Framework 4.3.17.RELEASE API](https://docs.spring.io/spring/docs/4.3.17.RELEASE/javadoc-api/) 10 | 11 | ## 系统学习教程 12 | 13 | ### 文档 14 | 15 | - [极客学院Spring Wiki](http://wiki.jikexueyuan.com/project/spring/transaction-management.html) 16 | - [Spring W3Cschool教程 ](https://www.w3cschool.cn/wkspring/f6pk1ic8.html) 17 | 18 | ### 视频 19 | 20 | - [网易云课堂——58集精通java教程Spring框架开发](http://study.163.com/course/courseMain.htm?courseId=1004475015#/courseDetail?tab=1&35) 21 | - [慕课网相关视频](https://www.imooc.com/) 22 | 23 | - **黑马视频和尚硅谷视频(非常推荐):** 微信公众号:“**JavaGuide**”后台回复关键字 “**1**” 免费领取。 24 | 25 | 26 | ## 面试必备知识点 27 | 28 | ### SpringAOP,IOC实现原理 29 | 30 | AOP实现原理、动态代理和静态代理、Spring IOC的初始化过程、IOC原理、自己实现怎么实现一个IOC容器?这些东西都是经常会被问到的。 31 | 32 | 推荐阅读: 33 | 34 | - [自己动手实现的 Spring IOC 和 AOP - 上篇](http://www.coolblog.xyz/2018/01/18/自己动手实现的-Spring-IOC-和-AOP-上篇/) 35 | 36 | - [自己动手实现的 Spring IOC 和 AOP - 下篇](http://www.coolblog.xyz/2018/01/18/自己动手实现的-Spring-IOC-和-AOP-下篇/) 37 | 38 | ### AOP 39 | 40 | AOP思想的实现一般都是基于 **代理模式** ,在JAVA中一般采用JDK动态代理模式,但是我们都知道,**JDK动态代理模式只能代理接口而不能代理类**。因此,Spring AOP 会这样子来进行切换,因为Spring AOP 同时支持 CGLIB、ASPECTJ、JDK动态代理。 41 | 42 | - 如果目标对象的实现类实现了接口,Spring AOP 将会采用 JDK 动态代理来生成 AOP 代理类; 43 | - 如果目标对象的实现类没有实现接口,Spring AOP 将会采用 CGLIB 来生成 AOP 代理类——不过这个选择过程对开发者完全透明、开发者也无需关心。 44 | 45 | 推荐阅读: 46 | 47 | - [静态代理、JDK动态代理、CGLIB动态代理讲解](http://www.cnblogs.com/puyangsky/p/6218925.html) :我们知道AOP思想的实现一般都是基于 **代理模式** ,所以在看下面的文章之前建议先了解一下静态代理以及JDK动态代理、CGLIB动态代理的实现方式。 48 | - [Spring AOP 入门](https://juejin.im/post/5aa7818af265da23844040c6) :带你入门的一篇文章。这篇文章主要介绍了AOP中的基本概念:5种类型的通知(Before,After,After-returning,After-throwing,Around);Spring中对AOP的支持:AOP思想的实现一般都是基于代理模式,在Java中一般采用JDK动态代理模式,Spring AOP 同时支持 CGLIB、ASPECTJ、JDK动态代理, 49 | - [Spring AOP 基于AspectJ注解如何实现AOP](https://juejin.im/post/5a55af9e518825734d14813f) : **AspectJ是一个AOP框架,它能够对java代码进行AOP编译(一般在编译期进行),让java代码具有AspectJ的AOP功能(当然需要特殊的编译器)**,可以这样说AspectJ是目前实现AOP框架中最成熟,功能最丰富的语言,更幸运的是,AspectJ与java程序完全兼容,几乎是无缝关联,因此对于有java编程基础的工程师,上手和使用都非常容易。Spring注意到AspectJ在AOP的实现方式上依赖于特殊编译器(ajc编译器),因此Spring很机智回避了这点,转向采用动态代理技术的实现原理来构建Spring AOP的内部机制(动态织入),这是与AspectJ(静态织入)最根本的区别。**Spring 只是使用了与 AspectJ 5 一样的注解,但仍然没有使用 AspectJ 的编译器,底层依是动态代理技术的实现,因此并不依赖于 AspectJ 的编译器**。 Spring AOP虽然是使用了那一套注解,其实实现AOP的底层是使用了动态代理(JDK或者CGLib)来动态植入。至于AspectJ的静态植入,不是本文重点,所以只提一提。 50 | - [探秘Spring AOP(慕课网视频,很不错)](https://www.imooc.com/learn/869):慕课网视频,讲解的很不错,详细且深入 51 | - [spring源码剖析(六)AOP实现原理剖析](https://blog.csdn.net/fighterandknight/article/details/51209822) :通过源码分析Spring AOP的原理 52 | 53 | ### IOC 54 | 55 | Spring IOC的初始化过程: 56 | ![Spring IOC的初始化过程](https://user-gold-cdn.xitu.io/2018/5/22/16387903ee72c831?w=709&h=56&f=png&s=4673) 57 | 58 | - [[Spring框架]Spring IOC的原理及详解。](https://www.cnblogs.com/wang-meng/p/5597490.html) 59 | 60 | - [Spring IOC核心源码学习](https://yikun.github.io/2015/05/29/Spring-IOC核心源码学习/) :比较简短,推荐阅读。 61 | - [Spring IOC 容器源码分析](https://javadoop.com/post/spring-ioc) :强烈推荐,内容详尽,而且便于阅读。 62 | 63 | ## Spring事务管理 64 | 65 | - [可能是最漂亮的Spring事务管理详解](https://juejin.im/post/5b00c52ef265da0b95276091) 66 | - [Spring编程式和声明式事务实例讲解](https://juejin.im/post/5b010f27518825426539ba38) 67 | 68 | ### Spring单例与线程安全 69 | 70 | - [Spring框架中的单例模式(源码解读)](http://www.cnblogs.com/chengxuyuanzhilu/p/6404991.html):单例模式是一种常用的软件设计模式。通过单例模式可以保证系统中一个类只有一个实例。spring依赖注入时,使用了 多重判断加锁 的单例模式。 71 | 72 | ### Spring源码阅读 73 | 74 | 阅读源码不仅可以加深我们对Spring设计思想的理解,提高自己的编码水平,还可以让自己在面试中如鱼得水。下面的是Github上的一个开源的Spring源码阅读,大家有时间可以看一下,当然你如果有时间也可以自己慢慢研究源码。 75 | 76 | - [spring-core](https://github.com/seaswalker/Spring/blob/master/note/Spring.md) 77 | - [spring-aop](https://github.com/seaswalker/Spring/blob/master/note/spring-aop.md) 78 | - [spring-context](https://github.com/seaswalker/Spring/blob/master/note/spring-context.md) 79 | - [spring-task](https://github.com/seaswalker/Spring/blob/master/note/spring-task.md) 80 | - [spring-transaction](https://github.com/seaswalker/Spring/blob/master/note/spring-transaction.md) 81 | - [spring-mvc](https://github.com/seaswalker/Spring/blob/master/note/spring-mvc.md) 82 | - [guava-cache](https://github.com/seaswalker/Spring/blob/master/note/guava-cache.md) 83 | -------------------------------------------------------------------------------- /docs/system-design/website-architecture/8 张图读懂大型网站技术架构.md: -------------------------------------------------------------------------------- 1 | > 本文是作者读 《大型网站技术架构》所做的思维导图,在这里分享给各位,公众号(JavaGuide)后台回复:“架构”。即可获得下面图片的源文件以及思维导图源文件! 2 | 3 | 4 | 5 | - [1. 大型网站架构演化](#1-大型网站架构演化) 6 | - [2. 大型架构模式](#2-大型架构模式) 7 | - [3. 大型网站核心架构要素](#3-大型网站核心架构要素) 8 | - [4. 瞬时响应:网站的高性能架构](#4-瞬时响应网站的高性能架构) 9 | - [5. 万无一失:网站的高可用架构](#5-万无一失网站的高可用架构) 10 | - [6. 永无止境:网站的伸缩性架构](#6-永无止境网站的伸缩性架构) 11 | - [7. 随机应变:网站的可扩展性架构](#7-随机应变网站的可扩展性架构) 12 | - [8. 固若金汤:网站的安全机构](#8-固若金汤网站的安全机构) 13 | 14 | 15 | 16 | 17 | ### 1. 大型网站架构演化 18 | 19 | ![1. 大型网站架构演化](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/1%20%E5%A4%A7%E5%9E%8B%E7%BD%91%E7%AB%99%E6%9E%B6%E6%9E%84%E6%BC%94%E5%8C%96.png) 20 | 21 | ### 2. 大型架构模式 22 | 23 | ![2. 大型架构模式](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2%20%E5%A4%A7%E5%9E%8B%E6%9E%B6%E6%9E%84%E6%A8%A1%E5%BC%8F.png) 24 | 25 | ### 3. 大型网站核心架构要素 26 | 27 | ![3. 大型网站核心架构要素](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/3%20%E5%A4%A7%E5%9E%8B%E7%BD%91%E7%AB%99%E6%A0%B8%E5%BF%83%E6%9E%B6%E6%9E%84%E8%A6%81%E7%B4%A0.png) 28 | 29 | ### 4. 瞬时响应:网站的高性能架构 30 | 31 | ![4. 瞬时响应:网站的高性能架构](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/4%20%E7%9E%AC%E6%97%B6%E5%93%8D%E5%BA%94%EF%BC%9A%E7%BD%91%E7%AB%99%E7%9A%84%E9%AB%98%E6%80%A7%E8%83%BD%E6%9E%B6%E6%9E%84.png) 32 | 33 | ### 5. 万无一失:网站的高可用架构 34 | 35 | ![5. 万无一失:网站的高可用架构](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/5%20%E4%B8%87%E6%97%A0%E4%B8%80%E5%A4%B1%EF%BC%9A%E7%BD%91%E7%AB%99%E7%9A%84%E9%AB%98%E5%8F%AF%E7%94%A8%E6%9E%B6%E6%9E%84.png) 36 | 37 | ### 6. 永无止境:网站的伸缩性架构 38 | 39 | ![6. 永无止境:网站的伸缩性架构](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/6%20%E6%B0%B8%E6%97%A0%E6%AD%A2%E5%A2%83%EF%BC%9A%E7%BD%91%E7%AB%99%E7%9A%84%E4%BC%B8%E7%BC%A9%E6%80%A7%E6%9E%B6%E6%9E%84.png) 40 | 41 | ### 7. 随机应变:网站的可扩展性架构 42 | 43 | ![7. 随机应变:网站的可扩展性架构](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/7%20%E9%9A%8F%E6%9C%BA%E5%BA%94%E5%8F%98%EF%BC%9A%E7%BD%91%E7%AB%99%E7%9A%84%E5%8F%AF%E6%89%A9%E5%B1%95%E6%9E%B6%E6%9E%84.png) 44 | 45 | ### 8. 固若金汤:网站的安全机构 46 | 47 | ![enter image description here](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/8%20%E5%9B%BA%E8%8B%A5%E9%87%91%E6%B1%A4%EF%BC%9A%E7%BD%91%E7%AB%99%E7%9A%84%E5%AE%89%E5%85%A8%E6%9E%B6%E6%9E%84.png) 48 | -------------------------------------------------------------------------------- /docs/system-design/website-architecture/分布式.md: -------------------------------------------------------------------------------- 1 | - ### 一 分布式系统的经典基础理论 2 | 3 | [分布式系统的经典基础理论](https://blog.csdn.net/qq_34337272/article/details/80444032) 4 | 5 | 本文主要是简单的介绍了三个常见的概念: **分布式系统设计理念** 、 **CAP定理** 、 **BASE理论** ,关于分布式系统的还有很多很多东西。 6 | ![分布式系统的经典基础理论总结](https://user-gold-cdn.xitu.io/2018/5/24/1639234237ec9805?w=791&h=466&f=png&s=55908) 7 | 8 | - ### 二 分布式事务 9 | 分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。以上是百度百科的解释,简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同数据库的数据一致性。 10 | * [深入理解分布式事务](http://www.codeceo.com/article/distributed-transaction.html) 11 | * [分布式事务?No, 最终一致性](https://zhuanlan.zhihu.com/p/25933039) 12 | * [聊聊分布式事务,再说说解决方案](https://www.cnblogs.com/savorboard/p/distributed-system-transaction-consistency.html) 13 | 14 | 15 | - ### 三 分布式系统一致性 16 | [分布式服务化系统一致性的“最佳实干”](https://www.jianshu.com/p/1156151e20c8) 17 | 18 | - ### 四 一致性协议/算法 19 | 早在1898年就诞生了著名的 **Paxos经典算法** (**Zookeeper就采用了Paxos算法的近亲兄弟Zab算法**),但由于Paxos算法非常难以理解、实现、排错。所以不断有人尝试简化这一算法,直到2013年才有了重大突破:斯坦福的Diego Ongaro、John Ousterhout以易懂性为目标设计了新的一致性算法—— **Raft算法** ,并发布了对应的论文《In Search of an Understandable Consensus Algorithm》,到现在有十多种语言实现的Raft算法框架,较为出名的有以Go语言实现的Etcd,它的功能类似于Zookeeper,但采用了更为主流的Rest接口。 20 | * [图解 Paxos 一致性协议](https://mp.weixin.qq.com/s?__biz=MzI0NDI0MTgyOA==&mid=2652037784&idx=1&sn=d8c4f31a9cfb49ee91d05bb374e5cdd5&chksm=f2868653c5f10f45fc4a64d15a5f4163c3e66c00ed2ad334fa93edb46671f42db6752001f6c0#rd) 21 | * [图解分布式协议-RAFT](http://ifeve.com/raft/) 22 | * [Zookeeper ZAB 协议分析](https://dbaplus.cn/news-141-1875-1.html) 23 | 24 | - ### 五 分布式存储 25 | 26 | **分布式存储系统将数据分散存储在多台独立的设备上**。传统的网络存储系统采用集中的存储服务器存放所有数据,存储服务器成为系统性能的瓶颈,也是可靠性和安全性的焦点,不能满足大规模存储应用的需要。分布式网络存储系统采用可扩展的系统结构,利用多台存储服务器分担存储负荷,利用位置服务器定位存储信息,它不但提高了系统的可靠性、可用性和存取效率,还易于扩展。 27 | 28 | * [分布式存储系统概要](http://witchiman.top/2017/05/05/distributed-system/) 29 | 30 | - ### 六 分布式计算 31 | 32 | **所谓分布式计算是一门计算机科学,它研究如何把一个需要非常巨大的计算能力才能解决的问题分成许多小的部分,然后把这些部分分配给许多计算机进行处理,最后把这些计算结果综合起来得到最终的结果。** 33 | 分布式网络存储技术是将数据分散的存储于多台独立的机器设备上。分布式网络存储系统采用可扩展的系统结构,利用多台存储服务器分担存储负荷,利用位置服务器定位存储信息,不但解决了传统集中式存储系统中单存储服务器的瓶颈问题,还提高了系统的可靠性、可用性和扩展性。 34 | 35 | * [关于分布式计算的一些概念](https://blog.csdn.net/qq_34337272/article/details/80549020) 36 | 37 | -------------------------------------------------------------------------------- /docs/system-design/设计模式.md: -------------------------------------------------------------------------------- 1 | # Java 设计模式 2 | 3 | 下面是自己学习设计模式的时候做的总结,有些是自己的原创文章,有些是网上写的比较好的文章,保存下来细细消化吧! 4 | 5 | **系列文章推荐:** 6 | 7 | ## 创建型模式 8 | 9 | ### 创建型模式概述 10 | 11 | - 创建型模式(Creational Pattern)对类的实例化过程进行了抽象,能够将软件模块中对象的创建和对象的使用分离。为了使软件的结构更加清晰,外界对于这些对象只需要知道它们共同的接口,而不清楚其具体的实现细节,使整个系统的设计更加符合单一职责原则。 12 | - 创建型模式在创建什么(What),由谁创建(Who),何时创建(When)等方面都为软件设计者提供了尽可能大的灵活性。创建型模式隐藏了类的实例的创建细节,通过隐藏对象如何被创建和组合在一起达到使整个系统独立的目的。 13 | 14 | ![创建型模式](https://user-gold-cdn.xitu.io/2018/6/16/1640641afcb7559b?w=491&h=241&f=png&s=51443) 15 | 16 | ### 常见创建型模式详解 17 | 18 | - **单例模式:** [深入理解单例模式——只有一个实例](https://blog.csdn.net/qq_34337272/article/details/80455972) 19 | - **工厂模式:** [深入理解工厂模式——由对象工厂生成对象](https://blog.csdn.net/qq_34337272/article/details/80472071) 20 | - **建造者模式:** [深入理解建造者模式 ——组装复杂的实例](http://blog.csdn.net/qq_34337272/article/details/80540059) 21 | - **原型模式:** [深入理解原型模式 ——通过复制生成实例](https://blog.csdn.net/qq_34337272/article/details/80706444) 22 | 23 | ## 结构型模式 24 | 25 | ### 结构型模式概述 26 | 27 | - **结构型模式(Structural Pattern):** 描述如何将类或者对象结合在一起形成更大的结构,就像搭积木,可以通过简单积木的组合形成复杂的、功能更为强大的结构 28 | ![结构型模式(Structural Pattern)](https://user-gold-cdn.xitu.io/2018/6/16/164064d6b3c205e3?w=719&h=233&f=png&s=270293) 29 | - **结构型模式可以分为类结构型模式和对象结构型模式:** 30 | - 类结构型模式关心类的组合,由多个类可以组合成一个更大的系统,在类结构型模式中一般只存在继承关系和实现关系。 31 | - 对象结构型模式关心类与对象的组合,通过关联关系使得在一个类中定义另一个类的实例对象,然后通过该对象调用其方法。根据“合成复用原则”,在系统中尽量使用关联关系来替代继承关系,因此大部分结构型模式都是对象结构型模式。 32 | 33 | ![结构型模式](https://user-gold-cdn.xitu.io/2018/6/16/1640655459d766d2?w=378&h=266&f=png&s=59652) 34 | 35 | ### 常见结构型模式详解 36 | 37 | - **适配器模式:** 38 | - [深入理解适配器模式——加个“适配器”以便于复用](https://segmentfault.com/a/1190000011856448) 39 | - [适配器模式原理及实例介绍-IBM](https://www.ibm.com/developerworks/cn/java/j-lo-adapter-pattern/index.html) 40 | - **桥接模式:** [设计模式笔记16:桥接模式(Bridge Pattern)](https://blog.csdn.net/yangzl2008/article/details/7670996) 41 | - **组合模式:** [大话设计模式—组合模式](https://blog.csdn.net/lmb55/article/details/51039781) 42 | - **装饰模式:** [java模式—装饰者模式](https://www.cnblogs.com/chenxing818/p/4705919.html)、[Java设计模式-装饰者模式](https://blog.csdn.net/cauchyweierstrass/article/details/48240147) 43 | - **外观模式:** [java设计模式之外观模式(门面模式)](https://www.cnblogs.com/lthIU/p/5860607.html) 44 | - **享元模式:** [享元模式](http://www.jasongj.com/design_pattern/flyweight/) 45 | - **代理模式:** 46 | - [代理模式原理及实例讲解 (IBM出品,很不错)](https://www.ibm.com/developerworks/cn/java/j-lo-proxy-pattern/index.html) 47 | - [轻松学,Java 中的代理模式及动态代理](https://blog.csdn.net/briblue/article/details/73928350) 48 | - [Java代理模式及其应用](https://blog.csdn.net/justloveyou_/article/details/74203025) 49 | 50 | 51 | ## 行为型模式 52 | 53 | ### 行为型模式概述 54 | 55 | - 行为型模式(Behavioral Pattern)是对在不同的对象之间划分责任和算法的抽象化。 56 | - 行为型模式不仅仅关注类和对象的结构,而且重点关注它们之间的相互作用。 57 | - 通过行为型模式,可以更加清晰地划分类与对象的职责,并研究系统在运行时实例对象之间的交互。在系统运行时,对象并不是孤立的,它们可以通过相互通信与协作完成某些复杂功能,一个对象在运行时也将影响到其他对象的运行。 58 | 59 | **行为型模式分为类行为型模式和对象行为型模式两种:** 60 | 61 | - **类行为型模式:** 类的行为型模式使用继承关系在几个类之间分配行为,类行为型模式主要通过多态等方式来分配父类与子类的职责。 62 | - **对象行为型模式:** 对象的行为型模式则使用对象的聚合关联关系来分配行为,对象行为型模式主要是通过对象关联等方式来分配两个或多个类的职责。根据“合成复用原则”,系统中要尽量使用关联关系来取代继承关系,因此大部分行为型设计模式都属于对象行为型设计模式。 63 | 64 | ![行为型模式](https://user-gold-cdn.xitu.io/2018/6/28/164467dd92c6172c?w=453&h=269&f=png&s=63270) 65 | 66 | - **职责链模式:** 67 | - [Java设计模式之责任链模式、职责链模式](https://blog.csdn.net/jason0539/article/details/45091639) 68 | - [责任链模式实现的三种方式](https://www.cnblogs.com/lizo/p/7503862.html) 69 | - **命令模式:** 在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计,使得请求发送者与请求接收者消除彼此之间的耦合,让对象之间的调用关系更加灵活。命令模式可以对发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。这就是命令模式的模式动机。 70 | - **解释器模式:** 71 | - **迭代器模式:** 72 | - **中介者模式:** 73 | - **备忘录模式:** 74 | - **观察者模式:** 75 | - **状态模式:** 76 | - **策略模式:** 77 | 78 | 策略模式作为设计原则中开闭原则最典型的体现,也是经常使用的。下面这篇博客介绍了策略模式一般的组成部分和概念,并用了一个小demo去说明了策略模式的应用。 79 | 80 | [java设计模式之策略模式](https://blog.csdn.net/zlj1217/article/details/81230077) 81 | 82 | - **模板方法模式:** 83 | - **访问者模式:** 84 | 85 | -------------------------------------------------------------------------------- /docs/tools/github/github-star-ranking.md: -------------------------------------------------------------------------------- 1 | ## 题外话 2 | 3 | 先来点题外话吧!如果想看正文的话可以直接看滑到下面正文。 4 | 5 | 来三亚旅行也有几天了,总体感觉很不错,后天就要返航回家了。偶尔出来散散心真的挺不错,放松一下自己的心情,感受一下大自然。个人感觉冬天的时候来三亚度假还是很不错的选择,但是不要 1 月份的时候过来(差不多就过年那会儿),那时候属于大旺季,各种东西特别是住宿都贵很多。而且,那时候的机票也很贵。很多人觉得来三亚会花很多钱,实际上你不是在大旺季来的话,花不了太多钱。我和我女朋友在这边玩的几天住的酒店都还不错(干净最重要!),价格差不多都在 200元左右,有一天去西岛和天涯海角那边住的全海景房间也才要 200多,不过过年那会儿可能会达到 1000+。 6 | 7 | 现在是晚上 7 点多,刚从外面玩耍完回来。女朋友拿着我的手机拼着图片,我一个只能玩玩电脑。这篇文章很早就想写了,毕竟不费什么事,所以逞着晚上有空写一下。 8 | 9 | 如果有读者想看去三亚拍的美照包括我和我女朋友的合照,可以在评论区扣个 “想看”,我可以整篇推文分享一下。 10 | 11 | ## 正文​ 12 | 13 | > 下面的 10 个项目还是很推荐的!JS 的项目占比挺大,其他基本都是文档/学习类型的仓库。 14 | 15 | 说明:数据统计于 2019-11-27。 16 | 17 | ### 1. freeCodeCamp 18 | 19 | - **Github地址**:[https://github.com/freeCodeCamp/freeCodeCamp](https://github.com/freeCodeCamp/freeCodeCamp) 20 | - **star**: 307 k 21 | - **介绍**: 开放源码代码库和课程。与数百万人一起免费学习编程。网站:[https://www.freeCodeCamp.org](https://www.freecodecamp.org/) (一个友好的社区,您可以在这里免费学习编码。它由捐助者支持、非营利组织运营,以帮助数百万忙碌的成年人学习编程技术。这个社区已经帮助10,000多人获得了第一份开发人员的工作。这里的全栈Web开发课程是完全免费的,并且可以自行调整进度。这里还有数以千计的交互式编码挑战,可帮助您扩展技能。) 22 | 23 | 比如我想学习 ES6 的语法,学习界面是下面这样的,你可以很方便地边练习边学习: 24 | 25 | ![Learn ES6](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-11/freecodemap-es6.jpg) 26 | 27 | ### 2. 996.ICU 28 | 29 | - **Github地址**:[https://github.com/996icu/996.ICU](https://github.com/996icu/996.ICU) 30 | - **star**: 248 k 31 | - **介绍**: `996.ICU` 是指“工作 996, 生病 ICU” 。这是中国程序员之间的一种自嘲说法,意思是如果按照 996 的模式工作,那以后就得进 ICU 了。这个项目最早是某个中国程序员发起的,然后就火遍全网,甚至火到了全世界很多其他国家,其网站被翻译成了多种语言。网站地址:[https://996.icu](https://996.icu/)。 32 | 33 | ![996.ICU-website](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-11/996.icu.jpg) 34 | 35 | ### 3. vue 36 | 37 | - **Github地址**:[https://github.com/vuejs/vue](https://github.com/vuejs/vue) 38 | - **star**: 153 k 39 | - **介绍**: 尤大的前端框架。国人用的最多(容易上手,文档比较丰富),所以 Star 数量比较多还是有道理的。Vue (读音 /vjuː/,类似于 **view**) 是一套用于构建用户界面的**渐进式框架**。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与[现代化的工具链](https://cn.vuejs.org/v2/guide/single-file-components.html)以及各种[支持类库](https://github.com/vuejs/awesome-vue#libraries--plugins)结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。 40 | 41 | ### 4. React 42 | 43 | - **Github地址**:[https://gitstar-ranking.com/facebook/react](https://gitstar-ranking.com/facebook/react) 44 | - **star**: 140 k 45 | - **介绍**: Facebook 开源的,大公司有保障。用于构建用户界面的声明式、基于组件开发,高效且灵活的JavaScript框架。我司大部分项目的前端都是 React ,我自己也用过一段时间,感觉还不错,但是也有一些小坑。 46 | 47 | ### 5. tensorflow 48 | 49 | - **Github地址**:[https://github.com/tensorflow/tensorflow](https://github.com/tensorflow/tensorflow) 50 | - **star**: 138 k 51 | - **介绍**: 适用于所有人的开源机器学习框架。[TensorFlow](https://www.tensorflow.org/)是用于机器学习的端到端开源平台。TensorFlow最初是由Google机器智能研究组织内Google Brain团队的研究人员和工程师开发的,用于进行机器学习和深度神经网络研究。该系统具有足够的通用性,也可以适用于多种其他领域。TensorFlow提供了稳定的[Python](https://www.tensorflow.org/api_docs/python) 和[C ++](https://www.tensorflow.org/api_docs/cc) API,以及[其他语言的](https://www.tensorflow.org/api_docs)非保证的向后兼容API 。 52 | 53 | ### 6. bootstrap 54 | 55 | - **Github地址**:[https://github.com/twbs/bootstrap](https://github.com/twbs/bootstrap) 56 | - **star**: 137 k 57 | - **介绍**: 相信初学前端的时候,大家一定或多或少地接触过这个框架。官网说它是最受欢迎的HTML,CSS和JavaScript框架,用于在网络上开发响应式,移动优先项目。 58 | 59 | ### 7. free-programming-books 60 | 61 | - **Github地址**:[https://github.com/EbookFoundation/free-programming-books](https://github.com/EbookFoundation/free-programming-books) 62 | - **star**: 132 k 63 | - **介绍**: 免费提供的编程书籍。我自己没太搞懂为啥这个项目 Star 数这么多,知道的麻烦评论区吱一声。 64 | 65 | ### 8. Awesome 66 | 67 | - **Github地址** : [https://github.com/sindresorhus/awesome](https://github.com/sindresorhus/awesome) 68 | - **star**: 120 k 69 | - **介绍**: github 上很多的各种 Awesome 系列合集。 70 | 71 | 下面是这个开源仓库的目录,可以看出其涵盖了很多方面的内容。 72 | 73 | 74 | 75 | 举个例子,这个仓库里面就有两个让你的电脑更好用的开源仓库,Mac 和 Windows都有: 76 | 77 | - Awesome Mac:https://github.com/jaywcjlove/awesome-mac/blob/master/README-zh.m 78 | - Awsome Windows: https://github.com/Awesome-Windows/Awesome/blob/master/README-cn.md 79 | 80 | ### 9. You-Dont-Know-JS 81 | 82 | - **Github地址**:[https://github.com/getify/You-Dont-Know-JS](https://github.com/getify/You-Dont-Know-JS) 83 | - **star**: 112 k 84 | - **介绍**: 您还不认识JS(书籍系列)-第二版 85 | 86 | ### 10. oh-my-zsh 87 | 88 | - **Github地址**:[https://github.com/ohmyzsh/ohmyzsh](https://github.com/ohmyzsh/ohmyzsh) 89 | - **star**: 99.4 k 90 | - **介绍**: 一个令人愉快的社区驱动的框架(拥有近1500个贡献者),用于管理zsh配置。包括200多个可选插件(rails, git, OSX, hub, capistrano, brew, ant, php, python等),140多个主题,可为您的早晨增光添彩,以及一个自动更新工具,可让您轻松保持与来自社区的最新更新…… 91 | 92 | 下面就是 oh-my-zsh 提供的一个花里胡哨的主题: 93 | 94 | ![oh-my-zsh-theme](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-11/ohmyzsh-theme.png) 95 | -------------------------------------------------------------------------------- /docs/tools/阿里云服务器使用经验.md: -------------------------------------------------------------------------------- 1 | 最近很多阿里云双 11 做活动,优惠力度还挺大的,很多朋友都买以最低的价格买到了自己的云服务器。不论是作为学习机还是部署自己的小型网站或者服务来说都是很不错的! 2 | 3 | 但是,很多朋友都不知道如何正确去使用。下面我简单分享一下自己的使用经验。 4 | 5 | 总结一下,主要涉及下面几个部分,对于新手以及没有这么使用过云服务的朋友还是比较友好的: 6 | 7 | 1. 善用阿里云镜像市场节省安装 Java 环境的时间,相关说明都在根目录下的 readme.txt. 文件里面; 8 | 2. 本地通过 SSH 连接阿里云服务器很容易,配置好 Host地址,通过 root 用户加上实例密码直接连接即可。 9 | 3. 本地连接 MySQL 数据库需要简单配置一下安全组和并且允许 root 用户在任何地方进行远程登录。 10 | 4. 通过 Alibaba Cloud Toolkit 部署 Spring Boot 项目到阿里云服务器真的很方便。 11 | 12 | **[活动地址](https://www.aliyun.com/1111/2019/group-buying-share?ptCode=32AE103FC8249634736194795A3477C4647C88CF896EF535&userCode=hf47liqn&share_source=copy_link)** (仅限新人,老用户可以考虑使用家人或者朋友账号购买,推荐799/3年 2核4G 这个性价比和适用面更广) 13 | 14 | ### 善用阿里云镜像市场节省安装环境的时间 15 | 16 | 基本的购买流程这里就不多说了,另外这里需要注意的是:其实 Java 环境是不需要我们手动安装配置的,阿里云提供的镜像市场有一些常用的环境。 17 | 18 | > 阿里云镜像市场是指阿里云建立的、由镜像服务商向用户提供其镜像及相关服务的网络平台。这些镜像在操作系统上整合了具体的软件环境和功能,比如Java、PHP运行环境、控制面板等,供有相关需求的用户开通实例时选用。 19 | 20 | 具体如何在购买云服务器的时候通过镜像创建实例或者已有ECS用户如何使用镜像可以查看官方详细的介绍,地址: 21 | 22 | https://help.aliyun.com/knowledge_detail/41987.html?spm=a2c4g.11186631.2.1.561e2098dIdCGZ 23 | 24 | ### 当我们成功购买服务器之后如何通过 SSH 连接呢? 25 | 26 | 创建好 ECS 后,你绑定的手机会收到短信,会告知你初始密码的。你可以登录管理控制台对密码进行修改,修改密码需要在管理控制台重启服务器才能生效。 27 | 28 | 你也可以在阿里云 ECS 控制台重置实例密码,如下图所示。 29 | 30 | ![](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/Screen Shot 2019-10-30 at 10.51.15 AM.png) 31 | 32 | **第一种连接方式是直接在阿里云服务器管理的网页上连接**。如上图所示, 点击远程连接,然后输入远程连接密码,这个并不是你重置实例密码得到的密码,如果忘记了直接修改远程连接密码即可。 33 | 34 | **第二种方式是在本地通过命令或者软件连接。** 推荐使用这种方式,更加方便。 35 | 36 | **Windows 推荐使用 Xshell 连接,具体方式如下:** 37 | 38 | > Window电脑在家,这里直接用找到的一些图片给大家展示一个。 39 | 40 | ![](https://img2018.cnblogs.com/blog/1070438/201812/1070438-20181226165727765-1335537850.png) 41 | 42 | ![](https://img2018.cnblogs.com/blog/1070438/201812/1070438-20181226170155651-1407670048.png) 43 | 44 | 接着点开,输入账号:root,命名输入刚才设置的密码,点ok就可以了 45 | 46 | ![](https://img2018.cnblogs.com/blog/1070438/201812/1070438-20181226170444344-411355334.png) 47 | 48 | **Mac 或者 Linux 系统都可以直接使用 ssh 命令进行连接,非常方便。** 49 | 50 | 成功连接之后,控制台会打印出如下消息。 51 | 52 | ```shell 53 | ➜ ~ ssh root@47.107.159.12 -p 22 54 | root@47.107.159.12's password: 55 | Last login: Wed Oct 30 09:31:31 2019 from 220.249.123.170 56 | 57 | Welcome to Alibaba Cloud Elastic Compute Service ! 58 | 59 | 欢迎使用 Tomcat8 JDK8 Mysql5.7 环境 60 | 61 | 使用说明请参考 /root/readme.txt 文件 62 | ``` 63 | 64 | 我当时选择是阿里云提供好的 Java 环境,自动就提供了 Tomcat、 JDK8 、Mysql5.7,所以不需要我们再进行安装配置了,节省了很多时间。另外,需要注意的是:**一定要看 /readme.txt ,Tomcat、 JDK8 、Mysql5.7相关配置以及安装路径等说明都在里面。** 65 | 66 | ### 如何连接数据库? 67 | 68 | **如需外网远程访问mysql 请参考以上网址 设置mysql及阿里云安全组**。 69 | 70 | ![开放安全组](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/开放安全组.png) 71 | 72 | Mysql为了安全性,在默认情况下用户只允许在本地登录,但是可以使用 SSH 方式连接。如果我们不想通过 SSH 方式连接的话就需要对 MySQL 进行简单的配置。 73 | 74 | ```shell 75 | #允许root用户在任何地方进行远程登录,并具有所有库任何操作权限: 76 | # *.*代表所有库表 “%”代表所有IP地址 77 | mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY "自定义密码" WITH GRANT OPTION; 78 | Query OK, 0 rows affected, 1 warning (0.00 sec) 79 | #刷新权限。  80 | mysql>flush privileges; 81 | #退出mysql 82 | mysql>exit 83 | #重启MySQL生效 84 | [root@snailclimb]# systemctl restart mysql 85 | ``` 86 | 87 | 这样的话,我们就能在本地进行连接了。Windows 推荐使用Navicat或者SQLyog。 88 | 89 | > Window电脑在家,这里用 Mac 上的MySQL可视化工具Sequel Pro给大家演示一下。 90 | 91 | 92 | 93 | ### 如何把一个Spring Boot 项目部署到服务器上呢? 94 | 95 | 默认大家都是用 IDEA 进行开发。另外,你要有一个简单的 Spring Boot Web 项目。如果还不了解 Spring Boot 的话,一个简单的 Spring Boot 版 "Hello World "项目,地址如下: 96 | 97 | https://github.com/Snailclimb/springboot-guide/blob/master/docs/start/springboot-hello-world.md 。 98 | 99 | **1.下载一个叫做 Alibaba Cloud Toolkit 的插件。** 100 | 101 | 102 | 103 | **2.进入 Preference 配置一个 Access Key ID 和 Access Key Secret。** 104 | 105 | 106 | 107 | **3.部署项目到 ECS 上。** 108 | 109 | ![](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-7/deploy-to-ecs1.png) 110 | 111 | 112 | 113 | 按照上面这样填写完基本配置之后,然后点击 run 运行即可。运行成功,控制台会打印出如下信息: 114 | 115 | ```shell 116 | [INFO] Deployment File is Uploading... 117 | [INFO] IDE Version:IntelliJ IDEA 2019.2 118 | [INFO] Alibaba Cloud Toolkit Version:2019.9.1 119 | [INFO] Start upload hello-world-0.0.1-SNAPSHOT.jar 120 | [INFO][##################################################] 100% (18609645/18609645) 121 | [INFO] Succeed to upload, 18609645 bytes have been uploaded. 122 | [INFO] Upload Deployment File to OSS Success 123 | [INFO] Target Deploy ECS: { 172.18.245.148 / 47.107.159.12 } 124 | [INFO] Command: { source /etc/profile; cd /springboot; } 125 | Tip: The deployment package will be temporarily stored in Alibaba Cloud Security OSS and will be 126 | deleted after the deployment is complete. Please be assured that no one can access it except you. 127 | 128 | [INFO] Create Deploy Directory Success. 129 | 130 | [INFO] Deployment File is Downloading... 131 | [INFO] Download Deployment File from OSS Success 132 | 133 | [INFO] File Upload Total time: 16.676 s 134 | ``` 135 | 136 | 通过控制台答应出的信息可以看出:通过这个插件会自动把这个 Spring Boot 项目打包成一个 jar 包,然后上传到你的阿里云服务器中指定的文件夹中,你只需要登录你的阿里云服务器,然后通过 `java -jar hello-world-0.0.1-SNAPSHOT.jar`命令运行即可。 137 | 138 | ```shell 139 | [root@snailclimb springboot]# ll 140 | total 18176 141 | -rw-r--r-- 1 root root 18609645 Oct 30 08:25 hello-world-0.0.1-SNAPSHOT.jar 142 | [root@snailclimb springboot]# java -jar hello-world-0.0.1-SNAPSHOT.jar 143 | ``` 144 | 145 | 然后你就可以在本地访问访问部署在你的阿里云 ECS 上的服务了。 146 | 147 | 148 | 149 | **[推荐一下阿里云双11的活动:云服务器1折起,仅86元/年,限量抢购!](https://www.aliyun.com/1111/2019/group-buying-share?ptCode=32AE103FC8249634736194795A3477C4647C88CF896EF535&userCode=hf47liqn&share_source=copy_link)** (仅限新人,老用户可以考虑使用家人或者朋友账号购买,推荐799/3年 2核4G 这个性价比和适用面更广) -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | JavaGuide 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 34 | 35 | 36 | 37 | 38 | 39 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /media/pictures/kafka/Broker和集群.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/media/pictures/kafka/Broker和集群.png -------------------------------------------------------------------------------- /media/pictures/kafka/Partition与消费模型.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/media/pictures/kafka/Partition与消费模型.png -------------------------------------------------------------------------------- /media/pictures/kafka/kafka存在文件系统上.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/media/pictures/kafka/kafka存在文件系统上.png -------------------------------------------------------------------------------- /media/pictures/kafka/segment是kafka文件存储的最小单位.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/media/pictures/kafka/segment是kafka文件存储的最小单位.png -------------------------------------------------------------------------------- /media/pictures/kafka/主题与分区.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/media/pictures/kafka/主题与分区.png -------------------------------------------------------------------------------- /media/pictures/kafka/发送消息.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/media/pictures/kafka/发送消息.png -------------------------------------------------------------------------------- /media/pictures/kafka/启动服务.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/media/pictures/kafka/启动服务.png -------------------------------------------------------------------------------- /media/pictures/kafka/消费者设计概要1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/media/pictures/kafka/消费者设计概要1.png -------------------------------------------------------------------------------- /media/pictures/kafka/消费者设计概要2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/media/pictures/kafka/消费者设计概要2.png -------------------------------------------------------------------------------- /media/pictures/kafka/消费者设计概要3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/media/pictures/kafka/消费者设计概要3.png -------------------------------------------------------------------------------- /media/pictures/kafka/消费者设计概要4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/media/pictures/kafka/消费者设计概要4.png -------------------------------------------------------------------------------- /media/pictures/kafka/消费者设计概要5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/media/pictures/kafka/消费者设计概要5.png -------------------------------------------------------------------------------- /media/pictures/kafka/生产者和消费者.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/media/pictures/kafka/生产者和消费者.png -------------------------------------------------------------------------------- /media/pictures/kafka/生产者设计概要.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/media/pictures/kafka/生产者设计概要.png -------------------------------------------------------------------------------- /media/pictures/rostyslav-savchyn-5joK905gcGc-unsplash.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/media/pictures/rostyslav-savchyn-5joK905gcGc-unsplash.jpg -------------------------------------------------------------------------------- /media/sponsor/WechatIMG143.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yueyi2019/JavaGuide/675fe2c9079582f8f2689684b848dddbf87b50aa/media/sponsor/WechatIMG143.jpeg --------------------------------------------------------------------------------