├── .gitattributes ├── .gitignore ├── A类 ├── A01-Java并发编程 │ ├── [极客时间]-Java并发编程-第1部分-并发理论基础.md │ ├── [极客时间]-Java并发编程-第2部分-并发工具类.md │ ├── [极客时间]-Java并发编程-第3部分-并发设计模式.md │ ├── [极客时间]-Java并发编程-第4部分-案例分析.md │ ├── 并发工具类.png │ ├── 并发工具类.xmind │ ├── 并发理论基础.png │ └── 并发理论基础.xmind ├── A02-Java虚拟机 │ ├── [拉勾教育]-深入浅出Java虚拟机.md │ ├── [极客时间]-深入拆解Java虚拟机-01基本原理.md │ ├── 深入拆解Java虚拟机-01基本原理.png │ └── 深入拆解Java虚拟机-01基本原理.xmind ├── A03-MySQL │ ├── MySQL实战-01基础篇.png │ ├── MySQL实战-01基础篇.xmind │ ├── SQL执行计划.md │ ├── [拉勾教育]-高性能MySQL实战-01基础篇.md │ ├── [极客时间]-MySQL实战-01基础篇.md │ └── [极客时间]-MySQL实战-02实践篇.md ├── A04-网络协议 │ ├── [极客时间]-趣谈网络协议.md │ ├── [极客时间]透视HTTP协议-01破冰篇.md │ ├── [极客时间]透视HTTP协议-02基础篇.md │ ├── [极客时间]透视HTTP协议-03进阶篇.md │ ├── [极客时间]透视HTTP协议-04安全篇.md │ ├── 趣谈网络协议.xmind │ └── 面试题.md ├── A05-数据结构与算法 │ ├── [极客时间]-数据结构与算法之美.md │ └── 算法面试通关40讲.md ├── A06-前端 │ ├── [极客时间]-React实战进阶.md │ └── [极客时间]-重学前端.md ├── A07-Java │ └── 深入剖析Java新特性-模块1-提升编码效率.md ├── Python │ ├── Python核心技术与实战 │ │ └── Python核心技术与实战-基础篇.md │ ├── README.md │ ├── sidebar.md │ └── 零基础学Python │ │ ├── 01Python介绍与安装.md │ │ ├── 02变量、数字、序列、映射和集合.md │ │ ├── 03条件和循环.md │ │ ├── 04文件、输入输出、异常.md │ │ ├── 05函数、模块.md │ │ ├── 06面向对象编程.md │ │ ├── 07多线程编程.md │ │ ├── 08标准库、机器学习库.md │ │ ├── 09第三方库.md │ │ └── python_knowledge_map.jpg └── README.md ├── B类 ├── B01-数据库综合 │ └── [极客时间]-SQL必知必会.md ├── B02-RPC │ ├── RPC实战与核心原理-01基础篇.png │ ├── RPC实战与核心原理-01基础篇.xmind │ ├── RPC实战与核心原理-02进阶篇.png │ ├── RPC实战与核心原理-02进阶篇.xmind │ ├── [极客时间]-RPC实战与核心原理-01基础篇.md │ ├── [极客时间]-RPC实战与核心原理-02进阶篇.md │ └── [极客时间]-RPC实战与核心原理-03高级篇.md ├── B03-消息队列 │ ├── SpringKafka.md │ ├── [极客时间]-01Kafka入门及基本使用.md │ ├── [极客时间]-02Kafka客户端实践及原理剖析.md │ ├── [极客时间]-03Kafka内核.md │ ├── [极客时间]-消息队列高手课-基础篇.md │ ├── [极客时间]-消息队列高手课-进阶篇.md │ └── [阿里云]-消息队列Kafka版.md ├── B04-Neo4j │ └── [个人整理]-Neo4J基础.md ├── B05-Redis │ ├── Redis-01原理、协议及使用.md │ ├── Redis-02进阶.md │ ├── Redis核心技术与实战-01基础篇.md │ ├── Redis核心技术与实战-02实践篇.md │ ├── Redis源码剖析与实战.md │ └── 《Redis设计与实现》读书笔记.md ├── B06-Spring │ ├── Spring-StateMachine.md │ ├── Spring响应式编程.md │ ├── Spring核心编程思想.md │ ├── Spring核心编程思想.xmind │ ├── Spring编程常见错误-01SpringCore篇.md │ ├── Spring编程常见错误-02SpringWeb篇.md │ ├── Spring编程常见错误-03Spring补充篇.md │ ├── Spring面试题-第一天.md │ ├── 《Spring揭秘》第三部分-Spring-AOP框架.md │ ├── 《Spring揭秘》第三部分-Spring-AOP框架.xmind │ ├── 《Spring揭秘》第二部分-Spring的IoC容器.md │ ├── 《Spring揭秘》第二部分-Spring的IoC容器.png │ ├── 《Spring揭秘》第二部分-Spring的IoC容器.xmind │ └── 《Spring揭秘》第五部分-事务管理.md ├── B07-Tomcat │ └── [极客时间]-深入拆解Tomcat.md ├── B08-设计模式 │ ├── [极客时间]-设计模式之美-01设计模式学习导读.md │ ├── [极客时间]-设计模式之美-02设计原则与思想.md │ └── [极客时间]-设计模式之美-04开源与项目实战.md ├── B09-MyBatis │ ├── 《MyBatis技术内幕》读书笔记.md │ └── 深入剖析MyBatis核心原理.md ├── B10-系统性能 │ ├── [拉勾教育]-应用性能分析实战.md │ ├── [极客时间]-性能测试-01基础篇.md │ ├── [极客时间]-性能测试-02工具及场景篇.md │ ├── [极客时间]-性能测试-05分析实战篇.md │ ├── [极客时间]-性能调优实战-01Java编程调优.md │ ├── [极客时间]-性能调优实战-02多线程调优.md │ ├── [极客时间]-性能调优实战-03JVM性能监测及调优.md │ ├── [网络博客]-性能调优实战.md │ ├── 性能调优实战-01Java编程调优.png │ ├── 性能调优实战-01Java编程调优.xmind │ ├── 性能调优实战-02多线程调优.png │ ├── 性能调优实战-02多线程调优.xmind │ ├── 性能调优实战-03JVM监测及调优.png │ └── 性能调优实战-03JVM监测及调优.xmind ├── B11-ZooKeeper │ ├── ZooKeeper学习笔记.png │ ├── ZooKeeper学习笔记.xmind │ ├── ZooKeeper技术内幕:Leader选举.md │ ├── ZooKeeper技术内幕:Leader选举.png │ ├── ZooKeeper技术内幕:Leader选举.xmind │ └── [个人整理]ZooKeeper学习笔记.md ├── B12-SpringCloud │ ├── [拉勾]-300分钟搞懂SpringCloud.md │ ├── [拉勾]-SpringCloudAlibaba实战-01微服务架构设计+Nacos服务治理.md │ ├── [拉勾]-SpringCloudAlibaba实战-02微服务通信+系统保护.md │ ├── [拉勾]-SpringCloud原理与实战-01基础篇.md │ ├── [拉勾]-SpringCloud原理与实战-02服务治理+API网关.md │ ├── [拉勾]-SpringCloud原理与实战-03服务容错+配置中心.md │ ├── [拉勾]-SpringCloud原理与实战-04事件驱动架构+服务安全.md │ └── [拉勾]-SpringCloud原理与实战-05链路跟踪+微服务测试.md ├── B13-Elasticsearch │ ├── ElasticSearch.jpg │ ├── [geek]-ElasticSearch核心技术与实践.md │ ├── 第1部分:初识ElasticSearch.md │ └── 第2部分:深入了解Elasticsearch.md ├── B14-SpringBoot │ ├── SpringBoot底层.md │ ├── [拉勾]-SpringBoot实战-01配置体系.md │ ├── [拉勾]-SpringBoot实战-02构建数据访问层.md │ ├── [拉勾]-SpringBoot实战-03构建Web服务层+消息通信层.md │ ├── [拉勾]-SpringBoot实战-04构建系统安全层+监控层.md │ ├── 《SpringBoot揭秘》--王福强2016.md │ └── 《深入浅出SpringBoot2.x》--杨开振2018.md ├── B15-Go语言 │ ├── [拉勾]-Go微服务实战.md │ └── [极客时间]-Go语言从入门到实战.md ├── B16-Lua │ └── [runoob]-Lua教程.md ├── B17-Camunda │ ├── Camunda.md │ └── Zeebe.md ├── B18-Kubernetes │ ├── Kubernetes原理与实战-01基础篇.md │ ├── Kubernetes原理与实战-02进阶篇.md │ ├── Kubernetes原理与实战-04安全篇.md │ ├── 深入剖析Kubernetes-01基础篇.md │ └── 深入剖析Kubernetes-02实践篇.md ├── B19-SpringSecurity │ └── SpringSecurity详解与实操.md ├── B20-其他 │ ├── ApacheCamel.md │ ├── ApacheShiro.md │ ├── Disconf.md │ ├── ElasticJob.md │ └── Pinpoint.md ├── B21-微服务组件 │ ├── Dubbo.md │ ├── Dubbo源码剖析与实战-01基础&特色篇.md │ ├── Dubbo源码剖析与实战-03源码篇.md │ ├── Dubbo源码剖析与实战-04扩展篇.md │ ├── Netflix-Hystrix.md │ └── Sentinel.md ├── README.md └── sidebar.md ├── C类 ├── C01-高并发系统设计 │ ├── [advanced-java]-高并发架构.md │ ├── [极客时间]-高并发系统设计-01基础篇.md │ ├── [极客时间]-高并发系统设计-02数据库篇.md │ ├── [极客时间]-高并发系统设计-03缓存篇.md │ ├── 高并发系统设计-01基础篇.png │ └── 高并发系统设计-01基础篇.xmind ├── C02-微服务 │ ├── [极客时间]-01微服务安全架构与实践.md │ ├── [极客时间]-03微服务网关Zuul架构与实践.md │ ├── [极客时间]-08构建OAuth2服务器.md │ ├── [极客时间]-SpringBoot与Kubernetes云原生微服务实践.md │ ├── [极客时间]-从0开始学微服务.md │ ├── [美团]Shepherd设计与实现.md │ └── 微服务架构和技术预览.png ├── C03-架构设计 │ ├── [极客时间]-从0开始学架构-01架构基础.md │ ├── [极客时间]-从0开始学架构-02高性能架构模式.md │ ├── [极客时间]-从0开始学架构-03高可用架构模式.md │ ├── [极客时间]-从0开始学架构-04可扩展架构模式.md │ ├── [极客时间]-从0开始学架构-05架构实战.md │ ├── [极客时间]-分布式金融架构.md │ ├── [极客时间]-架构实战案例解析-01业务架构篇.md │ ├── [极客时间]-架构实战案例解析-02技术架构篇.md │ ├── [极客时间]-郭东白的架构课-01生存法则.md │ ├── [极客时间]-郭东白的架构课-02价值创造.md │ ├── [极客时间]-郭东白的架构课-03职业成长.md │ ├── [极客时间]-郭东白的架构课-04思考力.md │ └── 企业级高可用延时消息设计.md ├── C04-分布式 │ ├── [advanced-java]-分布式系统.md │ ├── 分布式-01理论篇.md │ ├── 分布式-02协议和算法篇.md │ └── 分布式技术原理与算法解析-01.md ├── C05-DDD │ ├── [极客时间]-DDD实战课-01基础篇.md │ ├── [极客时间]-DDD实战课-02进阶篇.md │ ├── [极客时间]-DDD实战课-03实战篇.md │ └── 《实现领域驱动设计》.md ├── C06-Web安全 │ ├── RSA原理.md │ └── [极客时间]-OAuth2实战-基础篇.md ├── C07-SaaS │ └── SaaS架构设计.md ├── C08-高性能系统设计 │ └── 如何设计一个秒杀系统.md ├── C09-数据存储 │ ├── 后端存储实战-01创业篇.md │ ├── 后端存储实战-02高速增长篇.md │ └── 后端存储实战-03海量数据篇.md ├── C10-容量保障 │ └── 容量保障核心技术与实战.md ├── README.md └── sidebar.md ├── D类 ├── D01-GraphQL │ └── [graphql.cn]-调研graphql技术.md ├── D02-版本控制 │ └── [RUNOOB]-Maven教程.md ├── D03-软件工程 │ ├── [极客时间]-如何提高研发效率?.md │ └── [极客时间]-持续交付.md ├── D04-职业规划 │ ├── 20180808知识地图认定--整理.md │ ├── 202009月知识梳理计划.md │ ├── 202010月面试计划.md │ ├── 程序员进阶攻略.md │ ├── 职场求生攻略-01职业素养篇.md │ ├── 职场求生攻略-02职业选择篇.md │ ├── 职场求生攻略-03职场情商篇.md │ └── 职场求生攻略-04技术成长篇.md ├── D05-面试 │ ├── JavaGuide-01Java基础.md │ ├── JavaGuide-数据库.md │ ├── technotes-数据库.md │ └── 后端技术基础详解-01软件基础原理.md ├── D06-项目管理 │ └── [授客学堂]-项目管理实战训练.md ├── D07-anki │ ├── 知识转Anki进度.md │ └── 项目.apkg ├── D08-杂谈 │ ├── InfoQ公开课.md │ ├── [advanced-java]-海量数据处理.md │ ├── [极客时间]-说透中台.md │ ├── 一些idea.md │ └── 面试题.md ├── D10-业务踩坑 │ ├── [极客时间]-Java开发常见错误-01代码篇.md │ └── [极客时间]-Java开发常见错误-02设计篇.md ├── D11-读书 │ ├── 01-掘金小册《技术写作指南》--张鑫旭.md │ ├── 02-《大型网站技术架构》--李智慧.md │ ├── 03-《深入理解Java虚拟机》(周志明)读书笔记.md │ ├── 04-《认知觉醒》--周岭.md │ ├── 05-《红楼梦》.md │ ├── 06-《富爸爸穷爸爸》.md │ ├── 07-《从零开始学价值投资》.md │ ├── 08-《劳动法》.md │ ├── 08-《指数基金定投》.md │ ├── 09-香帅的北大金融学课.md │ ├── README.md │ └── empty.md ├── D12-技术预研 │ ├── KubeShpere.md │ └── KubeShpere_view.png ├── D13-实践与笔记 │ ├── 01-Intellij-Idea最佳实践.md │ ├── 02-Postman最佳实践.md │ ├── 03-Linux使用笔记.md │ ├── 04-Git使用笔记.md │ ├── 05-SQL使用笔记.md │ ├── 06-Node使用笔记.md │ ├── 07-Docker使用笔记.md │ ├── 08-SonarLint使用笔记.md │ ├── clone.sh │ ├── 惊奇代码-Disconf.md │ ├── 惊奇代码-Java8.md │ └── 惊奇代码-Spring.md ├── D14-行业视角 │ ├── 产品思维30讲-梁宁.md │ ├── 全栈工程师修炼指南.md │ └── 技术文档写作规范.md ├── D15-技术管理 │ └── 技术领导力实战笔记.md ├── README.md └── sidebar.md ├── README.md ├── commit.sh ├── coverpage.md ├── generate_sitemap.py ├── img ├── cover.jpg ├── cover2.jpeg ├── cover3.jpg ├── cover4.jpg ├── my_favicon.ico └── my_favicon.png ├── index.html ├── navbar.md ├── sidebar.md ├── sitemap.sh ├── sitemap.txt ├── sitemap.xml ├── 技术笔记.xmind └── 资源 └── 学习资源.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # ignore 2 | *.sh linguist-vendored 3 | *.html linguist-vendored 4 | 5 | # set language 6 | *.md linguist-language=html 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # idea 23 | .idea/ 24 | 25 | # class/ 26 | class/ 27 | 28 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 29 | hs_err_pid* 30 | 31 | .DS_Store 32 | -------------------------------------------------------------------------------- /A类/A01-Java并发编程/并发工具类.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/A类/A01-Java并发编程/并发工具类.png -------------------------------------------------------------------------------- /A类/A01-Java并发编程/并发工具类.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/A类/A01-Java并发编程/并发工具类.xmind -------------------------------------------------------------------------------- /A类/A01-Java并发编程/并发理论基础.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/A类/A01-Java并发编程/并发理论基础.png -------------------------------------------------------------------------------- /A类/A01-Java并发编程/并发理论基础.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/A类/A01-Java并发编程/并发理论基础.xmind -------------------------------------------------------------------------------- /A类/A02-Java虚拟机/深入拆解Java虚拟机-01基本原理.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/A类/A02-Java虚拟机/深入拆解Java虚拟机-01基本原理.png -------------------------------------------------------------------------------- /A类/A02-Java虚拟机/深入拆解Java虚拟机-01基本原理.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/A类/A02-Java虚拟机/深入拆解Java虚拟机-01基本原理.xmind -------------------------------------------------------------------------------- /A类/A03-MySQL/MySQL实战-01基础篇.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/A类/A03-MySQL/MySQL实战-01基础篇.png -------------------------------------------------------------------------------- /A类/A03-MySQL/MySQL实战-01基础篇.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/A类/A03-MySQL/MySQL实战-01基础篇.xmind -------------------------------------------------------------------------------- /A类/A03-MySQL/SQL执行计划.md: -------------------------------------------------------------------------------- 1 | # 01 | SQL语句执行顺序 2 | 3 | ![image-20211207155619563](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/image-20211207155619563.png) 4 | 5 | 1. FORM: 对FROM的左边的表和右边的表计算笛卡尔积。产生虚表VT1 6 | 2. ON: 对虚表VT1进行ON筛选,只有那些符合``的行才会被记录在虚表VT2中。 7 | 3. JOIN: 如果指定了OUTER JOIN(比如left join、 right join),那么保留表中未匹配的行就会作为外部行添加到虚拟表VT2中,产生虚拟表VT3, 如果 from子句中包含两个以上的表的话,那么就会对上一个join连接产生的结果VT3和下一个表重复执行步骤1~3这三个步骤,一直到处理完所有的表为止。 8 | 4. WHERE: 对虚拟表VT3进行WHERE条件过滤。只有符合``的记录才会被插入到虚拟表VT4中。 9 | 5. GROUP BY: 根据group by子句中的列,对VT4中的记录进行分组操作,产生VT5.(从此开始使用select中的别名,后面的语句中都可以使用) 10 | 6. CUBE|ROLLUP|SUM|AVG: 对表VT5进行sum或者avg操作,产生表VT6. 11 | 7. HAVING: 对虚拟表VT6应用having过滤,只有符合``的记录才会被 插入到虚拟表VT7中。 12 | 8. SELECT: 执行select操作,选择指定的列,插入到虚拟表VT8中。 13 | 9. DISTINCT: 对VT8中的记录进行去重。产生虚拟表VT9. 14 | 10. ORDER BY: 将虚拟表VT9中的记录按照进行排序操作,产生虚拟表VT10. 15 | 11. LIMIT:取出指定行的记录,产生虚拟表VT11, 并将结果返回。 16 | 17 | # 02 | 看懂执行计划 18 | 19 | ![image-20211207155807199](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/image-20211207155807199.png) 20 | 21 | 1. id: id是一组数字,表示查询中执行select子句或操作表的顺序,如果id相同,则执行顺序从上至下,如果是子查询, id的序号会递增, id越大则优先级越高,越先会被执行。 22 | 2. select_type:查询类型,有simple、 primary、 subquery、 dependent subquery、 derived、 union、 dependent union、 union result等 23 | 3. table:显示的查询表名,如果查询使用了别名,那么这里显示的是别名。如果不涉及对数据表的操作,那么这显示为null。如果显示为尖括号括起来的``就表示这个是临时表,后边的N就是执行计划中的id,表示结果来自于这个查询产生。 24 | 4. **type**:依次从好到差: system, const, eq_ref, ref, fulltext, ref_or_null, unique_subquery,index_subquery, range, index_merge, index, ALL。除了all之外,其他的type都可以使用到索引,除了index_merge之外,其他的type只可以用到一个索引。 25 | 5. **possible_keys**:查询可能使用到的索引都会在这里列出来。 26 | 6. **key**:查询真正使用到的索引, select_type为index_merge时,这里可能出现两个以上的索引,其他的select_type这里只会出现一个。 27 | 7. key_len:用于处理查询的索引长度,如果是单列索引,那就整个索引长度算进去,如果是多列索引,那么查询不一定都能使用到所有的列,具体使用到了多少个列的索引,这里就会计算进去,没有使用到的列,这里不会计算进去。 28 | 8. ref:如果是使用的常数等值查询,这里会显示const,如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段,如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func。 29 | 9. **rows**:这里是执行计划中估算的扫描行数,不是精确值。 30 | 10. extra:这个列可以显示的信息非常多,有几十种,常用的有: distinct、 using filesort、 using index、 using temporary 31 | 32 | # 03 | 计算字段区分度 33 | 34 | 计算公式:对字段去重统计值/表总行统计值。 35 | 36 | 例:select count(distinct pay_time)/count(1) from trade_flow 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /A类/A03-MySQL/[拉勾教育]-高性能MySQL实战-01基础篇.md: -------------------------------------------------------------------------------- 1 | # 开篇寄语:建立完整的MySQL知识体系 2 | 3 | ![image-20201020151410986](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/image-20201020151410986.png) 4 | 5 | -------------------------------------------------------------------------------- /A类/A04-网络协议/趣谈网络协议.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/A类/A04-网络协议/趣谈网络协议.xmind -------------------------------------------------------------------------------- /A类/A04-网络协议/面试题.md: -------------------------------------------------------------------------------- 1 | # 01 | 一个 TCP 连接可以发多少 HTTP 请求? 2 | 3 | > 来源:https://zhuanlan.zhihu.com/p/61423830 4 | 5 | 从 URL 在浏览器被输入到页面展现的过程中发生了什么? 6 | 7 | 如果继续问:收到的 HTML 如果包含几十个图片标签,这些图片是以什么方式、什么顺序、建立了多少连接、使用什么协议被下载下来的呢? 8 | 9 | 要搞懂这个问题,我们需要先解决下面五个问题: 10 | 11 | 1. 现代浏览器在与服务器建立了一个 TCP 连接后是否会在一个 HTTP 请求完成后断开?什么情况下会断开? 12 | 2. 一个 TCP 连接可以对应几个 HTTP 请求? 13 | 3. 一个 TCP 连接中 HTTP 请求发送可以一起发送么(比如一起发三个请求,再三个响应一起接收)? 14 | 4. 为什么有的时候刷新页面不需要重新建立 SSL 连接? 15 | 5. 浏览器对同一 Host 建立 TCP 连接的数量有没有限制? 16 | 17 | **第一个问题** 18 | 19 | 现代浏览器在与服务器建立了一个 TCP 连接后是否会在一个 HTTP 请求完成后断开?什么情况下会断开? 20 | 21 | 在 HTTP/1.0 中,一个服务器在发送完一个 HTTP 响应后,会断开 TCP 链接。但是这样每次请求都会重新建立和断开 TCP 连接,代价过大。所以虽然标准中没有设定,某些服务器对 Connection: keep-alive 的 Header 进行了支持。意思是说,完成这个 HTTP 请求之后,不要断开 HTTP 请求使用的 TCP 连接。这样的好处是连接可以被重新使用,之后发送 HTTP 请求的时候不需要重新建立 TCP 连接,以及如果维持连接,那么 SSL 的开销也可以避免,下面两张图片是我短时间内两次访问 https://www.github.com 的时间统计: 22 | 23 | ![image-20201011102340899](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/image-20201011102340899.png) 24 | 25 | 头一次访问,有初始化连接和 SSL 开销。 26 | 27 | ![image-20201011102323010](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/image-20201011102323010.png) 28 | 29 | 第二次访问,初始化连接和 SSL 开销消失了,说明使用的是同一个 TCP 连接。 30 | 31 | 持久连接:既然维持 TCP 连接好处这么多,HTTP/1.1 就把 Connection 头写进标准,并且默认开启持久连接,除非请求中写明 Connection: close,那么浏览器和服务器之间是会维持一段时间的 TCP 连接,不会一个请求结束就断掉。 32 | 33 | 所以第一个问题的答案是:默认情况下建立 TCP 连接不会断开,只有在请求报头中声明 Connection: close 才会在请求完成后关闭连接。 34 | 35 | **第二个问题** 36 | 37 | 一个 TCP 连接可以对应几个 HTTP 请求? 38 | 39 | 了解了第一个问题之后,其实这个问题已经有了答案,如果维持连接,一个 TCP 连接是可以发送多个 HTTP 请求的。至于多少个,需要根据 keep-alive 的时间和请求了多少次来决定。 40 | 41 | **第三个问题** 42 | 43 | 一个 TCP 连接中 HTTP 请求发送可以一起发送么(比如一起发三个请求,再三个响应一起接收)? 44 | 45 | HTTP/1.1 存在一个问题,单个 TCP 连接在同一时刻只能处理一个请求,意思是说:两个请求的生命周期不能重叠,任意两个 HTTP 请求从开始到结束的时间在同一个 TCP 连接里不能重叠。 46 | 47 | 虽然 HTTP/1.1 规范中规定了 Pipelining 来试图解决这个问题,但是这个功能在浏览器中默认是关闭的。 48 | 49 | 但是,HTTP2 提供了 Multiplexing 多路传输特性,可以在一个 TCP 连接中同时完成多个 HTTP 请求。至于 Multiplexing 具体怎么实现的就是另一个问题了。我们可以看一下使用 HTTP2 的效果。 50 | 51 | ![image-20201011103346770](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/image-20201011103346770.png) 52 | 53 | 绿色是发起请求到请求返回的等待时间,蓝色是响应的下载时间,可以看到都是在同一个 Connection,并行完成的 54 | 55 | 所以这个问题也有了答案:在 HTTP/1.1 存在 Pipelining 技术可以完成这个多个请求同时发送,但是由于浏览器默认关闭,所以可以认为这是不可行的。在 HTTP2 中由于 Multiplexing 特点的存在,多个 HTTP 请求可以在同一个 TCP 连接中并行进行。 56 | 57 | 那么在 HTTP/1.1 时代,浏览器是如何提高页面加载效率的呢?主要有下面两点: 58 | 59 | 1. 维持和服务器已经建立的 TCP 连接,在同一连接上顺序处理多个请求。 60 | 2. 和服务器建立多个 TCP 连接。 61 | 62 | **第四个问题** 63 | 64 | 为什么有的时候刷新页面不需要重新建立 SSL 连接? 65 | 66 | 在第一个问题的讨论中已经有答案了,TCP 连接有的时候会被浏览器和服务端维持一段时间。TCP 不需要重新建立,SSL 自然也会用之前的。 67 | 68 | **第五个问题** 69 | 70 | 浏览器对同一 Host 建立 TCP 连接的数量有没有限制? 71 | 72 | 假设我们还处在 HTTP/1.1 时代,那个时候没有多路传输,当浏览器拿到一个有几十张图片的网页该怎么办呢?肯定不能只开一个 TCP 连接顺序下载,那样用户肯定等的很难受,但是如果每个图片都开一个 TCP 连接发 HTTP 请求,那电脑或者服务器都可能受不了,要是有 1000 张图片的话总不能开 1000 个TCP 连接吧。 73 | 74 | 所以答案是:有。Chrome 最多允许对同一个 Host 建立六个 TCP 连接。不同的浏览器有一些区别。(区别可点击[这里](https://developers.google.com/web/tools/chrome-devtools/network/issues#queued-or-stalled-requestsdevelopers.google.com)) 75 | 76 | 那么回到最开始的问题,收到的 HTML 如果包含几十个图片标签,这些图片是以什么方式、什么顺序、建立了多少连接、使用什么协议被下载下来的呢? 77 | 78 | 如果图片都是 HTTPS 连接并且在同一个域名下,那么浏览器在 SSL 握手之后会和服务器商量能不能用 HTTP2,如果能的话就使用 Multiplexing 功能在这个连接上进行多路传输。不过也未必会所有挂在这个域名的资源都会使用一个 TCP 连接去获取,但是可以确定的是 Multiplexing 很可能会被用到。 79 | 80 | 如果发现用不了 HTTP2 呢?或者用不了 HTTPS(现实中的 HTTP2 都是在 HTTPS 上实现的,所以也就是只能使用 HTTP/1.1)。那浏览器就会在一个 HOST 上建立多个 TCP 连接,连接数量的最大限制取决于浏览器设置,这些连接会在空闲的时候被浏览器用来发送新的请求,如果所有的连接都正在发送请求呢?那其他的请求就只能等等了。 81 | 82 | # 02 | 万字长文拿下 HTTP 83 | 84 | **提纲** 85 | 86 | ![image-20201011104827735](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/image-20201011104827735.png) 87 | 88 | 1989年,蒂姆·伯纳斯 - 李(Tim Berners-Lee)在论文中提出可以在互联网上构建超链接文档,并提出了三点: 89 | 90 | URI:统一资源标识符。互联网的唯一ID 91 | HTML:超文本文档 92 | HTTP:传输超文本的文本传输协议 93 | 94 | **HTTP 应用在哪儿?** 95 | 96 | ![image-20201011110818814](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/image-20201011110818814.png) 97 | 98 | **HTTP 是什么?** 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /A类/A05-数据结构与算法/算法面试通关40讲.md: -------------------------------------------------------------------------------- 1 | # 01 课程综述 2 | 3 | 01 合格程序员的第一步:算法与数据结构 4 | 5 | 02 如何事半功倍地学习算法与数据结构 6 | 7 | 03 如何快速计算算法的时间复杂度 8 | 9 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2023/202304242132768.png) 10 | 11 | 04 如何通过 LeetCode 进行算法题目练习 12 | 13 | # ==数据结构== 14 | 15 | # 02 数组、链表 16 | 17 | 面试题一:如何反转一个单链表 18 | 19 | 面试题二:判断链表中是否有环 20 | 21 | - Set 判重 O(n) 22 | - 快慢指针 O(n) 23 | 24 | # 03 堆栈、队列 25 | 26 | 面试题一:判断括号字符串是否有效 27 | 28 | - 使用堆栈 29 | 30 | 面试题二:用栈实现队列 31 | 32 | 面试题三:用队列实现栈 33 | 34 | # 04 优先队列 35 | 36 | 实现机制 37 | 38 | 1. 堆(二叉堆) 39 | 2. 二叉搜索树 40 | 41 | 面试题一:返回数据流中的第 K 大元素 42 | 43 | 面试题二:返回滑动窗口中的最大值 44 | 45 | # 05 哈希表 46 | 47 | 面试题一:判断有效的字母异位词 48 | 49 | - 方法一:排序 O(nlogn) 50 | - 方法二:Map 计数 {letter: count} O(n) 51 | 52 | 面试题二:找出数组中和为目标值的两个数、三个数、四个数 53 | 54 | - 两数之和:a+b = 9 55 | - 方法一:暴力解法 O(n2) 56 | - 方法二:Set O(n) 57 | - 三数之和:a+b+c = 0 58 | - 方法一:暴力解法 O(n3) 59 | - 方法二:c = 0-(a+b) Set O(n2) 60 | 61 | # 06 树、二叉树、二叉搜索树 62 | 63 | 面试题一:验证二叉搜索树 64 | 65 | - 方法一:In-order 的 array 升序 66 | - 方法二:Recursion 67 | - validate(node.left) => max 68 | - validate(node.right) => min 69 | - return max < root && min > root 70 | 71 | 面试题二:二叉树的最近公共祖先 72 | 73 | 面试题三:二叉搜索树的最近公共祖先 74 | 75 | # ==算法== 76 | 77 | # 07 二叉树遍历 78 | 79 | 理论讲解 80 | 81 | - Pre-order:根-左-右 82 | - In-order:左-根-右 83 | - Post-order:左-右-根 84 | 85 | ```python 86 | def preorder(self, root): 87 | if root: 88 | self.traverse_path.append(root.val) 89 | self.preorder(root.left) 90 | self.preorder(root.right) 91 | 92 | def inorder(self, root): 93 | if root: 94 | self.inorder(root.left) 95 | self.traverse_path.append(root.val) 96 | self.inorder(root.right) 97 | 98 | def postorder(self, root): 99 | if root: 100 | self.postorder(root.left) 101 | self.postorder(root.right) 102 | self.traverse_path.append(root.val) 103 | ``` 104 | 105 | # 08 分治、递归 106 | 107 | 理论讲解 108 | 109 | 递归代码结构: 110 | 111 | ```python 112 | def recursion(level, param1, param2, ...): 113 | # 1.终止条件 114 | if level > MAX_LEVEL: 115 | print_result 116 | return 117 | # 2.前置处理 118 | process_data(level, data...) 119 | # 3.下钻 120 | self.recursion(level + 1, p1, ...) 121 | # 4.后续处理(按需) 122 | reverse_state(level) 123 | ``` 124 | 125 | 分治代码结构: 126 | 127 | ```python 128 | def divide_conquer(problem, param1, param2, ...): 129 | # 1.终止条件 130 | if problem is None: 131 | print_result 132 | return 133 | # 2.准备数据 134 | data = prepare_data(problem) 135 | subproblems = split_problem(problem, data) 136 | # 3.处理子问题 137 | subresult1 = self.divide_conquer(subproblems[0], p1, ...) 138 | subresult2 = self.divide_conquer(subproblems[1], p1, ...) 139 | subresult3 = self.divide_conquer(subproblems[1], p1, ...) 140 | # ... 141 | 142 | result = process_result(subresult1, subresult2, subresult3, ...) 143 | ``` 144 | 145 | 面试题一:实现计算 x 的 n 次幂函数 146 | 147 | - 方法一:暴力 O(n) 148 | - 方法二:递归 O(logn) 149 | - 方法三:位运算 150 | 151 | 面试题二:找出数组中出现次数大于 n/2 的元素 152 | 153 | # 09 贪心算法 154 | 155 | 定义:在对问题求解时,总是做出在当前看来是最好的选择。 156 | 157 | 面试题一:计算买卖股票的最佳时机 158 | 159 | - 贪心算法 O(n) 160 | - 动态规划 O(n) 161 | 162 | # 10 广度优先搜索、深度优先搜索 163 | 164 | 理论讲解 165 | 166 | 面试题一:二叉树层次遍历 167 | 168 | 面试题二:二叉树最大深度 169 | 170 | 面试题三:二叉树最小深度 171 | 172 | 面试题四:生成所有可能的有效括号组合 173 | 174 | # 11 剪枝 175 | 176 | 理论讲解 177 | 178 | 面试题一:如何使 N 个皇后彼此之间不能相互攻击? 179 | 180 | 面试题二:判断数独是否有效 181 | 182 | 面试题三:解决数独问题 183 | 184 | # 12 二分查找 185 | 186 | 二分查找的三个条件: 187 | 188 | - Sorted:单调递增或者递减 189 | - Bounded:存在上下界 190 | - Accessible by index:能够通过索引访问 191 | 192 | 面试题一:实现一个求解平方根的函数 193 | 194 | # 13 字典树(trie) 195 | 196 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2023/202304262220902.png) 197 | 198 | ![image-20230426223156410](https://technotes.oss-cn-shenzhen.aliyuncs.com/2023/202304262231473.png) 199 | 200 | ```java 201 | static final int ALPHABET_SIZE = 256; 202 | static class TrieNode { 203 | TrieNode[] children = new TrieNode[ALPHABET_SIZE]; 204 | boolean isEndOfWorld = false; 205 | TrieNode() { 206 | isEndOfWorld = false; 207 | for (int i = 0; i < ALPHABET_SIZE; i++) { 208 | children[i] = null; 209 | } 210 | } 211 | } 212 | ``` 213 | 214 | 面试题一:二维网格中的单词搜索问题 215 | 216 | 面试题二:实现一个字典树 217 | 218 | # 14 位运算的运用 219 | 220 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2023/202304262253113.png) 221 | 222 | 实战常用的位运算操作 223 | 224 | - x & 1 == 1 OR == 0 判断奇偶,相当于 x % 2 == 1 225 | - x = x & (x-1):清零最低位的1 226 | - x & -x:得到最低位的1 227 | 228 | 面试题一:二进制数中的比特位统计问题 229 | 230 | 面试题二:判断一个数是否为 2 的幂次方 231 | 232 | 面试题三:N 皇后问题的另一种解法 233 | 234 | # 15 动态规划 235 | 236 | 理论讲解 237 | 238 | 1. 递归+记忆化:递推 239 | 2. 状态的定义:opt[n], dp[n], fib[n] 240 | 3. 状态转移方程:opt[n] = best_of(opt[n-1], opt[n-2], ...) 241 | 4. 最优子结构 242 | 243 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2023/202304262335942.png) 244 | 245 | DP vs 递归 vs 贪心 246 | 247 | - 递归:重复计算的问题 248 | - 偏心:永远局部最优 249 | - DP:记录局部最优子结构 250 | 251 | 面试题一:爬楼梯问题 252 | 253 | 面试题二:三角形的最小路径和 254 | 255 | 面试题三:乘积最大子序列 256 | 257 | 面试题四:用动态规划解决买卖股票问题 258 | 259 | 面试题五:最长上升子序列 260 | 261 | 面试题六:不同面值硬币的兑换问题 262 | 263 | 面试题七:计算最短编辑距离问题 264 | 265 | # 16 并查集 266 | 267 | 理论讲解 268 | 269 | 面试题一:二维网格中的小岛数量统计问题 270 | 271 | 面试题二:计算矩阵中的朋友圈总数 272 | 273 | # 17 LRU Cache 274 | 275 | 理论讲解 276 | 277 | 面试题一:设计和实现一个 LRU 缓存机制 278 | 279 | # 18 布隆过滤器 280 | 281 | 理论讲解 282 | 283 | # 面试经验分享 284 | 285 | 解决婚姻问题的算法&重点算法代码模板回顾 286 | 287 | 常见问题答疑&面试中的切题四件套 288 | 289 | - Clarification:询问题目细节、边界条件、可能的极端错误情况 290 | - Possible Solution:所有可能的解法都和面试官司沟通一遍,包括时间&空间复杂度、最优解 291 | - Coding:写代码 292 | - Test Cases:测试用例 293 | 294 | 斐波拉契数列代码实战 295 | 296 | 斐波拉契数列白板实战 297 | 298 | 个人经验分享合辑 299 | 300 | - 三分学,七分练 301 | - 算法和数据结构是内力 302 | - 重在练习(修行) 303 | -------------------------------------------------------------------------------- /A类/Python/Python核心技术与实战/Python核心技术与实战-基础篇.md: -------------------------------------------------------------------------------- 1 | # 开篇词 | 从工程的角度深入理解Python 2 | 3 | 专栏的所有内容都基于 Python 最新的 3.7 版本,其中有大量独家解读、案例,以及不少我阅读源码后的发现和体会。 4 | 5 | 专栏主要分为四大版块。 6 | 7 | **1. Python 基础篇** 8 | 9 | - 列表和元组存储结构的差异是怎样的?它们性能的详细比较又如何? 10 | - 字符串相加的时间复杂度,你真的清楚吗? 11 | 12 | **2. Python 进阶篇** 13 | 14 | 比如装饰器、并发编程等等。 15 | 16 | **3. Python 规范篇** 17 | 18 | 这部分着重于教你把程序写得更加规范、更加稳定。 19 | 20 | **4. Python 实战篇** 21 | 22 | 这部分,我会通过量化交易系统这个具体的实战案例,带你综合运用前面所学的 Python 知识。 23 | 24 | # 01 | 如何逐步突破,成为Python高手? 25 | 26 | 对于一门新语言,Facebook 工程师基本上一两周后,日常编程便毫无压力了。他们遵循的方法就是“从工程的角度去学习 Python”。 27 | 28 | **不同语言,需融会贯通** 29 | 30 | 比如,在学习 Python 的条件与循环语句时,多回忆一下其他语言的语法是怎样的。 31 | 32 | 根据我多年的学习工作经验,我把编程语言的学习重点,总结成了下面这三步,无论你是否有其他语言的基础,都可以对照来做,稳步进阶。 33 | 34 | **第一步:大厦之基,勤加练习** 35 | 36 | 在掌握必要的基础时,就得多上手操作了。 37 | 38 | **第二步:代码规范,必不可少** 39 | 40 | 如果有不遵守代码规范的例子,哪怕只是一个函数或是一个变量的命名,我们都会要求原作者加以修改,严格规范才能保证代码库的代码质量。 41 | 42 | **第三步:开发经验,质的突破** 43 | 44 | 想要真正熟练地掌握 Python 或者是任何一门其他的编程语言,拥有大中型产品的开发经验是必不可少的。因为实战经验才能让你站得更高,望得更远。 45 | 46 | > 第1篇,说了很多废话。 47 | 48 | # 02 | Jupyter Notebook为什么是现代Python的必学技术? 49 | 50 | 为什么 Python 如此适合数学统计和机器学习呢?作为“老司机”的我可以肯定地告诉你,Jupyter Notebook (https://jupyter.org/)功不可没。 51 | 52 | **什么是 Jupyter Notebook?** 53 | 54 | 按照 Jupyter 创始人 Fernando Pérez 的说法,他最初的梦想是做一个综合 Ju (Julia)、Py (Python)和 R 三种科学运算语言的计算工具平台,所以将其命名为 Ju-Py-te-R。发展到现在,Jupyter 已经成为一个几乎支持所有语言,能够把软件代码、计算输出、解释文档、多媒体资源整合在一起的多功能科学运算平台。 55 | 56 | **Jupyter Notebook 的影响力** 57 | 58 | 从 2017 年开始,已有大量的北美顶尖计算机课程,开始完全使用 Jupyter Notebook 作为工具。比如李飞飞的 CS231N《计算机视觉与神经网络》课程,在 16 年时作业还是命令行 Python 的形式,但是 17 年的作业就全部在 Jupyter Notebook 上完成了。再如 UC Berkeley 的《数据科学基础》课程,从 17 年起,所有作业也全部用 Jupyter Notebook 完成。 59 | 60 | 而 Jupyter Notebook 在工业界的影响力更甚。在 Facebook,虽然大规模的后台开发仍然借助于功能齐全的 IDE,但是几乎所有的中小型程序,比如内部的一些线下分析软件,机器学习模块的训练都是借助于 Jupyter Notebook 完成的。据我了解,在别的硅谷一线大厂,例如 Google 的 AI Research 部门 Google Brain,也是清一色地全部使用 Jupyter Notebook,虽然用的是他们自己的改进定制版,叫 Google Colab。 61 | 62 | **Jupyter 的优点** 63 | 64 | - 整合所有的资源 65 | 66 | 在真正的软件开发中,上下文切换占用了大量的时间。 67 | 68 | Jupyter 通过把所有和软件编写有关的资源全部放在一个地方,解决了这个问题。当你打开一个 Jupyter Notebook 时,就已经可以看到相应的文档、图表、视频和相应的代码。这样,你就不需要切换窗口去找资料,只要看一个文件,就可以获得项目的所有信息。 69 | 70 | - 交互性编程体验 71 | 72 | 在机器学习和数学统计领域,Python 编程的实验性特别强,经常出现的情况是,一小块代码需要重写 100 遍,比如为了尝试 100 种不同的方法,但别的代码都不想动。 73 | 74 | Jupyter Notebook 引进了 Cell 的概念,每次实验可以只跑一小个 Cell 里的代码;并且,所见即所得,在代码下面立刻就可以看到结果。这样强的互动性,让 Python 研究员可以专注于问题本身,不被繁杂的工具链所累,不用在命令行直接切换,所有科研工作都能在 Jupyter 上完成。 75 | 76 | - 零成本重现结果 77 | 78 | 同样在机器学习和数学统计领域,Python 的使用是非常短平快的。常见的场景是,我在论文里看到别人的方法效果很好,可是当我去重现时,却发现需要 pip 重新安装一堆依赖软件。这些准备工作可能会消耗你 80% 的时间,却并不是真正的生产力。 79 | 80 | Jupyter 官方的 Binder 平台(介绍文档:https://mybinder.readthedocs.io/en/latest/index.html)和 Google 提供的 Google Colab 环境(介绍:https://colab.research.google.com/notebooks/welcome.ipynb)。它们让 Jupyter Notebook 变得和石墨文档、Google Doc 在线文档一样,在浏览器点开链接就能运行。 81 | 82 | 所以,现在当你用 Binder 打开一份 GitHub 上的 Jupyter Notebook 时,你不需要安装任何软件,直接在浏览器打开一份代码,就能在云端运行。 83 | 84 | **Jupyter Notebook 初体验** 85 | 86 | 比如这样一个[GitHub 文件](https://github.com/binder-examples/python2_with_3/blob/master/index3.ipynb)。在[Binder](https://mybinder.org/)中,你只要输入其对应的 GitHub Repository 的名字或者 URL,就能在云端打开整个 Repository,选择你需要的[notebook](https://mybinder.org/v2/gh/binder-examples/python2_with_3/master?filepath=index3.ipynb),你就能看到下图这个界面。 87 | 88 | ![image-20211207232540300](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20211207232540.png) 89 | 90 | 每一个 Jupyter 的运行单元都包含了 In、Out 的 Cell。如图所示,你可以使用 Run 按钮,运行单独的一个 Cell。当然,你也可以在此基础上加以修改,或者新建一个 notebook,写成自己想要的程序。 91 | 92 | **推荐网站** 93 | 94 | - 第一个是 Jupyter 官方:https://mybinder.org/v2/gh/binder-examples/matplotlib-versions/mpl-v2.0/?filepath=matplotlib_versions_demo.ipynb 95 | - 第二个是 Google Research 提供的 Colab 环境,尤其适合机器学习的实践应用:https://colab.research.google.com/notebooks/basic_features_overview.ipynb 96 | 97 | > 如果你想在本地或者远程的机器上安装 Jupyter Notebook,可以参考下面的两个文档。 98 | 99 | > 安装:https://jupyter.org/install.html 100 | 101 | > 运行:https://jupyter.readthedocs.io/en/latest/running.html#running 102 | 103 | 104 | 105 | --- 106 | 107 | 因工作当中用不上,故暂停学习。 108 | 109 | -------------------------------------------------------------------------------- /A类/Python/README.md: -------------------------------------------------------------------------------- 1 | # Python -------------------------------------------------------------------------------- /A类/Python/sidebar.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | - 零基础学Python 4 | - [01 | Python介绍与安装](A类/Python/零基础学Python/01Python介绍与安装.md) 5 | - [02 | 变量、数字、序列、映射和集合](A类/Python/零基础学Python/02变量、数字、序列、映射和集合.md) 6 | - [03 | 条件和循环.md](A类/Python/零基础学Python/03条件和循环.md) 7 | - [04 | 文件、输入输出、异常](A类/Python/零基础学Python/04文件、输入输出、异常.md) 8 | - [05 | 函数、模块.md](A类/Python/零基础学Python/05函数、模块.md) 9 | - [06 | 面向对象编程](A类/Python/零基础学Python/06面向对象编程.md) 10 | - [07 | 多线程编程](A类/Python/零基础学Python/07多线程编程.md) 11 | - [08 | 标准库、机器学习库](A类/Python/零基础学Python/08标准库、机器学习库.md) 12 | - [09 | 第三方库](A类/Python/零基础学Python/09第三方库.md) 13 | 14 | - Python核心技术与实战 15 | - [Python核心技术与实战-基础篇](A类/Python/Python核心技术与实战/Python核心技术与实战-基础篇.md) 16 | 17 | -------------------------------------------------------------------------------- /A类/Python/零基础学Python/01Python介绍与安装.md: -------------------------------------------------------------------------------- 1 | ![](https://cdn.jsdelivr.net/gh/studeyang/technotes@master/Python/零基础学Python/python_knowledge_map.jpg) 2 | 3 | ## 在Windows系统上安装Python 4 | 5 | 访问:https://www.python.org/downloads/release/python-365/。 6 | 7 | 进入&退出 python 环境: 8 | 9 | ```shell 10 | yanglulu@yangluludeMBP ~ % python3 11 | Python 3.8.2 (default, Sep 24 2020, 19:37:08) 12 | [Clang 12.0.0 (clang-1200.0.32.21)] on darwin 13 | Type "help", "copyright", "credits" or "license" for more information. 14 | >>> 15 | >>> 16 | >>> 17 | KeyboardInterrupt 18 | >>> exit 19 | Use exit() or Ctrl-D (i.e. EOF) to exit 20 | >>> exit() 21 | yanglulu@yangluludeMBP ~ % 22 | ``` 23 | 24 | **安装pip** 25 | 26 | ```shell 27 | curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py 28 | ``` 29 | 30 | ```shell 31 | python get-pip.py 32 | ``` 33 | 34 | ## 第一个Python程序 35 | 36 | ```python 37 | # 这是我的第一个Python程序 38 | 39 | import time # 我导入了一个时间模块 40 | 41 | 42 | print(time.time()) #在屏幕上打印出从1970年1月1日0:00 到现在经过了多少秒 43 | 44 | if 10-9 > 0: 45 | # 这行需要缩进,缩进用4个空格 46 | print('10大于9') 47 | ``` 48 | 49 | **Python程序的书写规则** 50 | 51 | ```python 52 | from __future__ import absolute_import 53 | from __future__ import division 54 | from __future__ import print_function 55 | 56 | # Imports 符号”#” 后面可以跟注释 57 | import numpy as np 58 | import tensorflow as tf 59 | 60 | tf.logging.set_verbosity(tf.logging.INFO) 61 | 62 | # Our application logic will be added here 63 | 64 | if __name__ == "__main__": 65 | tf.app.run() #代码缩进 66 | ``` 67 | 68 | **学习Python编程的利器** 69 | 70 | - Python官方文档:https://www.python.org/doc/ 71 | - iPython:https://www.python.org/doc/ 72 | - jupyter notebook:http://jupyter-notebook.readthedocs.io/en/latest/ 73 | - sublime text:https://www.sublimetext.com 74 | - PyCharm:https://www.jetbrains.com/pycharm/ 75 | - pip:https://pip.pypa.io/en/stable/installing/ 76 | 77 | **标准库** 78 | 79 | Python标准库的官方文档在如下位置:https://docs.python.org/3/library/index.html 80 | 81 | 日常应用比较广泛的模块是: 82 | 83 | 1. 文字处理的 re 84 | 2. 日期类型的time、datetime 85 | 3. 数字和数学类型的math、random 86 | 4. 文件和目录访问的pathlib、os.path 87 | 5. 数据压缩和归档的tarfile 88 | 6. 通用操作系统的os、logging、argparse 89 | 7. 多线程的 threading、queue 90 | 8. Internet数据处理的 base64 、json、urllib 91 | 9. 结构化标记处理工具的 html、xml 92 | 10. 开发工具的unitest 93 | 11. 调试工具的 timeit 94 | 12. 软件包发布的venv 95 | 13. 运行服务的`__main__` 96 | 97 | ## 基本数据类型 98 | 99 | - 整数(int):8 100 | - 浮点数(float):8.8 101 | - 字符串(str):“8” “Python” 102 | - 布尔值(bool):True False -------------------------------------------------------------------------------- /A类/Python/零基础学Python/02变量、数字、序列、映射和集合.md: -------------------------------------------------------------------------------- 1 | ## 变量 2 | 3 | **网络带宽计算器案例** 4 | 5 | 我们经常要估算一个文件要多久能传输完成,可以写一个计算器来计算传输时间。 6 | 7 | network_bandwidth.py 8 | 9 | ``` 10 | # 网络带宽计算 11 | # print(100/8) 12 | 13 | bandwidth = 100 14 | ratio = 8 15 | 16 | print(bandwidth/ratio) 17 | ``` 18 | 19 | ## 序列 20 | 21 | 序列是指它的成员都是有序排列,并且可以通过下标偏移量访问到它的一个或几个成员。序列包括: 22 | 23 | - 字符串:"abcd" 24 | - 列表:[ 0, "abcd"] 25 | - 元组:("abc", "def") 26 | 27 | **序列的基本操作** 28 | 29 | - 对象 [not] in 序列 30 | - 序列 + 序列 31 | - 序列 * 整数 32 | - 序列[0:整数] 33 | 34 | **计算生肖和星座案例** 35 | 36 | chinese_zodiac.py 37 | 38 | ``` 39 | # 记录生肖,根据年份来判断生肖 40 | 41 | chinese_zodiac = '猴鸡狗猪鼠牛虎兔龙蛇马羊' 42 | 43 | print (chinese_zodiac[0:4] ) # 猴鸡狗猪 44 | 45 | print (chinese_zodiac[-1]) # 羊 46 | 47 | year = 2018 48 | print (year % 12) # 2 49 | 50 | print (chinese_zodiac[year % 12]) # 狗 51 | 52 | print ( '狗' not in chinese_zodiac ) # False 53 | 54 | print (chinese_zodiac + 'abcd') # 猴鸡狗猪鼠牛虎兔龙蛇马羊abcd 55 | 56 | print (chinese_zodiac * 3 ) # 猴鸡狗猪鼠牛虎兔龙蛇马羊猴鸡狗猪鼠牛虎兔龙蛇马羊猴鸡狗猪鼠牛虎兔龙蛇马羊 57 | ``` 58 | 59 | zodiac.py 60 | 61 | ``` 62 | zodiac_name = (u'摩羯座', u'水瓶座', u'双鱼座', u'白羊座', u'金牛座', u'双子座', 63 | u'巨蟹座', u'狮子座', u'处女座', u'天秤座', u'天蝎座', u'射手座') 64 | zodiac_days = ((1, 20), (2, 19), (3, 21), (4, 21), (5, 21), (6, 22), 65 | (7, 23), (8, 23), (9, 23), (10, 23), (11, 23), (12, 23)) 66 | 67 | (month, day) = (2, 15) 68 | 69 | zodiac_day = filter(lambda x: x<=(month, day), zodiac_days) 70 | print(list(zodiac_day)) # [(1, 20)] 71 | 72 | zodac_len = len(list(zodiac_day)) % 12 73 | print(zodiac_name[zodac_len]) # 摩羯座 74 | ``` 75 | 76 | 列表: 77 | 78 | ``` 79 | a_list = ['abc', 'xyz'] 80 | a_list.append('X') 81 | print (a_list) # ['abc', 'xyz', 'X'] 82 | a_list.remove('xyz') 83 | print(a_list) # ['abc', 'X'] 84 | ``` -------------------------------------------------------------------------------- /A类/Python/零基础学Python/03条件和循环.md: -------------------------------------------------------------------------------- 1 | ## 条件语句 2 | 3 | ``` 4 | if 表达式: 5 | 代码块 6 | elif 表达式: 7 | 代码块 8 | else: 9 | 代码块 10 | ``` 11 | 12 | test_if.py 13 | 14 | ``` 15 | x = 'abcd' 16 | if x == 'abc': 17 | print('x 的值和abc 相等') 18 | else: 19 | print('x和 abc不相等') 20 | ``` 21 | 22 | chinese_zodiac_v2.py 23 | 24 | ``` 25 | # 记录生肖,根据年份来判断生肖 26 | 27 | chinese_zodiac = '猴鸡狗猪鼠牛虎兔龙蛇马羊' 28 | 29 | year = int(input('请用户输入出生年份')) 30 | 31 | if (chinese_zodiac[year % 12]) == '狗': 32 | print('狗年运势。。。') 33 | ``` 34 | 35 | ## 循环语句 36 | 37 | **for 循环** 38 | 39 | ``` 40 | for 迭代变量 in 可迭代对象: 41 | 代码块 42 | ``` 43 | 44 | chinese_zodiac_v2.py 45 | 46 | ``` 47 | chinese_zodiac = '猴鸡狗猪鼠牛虎兔龙蛇马羊' 48 | 49 | for cz in chinese_zodiac: 50 | print(cz) 51 | 52 | for i in range(1, 13): 53 | print(i) 54 | 55 | for year in range(2000, 2019): 56 | print('%s 年的生肖是 %s' % (year, chinese_zodiac[year % 12])) 57 | ``` 58 | 59 | **while 循环** 60 | 61 | ``` 62 | while 表达式: 63 | 代码块 64 | ``` 65 | 66 | 样例: 67 | 68 | ``` 69 | import time 70 | num = 5 71 | while True: 72 | num = num + 1 73 | 74 | if num == 10: 75 | continue 76 | 77 | print(num) 78 | time.sleep(1) 79 | ``` 80 | 81 | **for 循环语句中的 if 嵌套** 82 | 83 | ``` 84 | zodiac_name = (u'摩羯座', u'水瓶座', u'双鱼座', u'白羊座', u'金牛座', u'双子座', 85 | u'巨蟹座', u'狮子座', u'处女座', u'天秤座', u'天蝎座', u'射手座') 86 | zodiac_days = ((1, 20), (2, 19), (3, 21), (4, 21), (5, 21), (6, 22), 87 | (7, 23), (8, 23), (9, 23), (10, 23), (11, 23), (12, 23)) 88 | 89 | # 用户输入月份和日期 90 | int_month = int(input('请输入月份:')) 91 | int_day = int(input('请输入日期:')) 92 | 93 | for zd_num in range(len(zodiac_days)): 94 | if zodiac_days[zd_num] >= (int_month, int_day): 95 | print(zodiac_name[zd_num]) 96 | break 97 | elif int_month == 12 and int_day > 23: 98 | print(zodiac_name[0]) 99 | break 100 | ``` 101 | 102 | **while 循环语句中的 if 嵌套** 103 | 104 | ``` 105 | zodiac_name = (u'摩羯座', u'水瓶座', u'双鱼座', u'白羊座', u'金牛座', u'双子座', 106 | u'巨蟹座', u'狮子座', u'处女座', u'天秤座', u'天蝎座', u'射手座') 107 | zodiac_days = ((1, 20), (2, 19), (3, 21), (4, 21), (5, 21), (6, 22), 108 | (7, 23), (8, 23), (9, 23), (10, 23), (11, 23), (12, 23)) 109 | 110 | # 用户输入月份和日期 111 | int_month = int(input('请输入月份:')) 112 | int_day = int(input('请输入日期:')) 113 | 114 | n = 0 115 | while zodiac_days[n] < (int_month, int_day): 116 | if int_month == 12 and int_day > 23: 117 | break 118 | n += 1 119 | 120 | print(zodiac_name[n]) 121 | ``` 122 | 123 | ## 映射的类型:字典 124 | 125 | 字典包含哈希值和指向的对象,例如: 126 | 127 | {"哈希值": "对象"}、{'length':180, ’width':80} 128 | 129 | ``` 130 | dict1 = {} 131 | print(type(dict1)) # 132 | dict2 = {'x': 1, 'y': 2} 133 | dict2['z'] = 3 134 | 135 | print(dict2) # {'x': 1, 'y': 2, 'z': 3} 136 | ``` 137 | 138 | 统计生肖出现的次数: 139 | 140 | ``` 141 | chinese_zodiac = '猴鸡狗猪鼠牛虎兔龙蛇马羊' 142 | zodiac_name = (u'摩羯座', u'水瓶座', u'双鱼座', u'白羊座', u'金牛座', u'双子座', 143 | u'巨蟹座', u'狮子座', u'处女座', u'天秤座', u'天蝎座', u'射手座') 144 | zodiac_days = ((1, 20), (2, 19), (3, 21), (4, 21), (5, 21), (6, 22), 145 | (7, 23), (8, 23), (9, 23), (10, 23), (11, 23), (12, 23)) 146 | 147 | cz_num = {} 148 | for i in chinese_zodiac: 149 | cz_num[i] = 0 150 | 151 | z_num = {} 152 | for i in zodiac_name: 153 | z_num[i] = 0 154 | 155 | while True: 156 | 157 | # 用户输入出生年份月份和日期 158 | year = int(input('请输入年份:')) 159 | month = int(input('请输入月份:')) 160 | day = int(input('请输入日期:')) 161 | 162 | n = 0 163 | while zodiac_days[n] < (month, day): 164 | if month == 12 and day > 23: 165 | break 166 | n += 1 167 | # 输出生肖和星座 168 | print(zodiac_name[n]) 169 | 170 | print('%s 年的生肖是 %s' % (year, chinese_zodiac[year % 12])) 171 | 172 | cz_num[chinese_zodiac[year % 12]] += 1 173 | z_num[zodiac_name[n]] += 1 174 | 175 | # 输出生肖和星座的统计信息 176 | for each_key in cz_num.keys(): 177 | print('生肖 %s 有 %d 个' % (each_key, cz_num[each_key])) 178 | 179 | for each_key in z_num.keys(): 180 | print('星座 %s 有 %d 个' % (each_key, z_num[each_key])) 181 | ``` 182 | 183 | ## 列表推导式 184 | 185 | ``` 186 | # 从1 到 10 所有偶数的平方 187 | 188 | # 普通写法 189 | alist = [] 190 | for i in range(1, 11): 191 | if i % 2 == 0: 192 | alist.append(i * i) 193 | 194 | # 列表推导式 195 | alist = [i * i for i in range(1, 11) if (i % 2) == 0] 196 | ``` 197 | 198 | ## 字典推导式 199 | 200 | ``` 201 | zodiac_name = (u'摩羯座', u'水瓶座', u'双鱼座', u'白羊座', u'金牛座', u'双子座', 202 | u'巨蟹座', u'狮子座', u'处女座', u'天秤座', u'天蝎座', u'射手座') 203 | 204 | # 普通写法 205 | z_num = {} 206 | for i in zodiac_name: 207 | z_num[i] = 0 208 | 209 | # 字典推导式 210 | z_num = {i: 0 for i in zodiac_name} 211 | ``` -------------------------------------------------------------------------------- /A类/Python/零基础学Python/04文件、输入输出、异常.md: -------------------------------------------------------------------------------- 1 | ## 文件内建函数和方法 2 | 3 | - open():打开文件 4 | - read():输入 5 | - readline():输入一行 6 | - seek():文件内移动 7 | - write():输出 8 | - close():关闭文件 9 | 10 | file_op.py 11 | 12 | ``` 13 | # 将小说的主要人物记录在文件中 14 | # 写 15 | file1 = open('name.txt', 'w') 16 | file1.write('诸葛亮') 17 | file1.close() 18 | 19 | # 读 20 | file2 = open('name.txt') 21 | print(file2.read()) 22 | file2.close() 23 | 24 | # 追加写 25 | file3 = open('name.txt', 'a') 26 | file3.write('刘备') 27 | file3.close() 28 | 29 | # 读一行 30 | file4 = open('name.txt') 31 | for line in file4.readlines(): 32 | print(line) 33 | print('=====') 34 | file4.close() 35 | ``` 36 | 37 | 偏移操作: 38 | 39 | ``` 40 | file6 = open('name.txt') 41 | print('当前文件指针的位置 %s' % file6.tell()) # 0 42 | print('当前读取到了一个字符,字符的内容是 %s' % file6.read(1)) 43 | print('当前文件指针的位置 %s' % file6.tell()) # 1 44 | # 第一个参数代表偏移位置 45 | # 第二个参数: 0表示从文件开头偏移; 1表示从当前位置偏移; 2从文件结尾偏移; 46 | file6.seek(5, 0) 47 | print('我们进行了seek操作') 48 | print('当前文件指针的位置 %s' % file6.tell()) 49 | print('当前读取到了一个字符,字符的内容是 %s' % file6.read(1)) 50 | print('当前文件指针的位置 %s' % file6.tell()) 51 | file6.close() 52 | ``` 53 | 54 | ## 异常 55 | 56 | 异常是在出现错误时采用正常控制流以外的动作。 57 | 58 | ``` 59 | try: 60 | <监控异常> 61 | except Exception[, reason]: 62 | <异常处理代码> 63 | finally: 64 | <无论异常是否发生都执行> 65 | ``` 66 | 67 | 捕获异常: 68 | 69 | ``` 70 | try: 71 | year = int(input('input year:')) 72 | except ValueError: 73 | print('年份要输入数字') 74 | ``` 75 | 76 | 抛出异常: 77 | 78 | ``` 79 | try: 80 | raise NameError('helloError') 81 | except NameError: 82 | print('my custom error') 83 | ``` 84 | 85 | finnally 块: 86 | 87 | ``` 88 | try: 89 | a = open('name.txt') 90 | except Exception as e: 91 | print(e) 92 | 93 | finally: 94 | a.close() 95 | ``` -------------------------------------------------------------------------------- /A类/Python/零基础学Python/06面向对象编程.md: -------------------------------------------------------------------------------- 1 | ## 类与实例 2 | 3 | 面向对象编程(OOP)引入了类的概念,提供了另一种区别于面向过程的编程方法。 4 | 5 | 面向对象的特征:封装、继承、多态。 6 | 7 | ``` 8 | class Person(object): # 定义类 9 | def name(self): # 定义方法 10 | pass 11 | 12 | john = Person( … ) # 实例化 13 | ``` 14 | 15 | 设计游戏人物。 16 | 17 | ``` 18 | class Player(): # 定义一个类 19 | def __init__(self, name, hp, occu): 20 | self.__name = name # 变量被称作属性 21 | self.hp = hp 22 | self.occu = occu # 职业 23 | 24 | def print_role(self): # 定义一个方法 25 | print('%s: %s %s' % (self.__name, self.hp, self.occu)) 26 | 27 | def updateName(self, newname): 28 | self.name = newname 29 | 30 | 31 | class Monster(): 32 | '定义怪物类' 33 | 34 | def __init__(self, hp=100): 35 | self.hp = hp 36 | 37 | def run(self): 38 | print('移动到某个位置') 39 | 40 | def whoami(self): 41 | print('我是怪物父类') 42 | 43 | 44 | class Animals(Monster): 45 | '普通怪物' 46 | 47 | def __init__(self, hp=10): 48 | super().__init__(hp) 49 | 50 | 51 | class Boss(Monster): 52 | 'Boss类怪物' 53 | 54 | def __init__(self, hp=1000): 55 | super().__init__(hp) 56 | 57 | def whoami(self): 58 | print('我是怪物我怕谁') 59 | 60 | 61 | a1 = Monster(200) 62 | print(a1.hp) 63 | print(a1.run()) 64 | a2 = Animals(1) 65 | print(a2.hp) 66 | print(a2.run()) 67 | 68 | a3 = Boss(800) 69 | a3.whoami() 70 | 71 | print('a1的类型 %s' % type(a1)) 72 | print('a2的类型 %s' % type(a2)) 73 | print('a3的类型 %s' % type(a3)) 74 | 75 | print(isinstance(a2, Monster)) 76 | 77 | # 判断对象的类型 78 | print('a1的类型 %s' % type(a1)) 79 | print('a2的类型 %s' % type(a2)) 80 | print('a3的类型 %s' % type(a3)) 81 | 82 | print(isinstance(a2, Monster)) 83 | ``` 84 | 85 | ## 自定义with语句 86 | 87 | 可用 with 语句简化异常的编写。 88 | 89 | ``` 90 | class Testwith(object): 91 | """ 92 | with 包含了 __enter__ 和 __exit__ 方法 93 | """ 94 | 95 | def __enter__(self): 96 | print('run now ') 97 | 98 | def __exit__(self, exc_type, exc_val, exc_tb): 99 | if exc_tb is None: 100 | print('exit normal ') 101 | else: 102 | print('exit with exception') 103 | 104 | 105 | with Testwith(): 106 | print('test') 107 | raise NameError('Exception') 108 | ``` -------------------------------------------------------------------------------- /A类/Python/零基础学Python/07多线程编程.md: -------------------------------------------------------------------------------- 1 | ## 多线程编程的定义 2 | 3 | ``` 4 | import threading 5 | import time 6 | from threading import current_thread 7 | 8 | 9 | def myThread(arg1, arg2): 10 | print(current_thread().getName(), 'start') 11 | print('%s %s' % (arg1, arg2)) 12 | time.sleep(1) 13 | print(current_thread().getName(), 'stop') 14 | 15 | 16 | for i in range(1, 6, 1): 17 | # t1 = myThread(i, i+1) 18 | t1 = threading.Thread(target=myThread, args=(i, i + 1)) 19 | t1.start() 20 | 21 | print(current_thread().getName(), 'end') 22 | ``` 23 | 24 | 使用面向对象编写多线程。 25 | 26 | ``` 27 | import threading 28 | from threading import current_thread 29 | 30 | 31 | class Mythread(threading.Thread): 32 | def run(self): 33 | print(current_thread().getName(), 'start') 34 | print('run') 35 | print(current_thread().getName(), 'stop') 36 | 37 | 38 | t1 = Mythread() 39 | t1.start() 40 | t1.join() 41 | 42 | print(current_thread().getName(), 'end') 43 | ``` 44 | 45 | ## 生产者和消费者问题 46 | 47 | ``` 48 | from threading import Thread, current_thread 49 | import time 50 | import random 51 | from queue import Queue 52 | 53 | queue = Queue(5) 54 | 55 | 56 | class ProducerThread(Thread): 57 | def run(self): 58 | name = current_thread().getName() 59 | nums = range(100) 60 | global queue 61 | while True: 62 | num = random.choice(nums) 63 | queue.put(num) 64 | print('生产者 %s 生产了数据 %s' % (name, num)) 65 | t = random.randint(1, 3) 66 | time.sleep(t) 67 | print('生产者 %s 睡眠了 %s 秒' % (name, t)) 68 | 69 | 70 | class ConsumerTheard(Thread): 71 | def run(self): 72 | name = current_thread().getName() 73 | global queue 74 | while True: 75 | num = queue.get() 76 | queue.task_done() 77 | print('消费者 %s 消耗了数据 %s' % (name, num)) 78 | t = random.randint(1, 5) 79 | time.sleep(t) 80 | print('消费者 %s 睡眠了 %s 秒' % (name, t)) 81 | 82 | 83 | p1 = ProducerThread(name='p1') 84 | p1.start() 85 | p2 = ProducerThread(name='p2') 86 | p2.start() 87 | p3 = ProducerThread(name='p3') 88 | p3.start() 89 | c1 = ConsumerTheard(name='c1') 90 | c1.start() 91 | c2 = ConsumerTheard(name='c2') 92 | c2.start() 93 | ``` 94 | 95 | > queue.task_done() 不是很理解它的作用。 -------------------------------------------------------------------------------- /A类/Python/零基础学Python/python_knowledge_map.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/A类/Python/零基础学Python/python_knowledge_map.jpg -------------------------------------------------------------------------------- /A类/README.md: -------------------------------------------------------------------------------- 1 | # 基础类 2 | 3 | 基础类:可以是一种语言,软件工程师必须掌握,需要细啃的知识 4 | -------------------------------------------------------------------------------- /B类/B02-RPC/RPC实战与核心原理-01基础篇.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/B类/B02-RPC/RPC实战与核心原理-01基础篇.png -------------------------------------------------------------------------------- /B类/B02-RPC/RPC实战与核心原理-01基础篇.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/B类/B02-RPC/RPC实战与核心原理-01基础篇.xmind -------------------------------------------------------------------------------- /B类/B02-RPC/RPC实战与核心原理-02进阶篇.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/B类/B02-RPC/RPC实战与核心原理-02进阶篇.png -------------------------------------------------------------------------------- /B类/B02-RPC/RPC实战与核心原理-02进阶篇.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/B类/B02-RPC/RPC实战与核心原理-02进阶篇.xmind -------------------------------------------------------------------------------- /B类/B02-RPC/[极客时间]-RPC实战与核心原理-03高级篇.md: -------------------------------------------------------------------------------- 1 | # 目录 2 | 3 | 4 | 5 | # 17 | 异步RPC:压榨单机吞吐量 6 | 7 | 如果想更深入地了解 RPC ,就必须从 RPC 框架的整体性能上去考虑问题了。如何去提升 RPC 框架的性能、稳定性、安全性、吞吐量,以及如何在分布下场景下快速定位问题等等。 8 | 9 | 今天我们就先来讲讲,RPC 框架是如何压榨单机吞吐量的。 10 | 11 | **如何提升单机吞吐量?** 12 | 13 | 记得之前业务团队反馈过这样一个问题:我们的 TPS 始终上不去,压测的时候 CPU 压到 40% - 50% 就再也压不下去了,TPS 也不会提高,问我们这里有没有什么解决方案可以提升业务的吞吐量? 14 | 15 | 那是什么影响到了 RPC 调用的吞吐量呢? 16 | 17 | 其实根本原因就是由于处理 RPC 请求比较耗时,并且 CPU 大部分的时间都在等待而没有去计算,从而导致 CPU 的利用率不够。所以说,在大多数情况下,影响到 RPC 调用的吞吐量的原因也就是业务逻辑处理慢了,CPU 大部分时间都在等待资源。 18 | 19 | 该如何去提升单机吞吐量? 20 | 21 | 要提升吞吐量,其实关键就两个字:异步。 22 | 23 | 那 RPC 框架都有哪些异步策略呢? 24 | 25 | **调用端如何异步?** 26 | 27 | 最常用的方式就是返回 Future 方式,或者入参为 Callback 对象的回调方式。 28 | 29 | 连接发送4次异步请求并且拿到4个 Future,如下图所示,我们的吞吐量可能提升4倍! 30 | 31 | 32 | 33 | 那 RPC 框架的 Future 方式异步又该如何实现呢? 34 | 35 | 对于 RPC 框架,无论是同步调用还是异步调用,调用端的内部实现都是异步的。调用端发送的每条消息都有一个唯一的消息标识,并且在发送请求消息前会先创建一个 Future,并会存储这个消息标识与这个 Future 的映射,动态代理所获得的返回值最终就是从这个 Future 中获取的; 36 | 37 | 当收到服务端响应的消息时,调用端会根据响应消息的唯一标识,找到对应的 Future,最后动态代理从 Future 中获取正确的返回值。 38 | 39 | 所谓的同步调用,不过是 RPC 框架在调用端的处理逻辑中主动执行了这个 Future 的 get 方法,让动态代理等待返回值;而异步调用则是 RPC 框架没有主动执行这个 Future 的 get 方法,用户可以从请求上下文中得到这个 Future,自己决定什么时候执行这个 Future 的 get 方法。 40 | 41 | 42 | 43 | **如何做到 RPC 调用全异步?** 44 | 45 | 上面的 Future 异步,是调用端的一种异步方式,那么服务端呢?有什么实现方式? 46 | 47 | 其实我们可以让 RPC 框架支持 CompletableFuture,实现 RPC 在调用端与服务端之间完全异步。 48 | 49 | CompletableFuture 是 Java8 原生支持的。整个调用过程会分为这样几步: 50 | 51 | 1. 服务调用方发起 RPC 调用,直接拿到返回值 CompletableFuture 对象,直接就可以进行异步处理; 52 | 2. 在服务端的业务逻辑中创建一个返回值 CompletableFuture 对象,之后服务端真正的业务逻辑完全可以在一个线程池中异步处理,业务逻辑完成后再调用这个 CompletableFuture 对象的 complete 方法,完成异步通知; 53 | 3. 调用端在收到服务端发送过来的响应之后,这样一次异步调用就完成了。 54 | 55 | 通过对 CompletableFuture 的支持,RPC 框架可以真正地做到在调用端与服务端之间完全异步,同时提升了调用端与服务端两端的单机吞吐量,并且 CompletableFuture 是 Java8 原生支持,业务逻辑中没有任何代码入侵性。 56 | 57 | **课后思考** 58 | 59 | 对于 RPC 调用提升吞吐量这个问题,你是否还有其它解决方案?你还能想到哪些 RPC 框架的异步策略? 60 | 61 | # 18 | 安全体系:如何建立可靠的安全体系? 62 | 63 | **为什么需要考虑安全问题?** 64 | 65 | 要搞清楚这个问题,我们可以先看一个完整的 RPC 应用流程。 66 | 67 | 我们一般是先由服务提供方定义好一个接口,并把这个接口的 Jar 包发布到私服上去,然后在项目中去实现这个接口,最后通过 RPC 提供的 API 把这个接口和其对应的实现类完成对外暴露,如果是 Spring 应用的话直接定义成一个 Bean 就好了。到这儿,服务提供方就完成了一个接口的对外发布了。 68 | 69 | 这里其实存在一个安全隐患问题,因为私服上所有的 Jar 坐标我们所有人都可以看到,只要拿到了 Jar 的坐标,就可以把发布到私服的 Jar 引入到项目中完成 RPC 调用了。 70 | 71 | **调用方之间的安全保证** 72 | 73 | 我们只需要给每个调用方设定一个唯一的身份,每个调用方在调用之前都先来服务提供方这登记下身份,只有登记过的调用方才能继续放行,没有登记过的调用方一律拒绝。 74 | 75 | 那在 RPC 里面我们该怎么实现呢? 76 | 77 | 我们把进行调用接口登记的地方姑且称为“授权平台”。在调用方启动初始化接口的时候,带上授权平台上颁发的身份去服务提供方认证下,当认证通过后就认为这个接口可以调用。 78 | 79 | (每次调用服务方都去请求授权平台,这样是授权平台对高可性要求就比较高了) 80 | 81 | 那服务提供方验证对照的数据来自哪儿?总不能又去请求授权平台吧? 82 | 83 | 加密算法里面有一种叫做不可逆加密算法 HMAC,服务提供方应用里面放一个用于 HMAC 签名的私钥,在授权平台上用这个私钥为申请调用的调用方应用进行签名,这个签名生成的串就变成了调用方唯一的身份。服务提供方在收到调用方的授权请求之后,只要验证下这个签名跟调用方应用信息是否对应得上就行了。这样集中式授权的瓶颈也就不存在了。 84 | 85 | **服务发现也有安全问题吗?** 86 | 87 | 服务提供方把接口 Jar 发布到私服上,如果有人拿到这个 Jar 发布出来一个服务提供方,这样就导致调用方通过服务发现拿到的服务提供方 IP 地址集合里面会有那个伪造的提供方。 88 | 89 | 我们可以这样来解决:当服务向注册中心注册的时候,注册中心可以在收到注册请求时,验证下请求过来的应用是否跟接口绑定的应用一样,只有相同才允许注册,否则就返回错误信息给注册的应用,从而避免假冒的服务提供者对外提供错误服务。 90 | 91 | **课后思考** 92 | 93 | 如果想要对接口里部分方法作授权认证,该怎么做呢? 94 | 95 | # 19 | 分布式环境下如何快速定位问题? 96 | 97 | **分布式环境下定位问题有哪些困难?** 98 | 99 | 分布式系统有着较为复杂的依赖关系,我们很难判断是哪个环节出现的问题,而且在大型的分布式系统中,往往会有跨部门、跨团队合作的情况,在排查问题的时候会面临非常高的沟通成本。 100 | 101 | **如何做到快速定位问题?** 102 | 103 | 方法1:借助合理封闭的异常信息 104 | 105 | 哪类异常引起的问题(序列化问题或网络超时问题),是调用端还是服务端出现的异常,调用端与服务端的 IP 是什么,以及服务接口与服务分组都是什么等等。 106 | 107 | 108 | 109 | 由此可见,一款优秀的 RPC 框架要对异常进行详细地封装,还要对各类异常进行分类,每类异常都要有明确的异常标识码,并整理成一份简明的文档。 110 | 111 | 方法2:借助分布式链路跟踪 112 | 113 | 分布式链路跟踪有 Trace 与 Span 的概念。Trace 就是代表整个链路,每次分布式都会产生一个 Trace,每个 Trace都有它的唯一标识 TraceId,在分布式链路跟踪系统中,就是通过 TraceId 来区分每个 Trace 的。 114 | 115 | Span 就是代表了整个链路中的一段链路,也就是说 Trace 是由多个 Span 组成的。在一个 Trace 下,每个 Span 也都有它的唯一标识 SpanId,而 Span 是存在父子关系的,Span2 的父 Span 就是 Span1。如下图所示: 116 | 117 | 118 | 119 | RPC 在整合分布式链路跟踪需要做的最核心的两件事就是埋点和传递。 120 | 121 | 所谓埋点,就是分布式链路跟踪系统要想获得一次分布式调用的完整的链路信息,就必须对这次分布式调用进行数据采集,而采集这些数据的方法就是通过 RPC 框架对分布式链路跟踪进行埋点。 122 | 123 | 所谓传递,就是批上游调用端将 Trace 信息与父 Span 信息传递给下游的服务端,由下游触发埋点,对这些信息进行处理,在分布式链路跟踪系统中,每个子 Span 都存有父 Span 的相关信息以及 Trace 的相关信息。 124 | 125 | **思考题** 126 | 127 | 分布式环境下,你还知道哪些快速定位问题的方法? 128 | 129 | 答:skywalking、Zipkin 等开源分布式链路跟踪。 130 | 131 | # 20 | 详解时钟轮在RPC中的应用 132 | 133 | -------------------------------------------------------------------------------- /B类/B05-Redis/Redis-02进阶.md: -------------------------------------------------------------------------------- 1 | # 第01讲:Redis是如何淘汰key的? 2 | 3 | 本课时我们主要学习 Redis 淘汰原理、淘汰方式、以及 8 种淘汰策略等内容。 4 | 5 | **淘汰原理** 6 | 7 | 当 key 过期后,或者 Redis 实际占用的内存超过阀值(通过 maxmemory 设置)后,Redis 就会对 key 进行淘汰,删除过期的或者不活跃的 key,回收其内存,供新的 key 使用。 8 | 9 | 超过内存阀值后的淘汰策略,是通过 maxmemory-policy 设置的。 10 | 11 | Redis 会在 2 种场景下对 key 进行淘汰,第一种是在定期执行 serverCron 时,检查淘汰 key;第二种是在执行命令时,检查淘汰 key。 12 | 13 | 第一种场景,Redis 定期执行 serverCron 时,首先轮询每个 DB,随机选取 20 个样本 key,如果 20 个样本中,超过 5 个 key 都过期,即过期比例大于 25%,就继续从该 DB 的 expire dict 过期字典中,再随机取样 20 个 key 进行过期清理,持续循环,直到选择的 20 个样本 key 中,过期的 key 数小于等于 5,当前这个 DB 则清理完毕,然后继续轮询下一个 DB。 14 | 15 | 第二种场景,Redis 在执行命令请求时。会检查当前内存占用是否超过 maxmemory 的数值,如果超过,则按照设置的淘汰策略,进行删除淘汰 key 操作。 16 | 17 | **淘汰方式** 18 | 19 | Redis 中 key 的淘汰方式有两种,分别是同步删除淘汰和异步删除淘汰。 20 | 21 | **淘汰策略** 22 | 23 | Redis 引入基于样本的 eviction(驱逐; 驱赶) pool,来提升剔除的准确性。当 Redis 内存占用超过阀值后,按策略从主 dict 或者带过期时间的 expire dict 中随机选择 N 个 key(N 默认是 5),计算每个 key 的 idle 值,按 idle 值从小到大的顺序插入 evictionPool 中,然后选择 idle 最大的那个 key,进行淘汰。 24 | 25 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120091023.png) 26 | 27 | Redis 提供了 8 种 maxmemory_policy 淘汰策略来应对内存超过阀值的情况。 28 | 29 | 第一种淘汰策略是 noeviction,它是 Redis 的默认策略。在内存超过阀值后,Redis 不做任何清理工作,然后对所有写操作返回错误,但对读请求正常处理。noeviction 适合数据量不大的业务场景,将关键数据存入 Redis 中,将 Redis 当作 DB 来使用。 30 | 31 | 第二种淘汰策略是 volatile-lru,它对带过期时间的 key 采用最近最少访问算法来淘汰。使用这种策略,Redis 会从 redisDb 的 expire dict 过期字典中,首先随机选择 N 个 key,计算 key 的空闲时间,然后插入 evictionPool 中,最后选择空闲时间最久的 key 进行淘汰。这种策略适合的业务场景是,需要淘汰的key带有过期时间,且有冷热区分,从而可以淘汰最久没有访问的key。 32 | 33 | 第三种策略是 volatile-lfu,它对带过期时间的 key 采用最近最不经常使用的算法来淘汰。使用这种策略时,Redis 会从 redisDb 中的 expire dict 过期字典中,首先随机选择 N 个 key,然后根据其 value 的 lru 值,计算 key 在一段时间内的使用频率相对值。对于 lfu,要选择使用频率最小的 key,为了沿用 evictionPool 的 idle 概念,Redis 在计算 lfu 的 Idle 时,采用 255 减去使用频率相对值,从而确保 Idle 最大的 key 是使用次数最小的 key,计算 N 个 key 的 Idle 值后,插入 evictionPool,最后选择 Idle 最大,即使用频率最小的 key,进行淘汰。这种策略也适合大多数 key 带过期时间且有冷热区分的业务场景。 34 | 35 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120091030.png) 36 | 37 | 第四种策略是 volatile-ttl,它是对带过期时间的 key 中选择最早要过期的 key 进行淘汰。使用这种策略时,Redis 也会从 redisDb 的 expire dict 过期字典中,首先随机选择 N 个 key,然后用最大无符号 long 值减去 key 的过期时间来作为 Idle 值,计算 N 个 key 的 Idle 值后,插入evictionPool,最后选择 Idle 最大,即最快就要过期的 key,进行淘汰。这种策略适合,需要淘汰的key带过期时间,且有按时间冷热区分的业务场景。 38 | 39 | 第五种策略是 volatile-random,它是对带过期时间的 key 中随机选择 key 进行淘汰。使用这种策略时,Redis 从 redisDb 的 expire dict 过期字典中,随机选择一个 key,然后进行淘汰。如果需要淘汰的key有过期时间,没有明显热点,主要被随机访问,那就适合选择这种淘汰策略。 40 | 41 | 第六种策略是 allkey-lru,它是对所有 key,而非仅仅带过期时间的 key,采用最近最久没有使用的算法来淘汰。这种策略与 volatile-lru 类似,都是从随机选择的 key 中,选择最长时间没有被访问的 key 进行淘汰。区别在于,volatile-lru 是从 redisDb 中的 expire dict 过期字典中选择 key,而 allkey-lru 是从所有的 key 中选择 key。这种策略适合,需要对所有 key 进行淘汰,且数据有冷热读写区分的业务场景。 42 | 43 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120091038.png) 44 | 45 | 第七种策略是 allkeys-lfu,它也是针对所有 key 采用最近最不经常使用的算法来淘汰。这种策略与 volatile-lfu 类似,都是在随机选择的 key 中,选择访问频率最小的 key 进行淘汰。区别在于,volatile-flu从expire dict 过期字典中选择 key,而 allkeys-lfu 是从主 dict 中选择 key。这种策略适合的场景是,需要从所有的 key 中进行淘汰,但数据有冷热区分,且越热的数据访问频率越高。 46 | 47 | 第八种策略是 allkeys-random,它是针对所有 key 进行随机算法进行淘汰。它也是从主 dict 中随机选择 key,然后进行删除回收。如果需要从所有的 key 中进行淘汰,并且 key 的访问没有明显热点,被随机访问,即可采用这种策略。 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /B类/B06-Spring/Spring核心编程思想.md: -------------------------------------------------------------------------------- 1 | > 来自极客时间《Spring核心编程思想》--小马哥 2 | > 3 | > 课程源码:https://gitee.com/geektime-geekbang/geekbang-lessons 4 | 5 | -------------------------------------------------------------------------------- /B类/B06-Spring/Spring核心编程思想.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/B类/B06-Spring/Spring核心编程思想.xmind -------------------------------------------------------------------------------- /B类/B06-Spring/Spring面试题-第一天.md: -------------------------------------------------------------------------------- 1 | # 01 | 如何利用反射实现 Autowired 注解? 2 | 3 | **Autowired 的使用方式** 4 | 5 | Autowired 可以标注于类定义的多个位置,包括以下几个。 6 | 7 | - 域(Field)或者说属性(Property) 8 | 9 | ```java 10 | public class FXNewsPProvider { 11 | @Autowired 12 | private IFXNewsListener newsListener; 13 | @Autowired 14 | private IFXNewsPersister newPersistener; 15 | } 16 | ``` 17 | 18 | - 构造方法定义(Constructor) 19 | 20 | - 方法定义(Method) 21 | 22 | **@Autowired 依赖注入原型代码** 23 | 24 | ```java 25 | Object[] beans = ...; 26 | for(Object bean : beans) { 27 | if(autowriedExistsOnField(bean)) { 28 | Field f = getQulifiedField(bean); 29 | setAccessiableIfNecessary(f); 30 | f.set(getBeanByTypeFromContainer()); 31 | } 32 | if(autowiredExistsOnConstructor(bean)) { 33 | ... 34 | } 35 | if(autowiredExistsOnMethos(bean)) { 36 | ... 37 | } 38 | } 39 | ``` 40 | 41 | # 02 | 手撕 Spring IOC 源码 42 | 43 | 44 | 45 | # 03 | Spring 程序是如何启动的? 46 | 47 | 48 | 49 | # 04 | Spring 是如何加载配置文件到应用程序的? 50 | 51 | 52 | 53 | # 05 | 核心接口 BeanDefinitionReader 54 | 55 | 56 | 57 | # 06 | 核心接口 BeanFactory 58 | 59 | 60 | 61 | # 07 | 彻底搞懂 Spring 的 refresh 方法 62 | 63 | 64 | 65 | # 08 | BeanPostProcessor 接口的作用及实现 66 | 67 | 68 | 69 | # 09 | BeanFactoryPostProcessor 接口的作用及实现 70 | 71 | 72 | 73 | 74 | 75 | # 10 | Spring Bean 有没有必要实现 Aware 接口? 76 | 77 | # 11 | Spring Bean 的实例化过程大揭秘 78 | 79 | # 12 | Spring Bean 初始化到底干了什么? 80 | 81 | # 13 | 彻底理解 FactoryBean 接口 82 | 83 | # 14 | Spring Bean 的生命周期 84 | 85 | # 15 | Spring 的 Environment 接口有什么作用? 86 | 87 | # 16 | 为什么会产生循环依赖问题? 88 | 89 | # 17 | 循环依赖在 Spring 中是如何解决的? 90 | 91 | -------------------------------------------------------------------------------- /B类/B06-Spring/《Spring揭秘》第三部分-Spring-AOP框架.md: -------------------------------------------------------------------------------- 1 | # 目录 2 | 3 | 4 | 5 | # 第7章 一起来看 AOP 6 | 7 | > 本章内容: 8 | > 9 | > - AOP 的尴尬 10 | > - AOP 走向现实 11 | > - Java 平台上的 AOP 实现机制 12 | > - AOP 国家的公民 13 | 14 | **7.1 AOP 的尴尬** 15 | 16 | AOP 现在没有主权,所以,现时代的AOP实现都需要“寄生”于 OOP 的主权领土中,系统的维度也依然保持曾经 OOP 持有的“维度世界纪录”。 17 | 18 | **7.2 AOP 走向现实** 19 | 20 | Java 界的 AOP 框架或者说产品,可谓 AOP 土地上的一朵奇葩,在 Xerox 公司的 PARC (Paro Alto Research Center) 提出 AOP 的一套理论之后,Java 业界各种 AOP 框架就如雨后春笋般涌现,其走过的路亦不可谓不精彩,所以,让我们来回顾一下这段精彩历史如何? 21 | 22 | - 7.2.1 静态 AOP 时代 23 | 24 | 静态 AOP,即第一代 AOP,以最初的 AspectJ 为杰出代表,其特点是,相应的横切关注点以 Aspect 形式实现之后,会通过特定的编译器,将实现后的 Aspect 编译并织入到系统的静态类中。 25 | 26 | - 7.2.2 动态 AOP 时代 27 | 28 | 动态 AOP,又称为第二代 AOP,该时代的 AOP 框架或产品,大都通过 Java 语言提供的各种动态特性来实现 Aspect 织入到当前系统的过程,如 JBoss AOP, Spring AOP 以及 Nanning 等 AOP 框架。 29 | 30 | **7.3 Java 平台上的 AOP 实现机制** 31 | 32 | - 7.3.1 动态代理 33 | 34 | 我们可以将横切关注点逻辑封装到动态代理的 InvocationHandler 中,然后在系统运行期间,根据横切关注点需要织入的模块位置,将横切逻辑织入到相应的代理类中。 35 | 36 | - 7.3.2 动态字节码增强 37 | 38 | 可以使用 ASM 或者 CGLIB 等 Java 工具库,在程序运行期间,动态构建字节码的 class 文件。Spring AOP 在无法采用动态代理机制进行 AOP 功能扩展的时候,会使用 CGLIB 库的动态字节码增强支持来实现 AOP 的功能扩展。 39 | 40 | - 7.3.3 Java 代码生成 41 | 42 | EJB 容器根据部署描述符文件提供的织入信息,会为相应的功能模块类根据描述符所提供的信息生成对应的 Java 代码,然后通过部署工具或者部署接口编译 Java 代码生成相应的 Java 类。之后,部署到 EJB 容器的功能模块类就可以正常工作了。 43 | 44 | 这种方式比较古老,也就早期的 EJB 容器使用最多,现在已经了退休了。 45 | 46 | - 7.3.4 自定义类加载器 47 | 48 | 自定义类加载器通过读取外部文件规定的织入规则和必要信息,在加载 class 文件期间就可以将横切逻辑添加到系统模块类的现有逻辑中,然后将改动后的 class 交给 Java 虚拟机运行。 49 | 50 | - 7.3.5 AOL 扩展 51 | 52 | 在这种方式中,AOP 各种概念在 AOL 中大都有一一对应的实体。我们可以使用扩展的 AOL,实现任何 AOP 概念实体甚至 OOP 概念实体,比如 Aspect 以及 Class。 53 | 54 | **7.4 AOP 国家的公民** 55 | 56 | - 7.4.1 Joinpoint 57 | 58 | 这些将要在其之上进行织入操作的系统执行点称之为 Joinpoint。 59 | 60 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/一般程序流程图.png) 61 | 62 | 基本上,只要允许,程序执行过程中的任何时点都可以作为横切逻辑的织入点,而所有这些执行时点都是 Joinpoint。 63 | 64 | - 7.4.2 Pointcut 65 | 66 | 我们使用自然语言声明一个 Pointcut,该 Pointcut 指定了系统中符合条件的一组 Joinpoint。不过,在实际系统中我们不可能使用自然语言形式的 Pointcut。 67 | 68 | - 7.4.3 Advice 69 | 70 | After Advice 就是在相应连接点之后执行的 Advice 类型,但该类型的 Advice 还可以细分为三种:After returning Advice; After throwing Advice; After Advice。 71 | 72 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/各种Advice的执行时机.png) 73 | 74 | Around Advice:在 Joinpoint 前后都执行。 75 | 76 | Introduction:可以为原有的对象添加新的特性或行为。 77 | 78 | - 7.4.4 Aspect 79 | 80 | Aspect 是对系统中的横切关注点逻辑进行模块化封装的 AOP 概念实体。 81 | 82 | - 7.4.5 织入和织入器 83 | 84 | 织入(Weaving)过程就是“飞架” AOP 和 OOP 的那座桥,只有经过织入过程之后,以 Aspect 模块化的横切关注点才会集成到 OOP 的现存系统中。 85 | 86 | - 7.4.6 目标对象 87 | 88 | 符合 Pointcut 所指定的条件,将在织入过程中被织入横切逻辑的对象,称为目标对象。 89 | 90 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/AOP 各个概念所处的场景.png) 91 | 92 | # 第8章 Spring AOP概述及其实现机制 93 | 94 | > 本章内容 95 | > 96 | > - Spring AOP 概述 97 | > - Spring AOP 的实现机制 98 | 99 | **8.1 Spring AOP 概述** 100 | 101 | Spring AOP 的设计哲学简单而强大,它不打算将所有的 AOP 需求全部囊括在内,而是以有限的 20% 的 AOP 支持,来满足 80% 的 AOP 需求。 102 | 103 | Spring AOP 的 AOL 语言为 Java,所在 Spring AOP 对 AOP 的概念进行了适当的抽象和实现,使得每个 AOP 的概念都可以落到实处。 104 | 105 | **8.2 Spring AOP 的实现机制** 106 | 107 | - 8.2.1 设计模式之代理模式 108 | 109 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/代理模式相关类关系示意图.jpg) 110 | 111 | SubjectProxy 内部持有 SubjectImpl 的引用,实现请求的转发。 112 | 113 | - 8.2.2 动态代理 114 | 115 | 动态代理机制的实现主要由 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口组成。 116 | 117 | - 8.2.3 动态字节码生成 118 | 119 | CGLIB官网:http://cglib.sourceforge.net/ 120 | 121 | # 第9章 Spring AOP 一世 122 | 123 | > 本章内容 124 | > 125 | > - Spring AOP 中的 Joinpoint 126 | > - Spring AOP 中的 Pointcut 127 | > - Spring AOP 中的 Advice 128 | > - Spring AOP 中的 Aspect 129 | > - Spring AOP 的织入 130 | 131 | **9.1 Spring AOP 中的 Joinpoint** 132 | 133 | Spring AOP 仅提供方法拦截,如果需求特殊,不妨使用现有的其他 AOP 实现产品如 AspectJ。AspectJ 是 Java 平台对 AOP 支持最完善的产品。 134 | 135 | **9.2 Spring AOP 中的 Pointcut** 136 | 137 | Spring 中以接口定义 org.springframework.aop.Pointcut 作为其 AOP 框架中所有 Pointcut 的最顶层抽象。 138 | 139 | - 9.2.1 常见的 Pointcut 140 | 141 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/常见的Pointcut.jpg) 142 | 143 | - 9.2.2 扩展 Pointcut (Customize Pointcut) 144 | 145 | Spring AOP 的 Pointcut 类型可以划分为 StaticMethodMatcherPointcut 和 DynamicMethodMatcherPointcut 两类。要实现自定义 Pointcut,通常在这两个抽象类的基础上实现相应子类即可。 146 | 147 | **9.3 Spring AOP 中的 Advice** 148 | 149 | Spring AOP 加入了开源组织 AOP Alliance(http://aopalliance.sourceforge.net/),图 9-4 中就是 Spring 中各种 Advice 类型实现与 AOP Alliance 中标准接口之间的关系。 150 | 151 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/Spring中Advice略图.jpg) 152 | 153 | - 9.3.1 per-class 类型的 Advice 154 | 155 | Before Advice、ThrowsAdvice、AfterReturningAdvice、Aroud Advice 156 | 157 | - 9.3.2 per-instance 类型的 Advice 158 | 159 | per-instance 类型的 Advice 不会在目标类所有对象实例之间共享,而是会为不同的实例对象保存它们各自的状态以及相关逻辑。(类似于每个员工各自的电脑) 160 | 161 | **9.4 Spring AOP 中的 Aspect** 162 | 163 | 当所有的 Pointcut 和 Advice 准备好之后,就到了该把它们分门别类地装进箱子的时候了,箱子就是 Aspect。 164 | 165 | Advisor 代表 Spring 中的 Aspect,但是,与正常的 Aspect 不同,Advisor 通常只持有一个 Pointcut 和一个 Advice。而理论上,Aspect 定义中可以有多个 Pointcut 和多个 Advice,所以,我们可以认为 Advisor 是一种特殊的 Aspect。 166 | 167 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/Advisor分支.jpg) 168 | 169 | - 9.4.1 PointcutAdvisor 家族 170 | 171 | 实际上,org.springframework.aop.PointcutAdvisor 才是真正的定义一个 Pointcut 和一个 Advice 的Advisor。 172 | 173 | 常用的实现有:DefaultPointcutAdvisor、NameMatchMethodPointcutAdvisor、RegexpMethodPointcutAdvisor、DefaultBeanFactoryPointcutAdvisor。 174 | 175 | - 9.4.2 IntroductionAdvisor 分支 176 | 177 | IntroductionAdvisor 与 Point 178 | 179 | **9.5 Spring AOP 的织入** 180 | 181 | 182 | 183 | 184 | 185 | # 第10章 Spring AOP 二世 186 | 187 | > 本章内容 188 | > 189 | > - @AspectJ 形式的 Spring AOP 190 | > - 基于 Schema 的 AOP 191 | 192 | **10.1 @AspectJ 形式的 Spring AOP** 193 | 194 | 195 | 196 | **10.2 基于 Schema 的 AOP** 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | # 第11章 AOP 应用案例 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | # 第12章 Spring AOP 之扩展 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | -------------------------------------------------------------------------------- /B类/B06-Spring/《Spring揭秘》第三部分-Spring-AOP框架.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/B类/B06-Spring/《Spring揭秘》第三部分-Spring-AOP框架.xmind -------------------------------------------------------------------------------- /B类/B06-Spring/《Spring揭秘》第二部分-Spring的IoC容器.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/B类/B06-Spring/《Spring揭秘》第二部分-Spring的IoC容器.png -------------------------------------------------------------------------------- /B类/B06-Spring/《Spring揭秘》第二部分-Spring的IoC容器.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/B类/B06-Spring/《Spring揭秘》第二部分-Spring的IoC容器.xmind -------------------------------------------------------------------------------- /B类/B06-Spring/《Spring揭秘》第五部分-事务管理.md: -------------------------------------------------------------------------------- 1 | # 目录 2 | 3 | 4 | 5 | # 第17章 有关事务的楔子 6 | 7 | > 本章内容 8 | > 9 | > - 认识事务本身 10 | > - 初识事务家族成员 11 | 12 | **17.1 认识事务本身** 13 | 14 | 事务就是以可控的方式对数据资源进行访问的一组操作。事务有 4 个限定属性,即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。 15 | 16 | **17.2 初识事务家族成员** 17 | 18 | - Resource Manager。负责存储并管理系统数据资源的状态,比如数据库服务器、JMS 消息服务器; 19 | - Transaction Processing Monitor。职责是在分布式事务场景中协调包含多个 RM 的事务处理; 20 | - Transaction Manager。TP Monitor 中的核心模块,直接负责多 RM 之间事务处理的协调工作,并提供事务界定(Transaction Demarcation)、事务上下文传播(Transaction Context Propagation)等功能接口; 21 | - Application。事务边界的触发点。 22 | 23 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/全局事务示意图.jpg) 24 | 25 | # 第18章 群雄逐鹿下的 Java 事务管理 26 | 27 | > 本章内容 28 | > 29 | > - Java 平台的局部事务支持 30 | > - Java 平台的分布式事务支持 31 | > - 继续前行之前的反思 32 | 33 | **18.1 Java 平台的局部事务支持** 34 | 35 | 数据库资源的局部事务管理。可以将数据库连接(java.sql.Connection)的自动提交(AutoCommit)功能设置为 false,改为手动提交来控制事务的提交或回滚。 36 | 37 | 消息服务资源的局部事务管理。可以通过 JMS 的 java.jms.Session 来控制整个处理过程的事务。 38 | 39 | **18.2 Java 平台的分布式事务支持** 40 | 41 | Java 平台上的分布式事务管理,主要是通过 JTA(Java Transaction API)或者 JCA(Java Connector Architecture)提供支持的。 42 | 43 | - 18.2.1 基于 JTA 的分布式事务管理 44 | 45 | JTA 编程事务管理。通过使用 javax.transaction.UserTransaction 接口进行,各应用服务器都提供了针对它的 JNDI 查找服务。 46 | 47 | JTA 声明性事务管理。如果使用 EJB 进行声明性的分布式事务管理的话,JTA 的使用则只限于 EJB 容器内部,对于应用程序来说则完全就是透明的。 48 | 49 | - 18.2.2 基于 JCA 的分布式事务管理 50 | 51 | JCA 规范主要面向 EIS(Enterprise Information System)的集成,通过为遗留的 EIS 系统和 Java EE 应用服务器指定统一的通信标准,二者就可以实现各种服务上的互通。 52 | 53 | **18.3 继续前行之前的反思** 54 | 55 | 1. 局部事务的管理绑定到了具体的数据访问方式; 56 | 2. 事务的异常处理; 57 | 3. 事务处理 API 的多样性; 58 | 4. CMT 声明式事务的局限; 59 | 60 | # 第19章 Spring 事务王国的架构 61 | 62 | > 本章内容 63 | > 64 | > - 统一中原的过程 65 | > - 和平年代 66 | 67 | Spring 的事务框架设计理念的基本原则是:让事务管理的关注点与数据访问关注点相分离。 68 | 69 | **19.1 统一中原的过程** 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | # 第20章 使用 Spring 进行事务管理 84 | 85 | 86 | 87 | 88 | 89 | # 第21章 Spring 事务管理之扩展篇 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /B类/B08-设计模式/[极客时间]-设计模式之美-01设计模式学习导读.md: -------------------------------------------------------------------------------- 1 | - 23 种设计模式与范式实战精讲 2 | - 200+ 真实案例分析设计与实现 3 | - 顶尖互联网公司的编程经验分享 4 | - 应对设计模式面试的思路与技巧 5 | 6 | 专栏内容 7 | 8 | ![专栏内容](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120091340.png) 9 | 10 | # 开篇词 | 一对一的设计与编码集训,让你告别没有成长的烂代码! 11 | 12 | **一个人看书效果并不好** 13 | 14 | 一方面,每个人的理解能力是不一样的,对于同一本书,不同理解能力的人看完之后收获也是不一样的。跟着有经验的老师学比闷头自己看书要高效、收获更多、成长更快。 15 | 16 | 另一方面,编码本身就是一门实践课,光闷头看书本理论肯定是不够的,更重要的是在实践中学习如何应用这些理论。 17 | 18 | # 01 | 为什么说每个程序员都要尽早地学习并掌握设计模式相关知识? 19 | 20 | 如果说数据结构和算法是教你如何写出高效代码,那设计模式讲的是如何写出可扩展、可读、可维护的高质量代码,所以,它们跟平时的编码会有直接的关系,也会直接影响到你的开发能力。 21 | 22 | 接下来,我们就具体地聊一聊,我们为什么要学习设计模式? 23 | 24 | 1. **应对面试中的设计模式相关问题** 25 | 26 | 一些像 BAT、TMD 这样的大公司,比较重视候选人的基本功,经常会拿算法、设计模式之类的问题来考察候选人。 27 | 28 | 2. **告别写被人吐槽的烂代码** 29 | 30 | 代码写得好,能让你在团队中脱颖而出。 31 | 32 | 3. **提高复杂代码的设计和开发能力** 33 | 34 | 如何分层、分模块?应该怎么划分类?每个类应该具有哪些属性、方法?怎么设计类之间的交互?该用继承还是组合?该使用接口还是抽象类?怎样做到解耦、高内聚低耦合?该用单例模式还是静态方法?用工厂模式创建对象还是直接 new 出来?如何避免引入设计模式提高扩展性的同时带来的降低可读性问题? 35 | 36 | 4. **让读源码、学框架事半功倍** 37 | 38 | 对于一个有追求的程序员来说,对技术的积累,既要有广度,也要有深度。很多技术人早早就意识到了这一点,所以在学习框架、中间件的时候,都会抽空去研究研究原理,读一读源码,希望能在深度上有所积累,而不只是略知皮毛,会用而已 39 | 40 | 5. **为你的职场发展做铺垫** 41 | 42 | 在技术这条职场道路上,当成长到一定阶段之后,你势必要承担一些指导培养初级员工、新人,以及 code review 的工作。这个时候,如果你自己都对“什么是好的代码?如何写出好的代码?”不了解,那又该如何指导别人,如何让人家信服呢? 43 | 44 | **重点回顾** 45 | 46 | 投资要趁早,这样我们才能尽早享受复利。同样,有些能力,要早点锻炼;有些东西,要早点知道;有些书,要早点读。这样在你后面的生活、工作、学习中,才能一直都发挥作用。 47 | 48 | # 02 | 从哪些维度评判代码质量的好坏?如何具备写出高质量代码的能力? 49 | 50 | 对于程序员来说,辨别代码写得“好”还是“烂”,是一个非常重要的能力。这也是我们写出好代码的前提。毕竟,如果我们连什么是好代码、什么是烂代码,都分辨不清,又谈何写出好代码呢? 51 | 52 | **如何评价代码质量的高低?** 53 | 54 | 我们真的可以客观地量化一段代码质量的高低吗?答案是否定的。对一段代码的质量评价,常常有很强的主观性。 55 | 56 | 因为代码质量评价的主观性,使得这种主观评价的准确度,跟工程师自身经验有极大的关系。越是有经验的工程师,给出的评价也就越准确。相反,资历比较浅的工程师就常常会觉得,没有一个可执行的客观的评价标准作为参考,很难准确地判断一段代码写得好与坏。 57 | 58 | 有的时候,自己觉得代码写得已经够好了,但实际上并不是。所以,这也导致如果没有人指导的话,自己一个人闷头写代码,即便写再多的代码,代码能力也可能一直没有太大提高。 59 | 60 | **最常用的评价标准有哪几个?** 61 | 62 | 1. 可维护性(maintainability)(常) 63 | 64 | 所谓的“维护”无外乎就是修改 bug、修改老的代码、添加新的代码之类的工作。 所谓“代码易维护”就是指,在不破坏原有代码设计、不引入新的 bug 的情况下,能够快速地修改或者添加代码。 65 | 66 | 所谓“代码不易维护”就是指,修改或者添加代码需要冒着极大的引入新 bug 的风险,并且需要花费很长的时间才能完成。 67 | 68 | 从正面去分析一个代码是否易维护稍微有点难度。不过,我们可以从侧面上给出一个比较主观但又比较准确的感受。如果 bug 容易修复,修改、添加功能能够轻松完成,那我们就可以主观地认为代码对我们来说易维护。相反,如果修改一个 bug,修改、添加一个功能,需要花费很长的时间,那我们就可以主观地认为代码对我们来说不易维护。 69 | 70 | 2. 可读性(readability)(常) 71 | 72 | 软件设计大师 Martin Fowler 曾经说过:“Any fool can write code that a computer can understand. Good programmers write code that humans can understand.” 73 | 74 | “任何傻瓜都会编写计算机能理解的代码。好的程序员能够编写人能够理解的代码。” 75 | 76 | code review 是一个很好的测验代码可读性的手段。如果你的同事可以轻松地读懂你写的代码,那说明你的代码可读性很好;如果同事在读你的代码时,有很多疑问,那就说明你的代码可读性有待提高了。 77 | 78 | 3. 可扩展性(extensibility)(常) 79 | 80 | 代码的可扩展性表示,我们在不修改或少量修改原有代码的情况下,通过扩展的方式添加新的功能代码。 而不需要因为要添加一个功能而大动干戈,改动大量的原始代码。 81 | 82 | 4. 灵活性(flexibility) 83 | 84 | 当我们添加一个新的功能代码的时候,原有的代码已经预留好了扩展点,我们不需要修改原有的代码,只要在扩展点上添加新的代码即可。这个时候,我们除了可以说代码易扩展,还可以说代码写得好灵活。 85 | 86 | 当我们要实现一个功能的时候,发现原有代码中,已经抽象出了很多底层可以复用的模块、类等代码,我们可以拿来直接使用。这个时候,我们除了可以说代码易复用之外,还可以说代码写得好灵活。 87 | 88 | 当我们使用某组接口的时候,如果这组接口可以应对各种使用场景,满足各种不同的需求,我们除了可以说接口易用之外,还可以说这个接口设计得好灵活或者代码写得好灵活。 89 | 90 | 5. 简洁性(simplicity) 91 | 92 | 有一条非常著名的设计原则,那就是 KISS 原则:“Keep It Simple,Stupid”。这个原则说的意思就是,尽量保持代码简单。代码简单、逻辑清晰,也就意味着易读、易维护。 93 | 94 | 思从深而行从简,真正的高手能云淡风轻地用最简单的方法解决最复杂的问题。这也是一个编程老手跟编程新手的本质区别之一。 95 | 96 | 6. 可复用性(reusability) 97 | 98 | 代码的可复用性可以简单地理解为,尽量减少重复代码的编写,复用已有的代码 。 99 | 100 | 7. 可测试性(testability) 101 | 102 | 相对于前面六个评价标准,代码的可测试性是一个相对较少被提及,但又非常重要的代码质量评价标准。 103 | 104 | 代码的可测试性差,比较难写单元测试,那基本上就能说明代码设计得有问题。 105 | 106 | **如何才能写出高质量的代码?** 107 | 108 | 要写出满足这些评价标准的高质量代码,我们需要掌握一些更加细化、更加能落地的编程方法论,包括面向对象设计思想、设计原则、设计模式、编码规范、重构技巧等。 109 | 110 | # 03丨面向对象、设计原则、设计模式、编程规范、重构,这五者有何关系? 111 | 112 | ![面向对象、设计原则、设计模式、编程规范、重构五者的关系](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120091350.png) 113 | -------------------------------------------------------------------------------- /B类/B09-MyBatis/《MyBatis技术内幕》读书笔记.md: -------------------------------------------------------------------------------- 1 | # 第1章 MyBatis快速入门 2 | 3 | 整体架构 4 | 5 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120091440.png) 6 | 7 | 一条SQL语句的大致过程 8 | 9 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120091445.png) 10 | 11 | # 第2章 基础支持层 12 | 13 | 基础支持层包括:数据源模块、事务管理模块、缓存模块、Binding模块、反射模块、类型转换、日志模块、资源加载、解析器模块。 14 | 15 | **2.1 解析器模块** 16 | 17 | 对XML配置文件进行解析。 18 | 19 | **2.2 反射工具箱** 20 | 21 | MyBatis在进行参数处理、结果映射等操作时,会涉及大量的反射操作。 22 | 23 | **2.3 类型转换** 24 | 25 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120091454.png) 26 | 27 | **2.4 日志模块** 28 | 29 | 统一日志接口。 30 | 31 | **2.5 资源加载** 32 | 33 | `ClassLoaderWrapper`包装了多个`ClassLoader`对象,通过调整多个类加载器的使用有顺序,`ClassLoaderWrapper`可以确保返回给系统使用的是正确的类加载器。 34 | 35 | **2.6 DataSource** 36 | 37 | MyBatis 不仅可以集成第三方数据源组件,还提供了自己的数据源实现,`PooledDataSource`和`UnpooledDataSource`。 38 | 39 | **2.7 Transaction** 40 | 41 | MyBatis 使用`Transaction`接口对数据库事务进行了抽象,有`JdbcTransaction`和`ManagedTransaction`两个实现。 42 | 43 | **2.8 binding 模块** 44 | 45 | `Mapper`接口中定义的方法在 MyBatis 初始化过程中会与映射配置文件中定义的 SQL 语句相关联。如果存在无法关联的 SQL 语句,在 MyBatis 的初始化阶段就会抛出异常。 46 | 47 | **2.9 缓存模块** 48 | 49 | MyBatis 中的缓存分为一级缓存、二级缓存,它们都是`Cache`接口的实现。 50 | 51 | # 第3章 核心处理层 52 | 53 | 核心处理层包括:配置解析、参数映射、SQL解析、SQL执行、结果集映射、插件。 54 | 55 | **3.1 MyBatis 初始化** 56 | 57 | 类似于 Spring、MyBatis 等灵活性和可扩展性都很高的开源框架都提供了很多配置项,开发人员需要在使用时提供相应的配置信息,实现相应的需求。 58 | 59 | **3.2 SqlNode & SqlSource** 60 | 61 | 62 | -------------------------------------------------------------------------------- /B类/B10-系统性能/[拉勾教育]-应用性能分析实战.md: -------------------------------------------------------------------------------- 1 | # 课程介绍 2 | 3 | APM(Application Performance Management),也称应用性能分析系统。 4 | 5 | 如何掌握好 APM 这一高效工具呢? 6 | 7 | - 找到最短、最高效的学习路径。直接从原理、实践角度学习最主流、好用的 APM 工具,而不要去“啃”官方使用文档和解析源码。 8 | - 不止步“会用”,更要让工具“好用”。你可以通过了解 APM 协议、数据,以及关键模块落地实战,解决 APM 落地业务时的“水土不服”问题。 9 | - 工具之外,业务之内。通过学会使用、改造 APM 工具,了解其背后的性能定位、分布式链路追踪技能。 10 | 11 | Part 1. APM 产品落地实战 12 | 13 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210513223940.png) 14 | 15 | Part 2. 不读源码学原理 16 | 17 | 以 SkyWalking 和 Sentinel 核心作者的视角,带你“不读源码学原理”,发掘设计思想的意义,高维度学习源码。 18 | 19 | Part 3. APM 协议与数据精讲 20 | 21 | Part 4. 关键功能落地 22 | 23 | Part 5. APM 软技能提升 24 | 25 | # 01 | APM 引领者:落地 Apache SkyWalking 26 | 27 | 落地时,如何快速止损;落地中,如何解决水土不服;落地后,如何解决信息泄露的过程,阐述我的企业级落地实践。 28 | 29 | **探针不稳定,如何及时止损并修复?** 30 | 31 | 业务方接入 SkyWalking 探针时,需要进行一段时间的灰度接入,确保灰度一段时间没有问题,才可以全量接入。而如果灰度节点出现了问题,一些 CASE 自动(如进程挂掉)和兜底手动将通过脚本使用 Dump 命令对现场进行保留,然后打通发布平台快速摘除探针并上线。 32 | 33 | [SkyWalking 探针内核与 Web 容器的类加载器发生的死锁案例](https://github.com/apache/skywalking/issues/3784?fileGuid=xxQTRXtVcqtHK6j8)。 34 | 35 | **针对不同中间件,如何设计差异化落地方案?** 36 | 37 | 我们可以根据流量和业务复杂度两个特点,将要监控的业务系统快速的分为两类: 38 | 39 | - 高 QPS 低业务编排能力的底层系统 40 | - 低 QPS 高业务赋能的业务系统 41 | 42 | 其中底层系统只会开启应用系统全链路跟踪所必要的组件,如 HttpServer、RPC 框架、Kafka 等。如果底层系统还是占用了过多的资源,就会针对性地开启采样。 43 | 44 | **数据暴露的同时,如何保障信息安全?** 45 | 46 | SkyWalking 接入公司的登录系统,每个 APM 数据都必须有相应的应用归属。当用户查询数据时,只有用户所在的应用归属与 APM 数据的应用归属一致才可以展示。 47 | 48 | # 02 | 系统监控:老牌监控点评 CAT,依然经久不衰 49 | 50 | 点评[CAT(Central Application Tracking)](https://github.com/dianping/cat?fileGuid=xxQTRXtVcqtHK6j8)是使用 Java 开发实现的实时应用监控平台,专为大规模 Java 微服务集群提供实时监控报警场景打造。 51 | 52 | CAT 产品架构是由三个模块组成: 53 | 54 | - Cat-client 提供给应用以及中间层埋点的底层 SDK 55 | - Cat-consumer 用于实时分析从客户端提供的数据(收集器模块) 56 | - Cat-home 作为给用户提供展示的控制端(控制端模块) 57 | 58 | ![image-20210513234420046](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210513234546.png) 59 | 60 | 基于以上原理,所以 CAT 有两大特色优势,那就是代码段监控报表非常实时,并且客户端性能消耗低。 61 | 62 | **1. 实时的代码段监控报表** 63 | 64 | **2. 客户端性能损耗低** 65 | 66 | ![image-20210513234759049](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210513234933.png) 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /B类/B10-系统性能/[极客时间]-性能测试-05分析实战篇.md: -------------------------------------------------------------------------------- 1 | > 来自极客时间《性能测试实战30讲》--高楼 2 | 3 | # 26丨案例:手把手带你理解TPS趋势分析 4 | 5 | 在性能分析中,我们使用性能测试工具只需要关注几条曲线就够了:TPS、响应时间和错误率。 6 | 7 | 但是关注 TPS 到底应该关注什么内容,如何判断趋势,判断了趋势之后,又该如何做出调整,调整之后如何定位原因,这才是我们关注 TPS 的一系列动作。今天,我们就通过一个实际的案例来解析什么叫 TPS 的趋势分析。 8 | 9 | **案例描述** 10 | 11 | 用一个 2C4G 的 Docker 容器做服务器。 结构如下所示: 12 | 13 | ![image-20211124224448708](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20211124224448.png) 14 | 15 | 16 | 17 | **第一阶段** 18 | 19 | ![image-20211124224922336](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20211124224922.png) 20 | 21 | 22 | 23 | ![image-20211124224954709](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20211124224954.png) 24 | 25 | 26 | 27 | ![image-20211124225015711](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20211124225015.png) 28 | 29 | 30 | 31 | ![image-20211124225027338](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20211124225027.png) 32 | 33 | 34 | 35 | ![image-20211124225050653](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20211124225050.png) 36 | 37 | 第一阶段测试过程中,压力压的过快了。 38 | 39 | **第二阶段** 40 | 41 | 42 | 43 | 一定要记住这一点,不管是什么压力工具,都要在压力测试中把日志关掉,不然 TPS 会受到很严重的影响。 44 | 45 | **第三阶段** 46 | 47 | 通过注释掉打印日志的代码,可以得到如下结果: 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /B类/B10-系统性能/[网络博客]-性能调优实战.md: -------------------------------------------------------------------------------- 1 | # 01 | 一张 900w 的数据表,16s 执行的 SQL 优化到 300ms 2 | 3 | > 来源:https://www.jianshu.com/p/0768ebc4e28d 4 | > 5 | > 参考资料: 6 | > https://explainextended.com/2009/10/23/mysql-order-by-limit-performance-late-row-lookups/ 7 | > https://dev.mysql.com/doc/refman/5.7/en/innodb-information-schema-buffer-pool-tables.html 8 | 9 | 有一张财务流水表,未分库分表,目前的数据量为9555695,分页查询使用到了limit,优化之前的查询耗时16 s 938 ms (execution: 16 s 831 ms, fetching: 107 ms),按照下文的方式调整SQL后,耗时347 ms (execution: 163 ms, fetching: 184 ms); 10 | 11 | 操作:查询条件放到子查询中,子查询只查主键ID,然后使用子查询中确定的主键关联查询其他的属性字段; 12 | 13 | 原理:减少回表操作; 14 | 15 | ```sql 16 | -- 优化前SQL 17 | SELECT 各种字段 18 | FROM `table_name` 19 | WHERE 各种条件 20 | LIMIT 0,10; 21 | ``` 22 | 23 | ```sql 24 | -- 优化后SQL 25 | SELECT 各种字段 26 | FROM `table_name` main_tale 27 | RIGHT JOIN 28 | ( 29 | SELECT 子查询只查主键 30 | FROM `table_name` 31 | WHERE 各种条件 32 | LIMIT 0,10; 33 | ) temp_table ON temp_table.主键 = main_table.主键 34 | ``` 35 | 36 | **前言** 37 | 38 | 首先说明一下MySQL的版本: 39 | 40 | ![image-20201011111908734](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/image-20201011111908734.png) 41 | 42 | 表结构: 43 | 44 | ![image-20201011111936222](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/image-20201011111936222.png) 45 | 46 | id为自增主键,val为非唯一索引。 47 | 48 | 灌入大量数据,共500万: 49 | 50 | ![image-20201011112042287](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/image-20201011112042287.png) 51 | 52 | 我们知道,当limit offset rows中的offset很大时,会出现效率问题: 53 | 54 | ![image-20201011112110990](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/image-20201011112110990.png) 55 | 56 | 为了达到相同的目的,我们一般会改写成如下语句: 57 | 58 | ![image-20201011112213528](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/image-20201011112213528.png) 59 | 60 | 时间相差很明显。为什么会出现上面的结果?我们看一下`select * from test where val=4 limit 300000,5;`的查询过程: 61 | 62 | 1. 查询到索引叶子节点数据; 63 | 2. 根据叶子节点的主键值去聚簇索引上查询需要的全部字段值; 64 | 65 | 类似于下面这张图: 66 | 67 | ![image-20201011112713679](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/image-20201011112713679.png) 68 | 69 | 像上面这样,需要查询300005次索引节点,查询300005次聚簇索引的数据,最后再将结果过滤掉前300000条,取出最后5条。MySQL耗费了大量随机I/O在查询聚簇索引的数据上,而有300000次随机I/O查询到的数据是不会出现在结果集当中的。 70 | 71 | 肯定会有人问:既然一开始是利用索引的,为什么不先沿着索引叶子节点查询到最后需要的5个节点,然后再去聚簇索引中查询实际数据。这样只需要5次随机I/O,类似于下面图片的过程: 72 | 73 | ![image-20201011112904164](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/image-20201011112904164.png) 74 | 75 | **证实** 76 | 77 | 下面我们实际操作一下来证实上述的推论: 78 | 79 | 为了证实`select * from test where val=4 limit 300000,5`是扫描300005个索引节点和300005个聚簇索引上的数据节点,我们需要知道MySQL有没有办法统计在一个sql中通过索引节点查询数据节点的次数。我先试了`Handler_read_*`系列,很遗憾没有一个变量能满足条件。 80 | 81 | 我只能通过间接的方式来证实: 82 | 83 | InnoDB中有buffer pool。里面存有最近访问过的数据页,包括数据页和索引页。所以我们需要运行两个sql,来比较buffer pool中的数据页的数量。预测结果是运行`select * from test a inner join (select id from test where val=4 limit 300000,5);` 之后,buffer pool中的数据页的数量远远少于`select * from test where val=4 limit 300000,5;`对应的数量,因为前一个sql只访问5次数据页,而后一个sql访问300005次数据页。 84 | 85 | ```bash 86 | mysql> select index_name,count(*) from information_schema.INNODB_BUFFER_PAGE where INDEX_NAME in('val','primary') and TABLE_NAME like '%test%' group by index_name; 87 | 88 | Empty set (0.04 sec) 89 | ``` 90 | 91 | 可以看出,目前buffer pool中没有关于test表的数据页。 92 | 93 | ```bash 94 | mysql> select * from test where val=4 limit 300000,5; 95 | +---------+-----+--------+ 96 | | id | val | source | 97 | +---------+-----+--------+ 98 | | 3327622 | 4 | 4 | 99 | | 3327632 | 4 | 4 | 100 | | 3327642 | 4 | 4 | 101 | | 3327652 | 4 | 4 | 102 | | 3327662 | 4 | 4 | 103 | +---------+-----+--------+ 104 | 5 rows in set (26.19 sec) 105 | 106 | mysql> select index_name,count(*) from information_schema.INNODB_BUFFER_PAGE where INDEX_NAME in('val','primary') and TABLE_NAME like '%test%' group by index_name; 107 | +------------+----------+ 108 | | index_name | count(*) | 109 | +------------+----------+ 110 | | PRIMARY | 4098 | 111 | | val | 208 | 112 | +------------+----------+ 113 | 2 rows in set (0.04 sec) 114 | ``` 115 | 116 | 可以看出,此时buffer pool中关于test表有4098个数据页,208个索引页。 117 | 118 | 为了防止上次试验的影响,我们需要清空buffer pool,重启mysql。 119 | 120 | ```bash 121 | mysqladmin shutdown 122 | /usr/local/bin/mysqld_safe & 123 | ``` 124 | 125 | ```bash 126 | mysql> select index_name,count(*) from information_schema.INNODB_BUFFER_PAGE where INDEX_NAME in('val','primary') and TABLE_NAME like '%test%' group by index_name; 127 | 128 | Empty set (0.03 sec) 129 | ``` 130 | 131 | 运行sql: 132 | 133 | ```bash 134 | mysql> select * from test a inner join (select id from test where val=4 limit 300000,5) b on a.id=b.id; 135 | +---------+-----+--------+---------+ 136 | | id | val | source | id | 137 | +---------+-----+--------+---------+ 138 | | 3327622 | 4 | 4 | 3327622 | 139 | | 3327632 | 4 | 4 | 3327632 | 140 | | 3327642 | 4 | 4 | 3327642 | 141 | | 3327652 | 4 | 4 | 3327652 | 142 | | 3327662 | 4 | 4 | 3327662 | 143 | +---------+-----+--------+---------+ 144 | 5 rows in set (0.09 sec) 145 | 146 | mysql> select index_name,count(*) from information_schema.INNODB_BUFFER_PAGE where INDEX_NAME in('val','primary') and TABLE_NAME like '%test%' group by index_name; 147 | +------------+----------+ 148 | | index_name | count(*) | 149 | +------------+----------+ 150 | | PRIMARY | 5 | 151 | | val | 390 | 152 | +------------+----------+ 153 | 2 rows in set (0.03 sec) 154 | ``` 155 | 156 | 我们可以看明显的看出两者的差别:第一个sql加载了4098个数据页到buffer pool,而第二个sql只加载了5个数据页到buffer pool。符合我们的预测。也证实了为什么第一个sql会慢:读取大量的无用数据行(300000),最后却抛弃掉。 157 | 158 | 而且这会造成一个问题:加载了很多热点不是很高的数据页到buffer pool,会造成buffer pool的污染,占用buffer pool的空间。 159 | 160 | 为了在每次重启时确保清空buffer pool,我们需要关闭`innodb_buffer_pool_dump_at_shutdown`和`innodb_buffer_pool_load_at_startup`,这两个选项能够控制数据库关闭时dump出buffer pool中的数据和在数据库开启时载入在磁盘上备份buffer pool的数据。 161 | -------------------------------------------------------------------------------- /B类/B10-系统性能/性能调优实战-01Java编程调优.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/B类/B10-系统性能/性能调优实战-01Java编程调优.png -------------------------------------------------------------------------------- /B类/B10-系统性能/性能调优实战-01Java编程调优.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/B类/B10-系统性能/性能调优实战-01Java编程调优.xmind -------------------------------------------------------------------------------- /B类/B10-系统性能/性能调优实战-02多线程调优.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/B类/B10-系统性能/性能调优实战-02多线程调优.png -------------------------------------------------------------------------------- /B类/B10-系统性能/性能调优实战-02多线程调优.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/B类/B10-系统性能/性能调优实战-02多线程调优.xmind -------------------------------------------------------------------------------- /B类/B10-系统性能/性能调优实战-03JVM监测及调优.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/B类/B10-系统性能/性能调优实战-03JVM监测及调优.png -------------------------------------------------------------------------------- /B类/B10-系统性能/性能调优实战-03JVM监测及调优.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/B类/B10-系统性能/性能调优实战-03JVM监测及调优.xmind -------------------------------------------------------------------------------- /B类/B11-ZooKeeper/ZooKeeper学习笔记.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/B类/B11-ZooKeeper/ZooKeeper学习笔记.png -------------------------------------------------------------------------------- /B类/B11-ZooKeeper/ZooKeeper学习笔记.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/B类/B11-ZooKeeper/ZooKeeper学习笔记.xmind -------------------------------------------------------------------------------- /B类/B11-ZooKeeper/ZooKeeper技术内幕:Leader选举.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/B类/B11-ZooKeeper/ZooKeeper技术内幕:Leader选举.png -------------------------------------------------------------------------------- /B类/B11-ZooKeeper/ZooKeeper技术内幕:Leader选举.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/B类/B11-ZooKeeper/ZooKeeper技术内幕:Leader选举.xmind -------------------------------------------------------------------------------- /B类/B13-Elasticsearch/ElasticSearch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/B类/B13-Elasticsearch/ElasticSearch.jpg -------------------------------------------------------------------------------- /B类/B13-Elasticsearch/[geek]-ElasticSearch核心技术与实践.md: -------------------------------------------------------------------------------- 1 | # 第二部分:深入了解 Elasticsearch 2 | 3 | ## 第4章:深入搜索 4 | 5 | ## 第5章:分布式特性及分布式搜索的机制 6 | 7 | ## 第6章:深入聚合分析 8 | 9 | ## 第7章:数据建模 10 | 11 | # 第三部分:管理 Elasticsearch 集群 12 | 13 | ## 第8章:保护你的数据 14 | 15 | ## 第9章:水平扩展 Elasticsearch 集群 16 | 17 | ## 第10章:生产环境中的集群运维 18 | 19 | ## 第11章:索引生命周期管理 20 | 21 | # 第四部分:利用 ELK 做大数据分析 22 | 23 | ## 第12章:用 Logstash 和 Beats 构建数据管道 24 | 25 | ## 第13章:用 Kibana 进行数据可视化分析 26 | 27 | ## 第14章:探索 X-Pack 套件 28 | 29 | # 第五部分:应用实战工作坊 30 | 31 | ## 实战1:电影探索服务 32 | 33 | ## 实战2:Stackoverfow 用户调查问卷分析 34 | 35 | ## 备战:Elastic 认证 36 | 37 | -------------------------------------------------------------------------------- /B类/B13-Elasticsearch/第2部分:深入了解Elasticsearch.md: -------------------------------------------------------------------------------- 1 | # 第4章:深入搜索 2 | 3 | **基于 Term 的查询** 4 | 5 | Term 是表达语意的最小单位。在 ES 中, Term 查询不会对输入做分词,而是将输入作为一个整体,在倒排索引中查找准确的词项, 并且使用相关度算分公式为每个包含该词项的文档进行相关度算分。 6 | 7 | 首先,创建4条记录。 8 | 9 | ```json 10 | POST /products/_bulk 11 | { "index": { "_id": 1 }} 12 | { "productID" : "XHDK-A-1293-#fJ3","desc":"iPhone" } 13 | { "index": { "_id": 2 }} 14 | { "productID" : "KDKE-B-9947-#kL5","desc":"iPad" } 15 | { "index": { "_id": 3 }} 16 | { "productID" : "JODL-X-1937-#pV7","desc":"MBP" } 17 | ``` 18 | 19 | 再通过 productID 查询: 20 | 21 | ```json 22 | POST /products/_search 23 | { 24 | "query": { 25 | "term": { 26 | "productID": { 27 | "value": "XHDK-A-1293-#fJ3" 28 | } 29 | } 30 | } 31 | } 32 | ``` 33 | 34 | 查出的结果为空,可以通过对 "XHDK-A-1293-#fJ3" 进行分词分析。改为下述搜索,就可以查出结果了。 35 | 36 | ```json 37 | POST /products/_search 38 | { 39 | //"explain": true, 40 | "query": { 41 | "term": { 42 | "productID.keyword": { 43 | "value": "XHDK-A-1293-#fJ3" 44 | } 45 | } 46 | } 47 | } 48 | ``` 49 | 50 | **全文本查询** 51 | 52 | 全文查询时会进行分词,查询字符串首先会传递到一个合适的分词器,然后生成一个供查询的词项列表,并对每个词项进行查询,最后将结果进行合并。 53 | 54 | 例如查 “Matrix reloaded”,会查到包括 Matrix 或者 reload的所有结果。 55 | 56 | ![image-20220117225232717](https://technotes.oss-cn-shenzhen.aliyuncs.com/2022/learn/20220117225238.png) 57 | 58 | 整个 Match Query 的查询过程如下: 59 | 60 | ![image-20220117225353805](https://technotes.oss-cn-shenzhen.aliyuncs.com/2023/202311212237233.png) 61 | 62 | **结构化搜索** 63 | 64 | 结构化搜索(Structured search) 是指对结构化数据的搜索。 65 | 66 | 样例数据如下: 67 | 68 | ```json 69 | DELETE products 70 | POST /products/_bulk 71 | { "index": { "_id": 1 }} 72 | { "price" : 10,"avaliable":true,"date":"2018-01-01", "productID" : "XHDK-A-1293-#fJ3" } 73 | { "index": { "_id": 2 }} 74 | { "price" : 20,"avaliable":true,"date":"2019-01-01", "productID" : "KDKE-B-9947-#kL5" } 75 | { "index": { "_id": 3 }} 76 | { "price" : 30,"avaliable":true, "productID" : "JODL-X-1937-#pV7" } 77 | { "index": { "_id": 4 }} 78 | { "price" : 30,"avaliable":false, "productID" : "QQPX-R-3956-#aD8" } 79 | ``` 80 | 81 | - 布尔值 82 | 83 | ```json 84 | #对布尔值 match 查询,有算分 85 | POST products/_search 86 | { 87 | "profile": "true", 88 | "explain": true, 89 | "query": { 90 | "term": { 91 | "avaliable": true 92 | } 93 | } 94 | } 95 | ``` 96 | 97 | - 数字类型 98 | 99 | ```json 100 | #数字类型 Term 101 | POST products/_search 102 | { 103 | "profile": "true", 104 | "explain": true, 105 | "query": { 106 | "term": { 107 | "price": 30 108 | } 109 | } 110 | } 111 | ``` 112 | 113 | - 日期类型 114 | 115 | ```json 116 | # 日期 range 117 | POST products/_search 118 | { 119 | "query" : { 120 | "constant_score" : { 121 | "filter" : { 122 | "range" : { 123 | "date" : { 124 | "gte" : "now-1y" 125 | } 126 | } 127 | } 128 | } 129 | } 130 | } 131 | ``` 132 | 133 | **搜索的相关性算分** 134 | 135 | 搜索的相关性(Relevance)算分,描述了一个⽂档和查询语句匹配的程度。 ES 会对每个匹配查询条件的结果进行算分(_score)。 136 | 137 | 打分的本质是排序,需要把最符合用户需求的文档排在前面。 ES 5 之前,默认的相关性算分采用 TF-IDF,现在采用 BM 25。先来了解 TF-IDF。 138 | 139 | - 词频 TF(Term Frequency) 140 | 141 | 检索词在⼀篇文档中出现的频率,即检索词出现的次数除以⽂档的总字数。 142 | 143 | - 逆⽂档频率 IDF(Inverse Document Frequency) 144 | 145 | DF:检索词在所有文档中出现的频率。IDF= log(全部⽂档数/检索词出现过的文档总数) 146 | 147 | TF-IDF 被公认为是信息检索领域最重要的发明,Lucene 中的 TF-IDF 评分公式如下: 148 | 149 | ![image-20220118222933895](https://technotes.oss-cn-shenzhen.aliyuncs.com/2022/learn/20220118222934.png) 150 | 151 | 再来看 BM 25。和经典的TF-IDF相比,当 TF 无限增加时,BM 25算分会趋于⼀个数值。 152 | 153 | ![image-20220118223145299](https://technotes.oss-cn-shenzhen.aliyuncs.com/2022/learn/20220118223145.png) 154 | 155 | 我们可以通过 explain 查看 TF-IDF的值。 156 | 157 | ![image-20220118224352821](https://technotes.oss-cn-shenzhen.aliyuncs.com/2022/learn/20220118224352.png) 158 | 159 | 也可以对算分的规则进行自定义。 160 | 161 | ![image-20220118224435909](https://technotes.oss-cn-shenzhen.aliyuncs.com/2022/learn/20220118224435.png) 162 | 163 | **多字符串多字段查询** 164 | 165 | 假设要搜索一本电影,包含了以下一些条件: 166 | 167 | 评论中包含了 Guitar,⽤户打分高于 3 分,同时上映⽇期要在 1993 与 2000 年之间。 168 | 169 | 这时就需要用到多字段查询了,即 bool 查询。 170 | 171 | ![image-20220118230218718](https://technotes.oss-cn-shenzhen.aliyuncs.com/2022/learn/20220118230218.png) 172 | 173 | 在 Elasticsearch 中,有Query 和 Filter 两种不同的 Contex。Query Context 表示进行相关性算分;Filter Context 表示不需要算分( Yes or No),可以利⽤ Cache, 获得更好的性能。 174 | 175 | bool 查询,总共包括 4 种子句。其中 2 种会影响算分, 2 种不影响算分。 176 | 177 | 以下面数据为例。 178 | 179 | ```json 180 | POST /products/_bulk 181 | { "index": { "_id": 1 }} 182 | { "price" : 10,"avaliable":true,"date":"2018-01-01", "productID" : "XHDK-A-1293-#fJ3" } 183 | { "index": { "_id": 2 }} 184 | { "price" : 20,"avaliable":true,"date":"2019-01-01", "productID" : "KDKE-B-9947-#kL5" } 185 | { "index": { "_id": 3 }} 186 | { "price" : 30,"avaliable":true, "productID" : "JODL-X-1937-#pV7" } 187 | { "index": { "_id": 4 }} 188 | { "price" : 30,"avaliable":false, "productID" : "QQPX-R-3956-#aD8" } 189 | ``` 190 | 191 | ![image-20220118230332261](https://technotes.oss-cn-shenzhen.aliyuncs.com/2022/learn/20220118230332.png) 192 | 193 | ![image-20220118230345412](https://technotes.oss-cn-shenzhen.aliyuncs.com/2022/learn/20220118230345.png) 194 | 195 | **单字符串多字段查询** 196 | 197 | 在 Google 搜索引擎中就是这样一种场景,对于这种场景,通常需要用到 Disjunction Max Query。 198 | 199 | 样例数据如下: 200 | 201 | ```json 202 | PUT /blogs/_doc/1 203 | { 204 | "title": "Quick brown rabbits", 205 | "body": "Brown rabbits are commonly seen." 206 | } 207 | 208 | PUT /blogs/_doc/2 209 | { 210 | "title": "Keeping pets healthy", 211 | "body": "My quick brown fox eats rabbits on a regular basis." 212 | } 213 | ``` 214 | 215 | ![image-20220120221441851](https://technotes.oss-cn-shenzhen.aliyuncs.com/2022/learn/20220120221441.png) 216 | 217 | 218 | 219 | -------------------------------------------------------------------------------- /B类/B14-SpringBoot/SpringBoot底层.md: -------------------------------------------------------------------------------- 1 | # 01 | Spring Boot 核心运行原理 2 | 3 | Spring Boot自动配置功能核心运行原理图。 4 | 5 | ![image-20220303214852180](https://technotes.oss-cn-shenzhen.aliyuncs.com/2022/learn/20220303214852.png) 6 | 7 | **AutoConfigurationImportSelector源码解析** 8 | 9 | AutoConfigurationImportSelector 并没有直接实现ImportSelector接口,而是实现了它的子接口DeferredImportSelector。DeferredImportSelector接口与ImportSelector的区别是,前者会在所有的@Configuration类加载完成之后再加载返回的配置类,而ImportSelector是在加载完@Configuration类之前先去加载返回的配置类。 10 | 11 | AutoConfigurationImportSelector核心功能及流程图。 12 | 13 | ![image-20220303222452216](https://technotes.oss-cn-shenzhen.aliyuncs.com/2022/learn/20220303222452.png) 14 | 15 | 16 | 17 | 18 | 19 | **NacosPropertySourcePostProcessor实现BeanDefinitionRegistryPostProcessor的目的?** 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /B类/B14-SpringBoot/《SpringBoot揭秘》--王福强2016.md: -------------------------------------------------------------------------------- 1 | > 代码基于 SpringBoot 2.6.4 分析。 2 | > 3 | > 这本书不行,讲一个知识点太啰嗦,感觉是在凑文字。还不如网上的一些博客讲的通俗明了。 4 | 5 | # 第3章 SpringBoot的工作机制 6 | 7 | ## 3.2 @SpringBootApplication 背后的秘密 8 | 9 | **怎么创建 ApplicationContext 的?** 10 | 11 | SpringApplication 12 | 13 | ```java 14 | public ConfigurableApplicationContext run(String... args) { 15 | // ... 16 | context = createApplicationContext(); 17 | // ... 18 | } 19 | protected ConfigurableApplicationContext createApplicationContext() { 20 | return this.applicationContextFactory.create(this.webApplicationType); 21 | } 22 | ``` 23 | 24 | ApplicationContextFactory 25 | 26 | ```java 27 | ApplicationContextFactory DEFAULT = (webApplicationType) -> { 28 | try { 29 | switch (webApplicationType) { 30 | case SERVLET: 31 | return new AnnotationConfigServletWebServerApplicationContext(); 32 | case REACTIVE: 33 | return new AnnotationConfigReactiveWebServerApplicationContext(); 34 | default: 35 | return new AnnotationConfigApplicationContext(); 36 | } 37 | } 38 | }; 39 | ``` 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | ```java 48 | @SpringBootConfiguration 49 | @EnableAutoConfiguration 50 | @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), 51 | @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) 52 | public @interface SpringBootApplication { 53 | } 54 | ``` 55 | 56 | **@Configuration** 57 | 58 | 表示本身是 IoC 容器的配置类。@SpringBootConfiguration 这个注解只是更好区分这是 SpringBoot 的配置注解,本质还是用了 Spring 提供的 @Configuration 注解。 59 | 60 | **@EnableAutoConfiguration** 61 | 62 | ```java 63 | @AutoConfigurationPackage 64 | @Import(AutoConfigurationImportSelector.class) 65 | public @interface EnableAutoConfiguration { 66 | } 67 | ``` 68 | 69 | `@AutoConfigurationPackage`的作用是:应用去加载启动类所在包下面的所有类。 70 | 71 | `AutoConfigurationImportSelector`的作用是:AutoConfiguration 的 ImportSelector,加载所有`spring.factories`文件中的`org.springframework.boot.autoconfigure.EnableAutoConfiguration`的值。 72 | 73 | **@ComponentScan** 74 | 75 | > 跟踪一下 76 | 77 | ## 3.3 SpringApplication: SpringBoot程序启动的一站式解决方案 78 | 79 | 首先遍历执行所有通过 SpringFactoriesLoader 可以查找到并加载的 SpringApplicationRunListener,调用它他的 started() 方法。(代码A) 80 | 81 | ```java 82 | public ConfigurableApplicationContext run(String... args) { 83 | long startTime = System.nanoTime(); 84 | DefaultBootstrapContext bootstrapContext = createBootstrapContext(); 85 | ConfigurableApplicationContext context = null; 86 | configureHeadlessProperty(); 87 | SpringApplicationRunListeners listeners = getRunListeners(args); // A 88 | listeners.starting(bootstrapContext, this.mainApplicationClass); 89 | try { 90 | ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); 91 | ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments); 92 | configureIgnoreBeanInfo(environment); 93 | Banner printedBanner = printBanner(environment); 94 | context = createApplicationContext(); 95 | context.setApplicationStartup(this.applicationStartup); 96 | prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner); 97 | refreshContext(context); 98 | afterRefresh(context, applicationArguments); 99 | Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime); 100 | if (this.logStartupInfo) { 101 | new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup); 102 | } 103 | listeners.started(context, timeTakenToStartup); // A1 104 | callRunners(context, applicationArguments); 105 | } catch (Throwable ex) { 106 | handleRunFailure(context, ex, listeners); 107 | throw new IllegalStateException(ex); 108 | } 109 | try { 110 | Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime); 111 | listeners.ready(context, timeTakenToReady); 112 | } catch (Throwable ex) { 113 | handleRunFailure(context, ex, null); 114 | throw new IllegalStateException(ex); 115 | } 116 | return context; 117 | } 118 | ``` 119 | 120 | 121 | 122 | ## 3.4 再读自动配置 123 | 124 | 125 | 126 | # 第4章 了解纷杂的 spring-boot-starter 127 | 128 | ## 4.1 应用日志和 spring-boot-starter-logging 129 | 130 | ## 4.2 快速 Web 应用开发与 spring-boot-starter-web 131 | 132 | ## 4.3 数据访问与 spring-boot-starter-jdbc 133 | 134 | # 第5章 SpringBoot 微服务实践探索 135 | 136 | ## 5.1 使用 SpringBoot 构建微服务 137 | 138 | ## 5.2 SpringBoot 微服务的发布与部署 139 | 140 | ## 5.3 SpringBoot 微服务的注册与发现 141 | 142 | ## 5.4 SpringBoot 微服务的监控与运维 143 | 144 | ## 5.5 SpringBoot 微服务的安全与防护 145 | 146 | ## 5.6 SpringBoot 微服务体系的脊梁:发布与部署平台 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /B类/B14-SpringBoot/《深入浅出SpringBoot2.x》--杨开振2018.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/B类/B14-SpringBoot/《深入浅出SpringBoot2.x》--杨开振2018.md -------------------------------------------------------------------------------- /B类/B15-Go语言/[拉勾]-Go微服务实战.md: -------------------------------------------------------------------------------- 1 | # 开篇词 | 掌握 Go 和微服务,跟进未来服务端开发的主流趋势 2 | 3 | **为什么要学习 Go 微服务** 4 | 5 | 6 | 7 | **课程设置** 8 | 9 | 第一部分(01~05) 10 | 11 | - 云原生 12 | - 微服务 13 | - DDD 14 | - Service Mesh 15 | 16 | 第二部分(06~11) 17 | 18 | - Go 开发的基础知识(Go 语法和流程控制、Go 并发和 Go Web 应用开发等) 19 | - 采用 DDD 对货运平台的业务进行划分 20 | - 案例应用实战(微服务部署、容器编排、持续集成和自动化测试等) 21 | 22 | 第三部分(12~35) 23 | 24 | - 微服务架构中基础组件的原理 25 | - Go 业务案例的实战(服务注册与发现、RPC 调用、网关、容错处理、负载均衡、统一认证与授权,以及分布式链路追踪等) 26 | - 如何通过 Service Mesh 来整合这些组件提供的能力 27 | 28 | 第四部分(36~38) 29 | 30 | - Go 微服务开发中的相关经验和要点(日志采集、Go 错误处理、并发陷阱和系统监控等) 31 | 32 | # 第一部分(01~05) 33 | 34 | # 01 | 为什么说云原生重构了互联网产品开发模式? 35 | 36 | **云计算的前世今生** 37 | 38 | - 阶段1:虚拟化技术 39 | 40 | 41 | 42 | - 阶段2:虚拟机的市场化应用 43 | 44 | 45 | 46 | - 阶段3:容器化和容器编排的兴起 47 | 48 | 49 | 50 | **云原生出现的背景** 51 | 52 | 53 | 54 | **云原生解决了哪些问题** 55 | 56 | 57 | 58 | **不断更新的云原生定义** 59 | 60 | 61 | 62 | # 02 | 云原生基础架构的组成以及云原生应用的特征 63 | 64 | **云原生的基础架构** 65 | 66 | 1. 微服务 67 | 2. 容器 68 | 3. 服务网格 69 | 4. 不可变基础设施与 DevOps 70 | 5. 声明式 API 71 | 72 | **云原生应用的特征:云原生与“12 因素”** 73 | 74 | 1. 方法论和核心思想 75 | 2. 编码、部署和运维原则 76 | 3. 具体内容 77 | 78 | 79 | 80 | # 03 | 微服务架构是如何演进的? 81 | 82 | **服务端架构的演进** 83 | 84 | 1. 单体架构 85 | 2. 垂直分层架构 86 | 3. SOA 面向服务架构 87 | 4. 微服务架构 88 | 89 | **微服务框架的选型** 90 | 91 | 1. Go 语言的独特优势 92 | 2. Go Kit框架 93 | 3. Go Micro 框架 94 | 4. Go Kit 与 Go Micro 的对比 95 | 96 | **云原生与微服务架构是什么关系** 97 | 98 | # 04 | DDD 领域场景分析的战略模式 99 | 100 | **微服务就是“小”服务吗?** 101 | 102 | 103 | 104 | **DDD 应对软件复杂度之法** 105 | 106 | 107 | 108 | **DDD 是不是银弹?** 109 | 110 | 111 | 112 | **DDD 战略模式** 113 | 114 | 1. 领域和子域 115 | 2. 限界上下文和通用语言 116 | 117 | # 05 | 为什么说 Service Mesh 是下一代微服务架构? 118 | 119 | **Service Mesh 背后的诉求** 120 | 121 | 1. 微服务架构的复杂性 122 | 2. 微服务本身的挑战 123 | 3. 本质诉求 124 | 125 | **什么是 Service Mesh** 126 | 127 | 128 | 129 | **Service Mesh 的开源组件** 130 | 131 | 1. Istio 132 | 2. Linkerd 133 | 3. Envoy 134 | 135 | # 第二部分(06~11) 136 | 137 | # 06 | Go 语言开发快速回顾:语法、数据结构和流程控制 138 | 139 | **基础语法** 140 | 141 | ```go 142 | // fileName: simple.go 143 | package main 144 | import ( 145 | "fmt" 146 | "sync" 147 | ) 148 | func input(ch chan string) { 149 | defer wg.Done() 150 | defer close(ch) 151 | var input string 152 | fmt.Println("Enter 'EOF' to shut down: ") 153 | for { 154 | _, err := fmt.Scanf("%s", &input) 155 | if err != nil{ 156 | fmt.Println("Read input err: ", err.Error()) 157 | break 158 | } 159 | if input == "EOF"{ 160 | fmt.Println("Bye!") 161 | break 162 | } 163 | ch <- input 164 | } 165 | } 166 | func output(ch chan string) { 167 | defer wg.Done() 168 | for value := range ch{ 169 | fmt.Println("Your input: ", value) 170 | } 171 | } 172 | var wg sync.WaitGroup 173 | func main() { 174 | ch := make(chan string) 175 | wg.Add(2) 176 | go input(ch) // 读取输入 177 | go output(ch) // 输出到命令行 178 | wg.Wait() 179 | fmt.Println("Exit!") 180 | } 181 | ``` 182 | 183 | 1. 函数声明 184 | 2. 变量的声明与初始化 185 | 3. 指针 186 | 4. struct 187 | 188 | **数据结构** 189 | 190 | 1. array(数组) 191 | 2. slice(切片) 192 | 3. map(字典) 193 | 194 | **流程控制** 195 | 196 | 1. for 循环 197 | 2. 分支控制 198 | 3. defer 延迟执行 199 | 200 | # 07 | 如何使用 Go 更好地开发并发程序? 201 | 202 | **Go 的 MPG 线程模型** 203 | 204 | 205 | 206 | **goroutine 和 channel** 207 | 208 | 1. select 多路复用 209 | 210 | 2. Context 上下文 211 | 212 | 213 | 214 | # 08 | 如何基于 Go-kit 开发 Web 应用:从接口层到业务层再到数据层 215 | 216 | **使用 Go Modules 管理项目依赖** 217 | 218 | 219 | 220 | **一个基于 Go-kit 简单的 User 应用** 221 | 222 | https://github.com/longjoy/micro-go-course 223 | 224 | 225 | 226 | **使用 gorm 连接 My SQL 数据库** 227 | 228 | 229 | 230 | # 09 | 案例:货运平台应用的微服务划分 231 | 232 | 233 | 234 | # 10 | 案例:微服务 Docker 容器化部署和 Kubernetes 容器编排 235 | 236 | 237 | 238 | # 11 | 案例:如何结合 Jenkins 完成持续化集成和自动化测试? 239 | 240 | 241 | 242 | 243 | 244 | # 第三部分(12~35) 245 | 246 | # 12 | 服务注册与发现如何满足服务治理? 247 | 248 | ![image-20210512221432993](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210512221603.png) 249 | 250 | # 13 | 案例:如何基于 Consul 给微服务添加服务注册与发现? 251 | 252 | # 14 | 案例:如何在 Go-kit 和 Service Mesh 中进行服务注册与发现? 253 | 254 | # 15 | 微服务间如何进行远程方法调用? 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | -------------------------------------------------------------------------------- /B类/B15-Go语言/[极客时间]-Go语言从入门到实战.md: -------------------------------------------------------------------------------- 1 | # 课程介绍 2 | 3 | 基础篇 4 | 5 | - Go 语言简介 6 | - 基本程序结构 7 | - 常用集合 8 | - 字符串 9 | - 函数 10 | - 面向对象编程 11 | - 编写好的错误处理 12 | - 包和依赖管理 13 | 14 | 进阶篇 15 | 16 | - 并发编程 17 | - 典型并发任务 18 | - 测试 19 | - 反射和 Unsafe 20 | - 常见架构模式的实现 21 | - 常见任务 22 | - 性能调优 23 | - 高可用性服务设计 24 | 25 | # 基础篇 26 | 27 | # 01 | 第一个 Go 程序 28 | 29 | hello_world.go 30 | 31 | ```go 32 | package main 33 | 34 | import ( 35 | "fmt" 36 | "os" 37 | ) 38 | 39 | func main() { 40 | if len(os.Args) > 1 { 41 | fmt.Println("Hello World", os.Args[1]) 42 | } 43 | } 44 | ``` 45 | 46 | # 02 | 基本程序结构 47 | 48 | **常量** 49 | 50 | constant_try_test.go 51 | 52 | ```go 53 | package constant_test 54 | 55 | import "testing" 56 | 57 | const ( 58 | Monday = 1 + iota 59 | Tuesday 60 | Wednesday 61 | ) 62 | 63 | const ( 64 | Readable = 1 << iota 65 | Writable 66 | Executable 67 | ) 68 | 69 | func TestConstantTry(t *testing.T) { 70 | t.Log(Monday, Tuesday) 71 | } 72 | 73 | func TestConstantTry1(t *testing.T) { 74 | a := 1 //0001 75 | t.Log(a&Readable == Readable, a&Writable == Writable, a&Executable == Executable) 76 | } 77 | ``` 78 | 79 | **数据类型** 80 | 81 | ```go 82 | package type_test 83 | 84 | import "testing" 85 | 86 | type MyInt int64 87 | 88 | func TestImplicit(t *testing.T) { 89 | var a int32 = 1 90 | var b int64 91 | b = int64(a) 92 | var c MyInt 93 | c = MyInt(b) 94 | t.Log(a, b, c) 95 | } 96 | 97 | func TestPoint(t *testing.T) { 98 | a := 1 99 | aPtr := &a 100 | //aPtr = aPtr + 1 101 | t.Log(a, aPtr) 102 | t.Logf("%T %T", a, aPtr) 103 | } 104 | 105 | func TestString(t *testing.T) { 106 | var s string 107 | t.Log("*" + s + "*") //初始化零值是“” 108 | t.Log(len(s)) 109 | } 110 | ``` 111 | 112 | 113 | 114 | # 03 | 常用集合 115 | 116 | 117 | 118 | # 04 | 字符串 119 | 120 | # 05 | 函数 121 | 122 | # 06 | 面向对象编程 123 | 124 | # 07 | 编写好的错误处理 125 | 126 | # 08 | 包和依赖管理 127 | 128 | # 进阶篇 129 | 130 | # 09 | 并发编程 131 | 132 | # 10 | 典型并发任务 133 | 134 | # 11 | 测试 135 | 136 | # 12 | 反射和 Unsafe 137 | 138 | # 13 | 常见架构模式的实现 139 | 140 | # 14 | 常见任务 141 | 142 | # 15 | 性能调优 143 | 144 | # 16 | 高可用性服务设计 -------------------------------------------------------------------------------- /B类/B16-Lua/[runoob]-Lua教程.md: -------------------------------------------------------------------------------- 1 | # 01 | Lua 简介 2 | 3 | **设计目的** 4 | 5 | 为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。 6 | 7 | **应用场景** 8 | 9 | - 游戏开发 10 | - 独立应用脚本 11 | - Web 应用脚本 12 | - 扩展和数据库插件(如 MySQL Proxy 和 MySQL WorkBench) 13 | - 安全系统,如入侵检测系统 14 | 15 | # 02 | Lua 基础 16 | 17 | **交互式编程** 18 | 19 | 在命令行中输入以下命令进行交互模式: 20 | 21 | ```bash 22 | lua -i 或 lua 23 | ``` 24 | 25 | **脚本式编程** 26 | 27 | 保存为以 lua 结尾的文件,例如 hello.lua,执行: 28 | 29 | ```bash 30 | lua hello.lua 31 | ``` 32 | 33 | 也可以在开头添加: 34 | 35 | ```lua 36 | #!/usr/local/bin/lua 37 | 38 | print("Hello World!") 39 | ``` 40 | 41 | 42 | **数据类型** 43 | 44 | Lua 中有 8 个基本类型分别为:nil、boolean、number、string、userdata、function、thread 和 table。 45 | 46 | - nil(空) 47 | 48 | 赋值为 nil 等同于删除; 49 | nil 作比较时应该加上双引号; 50 | 51 | - boolean(布尔) 52 | 53 | false 和 nil 看作是 false; 54 | 其他包括数据 0 都是true; 55 | 56 | - number(数字) 57 | 58 | lua 只有这一种数字类型; 59 | 60 | - string(字符串) 61 | 62 | 可以用 2 个方括号 “[[]]” 来表示一个字符串; 63 | Lua 会尝试将数字字符串转成数字; 64 | 字符串连接使用的是 .. ; 65 | 使用 # 来计算字符串长度; 66 | 67 | - table(表) 68 | 69 | 表的默认初始索引是从 1 开始的; 70 | table 不会固定长度大小; 71 | 72 | - function(函数) 73 | 74 | 函数可以存在变量里; 75 | 76 | - thread(线程) 77 | 78 | 线程可以同时多个运行,而协程任意时刻只能运行一个,并且处于运行状态的协程只有被挂起(suspend)时才会暂停。 79 | 80 | - userdata(自定义类型) 81 | 82 | 用于表示一种由应用程序或 C/C++ 语言库所创建的类型。 83 | 84 | **变量** 85 | 86 | Lua 变量有三种类型:全局变量、局部变量、表中的域。 87 | 88 | 全局变量 89 | 90 | ```bash 91 | > print(b) 92 | nil 93 | > b=10 94 | 10 95 | > 96 | ``` 97 | 98 | 删除全局变量 99 | 100 | ```bash 101 | b=nil 102 | print(b) 103 | ``` 104 | 105 | **赋值语句** 106 | 107 | 可以对多个变量同时赋值; 108 | 先计算右边所有的值然后再执行赋值操作; 109 | 变量个数 > 值的个数,按变量个数补足 nil; 110 | 变量个数 < 值的个数,多余的值会被忽略; 111 | 112 | **索引** 113 | 114 | 使用方括号 [],例如:t[i]; 115 | 当索引为字符串类型时,可简化为:t.i; 116 | 117 | # 03 | 进阶语法 118 | 119 | **循环** 120 | 121 | 循环处理方式:while、for、repeat...until、循环嵌套; 122 | 循环控制语句:break、goto; 123 | 124 | **流程控制** 125 | 126 | if、if...else、if嵌套 127 | 128 | **函数** 129 | 130 | 默认为全局函数,可通过 local 设置为局部函数; 131 | 可设多返回值; 132 | 可变参数; 133 | 134 | **运算符** 135 | 136 | 算术运算符; 137 | 关系运算符; 138 | 逻辑运算符; 139 | 其他运算符:..、#; 140 | 运算符优先级; 141 | 142 | **字符串** 143 | 144 | 三种表示方法:单引号、双引号、[[]]; 145 | 字符串操作:截取、大小写转换、查找、反转、格式化、整数转换、匹配模式; 146 | 147 | **数组** 148 | 149 | 一维数组; 150 | 多维数组; 151 | 152 | **迭代器** 153 | 154 | 泛型for迭代器:保存迭代函数、状态常量、控制变量; 155 | 无状态的迭代器; 156 | 多状态的迭代器; 157 | 158 | (未完全理解,需要再查资料详细学习) 159 | 160 | # 04 | 高级语法 161 | 162 | 163 | 164 | # 05 | 实操演练 165 | 166 | 167 | 168 | -------------------------------------------------------------------------------- /B类/B18-Kubernetes/Kubernetes原理与实战-04安全篇.md: -------------------------------------------------------------------------------- 1 | > 来自拉勾教育《Kubernetes 原理剖析与实战应用》--正范 2 | 3 | 模块四,安全无忧:集群的安全性与稳定性。 4 | 5 | # 18 | 权限分析:Kubernetes 集群权限管理那些事儿 6 | 7 | 任何请求访问 Kubernetes 的 kube-apiserver 时,都要依次经历三个阶段:认证(Authentication,有时简写成 AuthN)、授权(Authorization,有时简写成 AuthZ)和准入控制(Admission Control)。 8 | 9 | ![image-20220328224657895](https://technotes.oss-cn-shenzhen.aliyuncs.com/2022/202203282246983.png) 10 | 11 | 上述三个阶段,任何一个阶段验证失败都会导致该请求被拒绝访问,我们现在深入认识一下每个阶段。 12 | 13 | **认证** 14 | 15 | 认证就是做身份校验,解决“你是谁?”的问题。这里我们简单介绍一下 Kubernetes 中几种常见的用户认证方式。 16 | 17 | - x509 证书 18 | 19 | Kubernetes 集群各个组件间相互通信,都是基于 x509 证书进行身份校验的。比如使用openssl命令行工具生成一个证书签名请求(CSR): 20 | 21 | ```shell 22 | openssl req -new -key zhangsan.pem -out zhangsan-csr.pem -subj "/CN=zhangsan/O=app1/O=app2" 23 | ``` 24 | 25 | 这条命令会使用用户名zhangsan生成一个 CSR,且它属于 "app1" 和 "app2" 两个用户组,然后我们使用 CA 证书根据这个 CSR 就可以签发出一对证书。当用这对证书去访问 APIServer 时,它拿到的用户就是zhangsan了。 26 | 27 | - Token 28 | 29 | 我们接着来看基于 Token 的验证方式,它又可以分为几种类型。 30 | 31 | 第一种是用户自己提供的静态 Token; 32 | 33 | 还有一种是ServiceAccount Token。当你创建一个 ServiceAccount 的时候,kube-controller-manager 会自动帮你创建出一个Secret来保存 Token,比如: 34 | 35 | ```shell 36 | $ kubectl create sa demo 37 | serviceaccount/demo created 38 | ➜ ~ kubectl get sa demo 39 | NAME SECRETS AGE 40 | demo 1 6s 41 | ➜ ~ kubectl describe sa demo 42 | Name: demo 43 | Namespace: default 44 | Labels: 45 | Annotations: 46 | Image pull secrets: 47 | Mountable secrets: demo-token-fvsjg 48 | Tokens: demo-token-fvsjg 49 | Events: 50 | ``` 51 | 52 | 可以看到这里自动创建了一个名为demo-token-fvsjg的 Secret,我们来查看一下其中的内容: 53 | 54 | ```shell 55 | $ kubectl get secret demo-token-fvsjg 56 | NAME TYPE DATA AGE 57 | demo-token-fvsjg kubernetes.io/service-account-token 3 27s 58 | $ kubectl describe secret demo-token-fvsjg 59 | Name: demo-token-fvsjg 60 | Namespace: default 61 | Labels: 62 | Annotations: kubernetes.io/service-account.name: demo 63 | kubernetes.io/service-account.uid: f8fe4799-9add-4a36-8c29-a6b2744ba9a2 64 | Type: kubernetes.io/service-account-token 65 | Data 66 | ==== 67 | token: eyJhbGciOi... 68 | ca.crt: 1025 bytes 69 | namespace: 7 bytes 70 | ``` 71 | 72 | **授权** 73 | 74 | 授权负责做权限管控,解决“你能干什么?”的问题。 75 | 76 | Kubernetes 内部有多种授权模块,比如 Node、ABAC、RBAC、Webhook。授权阶段会根据从 AuthN 拿到的用户信息,依次按配置的授权次序逐一进行权限验证。任一授权模块验证通过,即允许该请求继续访问。 77 | 78 | 我们这里简要讲一下 ABAC 和 RBAC 这两种授权模式。 79 | 80 | - ABAC 81 | 82 | ABAC (Attribute Based Access Control) 是一种基于属性的访问控制,可以给 APIServer 指定一个 JSON 文件--authorization-policy-file=SOME_FILENAME,该文件描述了一组属性组合策略,比如: 83 | 84 | ```json 85 | { 86 | "apiVersion": "abac.authorization.kubernetes.io/v1beta1", 87 | "kind": "Policy", 88 | "spec": { 89 | "user": "zhangsan", 90 | "namespace": "*", 91 | "resource": "pods", 92 | "readonly": true 93 | } 94 | } 95 | ``` 96 | 97 | 这条策略表示,用户 zhangsan 可以以只读的方式读取任何 namespace 中的 Pod。 98 | 99 | 不过在实际使用中,ABAC 使用得比较少,跟我们上面 AuthN 中提到的静态 Token 一样,不方便修改、更新,每次变更后都需要重启 APIServer。所以在实际使用中,RBAC 最常见,使用更广泛。 100 | 101 | - RBAC 102 | 103 | 相对而言,RBAC 使用起来就非常方便了,通过 Kubernetes 的对象就可以直接进行管理,也便于动态调整权限。 104 | 105 | RBAC 中引入了角色,所有的权限都是围着这个角色进行展开的,每个角色里面定义了可以操作的资源以及操作方式。在 Kubernetes 中有两种角色,一种是 namespace 级别的 Role,比如 Pod、Service,一种是集群级别的 ClusterRole,比如 Node、PV 等。 106 | 107 | 我们来看个例子: 108 | 109 | ```yaml 110 | kind: Role 111 | apiVersion: rbac.authorization.k8s.io/v1 112 | metadata: 113 | namespace: default 114 | name: pod-reader 115 | rules: 116 | - apiGroups: [""] # 空字符串""表明使用core API group 117 | resources: ["pods"] 118 | verbs: ["get", "watch", "list"] 119 | ``` 120 | 121 | 这样一个角色表示可以访问 default 命名空间下面的 Pods,并可以对其进行 get、watch 以及 list 操作。 122 | 123 | ClusterRole 除了可以定义集群方位的资源外,比如 Node,还可以定义跨 namespace 的资源访问,比如你想访问所有命名空间下面的 Pod,就可以这么定义: 124 | 125 | ```yaml 126 | kind: ClusterRole 127 | apiVersion: rbac.authorization.k8s.io/v1 128 | metadata: 129 | # 鉴于ClusterRole是集群范围对象,所以这里不需要定义"namespace"字段 130 | name: pods-reader 131 | rules: 132 | - apiGroups: [""] 133 | resources: ["pods"] 134 | verbs: ["get", "watch", "list"] 135 | ``` 136 | 137 | **准入控制** 138 | 139 | 准入控制其实就是由一组控制逻辑级联而成,对对象进行拦截校验、更改等操作。 140 | 141 | 比如你打算在一个名为 test 的 namespace 中创建一个 Pod,如果这个 namespace 不存在,集群要不要自动创建出来?或者直接拒绝掉该请求?这些逻辑都可以通过准入控制进行配置。 142 | 143 | 准入控制可以帮助我们在 APIServer 真正处理对象前做一些校验以及修改的工作。 144 | 145 | # 27 | K8s CRD:如何根据需求自定义你的 API? 146 | 147 | 随着使用的深入,你会发现 Kubernetes 中内置的对象定义,比如 Deployment、StatefulSet、Configmap,可能已经不能满足你的需求了。你很希望在 Kubernetes 定义一些自己的对象,一来可以通过 kube-apiserver 提供统一的访问入口,二来可以像其他内置对象一样,通过 kubectl 命令管理这些自定义的对象。 148 | 149 | Kubernetes 中提供了两种自定义对象的方式,一种是聚合 API,另一种是 CRD。 150 | 151 | **聚合 API** 152 | 153 | 聚合 API(Aggregation API,AA)是自 Kubernetes v1.7 版本就引入的功能,主要目的是方便用户将自己定义的 API 注册到 kube-apiserver 中,并且可以像使用其他内置的 API 一样,通过 APIServer 的 URL 就可以访问和操作。 154 | 155 | 官方文档在[这里](https://kubernetes.io/zh/docs/tasks/extend-kubernetes/setup-extension-api-server/)。 156 | 157 | **CRD** 158 | 159 | CRD(CustomResourceDefinitions)在 v1.7 刚引入进来的时候,其实是 ThirdPartyResources(TPR)的升级版本,而 TPR 在 v1.8 的版本被剔除了。CRD 目前使用非常广泛,各个周边项目都在使用它,比如 Ingress、Rancher。 160 | 161 | -------------------------------------------------------------------------------- /B类/B20-其他/ApacheCamel.md: -------------------------------------------------------------------------------- 1 | > 参考资料: 2 | > 3 | > - https://camel.apache.org/manual/index.html 4 | > - https://github.com/apache/camel-examples 5 | 6 | # 一、入门 7 | 8 | ## 1.1 创建您的第一个项目 9 | 10 | **第一步:生成项目** 11 | 12 | ``` 13 | mvn archetype:generate -B -DarchetypeGroupId=org.apache.camel.archetypes -DarchetypeArtifactId=camel-archetype-java -DarchetypeVersion=3.18.4 -Dpackage=org.apache.camel.learn -DgroupId=org.apache.camel.learn -DartifactId=first-camel-integration -Dversion=1.0.0-SNAPSHOT 14 | ``` 15 | 16 | **第二步:构建和运行项目** 17 | 18 | 构建项目: 19 | 20 | ``` 21 | mvn clean package 22 | ``` 23 | 24 | 运行项目: 25 | 26 | ``` 27 | mvn camel:run -Dcamel.main.durationMaxMessages=2 28 | ``` 29 | 30 | 您刚刚运行的工程使用了两个文件,在项目中的 `target/messages` 目录: 31 | 32 | ``` 33 | target/messages/others/message2.xml 34 | target/messages/uk/message1.xml 35 | ``` 36 | 37 | ## 1.2 了解项目 38 | 39 | 您创建的工程实现了一种称为基于内容的路由器的模式。此模式的 Camel 允许您根据消息内容实现路由消息的逻辑。 40 | 41 | 更具体地说,查看工程 `src/data` 目录中 XML 文件的内容。 42 | 43 | message1.xml 44 | 45 | ```xml 46 | 47 | 48 | James 49 | Strachan 50 | London 51 | 52 | ``` 53 | 54 | message2.xml 55 | 56 | ```xml 57 | 58 | 59 | Hiram 60 | Chirino 61 | Tampa 62 | 63 | ``` 64 | 65 | ### Endpoint 66 | 67 | 当我们谈论进程间通信(例如客户端/服务器或微服务)时,我们经常使用术语端点来指代软件实体,端点的一个特征是它可以在某个地址上进行联系,地址本身可以传达端点的附加特征。例如,地址 `host:port` 传达基于 TCP 的通信端点的端口和网络名称。 68 | 69 | Camel 为使用多种通信技术实现的端点提供开箱即用的支持。以下是受支持的端点技术的一些示例: 70 | 71 | - JMS 队列 72 | - web 服务 73 | - 一份文件(一个应用程序可能会将信息写入文件,然后另一个应用程序可能会读取该文件) 74 | - FTP 服务器 75 | - 一个电子邮件地址(客户端可以向电子邮件地址发送消息,服务器可以读取来自邮件服务器的传入消息) 76 | - POJO 77 | 78 | 在 Camel 中,统一资源标识符 (URI) 表示端点的地址。 79 | 80 | 大多数人都熟悉 URL(统一资源定位符),例如 `http://…` 、 `ftp://…` 、 `\mailto:…:` 。 81 | 82 | URN 是不同“唯一标识符”的包装器,它的语法是 `urn::` 。 URN 唯一标识资源(即:一本书、人或一件设备)。 URN 本身并不指定资源的位置。 83 | 84 | URI(统一资源标识符)是 URL 或 URN。 85 | 86 | ### Routes 87 | 88 | 在基于 Camel 的应用程序中,您可以创建路由。路由用于将源端点连接到目标端点。 89 | 90 | “路由”描述了消息从源端点通过某一类型的决策例程(例如过滤器和路由器)到目标端点的逐步移动。 91 | 92 | 在您创建的项目中,目录 `src/main/java/org/apache/camel/learn` 中应该有 2 个源文件: 93 | 94 | - `MainApp.java` :用于配置和启动应用程序的代码。 95 | - `MyRouteBuilder.java` :路由的代码。 96 | 97 | 路由代码: 98 | 99 | ```java 100 | public class MyRouteBuilder extends RouteBuilder { 101 | public void configure() { 102 | from("file:src/data?noop=true") 103 | .choice() 104 | .when(xpath("/person/city = 'London'")) 105 | .log("UK message") 106 | .to("file:target/messages/uk") 107 | .otherwise() 108 | .log("Other message") 109 | .to("file:target/messages/others"); 110 | } 111 | } 112 | ``` 113 | 114 | 在此路由配置中,我们将地址 `file:src/data?noop=true` 表示的源端点连接到地址 `file:target/messages/uk` 和 `file:target/messages/others` 表示的其他两个端点。 115 | 116 | ### Component 117 | 118 | 在 Camel 中,表示端点地址的 URI 采用以下格式: 119 | 120 | ``` 121 | component:resource[?options] 122 | ``` 123 | 124 | URI 的协议部分表示用于消费或生成数据的组件。 Camel 包含 300 多个组件,允许您的应用程序与许多系统、协议和应用程序进行通信。 125 | 126 | 以下是 Camel 的有效 URI 的一些示例: `jms:queue:order` 、 `kafka:myTopic?groupId=KafkaConsumerFullIT` 、 `direct:result` 。通过查看这些 URI,我们可以识别它们正在使用 `jms` 、 `kafka` 和 `direct` 组件。 127 | 128 | 每个组件都有其自己特定的一组功能、约束和要求,我们在使用它们时必须遵守这些功能、约束和要求。 Camel 通过 `resource` 和 `options` 公开它们。资源是什么取决于我们正在使用的组件。例如,在文件组件中,资源是一个目录;在Kafka组件中,资源就是主题; 129 | 130 | ### 添加路由并运行应用程序 131 | 132 | 在执行路由之前,需要对其进行配置并添加到 CamelContext 中。 133 | 134 | ```java 135 | public class MainApp { 136 | public static void main(String... args) throws Exception { 137 | Main main = new Main(); 138 | main.configure().addRoutesBuilder(new MyRouteBuilder()); 139 | main.run(args); 140 | } 141 | } 142 | ``` 143 | 144 | ## 1.3 基本概念和术语 145 | 146 | ### CamelContext 147 | 148 | CamelContext 是运行时系统,它将我们迄今为止介绍的所有基本概念(路由、端点、组件等)结合在一起。 149 | 150 | 这个上下文对象代表 Camel 运行时系统。通常,应用程序中有一个 CamelContext 实例。 151 | 152 | 您没有在创建的示例应用程序中操作 CamelContext,因为 Main 组件为您管理它。随着您的集成变得越来越复杂,您最终将需要对其进行操作。典型的应用程序执行以下步骤: 153 | 154 | - 创建上下文对象 155 | - 添加端点 156 | - 将路由添加到上下文对象以连接端点 157 | - 对上下文对象调用 `start()` 操作 158 | - 最终调用上下文对象上的 `stop()` 操作 159 | 160 | ### Message与Exchange 161 | 162 | `Message` 接口提供单个消息的抽象,例如请求、回复或异常消息。`Message` 接口的公共API提供了 getter 和 setter 方法。您可以使用它们来访问消息的消息 ID、正文和各个标头字段。 163 | 164 | `Exchange` 接口提供了消息交换的抽象,是请求消息及其响应或异常消息。 165 | 166 | ### Processor 167 | 168 | 处理器用于实现消息的消费或翻译等。例如你编写了一个实现处理器的类,如下所示: 169 | 170 | ```java 171 | public class MyProcessor implements Processor { 172 | 173 | public void process(Exchange exchange) throws Exception { 174 | // do something... 175 | } 176 | 177 | } 178 | ``` 179 | 180 | 然后您可以轻松地从 Java 调用该处理器,例如: 181 | 182 | ``` 183 | from("activemq:myQueue").process(new MyProcessor()); 184 | ``` 185 | 186 | ### JAVA DSL 187 | 188 | 我们使用术语“Java DSL”而不是“DSL”,Camel “Java DSL”是一个类库,您可以以几乎像 DSL 的方式使用它,只是它有一些 Java 语法包袱。 189 | 190 | Camel 为应用程序开发人员提供了三种指定路由的方法: 191 | 192 | - 使用 XML 193 | - 使用 YAML 194 | - 使用 Java 领域特定语言 (DSL) 195 | 196 | # 二、使用示例 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | -------------------------------------------------------------------------------- /B类/README.md: -------------------------------------------------------------------------------- 1 | # 进阶类 2 | 3 | 进阶类:某项开源技术,但需要掌握其原理的知识 4 | 5 | -------------------------------------------------------------------------------- /B类/sidebar.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | - **数据库综合** 4 | - [SQL必知必会](B类/B01-数据库综合/[极客时间]-SQL必知必会.md) 5 | - **RPC** 6 | - [RPC实战与核心原理-基础篇](B类/B02-RPC/[极客时间]-RPC实战与核心原理-01基础篇.md) 7 | - [RPC实战与核心原理-进阶篇](B类/B02-RPC/[极客时间]-RPC实战与核心原理-02进阶篇.md) 8 | - [RPC实战与核心原理-高级篇](B类/B02-RPC/[极客时间]-RPC实战与核心原理-03高级篇.md) 9 | - **消息队列** 10 | - [消息队列高手课-基础篇](B类/B03-消息队列/[极客时间]-消息队列高手课-基础篇.md) 11 | - [消息队列高手课-进阶篇](B类/B03-消息队列/[极客时间]-消息队列高手课-进阶篇.md) 12 | - [Kafka入门及基本使用](B类/B03-消息队列/[极客时间]-01Kafka入门及基本使用.md) 13 | - [Kafka客户端实践及原理剖析](B类/B03-消息队列/[极客时间]-02Kafka客户端实践及原理剖析.md) 14 | - [Kafka内核](B类/B03-消息队列/[极客时间]-03Kafka内核.md) 15 | - [阿里云-消息队列Kafka版](B类/B03-消息队列/[阿里云]-消息队列Kafka版.md) 16 | - **Neo4j** 17 | - [Neo4j介绍](B类/B04-Neo4j/[个人整理]-Neo4J基础.md) 18 | - **Redis** 19 | - [《Redis设计与实现》读书笔记](B类/B05-Redis/《Redis设计与实现》读书笔记.md) 20 | - [Redis-01原理、协议及使用](B类/B05-Redis/Redis-01原理、协议及使用.md) 21 | - [Redis-02进阶](B类/B05-Redis/Redis-02进阶.md) 22 | - [Redis核心技术与实战-基础篇](B类/B05-Redis/Redis核心技术与实战-01基础篇.md) 23 | - [Redis核心技术与实战-实践篇](B类/B05-Redis/Redis核心技术与实战-02实践篇.md) 24 | - **Spring** 25 | - [Spring的IoC容器](B类/B06-Spring/《Spring揭秘》第二部分-Spring的IoC容器.md) 26 | - [Spring AOP框架](B类/B06-Spring/《Spring揭秘》第三部分-Spring-AOP框架.md) 27 | - [Spring事务管理](B类/B06-Spring/《Spring揭秘》第五部分-事务管理.md) 28 | - [Spring面试题-第一天](B类/B06-Spring/Spring面试题-第一天.md) 29 | - [Spring响应式编程](B类/B06-Spring/Spring响应式编程.md) 30 | - [Spring编程常见错误-SpringCore篇](B类/B06-Spring/Spring编程常见错误-01SpringCore篇.md) 31 | - [Spring编程常见错误-SpringWeb篇](B类/B06-Spring/Spring编程常见错误-02SpringWeb篇.md) 32 | - [Spring编程常见错误-Spring补充篇](B类/B06-Spring/Spring编程常见错误-03Spring补充篇.md) 33 | - **SpringBoot** 34 | - [Spring Boot的配置体系](B类/B14-SpringBoot/[拉勾]-SpringBoot实战-01配置体系.md) 35 | - [Spring Boot构建数据访问层](B类/B14-SpringBoot/[拉勾]-SpringBoot实战-02构建数据访问层.md) 36 | - [Spring Boot构建Web层+消息通信层](B类/B14-SpringBoot/[拉勾]-SpringBoot实战-03构建Web服务层+消息通信层.md) 37 | - [Spring Boot构建系统安全层+监控层](B类/B14-SpringBoot/[拉勾]-SpringBoot实战-04构建系统安全层+监控层.md) 38 | - **Spring Cloud** 39 | - [300分钟搞懂SpringCloud](B类/B12-SpringCloud/[拉勾]-300分钟搞懂SpringCloud.md) 40 | - [SpringCloud原理与实战-01基础篇](B类/B12-SpringCloud/[拉勾]-SpringCloud原理与实战-01基础篇.md) 41 | - [SpringCloud原理与实战-02服务治理+API网关](B类/B12-SpringCloud/[拉勾]-SpringCloud原理与实战-02服务治理+API网关.md) 42 | - [SpringCloud原理与实战-03服务容错+配置中心](B类/B12-SpringCloud/[拉勾]-SpringCloud原理与实战-03服务容错+配置中心.md) 43 | - [SpringCloud原理与实战-04事件驱动架构+服务安全](B类/B12-SpringCloud/[拉勾]-SpringCloud原理与实战-04事件驱动架构+服务安全.md) 44 | - [SpringCloud原理与实战-05链路跟踪+微服务测试](B类/B12-SpringCloud/[拉勾]-SpringCloud原理与实战-05链路跟踪+微服务测试.md) 45 | - [SpringCloudAlibaba实战-01微服务架构设计+Nacos服务治理](B类/B12-SpringCloud/[拉勾]-SpringCloudAlibaba实战-01微服务架构设计+Nacos服务治理.md) 46 | - [SpringCloudAlibaba实战-02微服务通信+系统积护](B类/B12-SpringCloud/[拉勾]-SpringCloudAlibaba实战-02微服务通信+系统保护.md) 47 | - **Spring Security** 48 | - [Spring Security详解与实操](B类/B19-SpringSecurity/SpringSecurity详解与实操.md) 49 | - **Tomcat** 50 | - [深入拆解Tomcat](B类/B07-Tomcat/[极客时间]-深入拆解Tomcat.md) 51 | - **设计模式** 52 | - [设计模式之美-01设计模式学习导读](B类/B08-设计模式/[极客时间]-设计模式之美-01设计模式学习导读.md) 53 | - [设计模式之美-02设计原则与思想](B类/B08-设计模式/[极客时间]-设计模式之美-02设计原则与思想.md) 54 | - [设计模式之美-04开源与项目实战](B类/B08-设计模式/[极客时间]-设计模式之美-04开源与项目实战.md) 55 | - **MyBatis** 56 | - [《MyBatis技术内幕》读书笔记](B类/B09-MyBatis/《MyBatis技术内幕》读书笔记.md) 57 | - [深入剖析MyBatis核心原理](B类/B09-MyBatis/深入剖析MyBatis核心原理.md) 58 | - **系统性能** 59 | - [性能调优实战-Java编程调优](B类/B10-系统性能/[极客时间]-性能调优实战-01Java编程调优.md) 60 | - [性能调优实战-多线程调优](B类/B10-系统性能/[极客时间]-性能调优实战-02多线程调优.md) 61 | - [性能调优实战-JVM性能监测及调优](B类/B10-系统性能/[极客时间]-性能调优实战-03JVM性能监测及调优.md) 62 | - [性能调优实战(网络博客)](B类/B10-系统性能/[网络博客]-性能调优实战.md) 63 | - [性能测试-基础篇](B类/B10-系统性能/[极客时间]-性能测试-01基础篇.md) 64 | - [性能测试-工具及场景篇](B类/B10-系统性能/[极客时间]-性能测试-02工具及场景篇.md) 65 | - [性能测试-分析实战篇](B类/B10-系统性能/[极客时间]-性能测试-05分析实战篇.md) 66 | - **ZooKeeper** 67 | - [ZooKeeper基础](B类/B11-ZooKeeper/[个人整理]ZooKeeper学习笔记.md) 68 | - [ZooKeeper技术内幕:Leader选举](B类/B11-ZooKeeper/ZooKeeper技术内幕:Leader选举.md) 69 | - **Elasticsearch** 70 | - [第1部分:初识ElasticSearch](B类/B13-Elasticsearch/第1部分:初识ElasticSearch.md) 71 | - [第2部分:深入了解Elasticsearch](B类/B13-Elasticsearch/第2部分:深入了解Elasticsearch.md) 72 | - [ElasticSearch核心技术与实践](B类/B13-Elasticsearch/[geek]-ElasticSearch核心技术与实践.md) 73 | - **Go语言** 74 | - [Go语言从入门到实战](B类/B15-Go语言/[极客时间]-Go语言从入门到实战.md) 75 | - [Go微服务实战](B类/B15-Go语言/[拉勾]-Go微服务实战.md) 76 | - **Lua** 77 | - [Lua教程](B类/B16-Lua/[runoob]-Lua教程.md) 78 | - **Camunda** 79 | - [Camunda](B类/B17-Camunda/Camunda.md) 80 | - [Zeebe](B类/B17-Camunda/Zeebe.md) 81 | - **Kubernetes** 82 | - [Kubernetes原理与实战-基础篇](B类/B18-Kubernetes/Kubernetes原理与实战-01基础篇.md) 83 | - [Kubernetes原理与实战-进阶篇](B类/B18-Kubernetes/Kubernetes原理与实战-02进阶篇.md) 84 | - [深入剖析Kubernetes-基础篇](B类/B18-Kubernetes/深入剖析Kubernetes-01基础篇.md) 85 | - [深入剖析Kubernetes-实践篇](B类/B18-Kubernetes/深入剖析Kubernetes-02实践篇.md) 86 | - **SpringSecurity** 87 | - [SpringSecurity详解与实操](B类/B19-SpringSecurity/SpringSecurity详解与实操.md) 88 | - **其他** 89 | - [ApacheCamel](B类/B20-其他/ApacheCamel.md) 90 | - [Disconf](B类/B20-其他/Disconf.md) 91 | - **微服务组件** 92 | - [Dubbo](B类/B21-微服务组件/Dubbo.md) 93 | - [Dubbo源码剖析与实战](B类/B21-微服务组件/Dubbo源码剖析与实战.md) 94 | - [Netflix-Hystrix](B类/B21-微服务组件/Netflix-Hystrix.md) 95 | 96 | -------------------------------------------------------------------------------- /C类/C01-高并发系统设计/高并发系统设计-01基础篇.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/C类/C01-高并发系统设计/高并发系统设计-01基础篇.png -------------------------------------------------------------------------------- /C类/C01-高并发系统设计/高并发系统设计-01基础篇.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/C类/C01-高并发系统设计/高并发系统设计-01基础篇.xmind -------------------------------------------------------------------------------- /C类/C02-微服务/[极客时间]-03微服务网关Zuul架构与实践.md: -------------------------------------------------------------------------------- 1 | # 50 | Zuul基本应用场景 2 | 3 | **介绍** 4 | 5 | Netflix 于 2012 年初开源,2014 年被 Pivotal 集成入 Spring Cloud 体系。 6 | 7 | 亮点:可动态发布的过滤器机制。 8 | 9 | ![image-20210730231828599](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210730231828.png) 10 | 11 | **网关基本功能** 12 | 13 | ![image-20210730231326839](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210730231327.png) 14 | 15 | **Netflix 使用情况(2017)** 16 | 17 | - 支持超过 1000 种设备类型 18 | - 超过 50+ 前置 ELB 19 | - 每天处理百亿+请求 20 | - 支持 3个 AWS 区域(regions) 21 | - 部署超过 20+ 生产 Zuul 集群 22 | 23 | **国内公司落地案例** 24 | 25 | - 携程 26 | 27 | 部署生产实例 150+(分集群);
28 | 覆盖无线、H5、分销联盟、支付业务等场景;
29 | 日流量超 50 亿; 30 | 31 | - 拍拍贷 32 | 33 | 部署实例 40+(分集群);
覆盖无线、H5、第三方开放平台、联盟商等场景;
日流量超 5 亿; 34 | 35 | # 51 | Zuul高级应用场景 36 | 37 | **红绿部署** 38 | 39 | ![image-20210730233035233](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210730233035.png) 40 | 41 | **开发者测试分支** 42 | 43 | ![image-20210730233150596](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210730233150.png) 44 | 45 | **埋点测试** 46 | 47 | ![image-20210730233220214](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210730233220.png) 48 | 49 | **跨区域高可用(异地多活)** 50 | 51 | ![image-20210730233947685](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210730233947.png) 52 | 53 | # 52 | Zuul架构剖析 54 | 55 | **架构剖析** 56 | 57 | 模块一:网关过滤器管理模块; 58 | 59 | 模块二:网关过滤器加载模块; 60 | 61 | 模块三:网关过滤器核心运行时模块; 62 | 63 | ![image-20210730234216913](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210730234216.png) 64 | 65 | **请求处理生命周期** 66 | 67 | ![image-20210730234621463](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210730234621.png) 68 | 69 | **过滤器关键概念** 70 | 71 | - 类型 Type 72 | 73 | 分为前置(PRE)、路由(ROUTING)、后置(POST)、错误(ERROR)过滤器。 74 | 75 | - 执行顺序 Execution Order 76 | 77 | 在同一个 Type 中,过滤器可以定义执行顺序。 78 | 79 | - 条件 Criteria 80 | 81 | 过滤器执行的条件。 82 | 83 | - 动作 Action 84 | 85 | 如果条件满足,过滤器中将执行的动作。 86 | 87 | # 53 | Zuul核心源码 88 | 89 | netfix 源码:https://github.com/netflix/zuul 90 | 91 | Zuul 教学源码:https://github.com/spring2go/s2g-zuul 92 | 93 | **过滤器管理工具** 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /C类/C02-微服务/[极客时间]-08构建OAuth2服务器.md: -------------------------------------------------------------------------------- 1 | # 139 | 课程概述和背景 2 | 3 | **Why Golang?** 4 | 5 | - 简单入门门槛低,适合课程讲解 6 | - Google 开发支持,社区生态好 7 | - 云原生基础语言(k8s/docker/etcd/istio) 8 | - 微服务多语言(polyglot)开发趋势 9 | - OAuth2实现和具体语言无关 10 | 11 | **课程大纲** 12 | 13 | 139. 课程概述和背景 14 | 140. 架构和设计 15 | 141. 开发环境搭建(Lab01) 16 | 142. 基础代码(Code Review) 17 | 143. 数据访问模块(Code Review) 18 | 144. OAuth2服务模块(Code Review) 19 | 145. Web服务模块(Code Review) 20 | 146. 启动流程(Code Review) 21 | 147. 起步准备实验(Lab02) 22 | 148. OAuth2授权码模式实验(Lab03) 23 | 149. OAuth2简化模式实验(Lab04) 24 | 150. OAuth2用户名密码模式实验(Lab05) 25 | 151. OAuth2客户端模式实验(Lab06) 26 | 152. OAuth2令牌校验实验(Lab07) 27 | 153. OAuth2令牌刷新实验(Lab08) 28 | 154. 项目复盘和扩展环境 29 | 155. 参考资料 30 | 31 | # 140 | 架构和设计 32 | 33 | **总体架构** 34 | 35 | ![image-20201213223546190](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201213223556.png) 36 | 37 | **数据模型** 38 | 39 | ![image-20201215225448872](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201215225448.png) 40 | 41 | **接口模型** 42 | 43 | ![image-20201213224924821](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201213224924.png) 44 | 45 | 以上三个方面是一个系统本质,无论使用什么语言实现,都离不开这三方面。 46 | 47 | # 141 | 开发环境搭建 48 | 49 | 实验代码:spring2go/gravitee_lab 50 | 51 | 工程代码:spring2go/gravitee 52 | 53 | 大致步骤: 54 | 55 | 1. 安装 GO(Golang中国下载) 56 | 57 | GOROOT:GO安装目录; 58 | 59 | GOPATH:GO工作目录; 60 | 61 | 这2个目录的 bin 可以添加到环境变量 Path。 62 | 63 | 2. 下载 VS CODE; 64 | 65 | 3. 安装 go 扩展插件; 66 | 67 | 4. Hello World; 68 | 69 | 5. 安装 glide 包管理工具 70 | 71 | ``` 72 | go get github.com/Masterminds/glide 73 | go install github.com/Masterminds/glide 74 | ``` 75 | 76 | ``` 77 | glide install 78 | ``` 79 | 80 | install 后会多一个 vendor 目录。 81 | 82 | # 142 | 基础代码(Code Review) 83 | 84 | **项目结构** 85 | 86 | ``` 87 | |--cmd 88 | |--config 89 | |--database 90 | |--health 91 | |--log 92 | |--models 领域模型 93 | |--oauth 94 | |--public 95 | |--services 96 | |--session 97 | |--test-util 98 | |--user 99 | |--util 100 | |--vendor 依赖库 101 | |--web 102 | ``` 103 | 104 | # 143 | 数据访问模块(Code Review) 105 | 106 | **common.go** 107 | 108 | - MyGormModel 109 | 110 | 这是一个超类,定义了公共字段。 111 | 112 | **migrations.go** 113 | 114 | 创建表、建立模型间的依赖关系。 115 | 116 | **oauth.go** 117 | 118 | 使用gorm定义ORM。 119 | 120 | # 144 | OAuth2服务模块(Code Review) 121 | 122 | 先从简单的 health 模块入手。 123 | 124 | **health模块** 125 | 126 | - service_interface.go 127 | 128 | 定义接口 interface 129 | 130 | - service 131 | 132 | 服务类 133 | 134 | - handlers.go 135 | 136 | 服务逻辑 137 | 138 | - routes.go 139 | 140 | 路由 141 | 142 | **routes.go** 143 | 144 | - POST : oauth_tokens 145 | - POST : oauth_introspect 146 | 147 | # 145 | Web服务模块(Code Review) 148 | 149 | 150 | 151 | # 146 | 启动流程(Code Review) 152 | 153 | # 147 | 起步准备实验(Lab02) 154 | 155 | -------------------------------------------------------------------------------- /C类/C02-微服务/[美团]Shepherd设计与实现.md: -------------------------------------------------------------------------------- 1 | # 01 | 背景介绍 2 | 3 | **1.1 API 网关是什么?** 4 | 5 | API网关是运行于外部请求与内部服务之间的一个流量入口,实现对外部请求的协议转换、鉴权、流控、参数校验、监控等通用功能。 6 | 7 | ![image-20210531144242301](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210531144242.png) 8 | 9 | 总结来说,网关主要解决两个问题:第一,统一 API 的管理;第二,整合微服务的重复功能; 10 | 11 | **1.2 为什么要做 Shepherd API 网关** 12 | 13 | 主要原因有三点。 14 | 15 | 1、提高研发效率:在没有 Shepherd API 网关之前,美团业务研发人员如果要对外一个 HTTP API 接口,通常要先完成基础的鉴权、限流、日志监控、参数校验、协议转换等工作,同时需要维护代码逻辑,研发效率相对较低。 16 | 17 | 2、降低沟通成本:有了 Shepherd API 网关之后,业务研发人员配置好 API,可以自动生成 API 的前后端交互文档和客户端 SDK,方便前后端开发人员进行交互、联调。 18 | 19 | 3、提升资源利用率:这点怎么理解?像基础的鉴权、限流、日志监控、参数校验、协议转换等工作,如果每个 Web 应用都需要维护机器、配置、数据库,资源利用率非常差。 20 | 21 | 为美团提供高性能、高可用、可扩展的统一 API 网关解决方案,让业务研发人员通过配置的方式即可对外开放功能和数据。 22 | 23 | ![image-20210524213716338](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210524213716.png) 24 | 25 | 目前接入 Shepherd API 网关的 API 数量超过18000多个,线上运行的集群数量90多个,日均总调用次数在百亿以上。 26 | 27 | # 02 | 整体架构 28 | 29 | ![image-20210524214038571](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210524214038.png) 30 | 31 | **2.1 控制面** 32 | 33 | 包括管理平台(完成 API 的全生命周期管理)和监控中心(完成 API 请求监控数据的收集和业务告警功能)。 34 | 35 | ![image-20210528161002496](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210528161002.png) 36 | 37 | 业务研发人员从创建 API 开始,完成参数录入、DSL 脚本生成;接着可以通过文档和 MOCK 功能进行 API 测试; 38 | 39 | API 测试完成后,为了保证上线稳定性,Shepherd 管理平台提供了发布审批、灰度上线、版本回滚等一系列安全保证措施; 40 | 41 | 到这两步会监控 API 的调用失败情况、记录请求日志,一旦发现异常及时发出告警; 42 | 43 | 最后,对于不再使用的 API 进行下线操作后,会回收 API 所占用的各类资源并等待重新启用。 44 | 45 | **2.2 配置中心** 46 | 47 | 配置中心是用来完成控制面与数据面的信息交互。存放的是 API 的配置信息,这些配置信息是使用 DSL 领域专用语言来描述。DSL 语言所描述的 API 如下所示。 48 | 49 | ![image-20210528161104176](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210528161104.png) 50 | 51 | - Filters:API 使用到的功能组件; 52 | - Request:请求的域名、路径、参数等信息; 53 | - Response:响应的结果如异常处理、Header、Cookies 信息; 54 | - Invokers:后端服务(RPC/HTTP/Function)的请求规则; 55 | - FilterConfigs:API 使用到的功能组件的配置信息; 56 | 57 | **2.3 数据面** 58 | 59 | 泛化后端服务,响应结果。 60 | 61 | 当请求流量命中API请求路径进入服务端,具体处理逻辑由DSL中配置的一系列功能组件完成。 62 | 63 | ![image-20210528161202370](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210528161202.png) 64 | 65 | 当请求流量进入 Shepherd 服务端,具体处理逻辑由 API DSL 中配置的一系列功能组件完成。网关提供了 API 路由、功能组件集成、协议转换和服务调用。 66 | 67 | API 路由的实现: 68 | 69 | 经过这样一些功能组件后,最终会路由到微服务。路由的实现原理可以简单的理解成一种 Map 结构,其中 Key 就是完整的域名和路径信息,Value 是具体的 API 配置。 70 | 71 | ![image-20210528161248763](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210528161248.png) 72 | 73 | API 调用的最后一步,就是协议转换以及服务调用了。 74 | 75 | ![image-20210528161334312](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210528161334.png) 76 | 77 | # 03 | 高性能设计 78 | 79 | **3.1 性能优化** 80 | 81 | Shepherd对API请求做了全异步化处理: 82 | 83 | ![image-20210525224516711](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210525224516.png) 84 | 85 | QPS 为 2000。 86 | 87 | 性能优化一:打开 Nginx 与 Web 应用之间的长连接,性能提升到了 10000 以上。 88 | 89 | 性能优化二:对 Shepherd 服务进行 API 请求预热,减少主链路的本地日志打印,QPS 再次提升 30% 即 13000。 90 | 91 | 性能优化三:将 Jetty 容器替换为 Netty 网络框架,QPS 再提升 10% 达 15000 以上。 92 | 93 | ![image-20210525225358258](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210525225358.png) 94 | 95 | # 04 | 高可用设计 96 | 97 | **4.1 服务隔离** 98 | 99 | 服务隔离类型有两种: 100 | 101 | 一种是按业务线维度进行集群隔离。另一种是服务节点维度,快慢线程池隔离主要用于一些使用了同步阻塞组件的 API,例如 SSO 鉴权、自定义鉴权等,可能导致长时间阻塞共享业务线程池。 102 | 103 | ![image-20210525225614915](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210525225614.png) 104 | 105 | 快慢隔离的原理是统计 API 请求的处理时间,将请求处理耗时较长,超过容忍阈值的 API 请求隔离到慢线程池,避免影响其他正常 API 的调用。 106 | 107 | ![image-20210528142824419](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210528142824.png) 108 | 109 | **4.2 稳定性保障** 110 | 111 | 保障手段有:流量管控、请求缓存、超时管理、熔断降级。 112 | 113 | - 流量管控:从 App 限流、IP 限流、集群限流等多个维度提供流量保护。 114 | - 请求缓存:对于一些查询频繁的、数据及时性不敏感的请求,业务研发人员可开启请求缓存功能。 115 | - 超时管理:每个 API 都设置了处理超时时间,对于超时的请求,进行快速失败的处理,避免资源占用。 116 | - 熔断降级:达到配置的失败阈值后,自动熔断,返回默认值。 117 | 118 | ![image-20210528143028421](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210528143028.png) 119 | 120 | **4.3 监控告警** 121 | 122 | Shepherd 从机器指标(1)、业务指标(234)、服务状态指标(5)提供了监控,如下表所示。 123 | 124 | ![image-20210525231006254](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210525231006.png) 125 | 126 | 主要的告警能力如下表所示: 127 | 128 | ![image-20210525231127312](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210525231127.png) 129 | 130 | **4.4 易用性设计** 131 | 132 | 自动生成 DSL。 133 | 134 | ![image-20210525231339671](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210525231339.png) 135 | 136 | # 05 | 可扩展设计 137 | 138 | **5.1 自定义组件** 139 | 140 | Shepherd 通过提供加载自定义组件能力,支持业务完成一些自定义逻辑的扩展。 141 | 142 | 这是自定义组件实现的一个实例。Invoke 方法中实现自定义组件的业务逻辑,如继续执行、进行页面跳转、直接返回结果、抛出异常等。 143 | 144 | ![image-20210524223321317](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210524223321.png) 145 | 146 | **5.2 服务编排** 147 | 148 | 对于一些业务场景,需要通过调用多个接口来满足的,可以通过服务编排来实现。 149 | 150 | Shepherd 在创建 API 时,支持这种服务编排的 API,以满足扩展性需求。 151 | 152 | ![image-20210528142026069](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210528142026.png) 153 | 154 | ![image-20210528142039740](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210528142039.png) 155 | 156 | # 参考资料 157 | 158 | - https://tech.meituan.com/2021/05/20/shepherd-api-gateway.html 159 | - https://tech.meituan.com/2018/07/26/sep-service-arrange.html 160 | - https://www.infoq.cn/article/qxcl87g3fsiubnvulkoi -------------------------------------------------------------------------------- /C类/C02-微服务/微服务架构和技术预览.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/C类/C02-微服务/微服务架构和技术预览.png -------------------------------------------------------------------------------- /C类/C03-架构设计/[极客时间]-郭东白的架构课-02价值创造.md: -------------------------------------------------------------------------------- 1 | > 来源极客时间《郭东白的架构课》(15~34) 2 | 3 | # 15|模块导读:互联网时代架构师都面临哪些新挑战? 4 | 5 | > 内容有点高深了,本文观点说不教你架构的招式,而是教你思考力,但目前,我处在的是一个招式欠缺的阶段。 6 | > 7 | > 本课程学到此,感觉还是不太适合继续深入学习了。 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /C类/C03-架构设计/[极客时间]-郭东白的架构课-03职业成长.md: -------------------------------------------------------------------------------- 1 | > 来源极客时间《郭东白的架构课》(35~43) 2 | 3 | -------------------------------------------------------------------------------- /C类/C03-架构设计/[极客时间]-郭东白的架构课-04思考力.md: -------------------------------------------------------------------------------- 1 | > 来源极客时间《郭东白的架构课》(44~54) 2 | 3 | -------------------------------------------------------------------------------- /C类/C03-架构设计/企业级高可用延时消息设计.md: -------------------------------------------------------------------------------- 1 | # 01 | 延时业务场景需求分析及落地实现 2 | 3 | **延时需求** 4 | 5 | - 即时通讯消息重发 6 | 7 | IM 系统为了确保消息触达接收方,消息发出几秒后没有收到 ack,需要重发消息。 8 | 9 | - 订单状态流转 10 | 11 | 取消规定时间内未付款的订单;商家发货后,长时间未确认的订单自动确认收货。 12 | 13 | - 外置索引更新 14 | 15 | 信息发布后,外置索引更新相对滞后,立刻查询可能会查不到。 16 | 17 | **解决方案:时间轮算法** 18 | 19 | 时间轮算法可以用于高效的执行大量的定时任务,实现简单,且精度非常高。原理如下: 20 | 21 | ![image-20210519230556425](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210519230556.png) 22 | 23 | 构造一个内存时间轮,桶数量为 15,时间粒度为秒。当消息发出后,将事件放入游标的前一个桶,当收到 ACK 后记录 ACK 事件,然后遍历当前桶,如果 15 秒之内没有收到客户端的 ACK 确认,则重新发送消息。逻辑设计图如下: 24 | 25 | ![image-20210519231302869](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210519231302.png) 26 | 27 | 时间轮存储选择 Redis 的 List 数据结构。Key 存储桶,String 存储游标。如下图所示: 28 | 29 | ![image-20210519231936647](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210519231936.png) 30 | 31 | **时间轮结构** 32 | 33 | ![image-20210520100502894](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210520100503.png) 34 | 35 | - HashedWheelBucket 36 | 37 | 一个环形双向链表。 38 | 39 | - HashedWheelTimeout 40 | 41 | 定时任务项,在链表中的每一项表示。 42 | 43 | - tickDuration 44 | 45 | 时间轮的基本时间跨度,一个 bucket 代表的时间。 46 | 47 | - ticksPerWheel 48 | 49 | 一轮含有多少个 bucket。 50 | 51 | - Wheel.length 52 | 53 | 时间轮的时间格个数。 54 | 55 | - tick 56 | 57 | 表盘指针,用来表示时间轮当前指针跳动的次数。 58 | 59 | - tickDuration * (tick + 1) 60 | 61 | 下一次到期的任务。 62 | 63 | **时间轮运行逻辑** 64 | 65 | - startTime 66 | 67 | 时间轮启动时间。 68 | 69 | - deadline 70 | 71 | 延迟时间。 72 | 73 | 比如一个任务的延迟时间为24ms,那么会将当前的时间 currentTime + 24ms - startTime,然后将任务封装成 HashedWheelTimeout 加入到 timeouts 队列中。 74 | 75 | 假设现在时间轮在运行的时候会从 timeouts 中取 10 万个 HashedWheelTimeout 任务进行遍历,那么需要计算出以下几个参数值: 76 | 77 | - HashedWheelTimeout 的总共跳动的次数 78 | 79 | 即 tick 总共跳动的次数:deadline / tickDuration 80 | 81 | - 时间轮 round 次数 82 | 83 | (总次数 - 当前 tick 数量)/ 时间格个数 84 | 85 | - 该任务需要放置到时间轮(wheel)的槽位 86 | 87 | > 参考资料:https://www.cnblogs.com/luozhiyun/p/12075326.html 88 | 89 | **理解时间轮算法** 90 | 91 | HashedWheelTimer 是一个环形结构,可以用时钟来类比,钟面上有很多 bucket ,每一个 bucket 上可以存放多个任务,使用一个 List 保存该时刻到期的所有任务,同时一个指针随着时间流逝一格一格转动,并执行对应 bucket 上所有到期的任务。任务通过取模决定应该放入哪个 bucket 。和 HashMap 的原理类似,newTask 对应 put,使用 List 来解决 Hash 冲突。 92 | 93 | ![image-20210520164315221](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210520164315.png) 94 | 95 | 以上图为例,假设一个 bucket 是 1 秒,则指针转动一轮表示的时间段为 8s,假设当前指针指向 0,此时需要调度一个 3s 后执行的任务,显然应该加入到 (0+3=3) 的方格中,指针再走 3 次就可以执行了;如果任务要在 10s 后执行,应该等指针走完一轮零 2 格再执行,因此应放入 2,同时将 round(1)保存到任务中。检查到期任务时只执行 round 为 0 的, bucket 上其他任务的 round 减 1。 96 | 97 | 再看图中的 bucket5,我们可以知道在 $18+5=13s$ 后,有两个任务需要执行,在 $28+5=21s$ 后有一个任务需要执行。 98 | 99 | > 参考资料:https://mp.weixin.qq.com/s/v0LaRj_Knb8tDhhuNqB4Jw 100 | 101 | **是如何控制精度的?** 102 | 103 | 通过 tickDuration 参数控制。 104 | 105 | **什么时候执行 TimerTask 的 run 方法?** 106 | 107 | 108 | 109 | **在哪里执行的等待?** 110 | 111 | Work # run 方法的 waitForNextTick(); 112 | 113 | **Netty中时间轮的参数** 114 | 115 | threadFactory = new DefaultThreadFactory() 116 | tickDuration = 100 117 | unit = TimeUnit.MILLISECONDS 118 | ticksPerWheel = 512 119 | leakDetection = true 120 | 121 | # 02 | 企业级延时服务架构设计 122 | 123 | 企业级的延时服务,需要适用更多的场景,支持不同跨度的延时;且需要多个节点提供服务,以确保服务的高可用。 124 | 125 | ![image-20210519232907492](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210519232907.png) 126 | 127 | # 03 | 基于 RocketMQ 延时消息的代码级设计实现 128 | 129 | **RocketMQ 原理** 130 | 131 | ![image-20210519233028019](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210519233028.png) 132 | 133 | RocketMQ 支持 18 个级别的延时等级,默认值为 1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h。生产者发消息时通过设置 delayLevel 选择。 134 | 135 | ```java 136 | // 生产者选择 delayLevel 137 | public void setDelayTimeLevel(int level) { 138 | this.putProperty(MessageConst.PROPERTY_DELAY_TIME_LEVEL, String.valueOf(level)); 139 | } 140 | ``` 141 | 142 | **延时实现原理** 143 | 144 | 通过缓存延时消息到不同延时级别的队列 SCHEDULE_TOPIC_XXX,每个队列创建定时任务进行调度,延时消息到期后则重新投递到真实的 Topic。如下图所求: 145 | 146 | ![image-20210519233731588](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210519233731.png) 147 | 148 | Broker 将所有接收到的消息顺序写入 CommitLog 中,Dispatch 线程负责将消息的索引信息分发到 Topic 的 Queue 中。 149 | 150 | ![image-20210519234319574](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210519234319.png) 151 | 152 | **ScheduleLog 存储** 153 | 154 | 存放延时消息的一组文件,将延时消息按到期时间划分,以半小时位一个区间,存放到指定的 ScheduleLog 文件中。 155 | 156 | - 消息索引 157 | 158 | ![image-20210519234626784](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20210519234626.png) 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /C类/C04-分布式/分布式-01理论篇.md: -------------------------------------------------------------------------------- 1 | # 开篇词 | 想成为分布式高手?那就先把协议和算法烂熟于心吧 2 | 3 | **为什么要单独讲分布式协议和算法呢?** 4 | 5 | 它其实就是决定分布式系统如何运行的核心规则和关键步骤。 如果一个人想真正搞懂分布式技术,开发出一个分布式系统,最先需要掌握的就是这部分知识。 6 | 7 | 举个例子,学数学的时候,我们总是会学到很多公式或者定理,我上学的时候,还觉得这些定理枯燥至极。但后来我明白了,这些定理和公式其实就是前人花了很长时间思考、验证、总结出来的规律,如果我们能在这之上做事情,更容易快速地找到正确答案。 8 | 9 | **分布式算法是分布式技术中的核心** 10 | 11 | > 经典书籍:《分布式系统:概念与设计》《分布式系统原理与范型》 12 | 13 | 分布式系统里,最重要的事情,就是如何选择或设计适合的算法,解决一致性和可用性相关的问题了。 可尽管它是分布式技术中的核心与关键,但实际掌握的人或者公司却很少。 14 | 15 | > 我来说个真实的事儿。我刚刚提到的 InfluxDB 其实是一个开源的时序数据库系统,当然,开源的只是单机版本,如果你要使用集群功能,要么就是基于开源版本自研,要么就是购买人家的企业版本。而这里面,企业版本一个节点一年 License 授权费就是 1.5 万美刀,是不是很贵?那贵在哪里呢?相比于单机版本,企业版本的技术壁垒又是什么? 16 | > 17 | > 在我自己折腾了一番 InfluxDB 系统后,我捂着胸口和你说,它的护城河就是以分布式算法 18 | > 为核心的分布式集群能力。 19 | 20 | 说点儿更实际的,现阶段,掌握分布式算法也是你面试架构师、技术专家等高端岗位时的敲门砖。 你可以搜索看看,知名的公司在招聘架构师或者高级工程师时,岗位要求中是不是写着熟悉分布式算法相关理论等内容?不过从我作为面试官的经验来看,懂这部分的候选人实在是少之又少。 21 | 22 | **分布式算法学习难点** 23 | 24 | 分布式算法虽然很重要,但是也比较难学,原因有这样几点。 25 | 26 | - 经典论文中细节没有讲清楚 27 | 28 | 除了算法本身抽象,不容易理解之外,即使是非常经典的论文,也存在在一些关键细节上没有讲清楚的情况。比如,你比较熟悉的拜占庭将军问题,在阅读口信消息型拜占庭问题之解时,你是不是感到很吃力呢?那是因为论文没有说透彻。 29 | 30 | - 网上资料质量参差不齐 31 | 32 | 信息时代资料丰富,但质量参差不齐,甚至有错误。网上信息大多是“复制粘贴”的结果,而且因为分布式领域的研究多以英文论文的形式出现,中文翻译内容的错误非常多,这也给自主学习带来很多不必要的障碍和误导。如果你没有足够的好奇心和探究精神,很难完全吃透关键细节。 33 | 34 | - 理论未能结合实战应用 35 | 36 | 很多资料是为了讲解理论而讲解理论,无法站在“用”的角度,将理论和实战结合。最终,你只能在“嘴”上理解,而无法动手。 37 | 38 | **方法得当,知识并不难学** 39 | 40 | 在我看来,要想掌握这部分内容,不仅要理解常用算法的原理、特点和局限,还要能根据场景特点选择适合的分布式算法。 41 | 42 | 所以,为了更好地帮你轻松、透彻地搞懂分布式技术,理解其中最核心和最为精妙的内容,我希望将自己支撑海量互联网服务中的分布式算法实战心得分享给你。 43 | 44 | 理论篇(01-04):分布式架构设计核心且具有“实践指导性”的基础理论; 45 | 46 | 协议和算法篇(05-15):原理、特点、适用场景和常见误区等。 47 | 48 | 实战篇(16-20):掌握分布式基础理论和分布式算法在工程实践中的应用。 49 | 50 | # 01 | 拜占庭将军问题:有叛徒的情况下,如何才能达成共识? 51 | 52 | 接下来,我就以战国时期六国抗秦的故事为主线串联起整篇文章,让你读懂、学透拜占庭将军问题。 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /C类/C05-DDD/《实现领域驱动设计》.md: -------------------------------------------------------------------------------- 1 | # 实现领域驱动设计 2 | 3 | ## 为什么我们需要DDD 4 | 5 | - 使领域专家和开发者在一起工作 6 | - 准确传达业务规则 7 | - 可以帮助业务人员自我提高 8 | - 设计就是代码,代码就是设计 9 | 10 | 贫血型的领域对象 11 | 12 | ```java 13 | public void saveCustomer( 14 | String customerId, String customerFirstName, String customerLastName, 15 | String streetAddress1, String streetAddress2, String city, String stateOrProvince, 16 | String postalCode, String country, String homePhone, String mobilePhone, 17 | String primaryEmailAddress, String secondaryEmailAddress) { 18 | 19 | Customer customer = customerDao.readCustomer(customerId); 20 | 21 | if (customer == null) { 22 | customer = new Customer(); 23 | customer.setCustomerId(customerId); 24 | } 25 | 26 | customer.setCustomerFirstName(customerFirstName); 27 | //... 28 | 29 | customerDao.saveCustomer(customer); 30 | } 31 | ``` 32 | 33 | 上面的 saveCustomer() 至少存在三大问题: 34 | 35 | - saveCustomer() 业务意图不明确 36 | - 方法的实现本身增加了潜在的复杂性 37 | - Customer 领域对象根本就不是对象,而只是一个数据持有器(data holder) 38 | 39 | 我们将这种情况称为“由贫血症导致的失忆症”,在实际项目中,这种症状发生得太多了。 40 | 41 | 我们使用 DDD 的思想重新设计 saveCustomer() 方法。 42 | 43 | ```java 44 | public interface Customer { 45 | void changePersonalName(String firstName, String lastName); 46 | void relocateTo(PostalAddress changedPostalAddress); 47 | void changeHomeTelephone(Telephone telephone); 48 | } 49 | ``` 50 | 51 | 此时上面的例子已经能够反映出一个 Customer 应该支持的业务操作了。下面是应用层的代码: 52 | 53 | ```java 54 | @Transactional 55 | public void changeCustomerPersonalName( 56 | String customerId, String customerFirstName, String custmerLastName) { 57 | 58 | Customer customer = customerRepository.customerOfId(customerId); 59 | 60 | if (customer == null) { 61 | throw new IllegalStateException("Customer does not exist."); 62 | } 63 | 64 | customer.changePersonalName(customerFirstName, customerLastName); 65 | } 66 | ``` 67 | 68 | 通过这段代码,能很清晰理解它的业务意图。 69 | 70 | DDD 的强调“设计即代码,代码即设计”。 71 | 72 | 对于“注射流感疫苗”这个业务用例,当团队讨论到业务模型时,他们会说:“护士给病人注射标准剂量的流感疫苗。” 73 | 74 | ```java 75 | patient.setShotType(ShotTypes.TYPE_FLU); 76 | patient.setDose(dose); 77 | patient.setNurse(nurse); 78 | ``` 79 | 80 | ```java 81 | patien.giveFluShot(); 82 | ``` 83 | 84 | ```java 85 | Vaccine vaccine = vaccines.standardAdultFluDose(); 86 | nurse.administerFluVaccine(patient, vaccine); 87 | ``` 88 | 89 | 我们可以将DDD的业务价值大致总结为以下几点: 90 | 91 | 1. 你获得了一个非常有用的领域模型 92 | 2. 你的业务得到了更准确的定义和理解 93 | 3. 领域专家可以为软件设计做出贡献 94 | 4. 更好的用户体验 95 | 5. 清晰的模型边界 96 | 6. 更好的企业架构 97 | 7. 敏捷、迭代式和持续建模 98 | 8. 使用战略和战术新工具 99 | 100 | ## 将关注点放在核心域上 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /C类/C06-Web安全/RSA原理.md: -------------------------------------------------------------------------------- 1 | RSA 是一种非对称的签名算法,即签名密钥(私钥)与验签密钥(公钥)是不一样的,私钥用于签名,公钥用于验签。 其原理如下: 2 | 3 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2023/image-20230511140521053.png) 4 | 5 | > 上图译自[RSA Data Security Digital Signature Process](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc962021(v%3dtechnet.10)#rsa-data-security-digital-signature-process) 6 | 7 | 排列组合是指的生成签名原串的过程。 8 | 9 | **校验规则**: 当接收方的期待串与签名原串一致时, 校验成功;否则校验失败。 -------------------------------------------------------------------------------- /C类/C07-SaaS/SaaS架构设计.md: -------------------------------------------------------------------------------- 1 | > 参考资料:[《互联网时代的软件革命·SaaS架构设计》](https://book.douban.com/subject/3290016/) 2 | 3 | # 篇幅结构 4 | 5 | 第1篇 SaaS 商业模式 6 | 7 | - 第1章 SaaS 的前世今生 8 | 9 | 第2篇 SaaS 应用架构 10 | 11 | - 第2章 SaaS 成熟度模型 12 | - 第3章 构建 Multi-Tenant 应用 13 | - 第4章 高性能的 Multi-Tenant 最佳实践 14 | - 第5章 Multi-Tenant 应用的可配置性 15 | - 第6章 可伸缩的 SaaS 应用架构 16 | - 第7章 SaaS 系统安全 17 | - 第8章 离线应用 18 | 19 | 第3篇 SaaS 基础架构——云计算 20 | 21 | - 第9章 分布式文件存储 22 | - 第10章 分布式数据库 23 | - 第11章 分布式 Cache 24 | - 第12章 分布式计算 25 | 26 | 第4篇 开放的 SaaS 平台 27 | 28 | - 第13章 不 Open API 29 | - 第14章 开放的 SaaS 平台 30 | - 第15章 结束语 31 | 32 | # 第1章 SaaS 的前世今生 33 | 34 | **什么是 SaaS** 35 | 36 | 从用户的角度看。在计算机诞生初期,计算机就是软件; 37 | 38 | 随着计算机应用水平的提高,软件就是一种产品; 39 | 40 | 随着软件产品功能越来越强大,软件已经成为企业工作中必不可少的产品,用户也需要投入更高的成本以保证软件运行环境的稳定; 41 | 42 | 一些软件开发商看到了商机,提出了一种新的软件应用模式 ASP(Application Service Provider),即应用服务提供商,软件运行所需的人力、物力均由提供商维持,而用户只需使用软件即可。 43 | 44 | ASP 模式就是将软件统一托管到应用服务提供商的服务器中,这时,软件是一种被托管的应用。此时,从用户的角度看,用户更关心软件能提供什么服务。 45 | 46 | ASP 维持了几年之后,就渐渐销声匿迹了。软件开发商在多年的反思和总结基础上喊出了新的口号:软件即服务--SaaS。 47 | 48 | SaaS 将软件看作是一种服务,而不是一种产品。软件的用户是服务的需求者和消费者,而软件的提供者是服务的提供者和生产者。这样,将软件的商业模式从商品供需模式转换为服务供需模式,彻底颠覆了传统软件固有的经营模式。人类社会经过工业社会发展到信息社会,相应的经济活动也从以制造为中心转身以服务为中心,这是社会经济发展的大趋势。 49 | 50 | SaaS 与 ASP 的不同点有哪些呢? 51 | 52 | - 看问题的角度不同 53 | 54 | ASP 是站在软件开发商的角度来看问题的;SaaS 是站在用户的角度看问题的。 55 | 56 | - 关注的目标不同 57 | 58 | ASP 关注的是如何方便用户更容易地使用软件,并降低软件维护成本;SaaS 关注的是软件是否能为用户提供有效的服务,而不是将重点放在提供服务的形式上。 59 | 60 | - SaaS 与 ASP 的联系 61 | 62 | SaaS 软件继承了 ASP 的已有经验,并用新的“软件即服务”的理论指导,发展起来的新型软件商业模式。 63 | 64 | **SaaS 软件的优势** 65 | 66 | 给用户的优势: 67 | 68 | - 拿来即用:无须下载、安装、部署、配置。 69 | - 无须维护:用户无须关心软件维护和升级问题。 70 | - 按需使用:SaaS 软件是可按需使用的服务。 71 | - 随处可用:用户能连上互联网就可以使用 SaaS。 72 | - 风险减少:用户只需要支付一点费用就可以开始使用。 73 | - 成本降低:无须自己维护软件。 74 | - 先天防毒:SaaS 软件商都有专业的安全保障措施。 75 | 76 | 给软件商的优势: 77 | 78 | - 节省销售成本 79 | - 节省维护成本 80 | - 稳健的经营模式 81 | 82 | **SaaS 的缺点及解决办法** 83 | 84 | - 依赖互联网 85 | - 数据安全性 86 | - 数据保密性 87 | 88 | **SaaS 成功案例** 89 | 90 | - Saleforce.com 91 | - Google.com 92 | - Alisoft.com 93 | - Xtools 94 | - SaaSBB 95 | - 伟库网 96 | - 友商网 97 | 98 | 99 | 100 | # 第2章 SaaS 成熟度模型 101 | 102 | **SaaS 的规模效应** 103 | 104 | **SaaS 成熟度模型分级** 105 | 106 | | | 可配置 | 高性能 | 可伸缩 | 107 | | ------ | ------ | ------ | ------ | 108 | | Level1 | x | x | x | 109 | | Level2 | v | x | x | 110 | | Level3 | v | v | x | 111 | | Level4 | v | v | v | 112 | 113 | Level1:定制开发 114 | 115 | Level2:可配置 116 | 117 | Level3:高性能的多租户架构 118 | 119 | Level4:可伸缩性的多租户架构 120 | 121 | **如何选择合适的 SaaS 成熟度模型** 122 | 123 | 需要考虑的因素有: 124 | 125 | - 产品所面向的客户群的特征与需求 126 | - 产品的租户数量级别 127 | - 团队的开发能力与愿意付出的开发/改造成本 128 | 129 | **SaaS 软件的成熟度模型的渐进步骤** 130 | 131 | 可按照如下的步骤来逐步增加成熟度: 132 | 133 | - 实现多租户架构 134 | - 实现多租户架构下的高性能 135 | - 实现可配置 136 | - 实现伸缩性 137 | 138 | # 第3章 构建 Multi-Tenant 应用 139 | 140 | **第一阶段:做项目** 141 | 142 | - 场景视图 143 | 144 | 作为老板,我希望了解客户的增长和流失数量以及趋势; 145 | 146 | 作为员工,我希望保留我的客户资料随时查阅,并且通过邮件、IM、IP 电话快速与客户交谈; 147 | 148 | 作为员工,我希望以日历的方式提醒我当天和未来的商务行程; 149 | 150 | - 逻辑视图 151 | 152 | 模块划分与依赖关系:客户模块、行程模块、订单模块、报表模块。 153 | 154 | - 开发视图 155 | 156 | 开发环境、技术框架、分层策略、目录结构。 157 | 158 | - 过程视图 159 | 160 | 当前的系统暂无并发或同步等问题,所以将过程视图忽略。 161 | 162 | - 物理视图 163 | 164 | 系统部署时将 Web 服务器、应用服务器和 DB 服务器分离,以保证业务繁忙时快速的响应性能。 165 | 166 | **第二阶段:做产品** 167 | 168 | 梅超风公司有自己的业务员,她希望业务员之间的客户资料保密,业务 员只看到自己的客户。 169 | 170 | 可配置化: 171 | 172 | - MDA 模型驱动架构 173 | - MDA 四层模型 174 | 175 | **第三阶段:多租户** 176 | 177 | 多租户数据隔离级别: 178 | 179 | - 独立数据库 180 | - 共享数据库,隔离数据架构 181 | - 共享数据库,共享数据架构 182 | 183 | SaaS 多租户设计: 184 | 185 | - 租户管理 186 | - 数据隔离 187 | 188 | # 第4章 高性能的 Multi-Tenant 最佳实践 189 | 190 | **数据库层性能优化** 191 | 192 | - 建立合适的索引 193 | - 消除大数据表连接 194 | - 避免复杂 SQL 195 | 196 | **应用层性能优化** 197 | 198 | - Cache 199 | - 异步操作 200 | 201 | **Web 层性能优化** 202 | 203 | 分析并找出了以下几个原因: 204 | 205 | - 页面过大 206 | - 图片过多 207 | - iframe 过多 208 | - Cookie 过大 209 | 210 | **优化的效果** 211 | 212 | 即使在已经达到 1000 个用户的情况下,应用服务器和数据库服务器负载都稳定在 20% 左右,,对支撑 2000 个用户的目标应该是没有什么大问题了。 213 | 214 | # 第5章 Multi-Tenant 应用的可配置性 215 | 216 | **数据可配置** 217 | 218 | - 定制字段 219 | - 预分配字段 220 | - 名称值对 221 | 222 | **功能可配置** 223 | 224 | - 原子功能划分 225 | 226 | **界面可配置** 227 | 228 | - 系统菜单可配置 229 | - 页面元素可配置 230 | 231 | **流程可配置** 232 | 233 | 租户之间的流程是隔离的。 234 | 235 | **配置元数据管理** 236 | 237 | - 配置元数据 238 | - 租户配置数据 239 | - 配置元数据服务 240 | 241 | **可配置系统运行** 242 | 243 | 244 | 245 | 246 | 247 | SaaS 248 | 249 | SaaS 250 | 251 | SaaS 252 | 253 | SaaS 254 | 255 | SaaS 256 | 257 | SaaS 258 | 259 | SaaS 260 | 261 | SaaS 262 | 263 | 264 | 265 | -------------------------------------------------------------------------------- /C类/README.md: -------------------------------------------------------------------------------- 1 | # 架构类 2 | 3 | 架构类:架构设计 4 | -------------------------------------------------------------------------------- /C类/sidebar.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | - **高并发系统设计** 4 | - [高并发系统设计-基础篇](C类/C01-高并发系统设计/[极客时间]-高并发系统设计-01基础篇.md) 5 | - [高并发系统设计-数据库篇](C类/C01-高并发系统设计/[极客时间]-高并发系统设计-02数据库篇.md) 6 | - [高并发系统设计-缓存篇](C类/C01-高并发系统设计/[极客时间]-高并发系统设计-03缓存篇.md) 7 | - [高并发架构](C类/C01-高并发系统设计/[advanced-java]-高并发架构.md) 8 | 9 | - **微服务** 10 | - [从0开始学微服务](C类/C02-微服务/[极客时间]-从0开始学微服务.md) 11 | - [微服务安全架构与实践](C类/C02-微服务/[极客时间]-01微服务安全架构与实践.md) 12 | - [构建OAuth2服务器](C类/C02-微服务/[极客时间]-08构建OAuth2服务器.md) 13 | - [美团Shepherd设计与实现](C类/C02-微服务/[美团]Shepherd设计与实现.md) 14 | - [SpringBoot与Kubernetes云原生微服务实践](C类/C02-微服务/[极客时间]-SpringBoot与Kubernetes云原生微服务实践.md) 15 | 16 | - **架构设计** 17 | - [从0开始学架构-01架构基础](C类/C03-架构设计/[极客时间]-从0开始学架构-01架构基础.md) 18 | - [从0开始学架构-02高性能架构模式](C类/C03-架构设计/[极客时间]-从0开始学架构-02高性能架构模式.md) 19 | - [从0开始学架构-03高可用架构模式](C类/C03-架构设计/[极客时间]-从0开始学架构-03高可用架构模式.md) 20 | - [从0开始学架构-04可扩展架构模式](C类/C03-架构设计/[极客时间]-从0开始学架构-04可扩展架构模式.md) 21 | - [从0开始学架构-05架构实战](C类/C03-架构设计/[极客时间]-从0开始学架构-05架构实战.md) 22 | - [架构实战案例解析-01业务架构篇](C类/C03-架构设计/[极客时间]-架构实战案例解析-01业务架构篇.md) 23 | - [架构实战案例解析-02技术架构篇](C类/C03-架构设计/[极客时间]-架构实战案例解析-02技术架构篇.md) 24 | - [高可用架构](C类/C03-架构设计/[advanced-java]-高可用架构.md) 25 | - [郭东白的架构课](C类/C03-架构设计/[极客时间]-郭东白的架构课.md) 26 | - [企业级高可用延时消息设计](C类/C03-架构设计/企业级高可用延时消息设计.md) 27 | 28 | - **分布式** 29 | - [分布式-理论篇](C类/C04-分布式/分布式-01理论篇.md) 30 | - [分布式-协议和算法篇](C类/C04-分布式/分布式-02协议和算法篇.md) 31 | - [分布式系统](C类/C04-分布式/[advanced-java]-分布式系统.md) 32 | 33 | - **DDD** 34 | - [DDD实战课-基础篇](C类/C05-DDD/[极客时间]-DDD实战课-01基础篇.md) 35 | - [DDD实战课-进阶篇](C类/C05-DDD/[极客时间]-DDD实战课-02进阶篇.md) 36 | - [DDD实战课-实战篇](C类/C05-DDD/[极客时间]-DDD实战课-03实战篇.md) 37 | 38 | - **Web安全** 39 | - [OAuth2实战-基础篇](C类/C06-Web安全/[极客时间]-OAuth2实战-基础篇.md) 40 | 41 | - **SaaS** 42 | - [SaaS架构设计](C类/C07-SaaS/SaaS架构设计.md) 43 | 44 | - **高性能系统设计** 45 | - [如何设计一个秒杀系统](C类/C08-高性能系统设计/如何设计一个秒杀系统.md) 46 | 47 | - **数据存储** 48 | - [后端存储实战-01创业篇](C类/C09-数据存储/后端存储实战-01创业篇.md) 49 | - [后端存储实战-02高速增长篇](C类/C09-数据存储/后端存储实战-02高速增长篇.md) 50 | - [后端存储实战-03海量数据篇](C类/C09-数据存储/后端存储实战-03海量数据篇.md) 51 | -------------------------------------------------------------------------------- /D类/D03-软件工程/[极客时间]-如何提高研发效率?.md: -------------------------------------------------------------------------------- 1 | 模块二:研发流程 2 | 3 | # 04 | 流程优化:怎样才能让敏捷、精益真正为我所用? 4 | 5 | **如何实践方法论?** 6 | 7 | Facebook、Google 这些公司并没有明确提及敏捷、精益、看板这些方法论,或者没有严格地去使用 Scrum 等框架,但在开发流程中却实实在在地应用了这些方法论的精髓。所以说,方法论实施效果不好,关键在于没用好。 8 | 9 | 在学习方法论的时候,推荐使用类似美国著名作家、企业顾问西蒙斯 · 涅克(Simon Sinek)总结的 Why-How-What 黄金圈法则。参见下图:最中间的一个圆是 Why,也就是这个方法论的目标,是要解决一个什么问题;第二个圆是 How,也就是这个方法论的基本原则、指导思想;最外层的圆是 What,也就是这个方法论的具体实践。 10 | 11 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120094712.png) 12 | 13 | 接下来,来看一组提高研发流程的目标。 14 | 15 | **目标一:寻找用户价值** 16 | 17 | 第一条原则是:衡量每一个时间段成果的标准,应该是价值假设方面的进展。也就是说,你的工作应该让你学习到如何更好地给用户提供价值,而不是开发了多少功能。 18 | 19 | 第二条原则是:使用最小可行性产品(Minium Viable Product,MVP)来帮助学习。这里的关键点是,要以探索价值为出发点设计产品,最快地验证你的假设,功能要尽量少,能够使用就可以。具体的方法有数据驱动、A/B 测试、灰度发布等。 20 | 21 | 度量驱动开发(Metrics Driven Development)。如果你想深入了解这种开发方式,可以参考 Uber 公司的这篇[文章](https://eng.uber.com/experimentation-platform/)。 22 | 23 | **目标二:提高用户价值的流动效率** 24 | 25 | 软件研发是一条流水线,里面流动的是一个一个给用户提供价值的功能。那怎么提高这条流水线的效率呢? 26 | 27 | 这里有 4 条比较直观的基本原则: 28 | 29 | - 第一,让功能尽快地流动; 30 | 31 | 开发人员需要尽量把功能拆分,同时做好一个提交之后尽快提交。要做到这一点,关键原则是降低提交的交易成本(Transaction Cost)。 32 | 33 | - 第二,让节点之间的联动更加顺畅; 34 | 35 | 在具体实践上,个人代码上线后,在和他人的代码集成时容易出现问题,这时就可以使用 CI/CD(持续集成 / 持续交付)流水线来自动化代码集成过程。 36 | 37 | - 第三,节点之间的融合; 38 | 39 | 职能团队提供平台和工具,让全栈工程师能够自己处理端到端的工作。比如,测试团队提供测试平台和工具,运维团队提供运维平台和工具,这些平台和工具可以通过服务化自助使用。 40 | 41 | - 第四,发现整个流程中的瓶颈,并解决它们。 42 | 43 | **具体的实践有可视化和复盘** 44 | 45 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120094723.png) 46 | 47 | 通过任务可视化,我们可以直观地看到哪一个环节的任务特别多,卡住了,也就是瓶颈在哪儿。 48 | 49 | 在复盘方面,每个团队也会不定期地复盘,以定位瓶颈问题并提高。 50 | 51 | 52 | -------------------------------------------------------------------------------- /D类/D03-软件工程/[极客时间]-持续交付.md: -------------------------------------------------------------------------------- 1 | 持续交付36讲 2 | 3 | > 王潇俊 4 | 5 | # 01 | 持续交付到底有什么价值? 6 | 7 | **持续交付的定义** 8 | 9 | 持续交付是软件研发人员,如何将一个好点子,以最快的速度交付给用户的方法。*--《持续交付:发布可靠软件的系统方法》*。听起来有点抽象,我们可以把“持续交付”定义为“一套软件工程方法论和许许多多的最佳实践的集合”。 10 | 11 | **持续集成、持续交付和持续部署的关系** 12 | 13 | 持续集成:我们通常会把软件研发工作拆解,拆分成不同模块或不同团队后进行编码,编码完成后,进行集成构建和测试。这个从编码到构建再到测试的反复持续过程,就叫作“持续集成”。
持续交付:这个在“持续集成“之后,获取外部对软件的反馈再通过”持续集成“进行优化的过程就叫作”持续交付“,它是”持续集成“的自然延续。
持续部署:持续部署就是将可交付产品,快速且安全地交付给用户使用的一套方法和系统,它是”持续交付“的最后”一公里“。 14 | 15 | **持续交付的显性价值** 16 | 17 | 通常我们在实施持续交付后,都能够做到在保证交付质量的前提下,加快交付速度,从而更快地得到市场反馈,引领产品的方向,最终达到扩大收益的目的。 18 | 19 | **持续交付的隐性价值** 20 | 21 | CTO角度:1.技术选型的问题;2.已制定的标准难以落地;3.如何提高跨部门协作的效率;4.担心”黑天鹅“降临。
Team Leader角度:1.希望团队的知识能够传承;2.希望团队专注于业务而非工程;3.希望以一个较平稳的节奏持续工作。
产品经理角度:1.产品真正的第一个用户;2.完全知悉当前的进度和质量;3.产品应该随时能发布。
程序员角度:1.通过对持续交付的学习,进一步加强自己对整个软件工程的认识;2.利用持续交付的工具或最佳实践,提高自己的工作效率和质量; 22 | 23 | **如何评估持续交付的价值** 24 | 25 | 编译速度,发布速度,回滚速度,自动化测试速度等等 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /D类/D04-职业规划/202009月知识梳理计划.md: -------------------------------------------------------------------------------- 1 | # 第1部分 高并发架构(9.28/29/30/1/2) 2 | 3 | - [x] 1.1 消息队列 4 | - [x] 1.2 搜索引擎 5 | - [x] 1.3 缓存 6 | - [x] 1.4 分库分表 7 | - [ ] 1.5 读写分离 8 | - [ ] 1.6 高并发系统 9 | 10 | # 第2部分 分布式系统(10.3) 11 | 12 | - [ ] 2.1 系统拆分 13 | - [ ] 2.2 分布式服务框架 14 | - [ ] 2.3 分布式锁 15 | - [ ] 2.4 分布式事务 16 | - [ ] 2.5 分布式会话 17 | 18 | # 第3部分 高可用架构(10.4) 19 | 20 | - [ ] 3.1 基于Hystrix实现高可用 21 | - [ ] 3.2 高可用系统 22 | - [ ] 3.3 限流 23 | - [ ] 3.4 熔断 24 | - [ ] 3.5 降级 25 | 26 | # 第4部分 微服务架构(10.5) 27 | 28 | - [ ] 4.1 微服务的一些概念 29 | - [ ] 4.2 Spring Cloud 微服务架构 30 | 31 | # 第5部分 海量数据处理 32 | 33 | 10.6日:5.1,5.2,5.3,5.4,5.5 34 | 10.7日:5.6,5.7,5.8,5.9,5.10 35 | 36 | - [ ] 5.1 如何从大量的URL中找出相同的URL? 37 | - [ ] 5.2 如何从大量数据中找出高频词? 38 | - [ ] 5.3 如何找出某一天访问百度网站最多的 IP ? 39 | - [ ] 5.4 如何在大量的数据中找出不重复的整数? 40 | - [ ] 5.5 如何在大量数据中判断一个数是否存在? 41 | - [ ] 5.6 如何查询最热门的查询串? 42 | - [ ] 5.7 如何统计不同电话号码的个数? 43 | - [ ] 5.8 如何从5亿个数中找出中位数? 44 | - [ ] 5.9 如何按照query的频度排序? 45 | - [ ] 5.10 如何找出排名前500的数? 46 | 47 | # 第6部分 基础类(10.8) 48 | 49 | # 第7部分 进阶类(10.9) 50 | 51 | # 第8部分 架构类(10.10) 52 | 53 | # 第9部分 项目问题梳理(10.11) 54 | 55 | 主要是卷宗;少量See项目; 56 | 57 | # 第10部分 实践 58 | 59 | - [ ] 手写一个 Redis -------------------------------------------------------------------------------- /D类/D04-职业规划/202010月面试计划.md: -------------------------------------------------------------------------------- 1 | # 01 | 梳理卷宗项目架构(10.9) 2 | 3 | - [x] 文档梳理 4 | - [x] 简历补充 5 | 6 | 分表后 join 操作怎么进行? 7 | 8 | # 02 | 梳理基础知识(10.10) 9 | 10 | - [ ] 简历投递 11 | - [ ] 收藏的技术文章 12 | - [ ] Java并发编程 13 | - [ ] Java虚拟机 14 | - [ ] MySQL 15 | - [ ] 网络协议 16 | - [ ] 数据结构与算法 17 | 18 | 进阶知识 19 | 20 | - [ ] ZooKeeper 21 | 22 | # 03 | 梳理进阶知识(10.11) 23 | 24 | - [ ] 简历投递 25 | - [ ] RPC 26 | - [ ] 消息队列 27 | - [ ] Redis 28 | - [x] Spring 29 | - [ ] Tomcat 30 | - [ ] 设计模式 31 | 32 | # 04 | 梳理进阶知识(10.12) 33 | 34 | - [ ] 简历投递 35 | - [ ] MyBatis 36 | - [ ] 性能调优 37 | - [ ] Spring Cloud 38 | - [ ] Elasticsearch 39 | 40 | # 05 | 梳理架构知识(10.13) 41 | 42 | - [ ] 简历投递 43 | - [ ] 高并发架构 44 | - [ ] 分布式系统 45 | 46 | # 06 | 梳理架构知识(10.14) 47 | 48 | - [ ] 简历投递 49 | - [ ] 高可用架构 50 | - [ ] 微服务架构 51 | 52 | # 07 | 梳理架构知识(10.15) 53 | 54 | - [ ] 简历投递 55 | - [x] 海量数据处理问题 56 | 57 | # 08 | 思考篇 58 | 59 | -------------------------------------------------------------------------------- /D类/D04-职业规划/职场求生攻略-01职业素养篇.md: -------------------------------------------------------------------------------- 1 | > 来自极客时间《职场求生攻略》--臧萌 2 | 3 | # 开篇词 | 学会如何工作,和学习技术同等重要 4 | 5 | 很多人这么迷茫,是因为陷入了“技术之外,别的不重要”的误区。职场上,我们要知道如何工作。这不仅仅包括技术方面的事情,也包括如何与同事协作、如何与上司沟通、如何正确地使用邮件等等一系列需要与同事打交道并付诸实施的事情。 6 | 7 | 经过我这么多年的工作经验,我发现这些事情虽然琐碎,但其实可以大致分为 4 类,它们分别是职业素养、职业选择、生存发展和技术成长。这也是专栏的模块划分。 8 | 9 | - 职业素养篇中,我们将会讨论如何培养良好的工作习惯。这些习惯很容易影响我们的工作效率和与同事之间的关系。比如,邮件的背后有什么样的工作逻辑?再比如,来自领导和部门的任务那么多,我们要如何根据任务的性质划分出它们的重要性? 10 | - 职业选择篇中,我们将会探讨工作选择,以及与领导之间的关系。如何选择和自己“聊得来”的领导?他们都有怎样的特质?在此基础上,如何选择心仪的公司?你是更适合创业公司还是更适合成熟的大公司呢? 11 | - 职场情商篇中,我们会探讨一个比较敏感的话题,那就是职场政治。我们都说,有人的地方就有江湖,相信不少人都会对同事关系感到头疼。比如最常见的,为啥领导更喜欢他?工作能力也许是一个原因,但绝不是唯一的原因,在这背后,个人的输出、看问题的方式和立场、工作的方式也同样重要。 12 | - 技术成长篇中,是跟技术相关的一系列话题。在提升技术能力的道路上,我们需要注意哪些坑?技术是一种手段,也是一种观念,技术观为何如此重要?它能指导我们什么? 13 | 14 | **我是如何在文章中讲述这些内容的?** 15 | 16 | 问题已经摆出来了,那么如何带着你将每个问题都想透彻呢?我的做法是,以利益为视角,以换位思考为手段,以现实例子为场景来给你讲。 17 | 18 | 这套思考问题的方式,换在任何问题上,都是完全适用的。 19 | 20 | ![image-20250602225246085](https://technotes.oss-cn-shenzhen.aliyuncs.com/2024/202506022253737.png) 21 | 22 | - 以利益为视角 23 | 24 | 当我们想要理解工作中的各种问题和各种事情的时候,不妨坦诚地从“利益”这个视角思考,弄清事情背后的“原动力”。除了看得见摸得着的金钱,我们可以从工作中获取的“钱”还有很多,比如升职、学习、实战的积累、好的成长机会、可以复用的资源、公司内外的声誉等等。 25 | 26 | 可以说,利益贯穿了工作中的每个关键环节,是推动工作中几乎所有事情的原动力。这样想的话,很多时候事情的走向就会简单、明晰很多。 27 | 28 | - 换位思考为手段 29 | 30 | 换位思考是一种很重要的能力,很多事情之所以不能理解,甚至看上去匪夷所思,其实就是因为我们没有把自己的屁股坐在在对方的板凳上,站在对方的利益考虑问题。 31 | 32 | 换位思考到底对我有啥好处呢?我觉得最直接的一点就是,换位思考可以帮助我们自己更高效地工作,因为它能有效地帮我们避免一些麻烦,在做事情之前预知随之而来的后果。 33 | 34 | - 现实的场景为例子 35 | 36 | 咱们课程中的问题,其实原本就是现实工作中的,所以我在讲述的时候,基本都是把这些真实的场景直接给你给放进来。 37 | 38 | 在我开始讲之前,你可以去想想,如果你遇到了这个问题,你是怎么想的,你会怎么解决。然后,再看看我的做法,是不是和你的一样。这样对比的过程,你慢慢就能明白,我们的思考问题的方式,有啥不一样。 39 | 40 | 我一直坚信,学会如何工作,和学习具体的技术是同等重要的。我一直觉得,在职场中,我们每一步的经历都是有用的,我们在职场中遇到的每一个问题都不小。正是这一点一滴,才构成了我们的职场生活。 41 | 42 | # ==职业素养篇== 43 | 44 | # 01丨优先级:工作中那么多事情,我要如何安排优先级? 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /D类/D04-职业规划/职场求生攻略-03职场情商篇.md: -------------------------------------------------------------------------------- 1 | > 来自极客时间《职场求生攻略》--臧萌 2 | 3 | # ==职场情商篇== 4 | 5 | # 17 | 升职:看着周围的人都升职了,我什么时候才能升职? 6 | 7 | 8 | 9 | # 18 | 职场政治:我只想好好干活,职场政治和我有什么关系? 10 | 11 | 这篇文章的目的就是为了能让你理解职场政治的必要性,理解职场政治的基本要素——站队。 12 | 13 | **为什么我说一定会有职场政治?** 14 | 15 | 也许你也曾经天真如我,觉得自己全凭勤劳和真本事吃饭,觉得公司全靠和自己一样的写代码的人来养活。以至于像我这样想了太久,在公司里感觉腰杆子比铝合金电线杆子都硬气了。如果你是这样的人,那么我建议你仔细品品我下面说的这个故事。 16 | 17 | - 人少总是小而美 18 | 19 | 这是一个电商网站的故事。一开始,有一个“草台班子”,只有创始人单干,卖定制化小商品,比如 T 恤、杯子等等。所有的事情,包括产品研发、产品代工生产、进货、库存、编写电商商城代码、服务器维护、发货、售后、营销等等都是创始人一个人来包办。 20 | 21 | 后来商品卖得很不错,订单量越来越大。创始人又招了三个人,一个人负责生产,一个人负责营销,一个人负责售后。程序员太贵招不起,所以创始人自己继续负责商城的开发和服务器维护等,同时总管新来的三个人。 22 | 23 | > 这时候,其实问题已经来了。之前只有创始人一个人,赚多少都是自己的。现在有了三个手下,虽然他们现在还不管人,只是拿工资。但是年底奖金怎么分?加薪怎么给?谁多谁少?这些问题就开始接二连三地蹦出来了。 24 | 25 | 故事讲到到这里,你能够明显看出,公司从一个人发展到非常扁平的两层结构。公司规模不大,每个人为公司做的贡献和每个人的工作失误造成的损失都非常明显。这时候要做到奖惩分明,并不是特别难。 26 | 27 | - 人多就会有“江湖” 28 | 29 | 公司进一步往下发展的话,之前做产品的部分就会变成产品部和库管部,分别各有十几号人。营销部和售后部也都成立了,也都是好几个人的规模。同时,公司也终于有了商城研发组。创始人终于可以专心地管理公司了。 30 | 31 | 这时候,公司变成了三层结构,公司的人也越来越多,想做到奖惩分明已经非常难了。 32 | 33 | 比如说,产品是直接面向用户的,所以产品设计做得不好的话,对销量会有直接的影响。这时产品的销量有多少是要归在产品设计上,又有多少要归在营销上呢?营销需要经费,那么接下来的营销经费,是应该增加还是减少呢?售后不是利润部门,有多少客人是因为售后不好而流失的,又有多少新客是因为优质的售后才获得的增长呢?因为售后原因增加的客户和营销带来的新客户,又应该如何区分?这些问题的出现,让公司很难做到奖惩分明。 34 | 35 | 更不用说,公司除了奖惩分明之外,还有更高级更复杂的利益。比如大到某个部门的存留,小到某个项目是继续还是取消。举个例子,库管部负责商品进库、发货、清点等工作。这个工作并不是公司的核心竞争力,而且随着公司规模的扩大,可能交由更专业的公司来负责会更好。这时候,这个部门留是不留?这个部门的老大怎么证明自己部门的价值?是更安全、更快速、还是更省钱? 36 | 37 | 所有这些大大小小的事情背后,都是赤裸裸的利益。没有这些,你可能都没机会干活,没机会赚辛苦钱,也没机会升职加薪。如果不是商城部门的老大能搞定关系,给出各种让人信服的数据,背上各个方面给的 KPI,这个部门可能就被取代,下面的程序员可能就散了。如果不是老大能做出正确的决策,展示出让公司满意信服的成果,整个部门的加薪升职可能都要缩水。 38 | 39 | 而这整个过程,都是政治的运作。 40 | 41 | **一般公司里的那些职场政治** 42 | 43 | 44 | 45 | - 为啥要改组? 46 | 47 | 48 | 49 | - 不改组行不行? 50 | 51 | 52 | 53 | - 用谁的系统? 54 | 55 | 56 | 57 | **面对职场政治,程序员应该做什么?** 58 | 59 | 60 | 61 | - 尊重职场政治 62 | 63 | 64 | 65 | - 懂得组织的利益所在 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /D类/D04-职业规划/职场求生攻略-04技术成长篇.md: -------------------------------------------------------------------------------- 1 | > 来自极客时间《职场求生攻略》--臧萌 2 | 3 | # ==技术成长篇== 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /D类/D05-面试/JavaGuide-数据库.md: -------------------------------------------------------------------------------- 1 | > 来源:https://javaguide.cn/home.html 2 | 3 | # 01 | 基础 4 | 5 | # 02 | MySQL 6 | 7 | ## 2.1 MySQL 基础 8 | 9 | **MySQL 基础架构** 10 | 11 | ![img](https://technotes.oss-cn-shenzhen.aliyuncs.com/2022/202210140702245.png) 12 | 13 | 从上图可以看出, MySQL 主要由下面几部分构成: 14 | 15 | - **连接器:** 身份认证和权限相关(登录 MySQL 的时候)。 16 | - **查询缓存:** 执行查询语句的时候,会先查询缓存(MySQL 8.0 版本后移除,因为这个功能不太实用)。 17 | - **分析器:** 没有命中缓存的话,SQL 语句就会经过分析器,分析器说白了就是要先看你的 SQL 语句要干嘛,再检查你的 SQL 语句语法是否正确。 18 | - **优化器:** 按照 MySQL 认为最优的方案去执行。 19 | - **执行器:** 执行语句,然后从存储引擎返回数据。 执行语句之前会先判断是否有权限,如果没有权限的话,就会报错。 20 | - **插件式存储引擎** : 主要负责数据的存储和读取,采用的是插件式架构,支持 InnoDB、MyISAM、Memory 等多种存储引擎。 21 | 22 | ## 2.2 MySQL 存储引擎 23 | 24 | **MySQL 支持哪些存储引擎?默认使用哪个?** 25 | 26 | MySQL 支持多种存储引擎,你可以通过 `show engines` 命令来查看 MySQL 支持的所有存储引擎。 27 | 28 | ![查看 MySQL 提供的所有存储引擎](https://technotes.oss-cn-shenzhen.aliyuncs.com/2022/202210140704273.png) 29 | 30 | 从上图我们可以查看出, MySQL 当前默认的存储引擎是 InnoDB。并且,所有的存储引擎中只有 InnoDB 是事务性存储引擎,也就是说只有 InnoDB 支持事务。 31 | 32 | > 我这里使用的 MySQL 版本是 8.x,不同的 MySQL 版本之间可能会有差别。 33 | 34 | 35 | 36 | 37 | 38 | # 03 | Redis 39 | 40 | ## 3.1 Redis 基础 41 | 42 | **Redis 为什么这么快?** 43 | 44 | Redis 内部做了非常多的性能优化,比较重要的主要有下面 3 点: 45 | 46 | - Redis 基于内存,内存的访问速度是磁盘的上千倍; 47 | - Redis 基于 Reactor 模式设计开发了一套高效的事件处理模型,主要是单线程事件循环和 IO 多路复用(Redis 线程模式后面会详细介绍到); 48 | - Redis 内置了多种优化过后的数据结构实现,性能非常高。 49 | 50 | ![why-redis-so-fast](https://technotes.oss-cn-shenzhen.aliyuncs.com/2022/202210132139664.png) 51 | 52 | ## 3.2 Redis 数据结构 53 | 54 | 55 | 56 | **使用 Set 实现抽奖系统需要用到什么命令?** 57 | 58 | - `SPOP key count` : 随机移除并获取指定集合中一个或多个元素,适合不允许重复中奖的场景。 59 | - `SRANDMEMBER key count` : 随机获取指定集合中指定数量的元素,适合允许重复中奖的场景。 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | ## 3.3 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /D类/D05-面试/technotes-数据库.md: -------------------------------------------------------------------------------- 1 | # 01 | MySQL 2 | 3 | # 02 | Redis 4 | 5 | ## 2.1 基础篇 6 | 7 | **1. 手写一个键值库需要有哪些模块?** 8 | 9 | 一个键值数据库包括了访问框架、操作模块、索引模块和存储模块四部分。 10 | 11 | image-20220214212224815 12 | 13 | - 访问框架:以 Socket 通信的形式对外提供键值对操作; 14 | - 操作模块:可以对数据做什么操作? 15 | - 索引模块:如何定位键值对的位置? 16 | - 存储模块:可以存哪些数据? 17 | 18 | **2. Redis 总体包含哪些模块?** 19 | 20 | image-20220214214942389 21 | 22 | **3. Redis 底层数据结构有哪些?** 23 | 24 | Redis 底层数据结构一共有 6 种,分别是简单动态字符串、整数数组、双向链表、哈希表、压缩列表和跳表。它们和数据类型的对应关系如下图所示: 25 | 26 | image-20220217220143729 27 | 28 | - 压缩列表 29 | 30 | 压缩列表实际上类似于一个数组,数组中的每一个元素都对应保存一个数据。和数组不同的是,压缩列表在表头有三个字段 zlbytes、zltail 和 zllen,分别表示列表长度、列表尾的偏移量和列表中的 entry 个数;压缩列表在表尾还有一个 zlend,表示列表结束。 31 | 32 | image-20220221211852113 33 | 34 | 在压缩列表中,如果我们要查找定位第一个元素和最后一个元素,可以通过表头三个字段的长度直接定位,复杂度是 O(1)。而查找其他元素时,就没有这么高效了,只能逐个查找,此时的复杂度就是 O(N) 了。 35 | 36 | - 跳表 37 | 38 | 跳表在链表的基础上,增加了多级索引,通过索引位置的几个跳转,实现数据的快速定位,如下图所示: 39 | 40 | image-20220221210646026 41 | 42 | 当数据量很大时,跳表的查找复杂度就是 O(logN)。 43 | 44 | **4. 谈谈 Redis 渐进式 rehash** 45 | 46 | Redis 默认使用了两个全局哈希表:哈希表 1 和哈希表 2。一开始,当你刚插入数据时,默认使用哈希表 1,此时的哈希表 2 并没有被分配空间。随着数据逐步增多,Redis 开始执行 rehash,这个过程分为三步: 47 | 48 | 1. 给哈希表 2 分配更大的空间,例如是当前哈希表 1 大小的两倍; 49 | 2. 把哈希表 1 中的数据重新映射并拷贝到哈希表 2 中; 50 | 3. 释放哈希表 1 的空间,留作下一次 rehash 扩容备用。 51 | 52 | 渐进式 rehash 简单来说就是在第二步拷贝数据时,Redis 仍然正常处理客户端请求,每处理一个请求时,从哈希表 1 中的第一个索引位置开始,顺带着将这个索引位置上的所有 entries 拷贝到哈希表 2 中;等处理下一个请求时,再顺带拷贝哈希表 1 中的下一个索引位置的 entries。如下图所示: 53 | 54 | image-20220217214803853 55 | 56 | **5. 单线程 Redis 为什么那么快?** 57 | 58 | 第一,Redis 的大部分操作在内存上完成; 59 | 60 | 第二,Redis 采用了高效的数据结构,例如哈希表和跳表; 61 | 62 | 第三,Redis 采用了多路复用机制,使其在网络 IO 操作中能并发处理大量的客户端请求,实现高吞吐率。 63 | 64 | **6. 谈谈 Redis 的 IO 多路复用模型** 65 | 66 | Linux 中的 IO 多路复用机制是指一个线程处理多个 IO 流,就是我们经常听到的 select/epoll 机制。下图就是基于多路复用的 Redis IO 模型。Redis 网络框架调用 epoll 机制,让内核监听这些套接字。 67 | 68 | image-20220223221150517 69 | 70 | 为了在请求到达时能通知到 Redis 线程,select/epoll 提供了基于事件的回调机制,即针对不同事件的发生,调用相应的处理函数。这些事件会被放进一个事件队列,Redis 单线程对该事件队列不断进行处理。 71 | 72 | 以连接请求和读数据请求为例。这两个请求分别对应 Accept 事件和 Read 事件,Redis 分别对这两个事件注册 accept 和 get 回调函数。当 Linux 内核监听到有连接请求或读数据请求时,就会触发 Accept 事件和 Read 事件,此时,内核就会回调 Redis 相应的 accept 和 get 函数进行处理。 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /D类/D05-面试/后端技术基础详解-01软件基础原理.md: -------------------------------------------------------------------------------- 1 | # 开篇词 | 掌握软件开发技术的第一性原理 2 | 3 | **第一性原理——建立技术体系的起点** 4 | 5 | 物理学有一个第一性原理, 指的是根据一些最基本的物理学常量,从头进行物理学的推导,进而得到整个物理学体系。 6 | 7 | 第一性原理就是让我们抓住事物最本质的特征原理,依据事物本身的规律,去推导、分析、演绎事物的各种变化规律,进而洞悉事物在各种具体场景下的表现形式,而不是追随事物的表面现象,生搬硬套各种所谓的规矩、经验和技巧,以至于在各种纷繁复杂的冲突和纠结中迷失了方向。 8 | 9 | 比如我们的程序是如何被操作系统调度执行的?为什么高并发的时候系统会崩溃,原理是什么?在编程时,什么场合下应该使用链表,什么场合下应该使用数组,为什么?当我们使用 Hash 表的时候,什么情况下它的性能会急剧降低,原理又是什么?我们用 Redis 这样的分布式缓存的时候,到底要解决什么问题?分布式缓存是如何工作的?还有哪些技术看起来和 Redis 毫不相干,其实工作原理是一样的? 10 | 11 | **专栏如何帮你建立技术体系** 12 | 13 | 在这个专栏中,我对自己过去二十年软件编程生涯和业界的技术发展历史进行回顾总结,将软件知识技术体系分成软件的基础原理、软件的设计原理、架构的核心原理三个部分。 14 | 15 | 软件的基础原理主要是操作系统、数据结构、数据库原理等等,我会从一个常见的问题入手,直达这些基础技术最本质的原理,并覆盖这些基础技术的主要关键技术点。 16 | 17 | 在软件的设计原理里,我会讲述如何设计一个强大灵活,易复用,易维护的软件。 18 | 19 | 架构的核心原理围绕目前主要的互联网分布式架构以及大数据物联网架构进行剖析,分析这些架构背后的原理,它们都遵循了怎样的驱动力和设计思想,有哪些看似不同的技术其实原理是一样的,以及如何通过这些技术实现系统的高可用和高性能。 20 | 21 | # 01丨程序运行原理:程序是如何运行又是如何崩溃的? 22 | 23 | **程序是如何运行起来的** 24 | 25 | 软件被开发出来,是文本格式的代码,存储在文件系统中,这些代码被称为程序。 26 | 27 | 要想让程序处理数据,完成计算任务,必须把程序从外部设备加载到内存中,并在操作系统的管理调度下交给 CPU 去执行,去运行起来,才能真正发挥软件的作用,程序运行起来以后,被称作进程。 28 | 29 | 进程除了包含可执行的程序代码,还包括进程在运行期使用的堆内存空间、栈空间、供操作系统管理用的数据结构。如下图所示: 30 | 31 | image-20221116215047846 32 | 33 | **系统为什么会变慢,为什么会崩溃** 34 | 35 | 下面是一个 Java web 应用运行时的主要架构,有时也称作架构过程视图。 36 | 37 | image-20221116215726536 38 | 39 | web 程序都是被多线程执行的,web 开发天然就是多线程开发。既然是多线程,就会有线程安全问题,解决线程安全问题的办法就是加锁,锁会引起线程阻塞,如果有很多线程同时在运行,那么就会出现线程排队等待锁的情况,线程无法并行执行,系统响应速度就会变慢。此外 I/O 操作也会引起阻塞,对数据库连接的获取也可能会引起阻塞。 40 | 41 | 被阻塞的线程越多,占据的系统资源也越多,这些被阻塞的线程既不能继续执行,也不能释放当前已经占据的资源,在系统中一边等待一边消耗资源,如果阻塞的线程数超过了某个系统资源的极限,就会导致系统宕机,应用崩溃。 42 | 43 | > 解决系统因高并发而导致的响应变慢、应用崩溃的主要手段是使用分布式系统架构,用更多的服务器构成一个集群,以便共同处理用户的并发请求,保证每台服务器的并发负载不会太高。 44 | > 45 | > 此外必要时还需要在请求入口处进行限流,减小系统的并发请求数;在应用内进行业务降级,减小线程的资源消耗。 46 | 47 | # 02丨数据结构原理:Hash表的时间复杂度为什么是O(1)? 48 | 49 | 要了解 Hash 表,需要先从数组说起。 50 | 51 | **数组** 52 | 53 | 数组是最常用的数据结构,创建数组必须要内存中一块连续的空间,并且数组中必须存放相同的数据类型。 54 | 55 | 比如我们创建一个长度为 10,数据类型为整型的数组,在内存中的地址是从 1000 开始,那么它在内存中的存储格式如下。 56 | 57 | image-20221117215755351 58 | 59 | 由于每个整型数据占据 4 个字节的内存空间,因此整个数组的内存空间地址是 1000~1039,根据这个,我们就可以轻易算出数组中每个数据的内存下标地址。 60 | 61 | > 比如下标 2,就可以计算得到这个数据在内存中的位置 1008,从而对这个位置的数据 241 进行快速读写访问,时间复杂度为O(1)。 62 | 63 | **链表** 64 | 65 | 不同于数组必须要连续的内存空间,链表可以使用零散的内存空间存储数据。不过,因为链表在内存中的数据不是连续的,所以链表中的每个数据元素都必须包含一个指向下一个数据元素的内存地址指针。 66 | 67 | 如下图,链表的每个元素包含两部分,一部分是数据,一部分是指向下一个元素的地址指针。最后一个元素指向 null,表示链表到此为止。 68 | 69 | ![image-20221117215936562](https://technotes.oss-cn-shenzhen.aliyuncs.com/2022/202211172159597.png) 70 | 71 | **Hash 表** 72 | 73 | 事实上,知道部分数据查找完整数据的需求在软件开发中会经常用到,比如知道了商品ID,想要查找完整的商品信息;知道了词条名称,想要查找百科词条中的详细信息等。 74 | 75 | 这类场景就需要用到 Hash 表这种数据结构。Hash 表中数据以 Key、Value 的方式存储,上面例子中,商品 ID 和词条名称就是 Key,商品信息和词条详细信息就是 Value。存储的时候将 Key、Value 写入 Hash 表,读取的时候,只需要提供 Key,就可以快速查找到Value。 76 | 77 | ![image-20221117220058654](https://technotes.oss-cn-shenzhen.aliyuncs.com/2022/202211172200687.png) 78 | 79 | 上图这个例子中,Key 是字符串 abc,Value 是字符串 hello。我们先计算 Key 的哈希值,得到 101 这样一个整型值。然后用 101 对 8 取模,这个 8 是哈希表数组的长度。101 对 8 取模余 5,这个 5 就是数组的下标,这样就可以把 (“abc”,“hello”) 这样一个 Key、Value 值存储在下标为 5 的数组记录中。 80 | 81 | HashCode101 对 8 取模余数是 5,HashCode109 对 8 取模余数还是 5,也就是说,不同的 Key 有可能计算得到相同的数组下标,这就是所谓的 Hash 冲突,解决 Hash 冲突常用的方法是链表法。 82 | 83 | 如下图: 84 | 85 | image-20221117220237165 86 | 87 | --- 88 | 89 | 这个课程太泛了,想不到侧重点。 -------------------------------------------------------------------------------- /D类/D07-anki/知识转Anki进度.md: -------------------------------------------------------------------------------- 1 | A类 2 | 3 | - [x] Java并发编程 4 | - [x] Java虚拟机 5 | 6 | B类 -------------------------------------------------------------------------------- /D类/D07-anki/项目.apkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/D类/D07-anki/项目.apkg -------------------------------------------------------------------------------- /D类/D08-杂谈/InfoQ公开课.md: -------------------------------------------------------------------------------- 1 | # 微服务构架下的分布式事务解决方案 2 | 3 | > 作者:季敏
阿里中间件分布式事务团队负责人 4 | 5 | ## 微服务构架中的常见痛点分析 6 | 7 | **微服务架构** 8 | 9 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120094800.jpg) 10 | 11 | **微服务开发的痛点** 12 | 13 | ![image-20200802111455248](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120094806.png) 14 | 15 | **微服务构架为什么需要分布式事务** 16 | 17 | ![image-20200802114801456](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120094811.png) 18 | 19 | **微服务构架下的分布式事务解决方案有哪些?** 20 | 21 | 定时任务做数据补尝 22 | 23 | ## 分布式事务解决方案--Seata 24 | 25 | **事务角色** 26 | 27 | ![image-20200802115650329](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120094815.png) 28 | 29 | **事务过程动作** 30 | 31 | ![image-20200802115813627](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120094819.png) 32 | 33 | **微服务分布式事务调用** 34 | 35 | ![image-20200802120129023](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120094824.png) 36 | 37 | **Seata 4 种模式** 38 | 39 | ![image-20200802120445254](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120094828.png) 40 | 41 | ![image-20200802121316934](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120094832.png) 42 | 43 | ![image-20200802121504296](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120094837.png) 44 | 45 | **Seata 高可用** 46 | 47 | ![image-20200802121601430](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120094841.png) 48 | 49 | **事务模式对比** 50 | 51 | ![image-20200802122134200](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120094846.png) 52 | 53 | ## Seata 社区 54 | 55 | **现状** 56 | 57 | ![image-20200802122922151](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120094851.png) 58 | 59 | **用户案例** 60 | 61 | ![image-20200802123005198](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120094855.png) 62 | 63 | **版本演进** 64 | 65 | ![image-20200802123134861](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120094900.png) 66 | 67 | **实战演练** 68 | 69 | ![image-20200802123238726](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20201120094905.png) 70 | 71 | -------------------------------------------------------------------------------- /D类/D08-杂谈/[advanced-java]-海量数据处理.md: -------------------------------------------------------------------------------- 1 | > 来源:https://github.com/doocs/advanced-java/blob/master/docs/big-data/find-common-urls.md 2 | 3 | # 01 | 如何从大量的 URL 中找出相同的 URL? 4 | 5 | **题目描述** 6 | 7 | 给定 a、b 两个文件,各存放 50 亿个 URL,每个 URL 各占 64Byte,内存限制是 4G。请找出 a、b 两个文件共同的 URL。 8 | 9 | **解答思路** 10 | 11 | 每个 URL 占 64B,那么 50 亿个 URL 占用的空间大小约为 320GB。 12 | 13 | > 5,000,000,000 * 64Byte = 4.65GB * 64 = 298GB 14 | 15 | 由于内存大小只有 4G,因此,我们不可能一次性把所有 URL 加载到内存中处理。对于这种类型的题目,一般采用**分治策略**,即:把一个文件中的 URL 按照某个特征划分为多个小文件,使得每个小文件大小不超过 4G,这样就可以把这个小文件读到内存中进行处理了。 16 | 17 | 思路如下: 18 | 19 | 首先遍历文件 a,对遍历到的 URL 求 `hash(URL) % 1000` ,根据计算结果把遍历到的 URL 存储到 a0, a1, a2, ..., a999,这样每个大小约为 300MB。使用同样的方法遍历文件 b,把文件 b 中的 URL 分别存储到文件 b0, b1, b2, ..., b999 中。这样处理过后,所有可能相同的 URL 都在对应的小文件中,即 a0 对应 b0, ..., a999 对应 b999,不对应的小文件不可能有相同的 URL。那么接下来,我们只需要求出这 1000 对小文件中相同的 URL 就好了。 20 | 21 | 接着遍历 ai( `i∈[0,999]` ),把 URL 存储到一个 HashSet 集合中。然后遍历 bi 中每个 URL,看在 HashSet 集合中是否存在,若存在,说明这就是共同的 URL,可以把这个 URL 保存到一个单独的文件中。 22 | 23 | **方法总结** 24 | 25 | 1. 分而治之,进行哈希取余; 26 | 2. 对每个子文件进行 HashSet 统计。 27 | 28 | # 02 | 如何从大量数据中找出高频词? 29 | 30 | **题目描述** 31 | 32 | 有一个 1GB 大小的文件,文件里每一行是一个词,每个词的大小不超过 16B,内存大小限制是 1MB,要求返回频数最高的 100 个词(Top 100)。 33 | 34 | **解答思路** 35 | 36 | 由于内存限制,我们依然无法直接将大文件的所有词一次读到内存中。因此,同样可以采用**分治策略**,把一个大文件分解成多个小文件,保证每个文件的大小小于 1MB,进而直接将单个小文件读取到内存中进行处理。 37 | 38 | 思路如下: 39 | 40 | 首先遍历大文件,对遍历到的每个词 x,执行 `hash(x) % 5000` ,将结果为 i 的词存放到文件 ai 中。遍历结束后,我们可以得到 5000 个小文件。每个小文件的大小为 200KB 左右。如果有的小文件大小仍然超过 1MB,则采用同样的方式继续进行分解。 41 | 42 | 接着统计每个小文件中出现频数最高的 100 个词。最简单的方式是使用 HashMap 来实现。其中 key 为词,value 为该词出现的频率。具体方法是:对于遍历到的词 x,如果在 map 中不存在,则执行 `map.put(x, 1)` ;若存在,则执行 `map.put(x, map.get(x)+1)` ,将该词频数加 1。 43 | 44 | 上面我们统计了每个小文件单词出现的频数。接下来,我们可以通过维护一个**小顶堆**来找出所有词中出现频数最高的 100 个。具体方法是:依次遍历每个小文件,构建一个**小顶堆**,堆大小为 100。如果遍历到的词的出现次数大于堆顶词的出现次数,则用新词替换堆顶的词,然后重新调整为**小顶堆**,遍历结束后,小顶堆上的词就是出现频数最高的 100 个词。 45 | 46 | **方法总结** 47 | 48 | 1. 分而治之,进行哈希取余; 49 | 2. 使用 HashMap 统计频数; 50 | 3. 求解**最大**的 TopN 个,用**小顶堆**;求解**最小**的 TopN 个,用**大顶堆**。 51 | 52 | # 03 | 如何找出某一天访问百度网站最多的 IP? 53 | 54 | **题目描述** 55 | 56 | 现有海量日志数据保存在一个超大文件中,该文件无法直接读入内存,要求从中提取某天访问百度次数最多的那个 IP。 57 | 58 | **解答思路** 59 | 60 | 这道题只关心某一天访问百度最多的 IP,因此,可以首先对文件进行一次遍历,把这一天访问百度 IP 的相关信息记录到一个单独的大文件中。接下来采用的方法与上一题一样,大致就是先对 IP 进行哈希映射,接着使用 HashMap 统计重复 IP 的次数,最后计算出重复次数最多的 IP。 61 | 62 | > 注:这里只需要找出出现次数最多的 IP,可以不必使用堆,直接用一个变量 max 即可。 63 | 64 | **方法总结** 65 | 66 | 1. 分而治之,进行哈希取余; 67 | 2. 使用 HashMap 统计频数; 68 | 3. 求解**最大**的 TopN 个,用**小顶堆**;求解**最小**的 TopN 个,用**大顶堆**。 69 | 70 | # 04 | 如何在大量的数据中找出不重复的整数? 71 | 72 | **题目描述** 73 | 74 | 在 2.5 亿个整数中找出不重复的整数。 75 | 76 | > 注意:内存不足以容纳这 2.5 亿个整数。 77 | 78 | **解答思路** 79 | 80 | - 方法一:分治法 81 | 82 | 与前面的题目方法类似,先将 2.5 亿个数划分到多个小文件,用 HashSet/HashMap 找出每个小文件中不重复的整数,再合并每个子结果,即为最终结果。 83 | 84 | - 方法二:位图法 85 | 86 | 对于整数相关的算法的求解,位图法是一种非常实用的算法。假设 int 整数占用 4B,即 32bit,那么我们可以表示的整数的个数为 232。 87 | 88 | **那么对于这道题**,我们用 2 个 bit 来表示各个数字的状态: 89 | 90 | - 00 表示这个数字没出现过; 91 | - 01 表示这个数字出现过一次(即为题目所找的不重复整数); 92 | - 10 表示这个数字出现了多次。 93 | 94 | 那么这 232 个整数,总共所需内存为 232*2b=1GB。因此,当可用内存超过 1GB 时,可以采用位图法。假设内存满足位图法需求,进行下面的操作: 95 | 96 | 遍历 2.5 亿个整数,查看位图中对应的位,如果是 00,则变为 01,如果是 01 则变为 10,如果是 10 则保持不变。遍历结束后,查看位图,把对应位是 01 的整数输出即可。 97 | 98 | ```text 99 | 0 0 0 0 0 0 0...0 100 | 0 0 0 0 0 0 0...0 (2.5亿个) 101 | ``` 102 | 103 | 假如这2.5亿个整数为[6, 5, 1, 1 ...] 104 | 105 | 那么可表示为: 106 | 107 | ```text 108 | 0 1 0 0 0 0 0...0 109 | 0 0 0 0 0 1 1...0 (2.5亿个) 110 | ``` 111 | 112 | **方法总结** 113 | 114 | 判断数字是否重复的问题,位图法是一种非常高效的方法。 115 | 116 | # 05 | 如何在大量的数据中判断一个数是否存在? 117 | 118 | **题目描述** 119 | 120 | 给定 40 亿个不重复的没排过序的 unsigned int 型整数,然后再给定一个数,如何快速判断这个数是否在这 40 亿个整数当中? 121 | 122 | **解答思路** 123 | 124 | 40 亿个不重复整数,我们用 40 亿个 bit 来表示,初始位均为 0,那么总共需要内存:4, 000, 000, 000b≈512M。 125 | 126 | 我们读取这 40 亿个整数,将对应的 bit 设置为 1。接着读取要查询的数,查看相应位是否为 1,如果为 1 表示存在,如果为 0 表示不存在。 127 | 128 | **方法总结** 129 | 130 | 判断数字是否存在、判断数字是否重复的问题,位图法是一种非常高效的方法。 131 | 132 | **实现样例** 133 | 134 | > 来源:https://blog.csdn.net/qfzxhy/article/details/54951472 135 | 136 | ```java 137 | // 对16以下的数进行排序以及统计不同数字个数 138 | public class BitGraph { 139 | final int BITS_PRE_WORD = 32; 140 | final static int max = 16; 141 | void setBit(int[] arr, int n) { 142 | arr[n/BITS_PRE_WORD] |= (1 << (n % BITS_PRE_WORD)); 143 | } 144 | void clearBit(int[] arr, int n) {} 145 | int getBit(int[] arr, int n) { 146 | return (arr[n/BITS_PRE_WORD] & (1 << (n%BITS_PRE_WORD))) != 0 ? 1 : 0; 147 | } 148 | public static void main(String[] args) { 149 | // TODO Auto-generated method stub 150 | BitGraph bg = new BitGraph(); 151 | int[] datas = new int[] {1,13,14,15,7,8,9,13,1,13,14,15,7,8,9,13,2}; 152 | int[] arr = new int[max / 32 + 1]; 153 | for(int data : datas) { 154 | bg.setBit(arr, data); 155 | } 156 | int count = 0; 157 | for(int i = 0; i < max;i++) { 158 | if(bg.getBit(arr, i) == 1) { 159 | System.out.println(i); 160 | ++count; 161 | } 162 | } 163 | System.out.println("count" + count); 164 | } 165 | } 166 | ``` 167 | 168 | # 06 | 如何从 5 亿个数中找出中位数? 169 | 170 | **题目描述** 171 | 172 | 从 5 亿个数中找出中位数。数据排序后,位置在最中间的数就是中位数。当样本数为奇数时,中位数为 第 `(N+1)/2` 个数;当样本数为偶数时,中位数为 第 `N/2` 个数与第 `1+N/2` 个数的均值。 173 | 174 | **解答思路** 175 | 176 | 如果这道题没有内存大小限制,则可以把所有数读到内存中排序后找出中位数。但是最好的排序算法的时间复杂度都为 `O(NlogN)` 。这里使用其他方法。 177 | 178 | 分治法的思想是把一个大的问题逐渐转换为规模较小的问题来求解。 179 | 180 | 对于这道题,顺序读取这 5 亿个数字,对于读取到的数字 num,如果它对应的二进制中最高位为 1,则把这个数字写到 f1 中,否则写入 f0 中。通过这一步,可以把这 5 亿个数划分为两部分,而且 f0 中的数都大于 f1 中的数(最高位是符号位)。 181 | 182 | 划分之后,可以非常容易地知道中位数是在 f0 还是 f1 中。假设 f1 中有 1 亿个数,那么中位数一定在 f0 中,且是在 f0 中,从小到大排列的第 2 亿个数与它后面的一个数的平均值。 183 | 184 | > **提示**,5 亿数的中位数是第 2.5 亿与右边相邻一个数求平均值。若 f1 有一亿个数,那么中位数就是 f0 中从第 2 亿个数开始的两个数求得的平均值。 185 | 186 | 对于 f0 可以用次高位的二进制继续将文件一分为二,如此划分下去,直到划分后的文件可以被加载到内存中,把数据加载到内存中以后直接排序,找出中位数。 187 | 188 | > **注意**,当数据总数为偶数,如果划分后两个文件中的数据有相同个数,那么中位数就是数据较小的文件中的最大值与数据较大的文件中的最小值的平均值。 189 | 190 | **方法总结** 191 | 192 | 分治法。 -------------------------------------------------------------------------------- /D类/D08-杂谈/一些idea.md: -------------------------------------------------------------------------------- 1 | # 网络协议 2 | 3 | - [ ] 彻底理解 TCP/IP 协议(协议头、3次握手、4次挥手、顺序重传、流量控制、拥塞控制) 4 | 5 | # MySQL 6 | 7 | - [ ] 彻底理解 MySQL 索引(索引结构、回表、覆盖索引、前缀索引、索引下推、索引失效的情况) 8 | 9 | 10 | # Redis 11 | 12 | - [x] 面试官,请不要再问我 Redis 的淘汰策略了! 13 | 14 | # 日常思考 15 | 16 | 1. 有哪些渠道获取技术第一手资讯? 17 | 18 | 2. 互联网问题:如何实现一个秒杀系统? 19 | 20 | 3. 吊打面试官系列文章 21 | 22 | 4. 你工作中遇到的最难的问题是什么? 23 | 24 | 一次高并发缓存穿透导致的现场宕机; 25 | 26 | 一次搭建电子卷宗统计分析系统,解决的单点登录问题; 27 | 28 | 一次开发过程中,一家单位读到另一家单位配置值问题排查; 29 | 30 | 一次高并发场景下处理大材料 pdf 的拆分; 31 | 32 | # IDEA 33 | 34 | **20200725** 可以把工作经历的项目统一写下来,作为一个 github 仓库维护。 35 | 36 | -------------------------------------------------------------------------------- /D类/D08-杂谈/面试题.md: -------------------------------------------------------------------------------- 1 | # 01 | SpringCloud -------------------------------------------------------------------------------- /D类/D11-读书/02-《大型网站技术架构》--李智慧.md: -------------------------------------------------------------------------------- 1 | # 第1篇 概述 2 | 3 | # 01 | 大型网站架构演化 4 | 5 | **大型网站软件系统的特点** 6 | 7 | - 高并发,大流量 8 | - 高可用 9 | - 海量数据 10 | - 用户分布广泛,网络情况复杂 11 | - 安全环境恶劣 12 | - 需求快速变更 13 | - 渐进式发展 14 | 15 | **大型网站架构演化发展历程** 16 | 17 | - 初始阶段的网站架构 18 | 19 | ![image-20211216151354161](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20211216151354.png) 20 | 21 | - 应用服务和数据服务分离 22 | 23 | ![image-20211216151151478](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20211216151151.png) 24 | 25 | - 使用缓存改善网站性能 26 | 27 | ![image-20211216151225003](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20211216151225.png) 28 | 29 | - 使用应用服务器集群改善网站的并发处理能力 30 | 31 | ![image-20211216151456562](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20211216151456.png) 32 | 33 | - 数据库读写分离 34 | 35 | ![image-20211216151535082](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20211216151535.png) 36 | 37 | - 使用反向代理和CDN加速网站响应 38 | 39 | ![image-20211216151632054](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20211216151632.png) 40 | 41 | - 使用分布式文件系统和分布式数据库系统 42 | 43 | ![image-20211216151746744](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20211216151746.png) 44 | 45 | - 使用NoSQL和搜索引擎 46 | 47 | ![image-20211216163430332](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20211216163430.png) 48 | 49 | - 业务拆分 50 | 51 | ![image-20211216163543003](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20211216163543.png) 52 | 53 | - 分布式服务 54 | 55 | ![image-20211216163646398](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20211216163646.png) 56 | 57 | **网站架构设计误区** 58 | 59 | - 一味追随大公司的解决方案 60 | - 为了技术而技术 61 | - 企图用技术解决所有问题 62 | 63 | # 02 | 大型网站架构模式 64 | 65 | **网站架构模式** 66 | 67 | - 分层 68 | 69 | 将系统在横向维度上切分成几个部分,每个部分负责一部分相对比较单一的职责,然后通过上层对下层的依赖和调用组成一个完整的系统。 70 | 71 | - 分割 72 | 73 | 比如在应用层,将不同业务进行分割,例如将购物、论坛、搜索、广告分割成不同的应用,由独立的团队负责,部署在不同的服务器上; 74 | 75 | - 分布式 76 | 77 | 对于大型网站,分层和分割的一个主要目的是为了切分后的模块便于分布式部署,即将不同模块部署在不同的服务器上,通过远程调用协同工作。 78 | 79 | - 集群 80 | 81 | 多台服务器部署相同应用构成一个集群,通过负载均衡设备共同对外提供服务。 82 | 83 | - 缓存 84 | 85 | 缓存就是将数据存放在距离计算最近的位置以加快处理速度。 86 | 87 | - 异步 88 | 89 | 业务之间的消息传递不是同步调用,而是将一个业务操作分成多个阶段,每个阶段之间通过共享数据的方式异步执行进行协作。 90 | 91 | - 冗余 92 | 93 | 要想保证在服务器宕机的情况下网站依然可以继续服务,不丢失数据,就需要一定程度的服务器冗余运行,数据冗余备份。 94 | 95 | - 自动化 96 | 97 | 在无人值守的情况下网站可以正常运行,一切都可以自动化是网站的理想状态。 98 | 99 | - 安全 100 | 101 | 身份认证、用户信息加密存储、验证码、XSS攻击、SQL注入。 102 | 103 | **架构模式在新浪微博的应用** 104 | 105 | - 三层架构 106 | 107 | ![image-20211216225333239](https://technotes.oss-cn-shenzhen.aliyuncs.com/2021/images/20211216225333.png) 108 | 109 | (图片来源:http://timyang.net/architecture/weibo/) 110 | 111 | - 异步推拉结合的模式 112 | 113 | 用户发表微博后系统将微博写入消息队列后立即返回,用户响应迅速,消息队列消费者任务将微博推送给所有当前在线粉丝的订阅列表中,非在线用户登录后再根据关注列表拉取微博订阅列表。 114 | 115 | - 多级缓存策略 116 | 117 | 对于微博操作中最常见的“刷微博”操作,几乎全部都是缓存访问操作,可以获得很好的系统性能。 118 | 119 | - 多数据中心 120 | 121 | 用户可以就近访问最近的数据中心以加快访问速度,改善系统性能。 122 | 123 | - 自动化 124 | 125 | 自动化监控,自动化发布,自动化故障修复等。 126 | 127 | - 安全 128 | 129 | 新浪微博在开放平台上使用多级安全审核的策略以保护系统和用户。 130 | 131 | # 03 | 大型网站核心架构要素 132 | 133 | - 性能 134 | - 可用性 135 | - 伸缩性 136 | - 扩展性 137 | - 安全性 138 | 139 | # 第2篇 架构 140 | 141 | # 04 | 瞬时响应:网站的高性能架构 142 | 143 | **网站性能测试** 144 | 145 | 不同视角下的网站性能不一样。 146 | 147 | 性能测试指标、方法、优化策略。 148 | 149 | **Web前端性能优化** 150 | 151 | - 浏览器访问优化 152 | 153 | 减少 Http 请求、使用浏览器缓存、启用压缩、CSS 放在页面最上面、JavaScript 放在页面最下面、减少 Cookie 传输。 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | # 05 | 万无一失:网站的高可用架构 162 | 163 | 164 | 165 | 166 | 167 | # 06 | 永无止境:网站的伸缩性架构 168 | 169 | 170 | 171 | 172 | 173 | # 07 | 随机应变:网站的可扩展架构 174 | 175 | 176 | 177 | 178 | 179 | # 08 | 固若金汤:网站的安全架构 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | -------------------------------------------------------------------------------- /D类/D11-读书/03-《深入理解Java虚拟机》(周志明)读书笔记.md: -------------------------------------------------------------------------------- 1 | # 如何阅读本书 2 | 3 | 共分为五个部分:走近Java、自动内存管理机制、虚拟机执行子系统、程序编译与代码优化、高效并发。 4 | 5 | **第一部分:走近Java** 6 | 7 | (第1章)Java技术体系的过去、现在和未来的一些发展趋势。 8 | 9 | **第二部分:自动内存管理机制** 10 | 11 | (第2章--第5章)虚拟机内存划分、垃圾收集算法、垃圾收集器、JDK故障处理工具的使用、实际案例。 12 | 13 | **第三部分:虚拟机执行子系统** 14 | 15 | (第6章--第9章)Class文件结构组成、类加载过程、虚拟机如何执行方法、案例。 16 | 17 | **第四部分:程序编译与代码优化** 18 | 19 | (第10章--第11章)Java语法糖、HotSpot编译。 20 | 21 | **第五部分:高效并发** 22 | 23 | (第12章--第13章)Java内存模型、线程安全。 24 | 25 | # 第2章 Java内存区域与内存溢出异常 26 | 27 | > 本章主要内容:虚拟机内存划分 28 | 29 | **2.2 运行时数据区域** 30 | 31 | - Java 堆(Java Heap) 32 | 33 | 此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。 34 | 35 | - 方法区(Method Area) 36 | 37 | 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。 38 | 39 | - 程序计数器(Program Counter Register) 40 | 41 | 程序计数器可以看作是当前线程所执行的字节码的行号指示器。分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。 42 | 43 | - Java虚拟机栈(Java Virtual Machine Stacks) 44 | 45 | 每个方法在执行的同时都会创建一个栈帧(Stack Frame),用于存储局部变量表、操作数据栈、动态链接、方法出口等信息。 46 | 47 | - 本地方法栈(Native Method Stack) 48 | 49 | 本地方法栈为虚拟机使用到的 Native 方法服务。 50 | 51 | > - 直接内存(Direct Memory) 52 | > 53 | > 通过一个存储在 Java 堆中的 DirectByteBuffer 对象作为这块堆外内存的引用进行操作,提高性能。 54 | 55 | **2.3 HotSpot 虚拟机对象探秘** 56 | 57 | 58 | 59 | **2.4 实战:OutOfMemoryError异常** 60 | 61 | 62 | 63 | **2.5 本章小结** 64 | 65 | 66 | 67 | # 第3章 -------------------------------------------------------------------------------- /D类/D11-读书/05-《红楼梦》.md: -------------------------------------------------------------------------------- 1 | ![](https://technotes.oss-cn-shenzhen.aliyuncs.com/2023/202402282306950.png) 2 | 3 | ![image-20240228230707354](https://technotes.oss-cn-shenzhen.aliyuncs.com/2023/202402282307445.png) 4 | 5 | ![image-20240228230731248](https://technotes.oss-cn-shenzhen.aliyuncs.com/2023/202402282307302.png) 6 | 7 | ![image-20240228230751767](https://technotes.oss-cn-shenzhen.aliyuncs.com/2023/202402282307865.png) 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /D类/D11-读书/06-《富爸爸穷爸爸》.md: -------------------------------------------------------------------------------- 1 | 下意识地说“我可付不起”意味着精神上的懒惰。 2 | 3 | # 第一课 富人不为钱工作 4 | 5 | ### 建立合伙关系 6 | 7 | 当9岁的时候,罗伯特·清崎和他的儿时伙伴迈克被拒绝邀请到同学家的海滨别墅度假,因为他们是富人学校里的“穷孩子”。在听了穷爸爸——他的父亲,一位老师,生活不错但勉强维持着收支平衡——“去挣钱”的劝告后,他和他的朋友迈克照做了:他们收集废弃的牙膏皮(在那时牙膏皮是用铅制造的),把它熔化,然后使用熟石灰模型仿造硬币。 8 | 9 | 很快,他们就被罗伯特的父亲教训了一通,他建议他们和迈克的父亲谈一谈,迈克的父亲是一个八年级都没有读完但成功经营着多家公司的人。 10 | 11 | ### 课程开始了 12 | 13 | 迈克的父亲,书名里的“富爸爸”,答应教他们挣钱,但是要按照他的条件来。他要求他们每周六早上在他的一家便利店工作3个小时,清理食物的包装以及打扫卫生。他给他们每小时10美分的酬劳,罗伯特常常用这些钱买10美分一本的连环画。 14 | 15 | ### 30 美分以后 16 | 17 | 很快,罗伯特便对这枯燥的工作和少得可怜的薪水感到厌倦。当他告诉迈克他准备放弃的时候,迈克告诉他,他的父亲早已料到他会退出,并且建议罗伯特去见见他的父亲。迈克的父亲是一个少言寡语的人,他的教育方法也和别人不一样,这是罗伯特想要去了解的。 18 | 19 | ### 星期六的排队等候 20 | 21 | 第二个周六的早上,罗伯特去见迈克的父亲,却被迫在一个又脏又暗的客厅等了一个小时。 22 | 23 | ### 穷人和中产阶级为钱工作 24 | 25 | 钱并不能解决人们的问题。很多人有着高收入的工作但他们还是为钱所困——比如罗伯特的穷爸爸——因为他们不知道如何让钱为他们工作。 26 | 27 | ### 富人不为钱工作 28 | 29 | 罗伯特和迈克免费在便利店工作了三周。之后富爸爸出现了并把他们带到外面谈话。他问他们是否学到了什么东西,他们说还没有。富爸爸告诉他们如果他们学不会这一课,他们将会像大部分人一样,一辈子为一点点钱而卖命工作。他决定给他们每小时支付25美分的薪水,但他们拒绝了。他又涨到每小时1美元,甚至2美元。但是罗伯特仍然保持沉默。最后他出到了5美元一小时——这在当时是个不小的数目——但倔强的罗伯特并不买账。 30 | 31 | ### 避开一生中最大的陷阱 32 | 33 | 富爸爸说,他们没有被钱收买,这是好事。大部分人却做不到这样,因为他们的人生被恐惧和贪婪控制。没钱的恐惧促使他们努力工作,得到酬劳后,贪婪又让他们想拥有所有用钱能买到的东西。这使他们需要更多的钱,也让他们花更多的钱。这就是富爸爸所说的“老鼠赛跑”。 34 | 35 | 学校的教育固然重要,他说,但对大部分人来说,可悲的是离开学校是学习的终点,而不是起点。对于孩子们来说最主要的还是学会用感情来思考,而不是带着感情去思考。他们必须学会选择他们的想法。 36 | 37 | ### 看见了别人看不见的 38 | 39 | 他告诉他们要留意可以挣钱的途径:“如果你们能看到一个机会,就注定你们会在一生中不断地发现机会。” 40 | 41 | 孩子们照做了,很快他们便发现了一个创办阅览室的机会,只要小孩子买张票就能在阅览室里看两个小时的连环画——那些卖不出去、本该被便利店扔掉的连环画。 42 | 43 | # 第二课 为什么要教授财务知识 44 | 45 | ### 最富有的生意人 46 | 47 | 差不多35年后,我们再来看看罗伯特和迈克的情况。迈克接管了他爸爸的公司,做得比富爸爸还要好。至于罗伯特,他在1994年也就是他47岁的时候退休了。他和他的妻子的财富会自动增长,就像是一棵被培植得很好的大树一样。 48 | 49 | 他分享了一个一些最伟大的领导人和最富有的商界人士在1923年开会的故事——他们当中有人拥有最大的钢铁公司和煤气公司,有人经营纽约证券交易所,有人是内阁成员。然而25年之后,他们大多都落得悲惨的结局,有人破产,有人被流放,有人则被关进监狱。 50 | 51 | 1929年的股市大崩溃和大萧条可能影响了他们的命运,但今天我们生活在一个比那时更混乱、变化更快的时代。在这个时代,比钱更重要的生存之道是我们所受的教育和学习的能力。 52 | 53 | 重要的不是你挣了多少钱,而是你能留下多少钱,以及能够留住多久。 54 | 55 | ### 资产和负债的区别 56 | 57 | 资产是能把钱放进我口袋里的东西。负债是把钱从我口袋里取走的东西。 58 | 59 | ### 发财梦为什么变成噩梦 60 | 61 | 罗伯特讲了一对新婚夫妇开始共同生活的故事。随着他们收入的增长,他们的支出也在增长。 62 | 63 | 和大多数人一样,这对夫妇的第一项支出是税。对于许多人来说,最沉重的压力不是来自个人所得税而是社会保险。它的税率大概为15%(社会保险和医疗保险的税率加在一起,所有这些都是雇主拿他本该付给雇员的钱去支付的)。在这个量的基础上,雇员还要支付个人所得税。 64 | 65 | 这对年轻的夫妇也面临着这些税的问题,当他们买了房之后,还有房地产税。伴随新房子而来的是一辆新车,新的家具,以及新的电器。突然间,他们的负债就上来了,到处是抵押债务和信用卡债务。 66 | 67 | 这对夫妇落入了“老鼠赛跑”的陷阱。再加上新生的宝宝,于是他们更加努力工作:更高的收入导致了更高的税收。他们的账单不断增多,最终将他们的房屋抵押获得一个债务合并贷款。但是他们的消费习惯没有改变——所以信用卡债务一直持续着——更别提他们已经加重的家庭债务。 68 | 69 | 对于这对夫妇以及像他们这样的人来说,真正的问题是不懂得怎么处理他们手中的钱。这也是由缺乏财务知识以及不理解资产和负债的区别引起的。 70 | 71 | ### 为什么富人越来越富 72 | 73 | 很多人仍然相信他们的房子就是资产。但罗伯特教育他们说房子是负债,因为它把钱从你的口袋里拿走了——不仅仅因为那些伴随着房子的税收和支出,更因为房子的贬值和你把所有的钱都投在房子上后丢失的致富的机会,这也导致了你失去了学习投资经验的机会。 74 | 75 | 当你有足够的资产能产生大于支出的收入时,剩余的收入还可以对资产项进行再投资。这样,你的资产负债表上的资产项会不断增加,收入也会随之增加。结果便是能够分清资产和负债的富人变得更富。 76 | 77 | ### 为什么中产阶级无法摆脱财务问题 78 | 79 | 中产阶级深陷“老鼠赛跑”的陷阱是因为他们把房子当作资产,而没有把钱投在那些能带来收入的资产上。他们深陷其中还因为他们最重要的收入就是工资,而当工资增加的时候,税收也就增加了。 80 | 81 | # 第三课 关注自己的事业 82 | 83 | 关注自己的事业并不意味着要开一个公司,虽然有些人会这样。你的事业的重心应该是你的资产项,而不是你的收入项。 84 | 85 | 罗伯特告诉人们要开始关注自己的事业。你可以继续白天的工作,但要购买真正的资产,而不是负债或一带回家就没有价值的个人用品。保持低支出,降低负债,为坚实的资产打造基础。 86 | 87 | 真正的资产分为以下几类: 88 | 89 | 1. 不需我到场就可以正常运作的业务。我拥有它们,但由别人经营和管理。如果我必须在那儿工作,那它就不是我的事业而是我的职业了。 90 | 2. 股票 91 | 3. 债券 92 | 4. 能够产生收入的房地产 93 | 5. 票据(借据) 94 | 6. 版税,如音乐、手稿、专利 95 | 7. 其他任何有价值、可产生收入或有增值潜力并且有很好销路的东西 96 | 97 | # 第四课 税收的历史和公司的力量 98 | 99 | 公司就是一个装着法律文件的文件夹创造的法律实体。它不一定是一个真正的实体,不是一个工厂,也不是一群人。但是企业的所得税率要低于个人收入所得税率,而且公司的某些支出可以用税前收入支付。 100 | 101 | 让罗伯特这一切变为可能的是财商,或者叫财务知识。它由4部分组成: 102 | 103 | - 会计(财务知识,也就是解读数字的能力以及评估一项生意的优势和劣势)、 104 | - 投资(钱生钱的科学和策略)、 105 | - 了解市场(供给与需求的科学以及市场条件)、 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 | # 第六课 学会不为钱工作 -------------------------------------------------------------------------------- /D类/D11-读书/07-《从零开始学价值投资》.md: -------------------------------------------------------------------------------- 1 | > 《从零开始学价值投资:财务指标、量化选股与投资策略全解析》--杨金 2 | 3 | # 第3章 第一轮筛选:偿债能力 4 | 5 | ### 资产负债表 6 | 7 | 资产=负债+所有者权益。 8 | 9 | 我有1000万元的房产,但是房贷还有300万没还清,我有30万元的车,但是车贷也还有10万没还清。如果只说房产和车,共有资产1030万元。你背负着310万元的负债,那剩下的720万元,就是你的净资产,在会计学上也叫作“所有者权益”。 10 | 11 | 1000万元+30万元=(300万元+10万元)+720万元。 12 | 13 | 资产负债表表示在这一时刻,你的资产负债情况。进一步说,它表示的是目前状态下的存量,所以资产负债表也是存量表。 14 | 15 | ### 资产负债率 16 | 17 | 资产负债率是衡量企业偿债能力最重要的标准之一,计算公式:资产负债率=负债/资产。通常情况下,该指标不能超过50%。 18 | 19 | 负债率越高,企业经营的杠杆就越大。例如你用100元赚到了100元,资金回报率是100%。若你只有50元,再借50元,1年的利息是3元,同样赚了100元,此时你手中共有200元。连本带利还款53元,还剩147元,去除自己的50元本金,有97元的净利润。相当于用50元赚了97元,资金回报率194%。 20 | 21 | ### 其他偿债风险指标 22 | 23 | - 长期负债 24 | 25 | 长期负债率=长期负债/资产。 26 | 27 | 固定资产对长期负债率=固定资产/长期负债。 28 | 29 | 贵州茅台2016年每1元的长期负债,背后都有903元的固定资产作为支撑。哪怕茅台不干了,折价变卖固定资产,清偿债务也只是九牛一毛。 30 | 31 | # 第4章 第二轮筛选:盈利能力 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /D类/D11-读书/08-《劳动法》.md: -------------------------------------------------------------------------------- 1 | > 参考:http://www.mohrss.gov.cn/xxgk2020/fdzdgknr/zcfg/fl/202011/t20201102_394622.html 2 | 3 | # 第一章 总则 4 | 5 | 6 | 7 | # 第二章 劳动合同的订立 8 | 9 | 10 | 11 | # 第三章 劳动合同的履行和变更 12 | 13 | 14 | 15 | # 第四章 劳动合同的解除和终止 16 | 17 | **第三十六条** 用人单位与劳动者协商一致,可以解除劳动合同。 18 | 19 | **第三十八条** 用人单位有下列情形之一的,劳动者可以解除劳动合同: 20 | 21 |   (一)未按照劳动合同约定提供劳动保护或者劳动条件的; 22 | 23 |   (二)未及时足额支付劳动报酬的; 24 | 25 |   (三)未依法为劳动者缴纳社会保险费的; 26 | 27 |   (四)用人单位的规章制度违反法律、法规的规定,损害劳动者权益的; 28 | 29 |   (五)因本法第二十六条第一款规定的情形致使劳动合同无效的; 30 | 31 |   (六)法律、行政法规规定劳动者可以解除劳动合同的其他情形。 32 | 33 |   用人单位以暴力、威胁或者非法限制人身自由的手段强迫劳动者劳动的,或者用人单位违章指挥、强令冒险作业危及劳动者人身安全的,劳动者可以立即解除劳动合同,不需事先告知用人单位。 34 | 35 | **第四十条** 有下列情形之一的,用人单位提前三十日以书面形式通知劳动者本人或者额外支付劳动者一个月工资后,可以解除劳动合同: 36 | 37 |   (一)劳动者患病或者非因工负伤,在规定的医疗期满后不能从事原工作,也不能从事由用人单位另行安排的工作的; 38 | 39 |   (二)劳动者不能胜任工作,经过培训或者调整工作岗位,仍不能胜任工作的; 40 | 41 |   (三)劳动合同订立时所依据的客观情况发生重大变化,致使劳动合同无法履行,经用人单位与劳动者协商,未能就变更劳动合同内容达成协议的。 42 | 43 | **第四十一条** 有下列情形之一,需要裁减人员二十人以上或者裁减不足二十人但占企业职工总数百分之十以上的,用人单位提前三十日向工会或者全体职工说明情况,听取工会或者职工的意见后,裁减人员方案经向劳动行政部门报告,可以裁减人员: 44 | 45 |   (一)依照企业破产法规定进行重整的; 46 | 47 |   (二)生产经营发生严重困难的; 48 | 49 |   (三)企业转产、重大技术革新或者经营方式调整,经变更劳动合同后,仍需裁减人员的; 50 | 51 |   (四)其他因劳动合同订立时所依据的客观经济情况发生重大变化,致使劳动合同无法履行的。 52 | 53 |   裁减人员时,应当优先留用下列人员: 54 | 55 |   (一)与本单位订立较长期限的固定期限劳动合同的; 56 | 57 |   (二)与本单位订立无固定期限劳动合同的; 58 | 59 |   (三)家庭无其他就业人员,有需要扶养的老人或者未成年人的。 60 | 61 |   用人单位依照本条第一款规定裁减人员,在六个月内重新招用人员的,应当通知被裁减的人员,并在同等条件下优先招用被裁减的人员。 62 | 63 | **第四十四条** 有下列情形之一的,劳动合同终止: 64 | 65 |   (一)劳动合同期满的; 66 | 67 |   (二)劳动者开始依法享受基本养老保险待遇的; 68 | 69 |   (三)劳动者死亡,或者被人民法院宣告死亡或者宣告失踪的; 70 | 71 |   (四)用人单位被依法宣告破产的; 72 | 73 |   (五)用人单位被吊销营业执照、责令关闭、撤销或者用人单位决定提前解散的; 74 | 75 |   (六)法律、行政法规规定的其他情形。 76 | 77 | **第四十六条** 有下列情形之一的,用人单位应当向劳动者支付经济补偿: 78 | 79 |   (一)劳动者依照本法第三十八条规定解除劳动合同的; 80 | 81 |   (二)用人单位依照本法第三十六条规定向劳动者提出解除劳动合同并与劳动者协商一致解除劳动合同的; 82 | 83 |   (三)用人单位依照本法第四十条规定解除劳动合同的; 84 | 85 |   (四)用人单位依照本法第四十一条第一款规定解除劳动合同的; 86 | 87 |   (五)除用人单位维持或者提高劳动合同约定条件续订劳动合同,劳动者不同意续订的情形外,依照本法第四十四条第一项规定终止固定期限劳动合同的; 88 | 89 |   (六)依照本法第四十四条第四项、第五项规定终止劳动合同的; 90 | 91 |   (七)法律、行政法规规定的其他情形。 92 | 93 | # 第五章 特别规定 94 | 95 | 96 | 97 | ## 第一节 集体合同 98 | 99 | 100 | 101 | ## 第二节 劳务派遣 102 | 103 | 104 | 105 | ## 第三节 非全日制用工 106 | 107 | 108 | 109 | # 第六章 监督检查 110 | 111 | 112 | 113 | # 第七章 法律责任 114 | 115 | 116 | 117 | # 第八章 附则 118 | 119 | -------------------------------------------------------------------------------- /D类/D11-读书/08-《指数基金定投》.md: -------------------------------------------------------------------------------- 1 | > 《指数基金定投--普通人的低风险理财之路》--十点 2 | 3 | # 引言 长期定投的价值 4 | 5 | **月薪几千元也能存下百万元巨款** 6 | 7 | 第一,转变理念,拥抱资本市场。 8 | 9 | 第二,让自己慢下来,一步一个脚印,慢慢变富。 10 | 11 | 以下两种指数基金最能代表中国经济,其一是沪深300增强型指数基金,其二是恒生中国企业指数交易型开放式指数基金(简称恒生国企ETF)。 -------------------------------------------------------------------------------- /D类/D11-读书/README.md: -------------------------------------------------------------------------------- 1 | # 一、读/看过 2 | 3 | ## 1.1 书籍 4 | 5 | ### 《认知觉醒》(周岭) 6 | 7 | 触动点: 8 | 9 | 1、对我平时情绪的掌控起到了一些作用。作者将大脑分为了:情绪脑、本能脑、智慧脑。让我在马上要生气的时候,可以想到是自己的情绪脑掌握了主动,然后会有另外一种声音告诉自己不能失控。 10 | 11 | 2、每个人都有属于自己的认知体系,这个体系可以分为舒适区、边缘区、困难区。要时常在边缘区拉伸。 12 | 13 | 3、任何靠毅力坚持下来的事情都是不长久的。手上有正事,以正事为中心,构建出自己的知识体系,一切以扩展知识体系为出发点的事情,才能长久坚持。 14 | 15 | ## 1.2 影视剧 16 | 17 | ### 《天道》 18 | 19 | # 二、想读/看 20 | 21 | ## 2.1 书籍 22 | 23 | ### 个人成长 24 | 25 | 26 | 27 | ### 技术类 28 | 29 | 陈皓推荐 30 | 31 | - 《深入理解计算机系统》 32 | - 《TCP/IP详解卷l》 33 | - 《面向对象设计模式》 34 | - 《Java核心技术》 35 | - 《深入理解Java虚拟机》 36 | - 《Java 编程思想》 37 | - 《Effective Java》 38 | - 《Java并发编程》 39 | - 《算法导论》 40 | - 《代码整洁之道》 41 | - 《代码大全》 42 | 43 | ### 小说 44 | 45 | [《显微镜下的大明》](https://read.douban.com/ebook/419355111/?dcs=subject-rec&dcm=douban&dct=36384601)(豆瓣8.7分) 46 | 47 | [《入关》](https://book.douban.com/subject/36384601/)(豆瓣8.6分) 48 | 49 | ## 2.2 影视剧 50 | 51 | 据图书[《宋太祖》](https://book.douban.com/subject/35771888/)(豆瓣9.1分)想看 52 | 53 | - 《赵匡胤》 54 | 55 | ## 2.3 系列课 -------------------------------------------------------------------------------- /D类/D11-读书/empty.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/D类/D11-读书/empty.md -------------------------------------------------------------------------------- /D类/D12-技术预研/KubeShpere.md: -------------------------------------------------------------------------------- 1 | # 01 | KubeShpere全景图 2 | 3 | ![](./KubeShpere_view.png) 4 | 5 | 7大功能。 6 | 7 | **1. 多租户管理** 8 | 9 | 集群:F2B、电商 10 | 11 | 企业空间: 12 | 13 | 项目:团队(组) 14 | 对应的是 k8s 的 namespace 15 | 16 | 集群(cluster) > 企业空间(workspace) > 项目 17 | 18 | **2. 工作负载** 19 | 20 | 部署(Deployment) 21 | 22 | 有状态副本集(StatefulSet) 23 | 24 | 守护进程集(DeamonSet) 25 | 26 | 任务(Job) 27 | 28 | 定时任务(CronJob) 29 | 30 | **3. 执行化存储卷** 31 | 32 | 33 | 34 | **4. 服务与网络** 35 | 36 | 通过服务(Service)、应用路由(Ingress)来暴露服务。 37 | 38 | **5. 配置中心** 39 | 40 | Secret、ConfigMap 41 | 42 | **6. DevOps 工程资源** 43 | 44 | CI/CD流水线 45 | 46 | **7. 监控中心** 47 | 48 | 从不同视角进行监控:集群、企业空间、项目、工作负载(容器组)、容器。 49 | 50 | # 02 | 发布一个服务 51 | 52 | 首先进入到 Project 下,创建Secret/ConfigMap -> Application - Deploy New Application -> 填写环境变量。 53 | 54 | - 如何连接云上的 K8S? 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /D类/D12-技术预研/KubeShpere_view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/D类/D12-技术预研/KubeShpere_view.png -------------------------------------------------------------------------------- /D类/D13-实践与笔记/02-Postman最佳实践.md: -------------------------------------------------------------------------------- 1 | # 添加自定义变量 2 | 3 | 请求体 4 | 5 | ```json 6 | { 7 | "messageId": "{{messageId}}", 8 | "topic": "alpha-example", 9 | "type": "com.casstime.ec.cloud.example.event.ExampleEvent", 10 | "service": "postman", 11 | "content": "{\"jsonMessageType\":\"com.casstime.ec.cloud.example.event.ExampleEvent\",\"id\":\"{{messageId}}\",\"usage\":\"EVENT\",\"service\":\"postman\",\"topic\":\"alpha-example\",\"timeStamp\":{{$timestamp}},\"content\":\"1733\",\"handleCost\":100,\"exception\":false,\"now\":{{$timestamp}}}", 12 | "createdAt": "{{$timestamp}}", 13 | "usage": "EVENT", 14 | "cluster": "cassmall", 15 | "env": "default" 16 | } 17 | ``` 18 | 19 | `messageId`变量定义 20 | 21 | ```javascript 22 | // 在 Pre-request Script 增加以下代码 23 | function randomstr(length, chars) { 24 | var result = ''; 25 | for (var i =length; i > 0; i--) { 26 | result += chars[Math.floor(Math.random() * chars.length)]; 27 | } 28 | return result; 29 | } 30 | var random = randomstr(20, '0123456789abcdef'); 31 | pm.environment.set("messageId", "TEST" + random); 32 | ``` 33 | 34 | -------------------------------------------------------------------------------- /D类/D13-实践与笔记/03-Linux使用笔记.md: -------------------------------------------------------------------------------- 1 | ## 一、循环调用接口 2 | 3 | ```shell 4 | # !/bin/bash 5 | 6 | for i in {100..786} 7 | do 8 | id="sdbc0$i" 9 | data="{\"ids\":[\"$id\"],\"startTime\":\"2021-07-03 00:00:00\",\"endTime\":\"2021-07-03 23:59:59\"}" 10 | curl -v -H "accept: */*" -H "Content-Type:application/json" -X POST http://xxx/a -d "$data" >> reconsume.log 11 | done 12 | ``` 13 | 14 | ## 二、带颜色输出 15 | 16 | ```shell 17 | # 蓝色 18 | echo -e "\033[32m success. \033[0m" 19 | ``` 20 | 21 | ## 三、查看某个进程的线程数 22 | 23 | ```shell 24 | cat /proc/1/status | grep Threads 25 | ``` 26 | 27 | ## 四、查看某命令的进程号 28 | 29 | ```shell 30 | pgrep -f 'docsify serve -p 4000' 31 | ``` 32 | 33 | ## 五、查看本机ip地址 34 | 35 | ```shell 36 | hostname -I 37 | ``` 38 | 39 | ## 六、文件操作 40 | 41 | ```shell 42 | # 查找 /etc 目录下是否存在 nginx.conf 文件 43 | find /etc -name "nginx.conf" 44 | # 查找log目录 45 | find / -type d -name "log" 46 | ``` 47 | 48 | -------------------------------------------------------------------------------- /D类/D13-实践与笔记/04-Git使用笔记.md: -------------------------------------------------------------------------------- 1 | ## 一、分支操作 2 | 3 | ### 合并分支,将 feature-a 合并到 develop 4 | 5 | ```shell 6 | # 切换到 develop 7 | git checkout develop 8 | git pull 9 | # 将 feature-a 分支合并到 develop 10 | git merge --no-ff origin/feature-a 11 | ``` 12 | 13 | ### 删除远端分支 14 | 15 | ```shell 16 | git push origin --delete feature-a 17 | ``` 18 | 19 | 20 | 21 | ## 二、日志操作 22 | 23 | 查看日志 24 | 25 | ```shell 26 | $ git log --pretty=oneline 27 | 185ad4681b2f75867ff640d341ddc4d60bf24a51 (HEAD -> master, origin/master) 1.5.0-SNAPSHOT 28 | cfdd931caeb3eeb0cf011abaec2875acf4748b35 (tag: v1.4.1) 1.4.1版本 29 | 0279906190bb2abdc1bfb3573fffc9554518239f 升级1.5.0-SNAPSHOT 30 | fb7e7527dc8da20e69b6b2b02f0118985bcba03a merge release-Aston51 to develop 31 | ... 32 | ``` 33 | 34 | ## 三、标签操作 35 | 36 | ### 查看 tag 37 | 38 | ```shell 39 | $ git tag 40 | V1.0.3 41 | v1.0.0 42 | v1.0.0C01 43 | v1.0.1 44 | v1.0.2 45 | v1.0.4 46 | v1.1.0 47 | ``` 48 | 49 | ### 查看 tag,带上 tag message 50 | 51 | ```shell 52 | $ git tag -n1 53 | V1.0.3 消息可视化 54 | v1.0.0 正式版本 55 | v1.0.0C01 正式版本 56 | v1.0.1 v1.0.1 正式版本 57 | v1.0.2 正式版本 58 | v1.0.4 20迭代 正式版本 59 | v1.1.0 22迭代正式版本 60 | ``` 61 | 62 | ### 查看 tag 的详细信息 63 | 64 | ```shell 65 | $ git show v1.4 66 | tag v1.4 67 | Tagger: Ben Straub 68 | Date: Sat May 3 20:19:12 2014 -0700 69 | 70 | my version 1.4 71 | 72 | commit ca82a6dff817ec66f44342007202690a93763949 73 | Author: Scott Chacon 74 | Date: Mon Mar 17 21:52:11 2008 -0700 75 | 76 | changed the version number 77 | ``` 78 | 79 | ### tag 数量很多,如果只对 v1.0 系列感兴趣 80 | 81 | ```shell 82 | $ git tag -l v1.0* 83 | v1.0.0 84 | v1.0.0C01 85 | v1.0.1 86 | v1.0.2 87 | v1.0.4 88 | ``` 89 | 90 | ### 创建 tag 并推送至远端 91 | 92 | ```shell 93 | $ git tag -a v0.0.1 -m 'msg' 94 | $ git push origin v0.0.1 95 | ``` 96 | 97 | ### 轻量标签 98 | 99 | ```shell 100 | $ git tag v0.0.1-lw 101 | ``` 102 | 103 | ### 更新 tag 104 | 105 | ```shell 106 | $ git push origin --delete v0.0.1 107 | $ git log --pretty=oneline 108 | 15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch 'experiment' 109 | a6b4c97498bd301d84096da251c98a07c7723e65 beginning write support 110 | 0d52aaab4479697da7686c15f77a3d64d9165190 one more thing 111 | 6d52a271eda8725415634dd79daabbc4d9b6008e Merge branch 'experiment' 112 | 0b7434d86859cc7b8c3d5e1dddfed66ff742fcbc added a commit function 113 | 4682c3261057305bdd616e23b64b0857d832627b added a todo file 114 | 166ae0c4d3f420721acbb115cc33848dfcc2121a started write support 115 | 9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile 116 | 964f16d36dfccde844893cac5b347e7b3d44abbc commit the todo 117 | 8a5cbc430f1a9c3d00faaeffd07798508422908a updated readme 118 | $ git tag -a v0.0.1 9fceb02 119 | $ git push origin v0.0.1 120 | ``` 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /D类/D13-实践与笔记/05-SQL使用笔记.md: -------------------------------------------------------------------------------- 1 | ## 一、统计失败的日期范围 2 | 3 | ```sql 4 | SELECT MIN(created_at), MAX(created_at) FROM fail_message; 5 | ``` 6 | 7 | ## 二、按日期统计消费失败记录数 8 | 9 | ```sql 10 | SELECT DATE_FORMAT(created_at, '%Y-%m-%d'), COUNT(*) 11 | FROM fail_message 12 | GROUP BY DATE_FORMAT(created_at, '%Y-%m-%d'); 13 | ``` 14 | 15 | ## 三、统计失败原因 16 | 17 | ```sql 18 | SELECT reason, count(*) 19 | FROM fail_message 20 | WHERE created_at BETWEEN '2021-01-04 00:00:00' AND '2021-01-04 23:59:59' 21 | GROUP BY right(reason, 100); 22 | ``` 23 | 24 | -------------------------------------------------------------------------------- /D类/D13-实践与笔记/06-Node使用笔记.md: -------------------------------------------------------------------------------- 1 | ## 一、管理npm镜像 2 | 3 | 安装nrm 4 | 5 | ``` 6 | npm install -g nrm 7 | ``` 8 | 9 | 设置镜像 10 | 11 | ```shell 12 | #设置淘宝镜像 13 | npm config set registry http://registry.npm.taobao.org 14 | #查看 15 | npm get registry 16 | ``` 17 | 18 | 查看可使用的镜像地址 19 | 20 | ```javascript 21 | nrm ls 22 | ``` 23 | 24 | 切换选择 25 | 26 | ``` 27 | nrm use cnpm 28 | ``` 29 | 30 | ## 二、管理Node版本 31 | 32 | 安装n 33 | 34 | ``` 35 | npm install -g n 36 | ``` 37 | 38 | 管理本地node 39 | 40 | ```shell 41 | # 列出目前已经安装的 `Node.js` 版本 42 | n ls 43 | # 列出远程所有的 `Node.js` 版本(可以通过 `--all` 列举所有的) 44 | n ls-remote 45 | 46 | # 安装指定版本 47 | sudo n 16.10.0 48 | #安装最新正式发布版本 49 | sudo n latest 50 | # 安装最新的长期支持正式发布版本 51 | sudo n lts 52 | 53 | #切换版本 54 | sudo n 55 | 56 | # 卸载版本 57 | sudo n rm 12.22.1 58 | 59 | # 查看你当前的node版本 60 | node -v 61 | ``` 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /D类/D13-实践与笔记/07-Docker使用笔记.md: -------------------------------------------------------------------------------- 1 | ## 一、下载镜像 2 | 3 | 选择镜像网站:docker.1ms.run 4 | 5 | ``` 6 | docker pull docker.1ms.run/zookeeper:latest 7 | ``` 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /D类/D13-实践与笔记/08-SonarLint使用笔记.md: -------------------------------------------------------------------------------- 1 | ## 一、忽略代码扫描 2 | 3 | ### 1.1 标准SonarQube注释方式 4 | 5 | #### 忽略单个规则 6 | 7 | ```java 8 | @SuppressWarnings("java:S1234") // 忽略特定规则 9 | public void methodWithIssue() { 10 | // 有问题的代码 11 | } 12 | ``` 13 | 14 | #### 忽略多个规则 15 | 16 | ```java 17 | @SuppressWarnings({"java:S1234", "java:S5678"}) // 忽略多个规则 18 | public void methodWithMultipleIssues() { 19 | // 有问题的代码 20 | } 21 | ``` 22 | 23 | #### 忽略文件中的所有问题 24 | 25 | ```java 26 | @SuppressWarnings("all") // 忽略整个文件中的所有问题 27 | public class ClassWithIssues { 28 | // 类内容 29 | } 30 | ``` 31 | 32 | ### 1.2 SonarLint专用注释 33 | 34 | #### 针对代码块 35 | 36 | ```java 37 | // sonarignore:start 38 | public void problematicMethod() { 39 | // 这段代码将被SonarLint忽略 40 | } 41 | // sonarignore:end 42 | ``` 43 | 44 | #### 针对特定规则 45 | 46 | ```java 47 | // sonarignore:ruleKey S1234 48 | public void methodWithSpecificIssue() { 49 | // 仅忽略S1234规则的代码 50 | } 51 | ``` 52 | 53 | ### 1.3 行内忽略 54 | 55 | ```java 56 | public void someMethod() { 57 | String password = "123456"; // NOSONAR - 忽略这一行的所有问题 58 | int unusedVar = 42; // sonarignore:ruleKey S1481 - 仅忽略未使用变量警告 59 | } 60 | ``` 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /D类/D13-实践与笔记/clone.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # git@github.com:studeyang/blog.git 4 | url=$1 5 | 6 | # 1. git clone 7 | git clone $url 8 | 9 | # 2. cut dir 10 | 11 | # blog.git 12 | dir_git=${url##*/} 13 | # blog 14 | dir=${dir_git%.*} 15 | 16 | # 3. git config 17 | cd $dir 18 | git config --local user.name studeyang 19 | git config --local user.email studeyang@gmail.com 20 | 21 | echo "clone success: $url" 22 | -------------------------------------------------------------------------------- /D类/D13-实践与笔记/惊奇代码-Disconf.md: -------------------------------------------------------------------------------- 1 | ## 一、Disconf 2 | 3 | 手动注入配置值。 4 | 5 | ```java 6 | package com.fcbox.send.order.encrypt; 7 | 8 | import com.baidu.disconf.client.store.DisconfStoreProcessor; 9 | import com.baidu.disconf.client.store.DisconfStoreProcessorFactory; 10 | import com.baidu.disconf.client.store.processor.model.DisconfValue; 11 | 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | public class DisconfMock { 16 | 17 | private static final DisconfStoreProcessor disconfStoreProcessor = DisconfStoreProcessorFactory.getDisconfStoreFileProcessor(); 18 | 19 | public static void mockConfig(Integer value) { 20 | Map fileData = new HashMap<>(); 21 | fileData.put("write.encrypt.switch", String.valueOf(value)); 22 | disconfStoreProcessor.inject2Store("encrypt.properties", new DisconfValue(null, fileData)); 23 | } 24 | } 25 | ``` 26 | 27 | -------------------------------------------------------------------------------- /D类/D13-实践与笔记/惊奇代码-Java8.md: -------------------------------------------------------------------------------- 1 | ## 一、使用 Stream 实现 List 转 Map 2 | 3 | ### Value 对象类型不变 4 | 5 | ```java 6 | /* 7 | [ 8 | {"id": "100", "type": "created"}, 9 | {"id": "101", "type": "update"}, 10 | ] 11 | */ 12 | List messages = new ArrayList<>(); 13 | /* 14 | id -> {"id": "100", "type": "created"} 15 | */ 16 | Map map = messages.stream() 17 | .collect(Collectors.toMap(Message::getId, Function.identity())); 18 | ``` 19 | 20 | ### Value 对象类型转化 21 | 22 | ```java 23 | /* 24 | [ 25 | {"id": "100", "type": "created"}, 26 | {"id": "101", "type": "update"}, 27 | ] 28 | */ 29 | List messages = new ArrayList<>(); 30 | /* 31 | id -> type 32 | */ 33 | Map map = messages.stream() 34 | .collect(Collectors.toMap(Message::getId, Message::getType)); 35 | ``` 36 | 37 | ### 对象分组 38 | 39 | ```java 40 | /* 41 | [ 42 | {"id": "100", "type": "created"}, 43 | {"id": "100", "type": "update"} 44 | ] 45 | */ 46 | List messages = new ArrayList<>(); 47 | /* 48 | id -> [ 49 | {"id": "100", "type": "created"}, 50 | {"id": "100", "type": "created"} 51 | ] 52 | */ 53 | Map> map = messages.stream() 54 | .collect(Collectors.groupingBy(Message::getId)); 55 | ``` 56 | 57 | ## 二、使用 CompletableFuture 分批并发执行 58 | 59 | ### Usage 60 | 61 | ```java 62 | public static void main(String[] args) { 63 | 64 | Function function = billGroupId -> () -> { 65 | // long time to execute 66 | }; 67 | new HandleAfterRepayProcessor(getMetadata(), function, 50).process(); 68 | } 69 | ``` 70 | 71 | ### processor 72 | 73 | ```java 74 | package com.casstime.ec.cloud.service.biz; 75 | 76 | import com.google.common.collect.Lists; 77 | import lombok.extern.slf4j.Slf4j; 78 | import org.springframework.scheduling.concurrent.CustomizableThreadFactory; 79 | 80 | import java.util.List; 81 | import java.util.concurrent.*; 82 | import java.util.function.Function; 83 | import java.util.stream.Collectors; 84 | 85 | /** 86 | * @since 1.0 2023/6/6 87 | */ 88 | @Slf4j 89 | public class HandleAfterRepayProcessor { 90 | 91 | private final List> partitions; 92 | private final Function taskFunction; 93 | private final ExecutorService executorService; 94 | 95 | public HandleAfterRepayProcessor(List metadata, 96 | Function taskFunction, 97 | int partition) { 98 | this.partitions = Lists.partition(metadata, partition); 99 | this.taskFunction = taskFunction; 100 | this.executorService = new ThreadPoolExecutor( 101 | partition, 102 | partition, 103 | 0L, 104 | TimeUnit.MILLISECONDS, 105 | new LinkedBlockingQueue<>(1000), 106 | new CustomizableThreadFactory("handle-after-repay-"), 107 | new ThreadPoolExecutor.CallerRunsPolicy() 108 | ); 109 | } 110 | 111 | public void process() { 112 | for (int i = 0; i < partitions.size(); i++) { 113 | List partition = partitions.get(i); 114 | CompletableFuture future = processPartition(partition); 115 | future.join(); 116 | int batch = i + 1; 117 | future.thenRun(() -> log.debug("第 {} 批, 处理完成 {} 条数据", batch, partition.size())); 118 | } 119 | executorService.shutdown(); 120 | } 121 | 122 | /** 123 | * 异步转同步 124 | */ 125 | private CompletableFuture processPartition(List metadata) { 126 | List> futures = metadata 127 | .stream() 128 | .map(taskFunction) 129 | .map(task -> CompletableFuture.runAsync(task, executorService)) 130 | .collect(Collectors.toList()); 131 | return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])); 132 | } 133 | 134 | } 135 | ``` 136 | 137 | ## 三、Java 8 Map 的优雅写法 138 | 139 | ### 添加元素 140 | 141 | ```java 142 | public class MapListExample { 143 | public static void main(String[] args) { 144 | // 创建一个Map> 145 | Map> map = new HashMap<>(); 146 | 147 | // 添加元素的示例 148 | map.computeIfAbsent("fruits", k -> new ArrayList<>()).add("Apple"); 149 | map.computeIfAbsent("fruits", k -> new ArrayList<>()).add("Banana"); 150 | map.computeIfAbsent("vegetables", k -> new ArrayList<>()).add("Carrot"); 151 | 152 | // 打印Map内容 153 | System.out.println("Map内容: " + map); 154 | } 155 | } 156 | 157 | // Map内容: {fruits=[Apple, Banana], vegetables=[Carrot]} 158 | ``` 159 | 160 | ### 收集 161 | 162 | ```java 163 | // List> 怎么收集到一个 List 中?用 Java8 实现 164 | 165 | List> listOfLists = Arrays.asList( 166 | Arrays.asList("a", "b"), 167 | Arrays.asList("c", "d", "e"), 168 | Collections.singletonList("f") 169 | ); 170 | 171 | List flattenedList = listOfLists.stream() 172 | .flatMap(List::stream) // 将每个内部List转换为流,然后合并 173 | .collect(Collectors.toList()); 174 | 175 | System.out.println(flattenedList); // 输出: [a, b, c, d, e, f] 176 | ``` 177 | 178 | -------------------------------------------------------------------------------- /D类/D14-行业视角/产品思维30讲-梁宁.md: -------------------------------------------------------------------------------- 1 | # 导读:《梁宁·产品思维30讲》学习指南 2 | 3 | 第一部分是“微观视角” 4 | 5 | - 模块1,同理心,引入心理学的概念,剖析人性; 6 | 7 | 第二部分是“中观视角",也就是日常产品工作视角 8 | 9 | - 模块2,机会判断,一套底层思维,三个具体方法,发现机会; 10 | - 模块3,系统能力,四个步骤,打造个人、公司核心能力; 11 | - 模块4,用户体验,五大具体方法,优化你的表达界面和产品体验; 12 | 13 | 第三部分是“宏观视角” 14 | 15 | - 模块5,创新模式,五个创新模式,洞悉顶级公司的创新战略。 16 | 17 | # 发刊词:产品能力是每个人的底层能力 18 | 19 | 通过这30讲,我希望帮助你拥有三个东西: 20 | 21 | 第一是一双眼睛,是发现痛点、找到破局点的敏锐之眼; 22 | 23 | 第二是一双手,是动手优化、着手改变的行动之手; 24 | 25 | 第三是一颗心,是洞察人性的同理心,懂得自己,懂得用户,懂得一个产品上,每个细微的小点给到人的满足感、确认感和依赖感。 26 | 27 | # 02案例:用户体验与结 婚教练 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /D类/D14-行业视角/技术文档写作规范.md: -------------------------------------------------------------------------------- 1 | > 参考资料:https://github.com/ruanyf/document-style-guide 2 | 3 | ## 一、标题 4 | 5 | ### 1.1 层级 6 | 7 | 标题分为四级。 8 | 9 | - 一级标题:文章的标题 10 | - 二级标题:文章主要部分的大标题 11 | - 三级标题:二级标题下面一级的小标题 12 | - 四级标题:三级标题下面某一方面的小标题 13 | 14 | ### 1.2 原则 15 | 16 | **1、标题不能跨级** 17 | 18 | 一级标题下,不能直接出现三级标题。 19 | 20 | 示例:下面的文章结构,缺少二级标题。 21 | 22 | ```markdown 23 | # 一级标题 24 | 25 | ### 三级标题 26 | ``` 27 | 28 | **2、避免同级标题只有一个** 29 | 30 | 示例:下面的文章结构,`二级标题 A`只包含一个三级标题,完全可以省略`三级标题 A`。 31 | 32 | ```markdown 33 | ## 二级标题 A 34 | 35 | ### 三级标题 A 36 | 37 | ## 二级标题 B 38 | ``` 39 | 40 | **3、下级标题不重复上一级标题的名字** 41 | 42 | 示例:下面的文章结构,二级标题与下属的三级标题同名,建议避免。 43 | 44 | ```markdown 45 | ## 概述 46 | 47 | ### 概述 48 | ``` 49 | 50 | **4、谨慎使用四级标题,尽量避免出现,保持层级的简单,防止出现过于复杂的章节。** 51 | 52 | 如果三级标题下有并列性的内容,建议只使用项目列表(Item list)。 53 | 54 | 示例:下面的结构二要好于结构一。结构一适用的场景,主要是较长篇幅的内容。 55 | 56 | ```markdown 57 | 结构一 58 | 59 | ### 三级标题 60 | 61 | #### 四级标题 A 62 | 63 | #### 四级标题 B 64 | 65 | #### 四级标题 C 66 | 67 | 结构二 68 | 69 | ### 三级标题 70 | 71 | **(1)A** 72 | 73 | **(2)B** 74 | 75 | **(3)C** 76 | ``` 77 | 78 | ## 二、文本 79 | 80 | ### 2.1 字间距 81 | 82 | **1、全角中文字符与半角英文字符之间,应有一个半角空格。** 83 | 84 | ``` 85 | 错误:本文介绍如何快速启动Windows系统。 86 | 87 | 正确:本文介绍如何快速启动 Windows 系统。 88 | ``` 89 | 90 | **2、全角中文字符与半角阿拉伯数字之间,有没有半角空格都可,但必须保证风格统一,不能两种风格混杂。** 91 | 92 | ``` 93 | 正确:2011年5月15日,我订购了5台笔记本电脑与10台平板电脑。 94 | 95 | 正确:2011 年 5 月 15 日,我订购了 5 台笔记本电脑与 10 台平板电脑。 96 | ``` 97 | 98 | 半角的百分号,视同阿拉伯数字。 99 | 100 | ``` 101 | 正确:今年我国经济增长率是6.5%。 102 | 103 | 正确:今年我国经济增长率是 6.5%。 104 | ``` 105 | 106 | ### 2.2 句子 107 | 108 | **1、避免使用长句。** 109 | 110 | 不包含任何标点符号的单个句子,或者以逗号分隔的句子构件,长度尽量保持在 20 个字以内;20~29 个字的句子,可以接受;30~39 个字的句子,语义必须明确,才能接受;多于 40 个字的句子,任何情况下都不能接受。 111 | 112 | ``` 113 | 错误:本产品适用于从由一台服务器进行动作控制的单一节点结构到由多台服务器进行动作控制的并行处理程序结构等多种体系结构。 114 | 115 | 正确:本产品适用于多种体系结构。无论是由一台服务器(单一节点结构),还是由多台服务器(并行处理结构)进行动作控制,均可以使用本产品。 116 | ``` 117 | 118 | 逗号分割的长句,总长度不应该超过 100 字或者正文的 3 行。 119 | 120 | **2、尽量使用简单句和并列句,避免使用复合句。** 121 | 122 | ``` 123 | 并列句:他昨天生病了,没有参加会议。 124 | 125 | 复合句:那个昨天生病的人没有参加会议。 126 | ``` 127 | 128 | **3、同样一个意思,尽量使用肯定句表达,不使用否定句表达。** 129 | 130 | ``` 131 | 错误:请确认没有接通装置的电源。 132 | 133 | 正确:请确认装置的电源已关闭。 134 | ``` 135 | 136 | **4、避免使用双重否定句。** 137 | 138 | ``` 139 | 错误:没有删除权限的用户,不能删除此文件。 140 | 141 | 正确:用户必须拥有删除权限,才能删除此文件。 142 | ``` 143 | 144 | ### 2.3 写作风格 145 | 146 | **1、尽量使用主动语句。** 147 | 148 | 尽量不使用被动语句,改为使用主动语句。 149 | 150 | ``` 151 | 错误:假如此软件尚未被安装, 152 | 153 | 正确:假如尚未安装这个软件, 154 | ``` 155 | 156 | **2、不使用冷僻、生造或者文言文的词语,而要使用现代汉语的常用表达方式。** 157 | 158 | ``` 159 | 错误:这是唯二的快速启动的方法。 160 | 161 | 正确:这是仅有的两种快速启动的方法。 162 | ``` 163 | 164 | **3、用对“的”、“地”、“得”。** 165 | 166 | ``` 167 | 她露出了开心的笑容。 168 | (形容词+的+名词) 169 | 170 | 她开心地笑了。 171 | (副词+地+动词) 172 | 173 | 她笑得很开心。 174 | (动词+得+副词) 175 | ``` 176 | 177 | **4、名词前不要使用过多的形容词。** 178 | 179 | ``` 180 | 错误:此设备的使用必须在接受过本公司举办的正式的设备培训的技师的指导下进行。 181 | 182 | 正确:此设备必须在技师的指导下使用,且指导技师必须接受过由本公司举办的正式设备培训。 183 | ``` 184 | 185 | ### 2.4 段落 186 | 187 | **1、一个段落只能有一个主题,或一个中心句子。** 188 | 189 | **2、段落的中心句子放在段首,对全段内容进行概述。后面陈述的句子为中心句子服务。** 190 | 191 | ## 三、标点符号 192 | 193 | ### 3.1 逗号 194 | 195 | **1、逗号(`,`)表示句子内部的一般性停顿。** 196 | 197 | **2、注意避免“一逗到底”,即整个段落除了结尾,全部停顿都使用逗号。** 198 | 199 | ### 3.2 顿号 200 | 201 | **1、句子内部的并列词,应该用全角顿号(`、`) 分隔,而不用逗号,即使并列词是英语也是如此。** 202 | 203 | ``` 204 | 错误:我最欣赏的科技公司有 Google, Facebook, 腾讯, 阿里和百度等。 205 | 206 | 正确:我最欣赏的科技公司有 Google、Facebook、腾讯、阿里和百度等。 207 | ``` 208 | 209 | **2、英文句子中,并列词语之间使用半角逗号(`,`)分隔。** 210 | 211 | ``` 212 | 例句:Microsoft Office includes Word, Excel, PowerPoint, Outlook and other components. 213 | ``` 214 | 215 | **3、中文句子内部的并列词,最后一个尽量使用(`和`)来连接,使句子读起来更加连贯,下面两个句子都可以,第二个更优。** 216 | 217 | ``` 218 | 正确:我最欣赏的科技公司有 Google、Facebook、腾讯、阿里,以及百度等。 219 | 220 | 正确:我最欣赏的科技公司有 Google、Facebook、腾讯、阿里和百度等。 221 | ``` 222 | 223 | ## 四、文档体系 224 | 225 | 软件手册是一部完整的书,建议采用下面的结构。 226 | 227 | - **简介**(Introduction):[必备] [文件] 提供对产品和文档本身的总体的、扼要的说明 228 | 229 | - **快速上手**(Getting Started):[可选] [文件] 如何最快速地使用产品 230 | 231 | - 入门篇 232 | 233 | (Basics):[必备] [目录] 又称“使用篇”,提供初级的使用教程 234 | 235 | - **环境准备**(Prerequisite):[必备] [文件] 软件使用需要满足的前置条件 236 | - **安装**(Installation):[可选] [文件] 软件的安装方法 237 | - **设置**(Configuration):[必备] [文件] 软件的设置 238 | 239 | - **进阶篇**(Advanced):[可选] [目录] 又称“开发篇”,提供中高级的开发教程 240 | 241 | - **API**(Reference):[可选] [目录|文件] 软件 API 的逐一介绍 242 | 243 | - **FAQ**:[可选] [文件] 常见问题解答 244 | 245 | - 附录 246 | 247 | (Appendix):[可选] [目录] 不属于教程本身、但对阅读教程有帮助的内容 248 | 249 | - **Glossary**:[可选] [文件] 名词解释 250 | - **Recipes**:[可选] [文件] 最佳实践 251 | - **Troubleshooting**:[可选] [文件] 故障处理 252 | - **ChangeLog**:[可选] [文件] 版本说明 253 | - **Feedback**:[可选] [文件] 反馈方式 254 | 255 | 下面是两个真实范例,可参考。 256 | 257 | - [Redux 手册](https://redux.js.org/introduction/getting-started) 258 | - [Atom 手册](http://flight-manual.atom.io/) 259 | 260 | ## 参考资料 261 | 262 | - [产品手册中文写作规范](https://www.taodocs.com/p-51273.html), by 华为 263 | - [写作规范和格式规范](http://guide.daocloud.io/dcs/写作规范和格式规范-9153803.html), by DaoCloud 264 | - [技术写作技巧在日汉翻译中的应用](http://www.hitachi-tc.co.jp/company/thesis/thesis.pdf), by 刘方 265 | - [简体中文规范指南](https://www.lengoo.de/documents/styleguides/lengoo_styleguide_ZH.pdf), by lengoo 266 | - [文档风格指南](https://open.leancloud.cn/copywriting-style-guide.html), by LeanCloud 267 | - [豌豆荚文案风格指南](https://docs.google.com/document/d/1R8lMCPf6zCD5KEA8ekZ5knK77iw9J-vJ6vEopPemqZM/edit), by 豌豆荚 268 | - [中文文案排版指北](https://github.com/sparanoid/chinese-copywriting-guidelines), by sparanoid 269 | - [中文排版需求](http://w3c.github.io/clreq/), by W3C 270 | - [Google Developer Documentation Style Guide](https://developers.google.com/style/), by Google 271 | - [出版物上数字用法的规定(国家标准GBT15835-2011)](http://www.moe.gov.cn/ewebeditor/uploadfile/2015/01/13/20150113091154536.pdf) 272 | - [GB 3100-1993 国际单位制及其应用](https://zh.wikisource.org/zh-hans/GB_3100-1993_国际单位制及其应用) 273 | 274 | -------------------------------------------------------------------------------- /D类/README.md: -------------------------------------------------------------------------------- 1 | # 扩展类 2 | 3 | 扩展类:杂项,需达到了解程度。 4 | -------------------------------------------------------------------------------- /D类/sidebar.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | - **GraphQL** 4 | - [graphql技术调研](D类/D01-GraphQL/[graphql.cn]-调研graphql技术.md) 5 | 6 | - **版本控制** 7 | - [Maven](D类/D02-版本控制/[RUNOOB]-Maven教程.md) 8 | 9 | - **软件工程** 10 | - [持续交付](D类/D03-软件工程/[极客时间]-持续交付.md) 11 | - [如何提高研发效率?](D类/D03-软件工程/[极客时间]-如何提高研发效率?.md) 12 | 13 | - **职业规划** 14 | - [程序员进阶攻略](D类/D04-职业规划/程序员进阶攻略.md) 15 | 16 | - **项目管理** 17 | - [项目管理实战训练](D类/D06-项目管理/[授客学堂]-项目管理实战训练.md) 18 | 19 | - **杂谈** 20 | - [中台](D类/D08-杂谈/[极客时间]-说透中台.md) 21 | - [海量数据处理](D类/D08-杂谈/[advanced-java]-海量数据处理.md) 22 | - [Info公开课](D类/D08-杂谈/InfoQ公开课.md) 23 | 24 | - **业务踩坑** 25 | - [Java开发常见错误-代码篇](D类/D10-业务踩坑/[极客时间]-Java开发常见错误-01代码篇.md) 26 | - [Java开发常见错误-设计篇](D类/D10-业务踩坑/[极客时间]-Java开发常见错误-02设计篇.md) 27 | 28 | - **最佳实践** 29 | - [Intellij Idea最佳实践](D类/D13-实践与笔记/01-Intellij-Idea最佳实践.md) 30 | - [Postman最佳实践](D类/D13-实践与笔记/02-Postman最佳实践.md) 31 | 32 | - **行业规范** 33 | - [技术文档写作规范](D类/D14-行业视角/技术文档写作规范.md) 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 互联网技术学习笔记 2 | 3 | 学习过程中的笔记。更好的阅读效果:https://studeyang.tech/technotes 4 | 5 | ## 如何搜索 6 | 7 | 1、使用 Github 自带的搜索。比如要搜索 redis: 8 | 9 | ![image-20230111101852521](https://technotes.oss-cn-shenzhen.aliyuncs.com/2023/image-20230111101852521.png) 10 | 11 | 2、使用 [Sourcegraph.com](https://sourcegraph.com/github.com/studeyang/technotes) 搜索。 12 | 13 | 3、将这个仓库克隆到本地,然后在仓库目录使用下面的命令。 14 | 15 | ```shell 16 | $ grep -nri [搜索词] docs | cat --number 17 | ``` 18 | 19 | 比如,搜索 redis 相关内容。 20 | 21 | ```shell 22 | $ grep -nri redis docs | cat --number 23 | ``` 24 | 25 | ## 简介 26 | 27 | ### 基础类 28 | 29 | [基础类](sidebar.md ':include') 30 | 31 | ### 进阶类 32 | 33 | [进阶类](B类/sidebar.md ':include') 34 | 35 | ### 架构类 36 | 37 | [架构类](C类/sidebar.md ':include') 38 | 39 | ### 扩展类 40 | 41 | [扩展类](D类/sidebar.md ':include') 42 | 43 | ## 技术支持 44 | 45 | - Apollo:https://github.com/apolloconfig/apollo/tree/master/docs 46 | - Docsify:https://docsify.js.org/#/zh-cn/ 47 | 48 | ## 每周分享 49 | 50 | 在学习过程中,如果遇到有深度、有帮助的内容,我会以文章的形式分享出来,内容会发表在我的[公众号](https://mp.weixin.qq.com/s/TWRVaQPhrQf9oPxsAsuIKQ)、[掘金](https://juejin.cn/user/2594503173605767/posts)和[今日头条](https://www.toutiao.com/c/user/token/MS4wLjABAAAArFlpgpSvRI74ttxw76bAENUnFIFcYTJQnZYS77fZmNQ/?source=mp_msg&tab=article),也会维护在 Github:[studeyang/leanrning-share](https://github.com/studeyang/learning-share)。 51 | 52 | 公众号可通过微信搜索「杨同学technotes」或者扫下面的二维码,即可关注。 53 | 54 | ![微信公众号二维码](https://technotes.oss-cn-shenzhen.aliyuncs.com/2022/qrcode_for_gh_8d08add0e5a6_258.jpg) 55 | -------------------------------------------------------------------------------- /commit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | git add . 4 | git commit -m $1 5 | git push 6 | 7 | echo "\033[32m push success: $1 \033[0m" 8 | -------------------------------------------------------------------------------- /coverpage.md: -------------------------------------------------------------------------------- 1 | logo 2 | 3 | # 互联网技术学习笔记 4 | 5 | 涵盖基础知识、互联网进阶、架构视角、行业观等内容 6 | 7 | [Get Started](README) 8 | [GitHub](https://github.com/studeyang/technotes.git) 9 | 10 | -------------------------------------------------------------------------------- /generate_sitemap.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import os 3 | 4 | url = 'https://studeyang.tech/technotes/#' 5 | exclude_files = [ 6 | 'coverpage', 'navbar', 'README', 'sidebar', 7 | 'A类/README', 'A类/Python/README', 'A类/Python/sidebar', 8 | 'B类/README', 'B类/sidebar', 9 | 'C类/README', 'C类/sidebar', 10 | 'D类/README', 'D类/sidebar', 'D类/D04-职业规划/20180808知识地图认定--整理', 'D类/D04-职业规划/202009月知识梳理计划', 'D类/D04-职业规划/202010月面试计划', 11 | 'D类/D07-anki/知识转Anki进度', 'D类/D08-杂谈/一些idea', 'D类/D08-杂谈/面试题', 12 | '资源/学习资源' 13 | ] 14 | 15 | 16 | def create_sitemap(): 17 | xml = '\n' 18 | xml += '\n' 19 | txt = '' 20 | for path, dirs, files in os.walk("./"): 21 | for file in files: 22 | if not file.endswith('.md'): 23 | continue 24 | try: 25 | if not path.endswith('/'): 26 | path += '/' 27 | new_path = (path.replace('\\', '/') + file)[2:-3] 28 | if new_path in exclude_files: 29 | continue 30 | print(new_path) 31 | txt += f'{url}/{new_path}\n' 32 | xml += ' \n' 33 | xml += f' {url}/{new_path}\n' 34 | lastmod = datetime.datetime.utcfromtimestamp(os.path.getmtime(path + file)).strftime('%Y-%m-%d') 35 | xml += f' {lastmod}\n' 36 | xml += ' monthly\n' 37 | xml += ' 0.5\n' 38 | xml += ' \n' 39 | except Exception as e: 40 | print(path, file, e) 41 | break 42 | xml += f'\n' 43 | 44 | with open('./sitemap.xml', 'w', encoding='utf-8') as sitemap: 45 | sitemap.write(xml) 46 | with open('./sitemap.txt', 'w', encoding='utf-8') as sitemap: 47 | sitemap.write(txt) 48 | 49 | 50 | if __name__ == '__main__': 51 | create_sitemap() 52 | -------------------------------------------------------------------------------- /img/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/img/cover.jpg -------------------------------------------------------------------------------- /img/cover2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/img/cover2.jpeg -------------------------------------------------------------------------------- /img/cover3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/img/cover3.jpg -------------------------------------------------------------------------------- /img/cover4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/img/cover4.jpg -------------------------------------------------------------------------------- /img/my_favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/img/my_favicon.ico -------------------------------------------------------------------------------- /img/my_favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/img/my_favicon.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 互联网技术学习笔记 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 24 | 25 | 26 |
加载中...
27 | 28 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /navbar.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | - [基础知识](sidebar.md) 4 | 5 | 6 | - [互联网进阶](B类/sidebar.md) 7 | - [架构视角](C类/sidebar.md) 8 | - [行业观](D类/sidebar.md) 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /sidebar.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | - **Java并发编程** 4 | - [并发理论基础](A类/A01-Java并发编程/[极客时间]-Java并发编程-第1部分-并发理论基础.md "并发编程理论基础") 5 | - [并发工具类](A类/A01-Java并发编程/[极客时间]-Java并发编程-第2部分-并发工具类.md "Java并发编程的工具类") 6 | - [并发设计模式](A类/A01-Java并发编程/[极客时间]-Java并发编程-第3部分-并发设计模式.md "并发编程的设计模式") 7 | - [案例分析](A类/A01-Java并发编程/[极客时间]-Java并发编程-第4部分-案例分析.md "并发编程案例分析") 8 | 9 | - **Java虚拟机** 10 | - [深入拆解Java虚拟机-基本原理](A类/A02-Java虚拟机/[极客时间]-深入拆解Java虚拟机-01基本原理.md) 11 | - [深入浅出Java虚拟机](A类/A02-Java虚拟机/[拉勾教育]-深入浅出Java虚拟机.md) 12 | 13 | - **MySQL** 14 | - [MySQL实战-基础篇](A类/A03-MySQL/[极客时间]-MySQL实战-01基础篇.md) 15 | - [MySQL实战-实践篇](A类/A03-MySQL/[极客时间]-MySQL实战-02实践篇.md) 16 | - [高性能MySQL实战-基础篇](A类/A03-MySQL/[拉勾教育]-高性能MySQL实战-01基础篇.md) 17 | 18 | - **网络协议** 19 | - [趣谈网络协议](A类/A04-网络协议/[极客时间]-趣谈网络协议.md) 20 | - [透视HTTP协议-01破冰篇](A类/A04-网络协议/[极客时间]透视HTTP协议-01破冰篇.md) 21 | - [透视HTTP协议-02基础篇](A类/A04-网络协议/[极客时间]透视HTTP协议-02基础篇.md) 22 | - [透视HTTP协议-03进阶篇](A类/A04-网络协议/[极客时间]透视HTTP协议-03进阶篇.md) 23 | - [透视HTTP协议-04安全篇](A类/A04-网络协议/[极客时间]透视HTTP协议-04安全篇.md) 24 | - [面试题](A类/A04-网络协议/面试题.md) 25 | 26 | - **数据结构与算法** 27 | - [数据结构与算法之美](A类/A05-数据结构与算法/[极客时间]-数据结构与算法之美.md) 28 | 29 | - **前端** 30 | - [重学前端](A类/A06-前端/[极客时间]-重学前端.md) 31 | - [React实战进阶](A类/A06-前端/[极客时间]-React实战进阶.md) 32 | 33 | - **Java** 34 | - [深入剖析Java新特性](A类/A07-Java/深入剖析Java新特性-模块1-提升编码效率.md) 35 | 36 | - 零基础学Python 37 | - [01 | Python介绍与安装](A类/Python/零基础学Python/01Python介绍与安装.md) 38 | - [02 | 变量、数字、序列、映射和集合](A类/Python/零基础学Python/02变量、数字、序列、映射和集合.md) 39 | - [03 | 条件和循环.md](A类/Python/零基础学Python/03条件和循环.md) 40 | - [04 | 文件、输入输出、异常](A类/Python/零基础学Python/04文件、输入输出、异常.md) 41 | - [05 | 函数、模块.md](A类/Python/零基础学Python/05函数、模块.md) 42 | - [06 | 面向对象编程](A类/Python/零基础学Python/06面向对象编程.md) 43 | - [07 | 多线程编程](A类/Python/零基础学Python/07多线程编程.md) 44 | - [08 | 标准库、机器学习库](A类/Python/零基础学Python/08标准库、机器学习库.md) 45 | - [09 | 第三方库](A类/Python/零基础学Python/09第三方库.md) 46 | 47 | - Python核心技术与实战 48 | - [Python核心技术与实战-基础篇](A类/Python/Python核心技术与实战/Python核心技术与实战-基础篇.md) -------------------------------------------------------------------------------- /sitemap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sitemap="sitemap.xml" 4 | website_link="https://studeyang.tech/technotes" 5 | ignore=( 6 | sidebar.md 7 | A类/Python/sidebar.md 8 | B类/sidebar.md 9 | C类/sidebar.md 10 | D类/sidebar.md 11 | README.md 12 | A类/Python/README.md 13 | A类/README.md 14 | B类/README.md 15 | C类/README.md 16 | D类/README.md 17 | coverpage.md 18 | navbar.md 19 | ) 20 | 21 | urlencode() { 22 | local length="${#1}" 23 | for ((i = 0; i < length; i++)); do 24 | local c="${1:i:1}" 25 | case $c in 26 | [a-zA-Z0-9.~_+-/]) printf "$c" ;; 27 | *) printf "$c" | xxd -p -c1 | while read x; do printf "%%%s" "$x"; done ;; 28 | esac 29 | done 30 | } 31 | files=$( 32 | git ls-files -z '*.md' | 33 | xargs -0 -n1 -I{} -- git log -1 --format="%at {}" {} | 34 | sort -r | 35 | cut -d " " -f2- 36 | ) 37 | 38 | items="" 39 | for file in ${files[@]}; do 40 | [[ ${ignore[@]/${file}/} != ${ignore[@]} ]] && continue 41 | echo $file 42 | encode=$(urlencode "${file::-3}") 43 | link="$website_link/#/$encode" 44 | date=$(git log -1 --format="%ad" --date="iso-strict-local" -- $file) 45 | item=" 46 | 47 | $link 48 | $date 49 | 50 | " 51 | items="$items $item" 52 | done 53 | 54 | now=$(git log -1 --format="%ad" --date="iso-strict-local") 55 | sitemap_content=" 56 | 57 | 58 | $website_link 59 | $now 60 | 61 | $items 62 | " 63 | 64 | echo "$sitemap_content" >$sitemap 65 | -------------------------------------------------------------------------------- /技术笔记.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studeyang/technotes/2e88c212c14242cb24ff48a5afba4858f2bbdc47/技术笔记.xmind -------------------------------------------------------------------------------- /资源/学习资源.md: -------------------------------------------------------------------------------- 1 | ## 01 系统架构师 2 | 3 | ![资源概览](https://technotes.oss-cn-shenzhen.aliyuncs.com/2022/image-20221129193357995.png) 4 | 5 | > 领取地址:https://www.aliyundrive.com/s/9QVT8bu35bn 6 | 7 | ## 02 技术类电子书 8 | 9 | ![资源概览](https://technotes.oss-cn-shenzhen.aliyuncs.com/2022/image-20221129191924796.png) 10 | 11 | > 领取地址:https://www.aliyundrive.com/s/GFznn8hSu4W 12 | 13 | ## 03 面试资料 14 | 15 | > **651页Java面试题库** 16 | > 17 | > - 链接: https://pan.baidu.com/s/13XVhNG2sB9k-8v9G-kDPXQ?pwd=24m4 18 | > 19 | > **SQL面试必知100问** 20 | > 21 | > - 链接: https://pan.baidu.com/s/1_lbOWLVoqIlfi1mkNgmkpw?pwd=72sb 22 | > 23 | > **剑指Java面试-Offer直通车** 24 | > 25 | > - 链接:https://pan.baidu.com/s/1xSsewyRMcQnGGXQR-8auNg?pwd=z3co 26 | 27 | ## 04 编程视频 28 | 29 | > **Vue3实战商城后台管理系统开发** 30 | > 31 | > - 链接: https://pan.baidu.com/s/1DkuudwIr7-ManQpW14o8bQ?pwd=sc7c 提取码: sc7c 32 | > 33 | > **Three.js企业3D可视化系统项目实战** 34 | > 35 | > - 链接: https://pan.baidu.com/s/1UCdH7pVMoNDSIEPmjhX2Aw?pwd=we52 提取码: we52 36 | > 37 | > **淘淘商城** 38 | > 39 | > - 链接: https://pan.baidu.com/s/11RNihtXha0WMuF24fAjfCQ 密码: t5pa 40 | > 41 | > **Java 大数据高并发系统架构实战** 42 | > 43 | > - 链接: https://pan.baidu.com/s/1UXcqHgGywHYk9z7EFUE37g 提取码: 9mr3 44 | > 45 | > **Vue.js 高仿饿了么外卖App** 46 | > 47 | > - 链接: https://pan.baidu.com/s/12jfVVLM5WXJSi54mfyw1VQ 提取码: cvpf 48 | > 49 | > **微服务架构的分布式事务解决方案** 50 | > 51 | > - 链接: https://pan.baidu.com/s/17GEmCvAD2wBlNxn1vqOAxQ 提取码: vquf 52 | > 53 | > **Java 在线支付实战-微信支付** 54 | > 55 | > - 链接: https://pan.baidu.com/s/1tGA0y-Va2rY3uKFPzyo3yw 提取码: dba1 56 | > 57 | > **基于SpringBoot+MyBatis+Vue的音乐网站** 58 | > 59 | > - 链接: https://pan.baidu.com/s/14pkRxSTEhmfHl55xBiNfpg 提取码: 04jj 60 | > 61 | > **SpringCloud+Dubbo+K8S+ELK 生产级实践指南,从部署到核心应用** 62 | > 63 | > - 链接: https://pan.baidu.com/s/1fo5hrLaX_D5F-TXC8-GlJw 提取码: ku78 64 | > 65 | > **Docker 与微服务实战 95讲(2022版)** 66 | > 67 | > - 链接: https://pan.baidu.com/s/1EfglFPbMhVam3WM0aSDJhg?pwd=k6gl 提取码: k6gl 68 | > 69 | > **SpringCcloud+Kubernetes 微服务的容器化持续交付** 70 | > 71 | > - 链接: https://pan.baidu.com/s/1kQwwZhgh-WqvwQCiYJc_fg?pwd=038i 提取码: 038i 72 | > 73 | > **SpringBoot 通用版,电商支付实战+电商平台双系统** 74 | > 75 | > - 链接: https://pan.baidu.com/s/1Q_xkZSBR3ddm_V_8iv3GnQ?pwd=ewia 提取码: ewia 76 | > 77 | > **87讲的 SpringBoot 2.4 从实战到源码分析** 78 | > 79 | > - 链接: https://pan.baidu.com/s/1UATQY7d_FGvzFeM2CktvRg?pwd=ie54 提取码: ie54 80 | > 81 | > **SpringBoot +MyBatis-Plus 微信支付** 82 | > 83 | > - 链接: https://pan.baidu.com/s/117qnMzeg3wGxx8wW5rHAFA?pwd=557g 提取码: 557g 84 | > 85 | > **SpringBoot 通用权限系统** 86 | > 87 | > - 链接: https://pan.baidu.com/s/1LLclJV25zeCcrh7zZodTIw?pwd=pot6 提取码: pot6 88 | > 89 | > **170讲Dubbo 3 源码深度剖析 2022年** 90 | > 91 | > - 链接:https://pan.baidu.com/s/1lvU9zVtkOKlXmZc1mL99rA?pwd=k978 提取码:k978 92 | > 93 | > **【120讲】全方位深入解析最新版SpringBoot源码新手都能学懂** 94 | > 95 | > - 链接: https://pan.baidu.com/s/1Pz-TsVgatogO1XQ-xm1Kjg?pwd=kol1 提取码: kol1 96 | 97 | ## 05 技能图谱 98 | 99 | ![image-20221129193429466](https://technotes.oss-cn-shenzhen.aliyuncs.com/2022/image-20221129193429466.png) 100 | 101 | > 领取地址:https://www.aliyundrive.com/s/cqkFMbUz3qz 102 | 103 | ## 06 技术手册 104 | 105 | > **最新版数据结构与算法面试题手册** 106 | > 107 | > - 链接: https://pan.baidu.com/s/1Sk9gIBYi2hcK1wlZ2eNr6w?pwd=aydf 108 | > 109 | > **前端开发者手册** 110 | > 111 | > - 链接: https://pan.baidu.com/s/1Oq9GP0LuGnOdiBuUkGDuqQ?pwd=qrmh 112 | > 113 | > **23种设计模式整理** 114 | > 115 | > - 链接: https://pan.baidu.com/s/1yHT2yONIQJq-BR981YUzKA?pwd=n6nj 116 | > 117 | > **Linux学习笔记(强悍总结值得一看)** 118 | > 119 | > - 链接: https://pan.baidu.com/s/16rNeUwkUDGRb3ZlAUzAgug?pwd=62nz 120 | > 121 | > **阿里调优手册** 122 | > 123 | > - 链接: https://pan.baidu.com/s/1-l77Kg_x-Yu0sRhICS-J9g?pwd=ip2u 124 | > 125 | > **Redis全套学习笔记** 126 | > 127 | > - 链接: https://pan.baidu.com/s/1Uu72aJjNNKQJEbp1w6FQ0Q?pwd=4cen 128 | 129 | ## 07 源码资源 130 | 131 | > **用于快速开发、基于 Spring Cloud 开源分布式物联网(IOT)平台** 132 | > 133 | > - 链接:https://gitee.com/pnoker/dc3-web 134 | > 135 | > **企业级聚合支付项目** 136 | > 137 | > - 链接:https://gitee.com/jeequan/jeepay 138 | > 139 | > **SpringBoot+代码生成器的快速开发平台** 140 | > 141 | > - 链接:https://github.com/jeecgboot/jeecg-boot 142 | > 143 | > **SpringBoot+Vue 前后端分离手机商城系统** 144 | > 145 | > - 链接:https://gitee.com/guchengwuyue/yshopmall 146 | > 147 | > **SpringCloud+Vue 在线教育系统** 148 | > 149 | > - 链接:https://gitee.com/itxinfei/xuecheng-parent 150 | > 151 | > **商业级Java智慧小区物业项目** 152 | > 153 | > - HC小区后端代码:https://gitee.com/wuxw7/MicroCommunity 154 | > - WebHC智慧家庭(公众号和小程序):https://gitee.com/java110/WechatOwnerService 155 | > - HC掌上物业:https://gitee.com/java110/PropertyApp 156 | > 157 | > **高仿微信** 158 | > 159 | > - 开源链接:https://gitee.com/edceezyy/TLChat 160 | > 161 | > **CMS企业级 SpringBoot+Vue 网站生成神器** 162 | > 163 | > - 链接:http://gitee.com/mingSoft/MCMS 164 | 165 | ## 更多资源陆续准备中... 166 | 167 | 详情请关注公众号:杨同学technotes --------------------------------------------------------------------------------