diff --git a/docs/distributed-system/distributed-lock-implementations.md b/docs/distributed-system/distributed-lock-implementations.md index 2d1ec40cff4..cb4504c4a7a 100644 --- a/docs/distributed-system/distributed-lock-implementations.md +++ b/docs/distributed-system/distributed-lock-implementations.md @@ -202,13 +202,11 @@ Redlock 是直接操作 Redis 节点的,并不是通过 Redis 集群操作的 Redlock 实现比较复杂,性能比较差,发生时钟变迁的情况下还存在安全性隐患。《数据密集型应用系统设计》一书的作者 Martin Kleppmann 曾经专门发文([How to do distributed locking - Martin Kleppmann - 2016](https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html))怼过 Redlock,他认为这是一个很差的分布式锁实现。感兴趣的朋友可以看看[Redis 锁从面试连环炮聊到神仙打架](https://mp.weixin.qq.com/s?__biz=Mzg3NjU3NTkwMQ==&mid=2247505097&idx=1&sn=5c03cb769c4458350f4d4a321ad51f5a&source=41#wechat_redirect)这篇文章,有详细介绍到 antirez 和 Martin Kleppmann 关于 Redlock 的激烈辩论。 -实际项目中不建议使用 Redlock 算法,成本和收益不成正比。 - -如果不是非要实现绝对可靠的分布式锁的话,其实单机版 Redis 就完全够了,实现简单,性能也非常高。如果你必须要实现一个绝对可靠的分布式锁的话,可以基于 ZooKeeper 来做,只是性能会差一些。 +实际项目中不建议使用 Redlock 算法,成本和收益不成正比,可以考虑基于 Redis 主从复制+哨兵模式实现分布式锁。 ## 基于 ZooKeeper 实现分布式锁 -Redis 实现分布式锁性能较高,ZooKeeper 实现分布式锁可靠性更高。实际项目中,我们应该根据业务的具体需求来选择。 +ZooKeeper 相比于 Redis 实现分布式锁,除了提供相对更高的可靠性之外,在功能层面还有一个非常有用的特性:**Watch 机制**。这个机制可以用来实现公平的分布式锁。不过,使用 ZooKeeper 实现的分布式锁在性能方面相对较差,因此如果对性能要求比较高的话,ZooKeeper 可能就不太适合了。 ### 如何基于 ZooKeeper 实现分布式锁? @@ -365,14 +363,19 @@ private static class LockData ## 总结 -在这篇文章中,我介绍了实现分布式锁的两种常见方式: Redis 和 ZooKeeper。至于具体选择 Redis 还是 ZooKeeper 来实现分布式锁,还是要看业务的具体需求。 +在这篇文章中,我介绍了实现分布式锁的两种常见方式:**Redis** 和 **ZooKeeper**。至于具体选择 Redis 还是 ZooKeeper 来实现分布式锁,还是要根据业务的具体需求来决定。 + +- 如果对性能要求比较高的话,建议使用 Redis 实现分布式锁。推荐优先选择 **Redisson** 提供的现成分布式锁,而不是自己实现。实际项目中不建议使用 Redlock 算法,成本和收益不成正比,可以考虑基于 Redis 主从复制+哨兵模式实现分布式锁。 +- 如果对可靠性要求比较高,建议使用 ZooKeeper 实现分布式锁,推荐基于 **Curator** 框架来实现。不过,现在很多项目都不会用到 ZooKeeper,如果单纯是因为分布式锁而引入 ZooKeeper 的话,那是不太可取的,不建议这样做,为了一个小小的功能增加了系统的复杂度。 + +需要注意的是,无论选择哪种方式实现分布式锁,包括 Redis、ZooKeeper 或 Etcd(本文没介绍,但也经常用来实现分布式锁),都无法保证 100% 的安全性,特别是在遇到进程垃圾回收(GC)、网络延迟等异常情况下。 -- 如果对性能要求比较高的话,建议使用 Redis 实现分布式锁(优先选择 Redisson 提供的现成的分布式锁,而不是自己实现)。 -- 如果对可靠性要求比较高的话,建议使用 ZooKeeper 实现分布式锁(推荐基于 Curator 框架实现)。不过,现在很多项目都不会用到 ZooKeeper,如果单纯是因为分布式锁而引入 ZooKeeper 的话,那是不太可取的,不建议这样做,为了一个小小的功能增加了系统的复杂度。 +为了进一步提高系统的可靠性,建议引入一个兜底机制。例如,可以通过 **版本号(Fencing Token)机制** 来避免并发冲突。 -最后,再分享两篇我觉得写的还不错的文章: +最后,再分享几篇我觉得写的还不错的文章: - [分布式锁实现原理与最佳实践 - 阿里云开发者](https://mp.weixin.qq.com/s/JzCHpIOiFVmBoAko58ZuGw) - [聊聊分布式锁 - 字节跳动技术团队](https://mp.weixin.qq.com/s/-N4x6EkxwAYDGdJhwvmZLw) +- [Redis、ZooKeeper、Etcd,谁有最好用的分布式锁? - 腾讯云开发者](https://mp.weixin.qq.com/s/yZC6VJGxt1ANZkn0SljZBg) diff --git a/docs/high-quality-technical-articles/programmer/high-value-certifications-for-programmers.md b/docs/high-quality-technical-articles/programmer/high-value-certifications-for-programmers.md index 4d528716b36..7ea9f7932e0 100644 --- a/docs/high-quality-technical-articles/programmer/high-value-certifications-for-programmers.md +++ b/docs/high-quality-technical-articles/programmer/high-value-certifications-for-programmers.md @@ -13,19 +13,19 @@ tag: 全国计算机技术与软件专业技术资格(水平)考试,简称“软考”,是国内认可度较高的一项计算机技术资格认证。尽管一些人吐槽其实际价值,但在特定领域和情况下,它还是非常有用的,例如软考证书在国企和事业单位中具有较高的认可度、在某些城市软考证书可以用于积分落户、可用于个税补贴。 -软考有初、中、高三个级别,建议直接考高级。相比于PMP(项目管理专业人士认证),软考高项的难度更大,特别是论文部分,绝大部分人都挂在了论文部分。过了软考高项,在一些单位可以内部挂证,每个月多拿几百。 +软考有初、中、高三个级别,建议直接考高级。相比于 PMP(项目管理专业人士认证),软考高项的难度更大,特别是论文部分,绝大部分人都挂在了论文部分。过了软考高项,在一些单位可以内部挂证,每个月多拿几百。 ![软考高级证书](https://oss.javaguide.cn/github/javaguide/programmer-life/programmer-certification/ruankao-advanced-certification%20.jpg) 官网地址:。 -备考建议:[2024年上半年,一次通过软考高级架构师考试的备考秘诀 - 阿里云开发者](https://mp.weixin.qq.com/s/9aUXHJ7dXgrHuT19jRhCnw) +备考建议:[2024 年上半年,一次通过软考高级架构师考试的备考秘诀 - 阿里云开发者](https://mp.weixin.qq.com/s/9aUXHJ7dXgrHuT19jRhCnw) ## PAT 攀拓计算机能力测评(PAT)是一个专注于考察算法能力的测评体系,由浙江大学主办。该测评分为四个级别:基础级、乙级、甲级和顶级。 -通过PAT测评并达到联盟企业规定的相应评级和分数,可以跳过学历门槛,免除筛选简历和笔试环节,直接获得面试机会。具体有哪些公司可以去官网看看: 。 +通过 PAT 测评并达到联盟企业规定的相应评级和分数,可以跳过学历门槛,免除筛选简历和笔试环节,直接获得面试机会。具体有哪些公司可以去官网看看: 。 对于考研浙江大学的同学来说,PAT(甲级)成绩在一年内可以作为硕士研究生招生考试上机复试成绩。 @@ -33,7 +33,7 @@ tag: ## PMP -PMP(Project Management Professional)认证由美国项目管理协会(PMI)提供,是全球范围内认可度最高的项目管理专业人士资格认证。PMP认证旨在提升项目管理专业人士的知识和技能,确保项目顺利完成。 +PMP(Project Management Professional)认证由美国项目管理协会(PMI)提供,是全球范围内认可度最高的项目管理专业人士资格认证。PMP 认证旨在提升项目管理专业人士的知识和技能,确保项目顺利完成。 ![PMP 证书](https://oss.javaguide.cn/github/javaguide/programmer-life/programmer-certification/pmp-certification.png) @@ -45,11 +45,11 @@ PMP 是“一证在手,全球通用”的资格认证,对项目管理人士 ## ACP -ACP(Agile Certified Practitioner)认证同样由美国项目管理协会(PMI)提供,是项目管理领域的另一个重要认证。与PMP(Project Management Professional)注重传统的瀑布方法论不同,ACP专注于敏捷项目管理方法论,如Scrum、Kanban、Lean、Extreme Programming(XP)等。 +ACP(Agile Certified Practitioner)认证同样由美国项目管理协会(PMI)提供,是项目管理领域的另一个重要认证。与 PMP(Project Management Professional)注重传统的瀑布方法论不同,ACP 专注于敏捷项目管理方法论,如 Scrum、Kanban、Lean、Extreme Programming(XP)等。 ## OCP -Oracle Certified Professional(OCP)是Oracle公司提供的一项专业认证,专注于Oracle数据库及相关技术。这个认证旨在验证和认证个人在使用和管理Oracle数据库方面的专业知识和技能。 +Oracle Certified Professional(OCP)是 Oracle 公司提供的一项专业认证,专注于 Oracle 数据库及相关技术。这个认证旨在验证和认证个人在使用和管理 Oracle 数据库方面的专业知识和技能。 下图展示了 Oracle 认证的不同路径和相应的认证级别,分别是核心路径(Core Track)和专业路径(Speciality Track)。 @@ -57,7 +57,7 @@ Oracle Certified Professional(OCP)是Oracle公司提供的一项专业认证 ## 阿里云认证 -阿里云(Alibaba Cloud)提供的专业认证,认证方向包括云计算、大数据、人工智能、Devops等。职业认证分为 ACA、ACP、ACE 三个等级,除了职业认证之外,还有一个开发者Clouder认证,这是专门为开发者设立的专项技能认证。 +阿里云(Alibaba Cloud)提供的专业认证,认证方向包括云计算、大数据、人工智能、Devops 等。职业认证分为 ACA、ACP、ACE 三个等级,除了职业认证之外,还有一个开发者 Clouder 认证,这是专门为开发者设立的专项技能认证。 ![](https://oss.javaguide.cn/github/javaguide/programmer-life/programmer-certification/aliyun-professional-certification.png) @@ -65,13 +65,13 @@ Oracle Certified Professional(OCP)是Oracle公司提供的一项专业认证 ## 华为认证 -华为认证是由华为技术有限公司提供的面向ICT(信息与通信技术)领域的专业认证,认证方向包括网络、存储、云计算、大数据、人工智能等,非常庞大的认证体系。 +华为认证是由华为技术有限公司提供的面向 ICT(信息与通信技术)领域的专业认证,认证方向包括网络、存储、云计算、大数据、人工智能等,非常庞大的认证体系。 ![](https://oss.javaguide.cn/github/javaguide/programmer-life/programmer-certification/huawei-professional-certification.png) ## AWS 认证 -AWS云认证考试是AWS云计算服务的官方认证考试,旨在验证IT专业人士在设计、部署和管理AWS基础架构方面的技能。 +AWS 云认证考试是 AWS 云计算服务的官方认证考试,旨在验证 IT 专业人士在设计、部署和管理 AWS 基础架构方面的技能。 AWS 认证分为多个级别,包括基础级、从业者级、助理级、专业级和专家级(Specialty),涵盖多个角色和技能: @@ -80,7 +80,7 @@ AWS 认证分为多个级别,包括基础级、从业者级、助理级、专 - **专业级别**:包括 AWS Certified Solutions Architect – Professional 和 AWS Certified DevOps Engineer – Professional,适合高级专业人士,验证其在复杂和大规模 AWS 环境中的能力。 - **专家级别**:包括 AWS Certified Advanced Networking – Specialty、AWS Certified Big Data – Specialty 等,专注于特定技术领域的深度知识和技能。 -备考建议:[小白入门云计算的最佳方式,是去考一张AWS的证书(附备考经验)](https://mp.weixin.qq.com/s/xAqNOnfZ05GDRuUbAiMHIA) +备考建议:[小白入门云计算的最佳方式,是去考一张 AWS 的证书(附备考经验)](https://mp.weixin.qq.com/s/xAqNOnfZ05GDRuUbAiMHIA) ## Google Cloud 认证 @@ -111,4 +111,4 @@ Elastic 认证是由 Elastic 公司提供的一系列专业认证,旨在验证 ## 其他 - PostgreSQL 认证:国内的 PostgreSQL 认证分为专员级(PCA)、专家级(PCP)和大师级(PCM),主要考查 PostgreSQL 数据库管理和优化,价格略贵,不是很推荐。 -- Kubernetes 认证:Cloud Native Computing Foundation (CNCF) 提供了几个官方认证,例如Certified Kubernetes Administrator (CKA)、Certified Kubernetes Application Developer (CKAD),主要考察Kubernetes 方面的技能和知识。 +- Kubernetes 认证:Cloud Native Computing Foundation (CNCF) 提供了几个官方认证,例如 Certified Kubernetes Administrator (CKA)、Certified Kubernetes Application Developer (CKAD),主要考察 Kubernetes 方面的技能和知识。 diff --git a/docs/java/basis/java-basic-questions-01.md b/docs/java/basis/java-basic-questions-01.md index dabe3bfcf27..d140f9fcb0f 100644 --- a/docs/java/basis/java-basic-questions-01.md +++ b/docs/java/basis/java-basic-questions-01.md @@ -50,6 +50,8 @@ head: Java 虚拟机(Java Virtual Machine, JVM)是运行 Java 字节码的虚拟机。JVM 有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们都会给出相同的结果。字节码和不同系统的 JVM 实现是 Java 语言“一次编译,随处可以运行”的关键所在。 +如下图所示,不同编程语言(Java、Groovy、Kotlin、JRuby、Clojure ...)通过各自的编译器编译成 `.class` 文件,并最终通过 JVM 在不同平台(Windows、Mac、Linux)上运行。 + ![运行在 Java 虚拟机之上的编程语言](https://oss.javaguide.cn/github/javaguide/java/basis/java-virtual-machine-program-language-os.png) **JVM 并不是只有一种!只要满足 JVM 规范,每个公司、组织或者个人都可以开发自己的专属 JVM。** 也就是说我们平时接触到的 HotSpot VM 仅仅是是 JVM 规范的一种实现而已。 @@ -60,11 +62,18 @@ Java 虚拟机(Java Virtual Machine, JVM)是运行 Java 字节码的虚拟 #### JDK 和 JRE -JDK(Java Development Kit),它是功能齐全的 Java SDK,是提供给开发者使用,能够创建和编译 Java 程序的开发套件。它包含了 JRE,同时还包含了编译 java 源码的编译器 javac 以及一些其他工具比如 javadoc(文档注释工具)、jdb(调试器)、jconsole(基于 JMX 的可视化监控⼯具)、javap(反编译工具)等等。 +JDK(Java Development Kit)是一个功能齐全的 Java 开发工具包,供开发者使用,用于创建和编译 Java 程序。它包含了 JRE(Java Runtime Environment),以及编译器 javac 和其他工具,如 javadoc(文档生成器)、jdb(调试器)、jconsole(监控工具)、javap(反编译工具)等。 + +JRE 是运行已编译 Java 程序所需的环境,主要包含以下两个部分: + +1. **JVM** : 也就是我们上面提到的 Java 虚拟机。 +2. **Java 基础类库(Class Library)**:一组标准的类库,提供常用的功能和 API(如 I/O 操作、网络通信、数据结构等)。 -JRE(Java Runtime Environment) 是 Java 运行时环境。它是运行已编译 Java 程序所需的所有内容的集合,主要包括 Java 虚拟机(JVM)、Java 基础类库(Class Library)。 +简单来说,JRE 只包含运行 Java 程序所需的环境和类库,而 JDK 不仅包含 JRE,还包括用于开发和调试 Java 程序的工具。 -也就是说,JRE 是 Java 运行时环境,仅包含 Java 应用程序的运行时环境和必要的类库。而 JDK 则包含了 JRE,同时还包括了 javac、javadoc、jdb、jconsole、javap 等工具,可以用于 Java 应用程序的开发和调试。如果需要进行 Java 编程工作,比如编写和编译 Java 程序、使用 Java API 文档等,就需要安装 JDK。而对于某些需要使用 Java 特性的应用程序,如 JSP 转换为 Java Servlet、使用反射等,也需要 JDK 来编译和运行 Java 代码。因此,即使不打算进行 Java 应用程序的开发工作,也有可能需要安装 JDK。 +如果需要编写、编译 Java 程序或使用 Java API 文档,就需要安装 JDK。某些需要 Java 特性的应用程序(如 JSP 转换为 Servlet 或使用反射)也可能需要 JDK 来编译和运行 Java 代码。因此,即使不进行 Java 开发工作,有时也可能需要安装 JDK。 + +下图清晰展示了 JDK、JRE 和 JVM 的关系。 ![jdk-include-jre](https://oss.javaguide.cn/github/javaguide/java/basis/jdk-include-jre.png) @@ -272,9 +281,26 @@ Java 中的注释有三种: ### 自增自减运算符 -在写代码的过程中,常见的一种情况是需要某个整数类型变量增加 1 或减少 1,Java 提供了一种特殊的运算符,用于这种表达式,叫做自增运算符(++)和自减运算符(--)。 +在写代码的过程中,常见的一种情况是需要某个整数类型变量增加 1 或减少 1。Java 提供了自增运算符 (`++`) 和自减运算符 (`--`) 来简化这种操作。 + +`++` 和 `--` 运算符可以放在变量之前,也可以放在变量之后: + +- **前缀形式**(例如 `++a` 或 `--a`):先自增/自减变量的值,然后再使用该变量,例如,`b = ++a` 先将 `a` 增加 1,然后把增加后的值赋给 `b`。 +- **后缀形式**(例如 `a++` 或 `a--`):先使用变量的当前值,然后再自增/自减变量的值。例如,`b = a++` 先将 `a` 的当前值赋给 `b`,然后再将 `a` 增加 1。 + +为了方便记忆,可以使用下面的口诀:**符号在前就先加/减,符号在后就后加/减**。 + +下面来看一个考察自增自减运算符的高频笔试题:执行下面的代码后,`a` 、`b` 、 `c` 、`d`和`e`的值是? + +```java +int a = 9; +int b = a++; +int c = ++a; +int d = c--; +int e = --d; +``` -++ 和 -- 运算符可以放在变量之前,也可以放在变量之后,当运算符放在变量之前时(前缀),先自增/减,再赋值;当运算符放在变量之后时(后缀),先赋值,再自增/减。例如,当 `b = ++a` 时,先自增(自己增加 1),再赋值(赋值给 b);当 `b = a++` 时,先赋值(赋值给 b),再自增(自己增加 1)。也就是,++a 输出的是 a+1 的值,a++输出的是 a 值。用一句口诀就是:“符号在前就先加/减,符号在后就后加/减”。 +答案:`a = 11` 、`b = 9` 、 `c = 10` 、 `d = 10` 、 `e = 10`。 ### 移位运算符 @@ -293,7 +319,18 @@ static final int hash(Object key) { ``` -在 Java 代码里使用 `<<`、 `>>` 和`>>>`转换成的指令码运行起来会更高效些。 +**使用移位运算符的主要原因**: + +1. **高效**:移位运算符直接对应于处理器的移位指令。现代处理器具有专门的硬件指令来执行这些移位操作,这些指令通常在一个时钟周期内完成。相比之下,乘法和除法等算术运算在硬件层面上需要更多的时钟周期来完成。 +2. **节省内存**:通过移位操作,可以使用一个整数(如 `int` 或 `long`)来存储多个布尔值或标志位,从而节省内存。 + +移位运算符最常用于快速乘以或除以 2 的幂次方。除此之外,它还在以下方面发挥着重要作用: + +- **位字段管理**:例如存储和操作多个布尔值。 +- **哈希算法和加密解密**:通过移位和与、或等操作来混淆数据。 +- **数据压缩**:例如霍夫曼编码通过移位运算符可以快速处理和操作二进制数据,以生成紧凑的压缩格式。 +- **数据校验**:例如 CRC(循环冗余校验)通过移位和多项式除法生成和校验数据完整性。。 +- **内存对齐**:通过移位操作,可以轻松计算和调整数据的对齐地址。 掌握最基本的移位运算符知识还是很有必要的,这不光可以帮助我们在代码中使用,还可以帮助我们理解源码中涉及到移位运算符的代码。 @@ -303,6 +340,8 @@ Java 中有三种移位运算符: - `>>` :带符号右移,向右移若干位,高位补符号位,低位丢弃。正数高位补 0,负数高位补 1。`x >> n`,相当于 x 除以 2 的 n 次方。 - `>>>` :无符号右移,忽略符号位,空位都以 0 补齐。 +虽然移位运算本质上可以分为左移和右移,但在实际应用中,右移操作需要考虑符号位的处理方式。 + 由于 `double`,`float` 在二进制中的表现比较特殊,因此不能来进行移位操作。 移位操作符实际上支持的类型只有`int`和`long`,编译器在对`short`、`byte`、`char`类型进行移位前,都会将其转换为`int`类型再操作。 @@ -361,31 +400,31 @@ System.out.println("左移 10 位后的数据对应的二进制字符 " + Intege 思考一下:下列语句的运行结果是什么? ```java - public static void main(String[] args) { - boolean flag = false; - for (int i = 0; i <= 3; i++) { - if (i == 0) { - System.out.println("0"); - } else if (i == 1) { - System.out.println("1"); - continue; - } else if (i == 2) { - System.out.println("2"); - flag = true; - } else if (i == 3) { - System.out.println("3"); - break; - } else if (i == 4) { - System.out.println("4"); - } - System.out.println("xixi"); - } - if (flag) { - System.out.println("haha"); - return; +public static void main(String[] args) { + boolean flag = false; + for (int i = 0; i <= 3; i++) { + if (i == 0) { + System.out.println("0"); + } else if (i == 1) { + System.out.println("1"); + continue; + } else if (i == 2) { + System.out.println("2"); + flag = true; + } else if (i == 3) { + System.out.println("3"); + break; + } else if (i == 4) { + System.out.println("4"); } - System.out.println("heihei"); + System.out.println("xixi"); } + if (flag) { + System.out.println("haha"); + return; + } + System.out.println("heihei"); +} ``` 运行结果: diff --git a/docs/java/basis/java-basic-questions-03.md b/docs/java/basis/java-basic-questions-03.md index bbce950e204..5c71236427a 100644 --- a/docs/java/basis/java-basic-questions-03.md +++ b/docs/java/basis/java-basic-questions-03.md @@ -286,7 +286,7 @@ class GeneratorImpl implements Generator{ 实现泛型接口,指定类型: ```java -class GeneratorImpl implements Generator{ +class GeneratorImpl implements Generator { @Override public String method() { return "hello";