diff --git a/docs/database/redis/redis-common-blocking-problems-summary.md b/docs/database/redis/redis-common-blocking-problems-summary.md index adddb099..70fadcc5 100644 --- a/docs/database/redis/redis-common-blocking-problems-summary.md +++ b/docs/database/redis/redis-common-blocking-problems-summary.md @@ -111,7 +111,7 @@ Redis 集群可以进行节点的动态扩容缩容,这一过程目前还处 ## Swap(内存交换) -什么是 Swap?Swap 直译过来是交换的意思,Linux 中的 Swap 常被称为内存交换或者交换分区。类似于 Windows 中的虚拟内存,就是当内存不足的时候,把一部分硬盘空间虚拟成内存使用,从而解决内存容量不足的情况。因此,Swap 分区的作用就是牺牲硬盘,增加内存,解决 VPS 内存不够用或者爆满的问题。 +**什么是 Swap?** Swap 直译过来是交换的意思,Linux 中的 Swap 常被称为内存交换或者交换分区。类似于 Windows 中的虚拟内存,就是当内存不足的时候,把一部分硬盘空间虚拟成内存使用,从而解决内存容量不足的情况。因此,Swap 分区的作用就是牺牲硬盘,增加内存,解决 VPS 内存不够用或者爆满的问题。 Swap 对于 Redis 来说是非常致命的,Redis 保证高性能的一个重要前提是所有的数据在内存中。如果操作系统把 Redis 使用的部分内存换出硬盘,由于内存与硬盘读写的速度并几个数量级,会导致发生交换后的 Redis 性能急剧下降。 diff --git a/docs/database/redis/redis-questions-02.md b/docs/database/redis/redis-questions-02.md index f548e7f1..8d9c7bd6 100644 --- a/docs/database/redis/redis-questions-02.md +++ b/docs/database/redis/redis-questions-02.md @@ -186,6 +186,11 @@ Redis 从 2.6 版本开始支持执行 Lua 脚本,它的功能和事务非常 ## Redis 性能优化(重要) +除了下面介绍的内容之外,再推荐两篇不错的文章: + +- [你的 Redis 真的变慢了吗?性能优化如何做 - 阿里开发者](https://mp.weixin.qq.com/s/nNEuYw0NlYGhuKKKKoWfcQ) +- [Redis 常见阻塞原因总结 - JavaGuide](./redis-common-blocking-problems-summary.md) + ### 使用批量操作减少网络传输 一个 Redis 命令的执行可以简化为以下 4 步: @@ -271,7 +276,7 @@ Lua 脚本同样支持批量操作多条命令。一段 Lua 脚本可以视作 个人建议不管是否开启 lazy-free,我们都尽量给 key 设置随机过期时间。 -### Redis bigkey +### Redis bigkey(大 Key) #### 什么是 bigkey? @@ -279,7 +284,7 @@ Lua 脚本同样支持批量操作多条命令。一段 Lua 脚本可以视作 #### bigkey 有什么危害? -除了会消耗更多的内存空间,bigkey 对性能也会有比较大的影响。因此,我们应该尽量避免写入 bigkey! +bigkey 除了会消耗更多的内存空间和带宽,还会对性能造成比较大的影响。因此,我们应该尽量避免 Redis 中存在 bigkey。 #### 如何发现 bigkey? @@ -313,7 +318,7 @@ Biggest string found '"ballcat:oauth:refresh_auth:f6cdb384-9a9d-4f2f-af01-dc3f28 从这个命令的运行结果,我们可以看出:这个命令会扫描(Scan) Redis 中的所有 key ,会对 Redis 的性能有一点影响。并且,这种方式只能找出每种数据结构 top 1 bigkey(占用内存最大的 string 数据类型,包含元素最多的复合数据类型)。 -**2、分析 RDB 文件** +**2、借助开源工具分析 RDB 文件。** 通过分析 RDB 文件来找出 big key。这种方案的前提是你的 Redis 采用的是 RDB 持久化。 @@ -322,6 +327,130 @@ Biggest string found '"ballcat:oauth:refresh_auth:f6cdb384-9a9d-4f2f-af01-dc3f28 - [redis-rdb-tools](https://github.com/sripathikrishnan/redis-rdb-tools):Python 语言写的用来分析 Redis 的 RDB 快照文件用的工具 - [rdb_bigkeys](https://github.com/weiyanwei412/rdb_bigkeys) : Go 语言写的用来分析 Redis 的 RDB 快照文件用的工具,性能更好。 +**3、借助公有云的 Redis 分析服务。** + +如果你用的是公有云的 Redis 服务的话,可以看看其是否提供了 key 分析功能(一般都提供了)。 + +这里以阿里云 Redis 为例说明,它支持 bigkey 实时分析、发现,文档地址: 。 + +![阿里云Key分析](https://oss.javaguide.cn/github/javaguide/database/redis/aliyun-key-analysis.png) + +#### 如何处理 bigkey? + +bigkey 的常见处理以及优化办法如下(这些方法可以配合起来使用): + +- **分割 bigkey**:将一个 bigkey 分割为多个小 key。这种方式需要修改业务层的代码,一般不推荐这样做。 +- **手动清理**:Redis 4.0+ 可以使用 `UNLINK` 命令来异步删除一个或多个指定的 key。Redis 4.0 以下可以考虑使用 `SCAN` 命令结合 `DEL` 命令来分批次删除。 +- **采用合适的数据结构**:比如使用 HyperLogLog 统计页面 UV。 + +### Redis hotkey(热 Key) + +#### 什么是 hotkey? + +简单来说,如果一个 key 的访问次数比较多且明显多于其他 key 的话,那这个 key 就可以看作是 hotkey。例如在 Redis 实例的每秒处理请求达到 5000 次,而其中某个 key 的每秒访问量就高达 2000 次,那这个 key 就可以看作是 hotkey。 + +hotkey 出现的原因主要是某个热点数据访问量暴增,如重大的热搜事件、参与秒杀的商品。 + +#### hotkey 有什么危害? + +处理 hotkey 会占用大量的 CPU 和带宽,可能会影响 Redis 实例对其他请求的正常处理。此外,如果突然访问 hotkey 的请求超出了 Redis 的处理能力,Redis 就会直接宕机。这种情况下,大量请求将落到后面的数据库上,可能会导致数据库崩溃。 + +因此,hotkey 很可能成为系统性能的瓶颈点,需要单独对其进行优化,以确保系统的高可用性和稳定性。 + +#### 如何发现 hotkey? + +**1、使用 Redis 自带的 `--hotkeys` 参数来查找。** + +Redis 4.0.3 版本中新增了 `hotkeys` 参数,该参数能够返回所有 key 的被访问次数。 + +使用该方案的前提条件是 Redis Server 的 `maxmemory-policy` 参数设置为 LFU 算法,不然就会出现如下所示的错误。 + +```bash +# redis-cli -p 6379 --hotkeys + +# Scanning the entire keyspace to find hot keys as well as +# average sizes per key type. You can use -i 0.1 to sleep 0.1 sec +# per 100 SCAN commands (not usually needed). + +Error: ERR An LFU maxmemory policy is not selected, access frequency not tracked. Please note that when switching between policies at runtime LRU and LFU data will take some time to adjust. +``` + +Redis 中有两种 LFU 算法: + +- **volatile-lru(least recently used)**:从已设置过期时间的数据集(`server.db[i].expires`)中挑选最近最少使用的数据淘汰。 +- **allkeys-lru(least recently used)**:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(这个是最常用的)。 + +以下是配置文件 `redis.conf` 中的示例: + +```properties +# 使用 volatile-lfu 策略 +maxmemory-policy volatile-lfu + +# 或者使用 allkeys-lfu 策略 +maxmemory-policy allkeys-lfu +``` + +需要注意的是,`hotkeys` 命令也会增加 Redis 实例的 CPU 和内存消耗(全局扫描),因此需要谨慎使用。 + +**2、使用`monitor` 命令。** + +`monitor` 命令是 Redis 提供的一种实时查看 Redis 的所有操作的方式,可以用于临时监控 Redis 实例的操作情况,包括读写、删除等操作。 + +由于该命令对 Redis 性能的影响比较大,因此禁止长时间开启 `monitor`(生产环境中建议谨慎使用该命令)。 + +```java +# redis-cli +127.0.0.1:6379> monitor +OK +1683638260.637378 [0 172.17.0.1:61516] "ping" +1683638267.144236 [0 172.17.0.1:61518] "smembers" "mySet" +1683638268.941863 [0 172.17.0.1:61518] "smembers" "mySet" +1683638269.551671 [0 172.17.0.1:61518] "smembers" "mySet" +1683638270.646256 [0 172.17.0.1:61516] "ping" +1683638270.849551 [0 172.17.0.1:61518] "smembers" "mySet" +1683638271.926945 [0 172.17.0.1:61518] "smembers" "mySet" +1683638274.276599 [0 172.17.0.1:61518] "smembers" "mySet2" +1683638276.327234 [0 172.17.0.1:61518] "smembers" "mySet" +``` + +在发生紧急情况时,我们可以选择在合适的时机短暂执行 monitor 命令并将输出重定向至文件,在关闭 monitor 命令后通过对文件中请求进行归类分析即可找出这段时间中的 hotkey。 + +**3、借助开源项目。** + +京东零售的 [hotkey](https://gitee.com/jd-platform-opensource/hotkey) 这个项目不光支持 hotkey 的发现,还支持 hotkey 的处理。 + +![京东零售开源的 hotkey](https://oss.javaguide.cn/github/javaguide/database/redis/jd-hotkey.png) + +**4、根据业务情况提前预估。** + +可以根据业务情况来预估一些 hotkey,比如参与秒杀活动的商品数据等。不过,我们无法预估所有 hotkey 的出现,比如突发的热点新闻事件等。 + +**5、业务代码中记录分析。** + +在业务代码中添加相应的逻辑对 key 的访问情况进行记录分析。不过,这种方式会让业务代码的复杂性增加,一般也不会采用。 + +**6、借助公有云的 Redis 分析服务。** + +如果你用的是公有云的 Redis 服务的话,可以看看其是否提供了 key 分析功能(一般都提供了)。 + +这里以阿里云 Redis 为例说明,它支持 hotkey 实时分析、发现,文档地址: 。 + +![阿里云Key分析](https://oss.javaguide.cn/github/javaguide/database/redis/aliyun-key-analysis.png) + +#### 如何解决 hotkey? + +hotkey 的常见处理以及优化办法如下(这些方法可以配合起来使用): + +- **读写分离**:主节点处理写请求,从节点处理读请求。 +- **使用 Redis Cluster**:将热点数据分散存储在多个 Redis 节点上。 +- **二级缓存**:hotkey 采用二级缓存的方式进行处理,将 hotkey 存放一份到 JVM 本地内存中(可以用 Caffeine)。 + +除了这些方法之外,如果你使用的公有云的 Redis 服务话,还可以留意其提供的开箱即用的解决方案。 + +这里以阿里云 Redis 为例说明,它支持通过代理查询缓存功能(Proxy Query Cache)优化热点 Key 问题。 + +![通过阿里云的Proxy Query Cache优化热点Key问题](https://oss.javaguide.cn/github/javaguide/database/redis/aliyun-hotkey-proxy-query-cache.png) + ### Redis 内存碎片 **相关问题**: @@ -518,5 +647,6 @@ Cache Aside Pattern 中遇到写请求是这样的:更新 DB,然后直接删 - 《Redis 开发与运维》 - 《Redis 设计与实现》 -- Redis Transactions : https://redis.io/docs/manual/transactions/ -- What is Redis Pipeline:https://buildatscale.tech/what-is-redis-pipeline/ +- Redis Transactions : +- What is Redis Pipeline: +- 一文详解 Redis 中 BigKey、HotKey 的发现与处理: diff --git a/docs/distributed-system/rpc/dubbo.md b/docs/distributed-system/rpc/dubbo.md index 1a14b77c..f926ef90 100644 --- a/docs/distributed-system/rpc/dubbo.md +++ b/docs/distributed-system/rpc/dubbo.md @@ -435,7 +435,7 @@ Dubbo 中的 `RoundRobinLoadBalance` 的代码实现被修改重建了好几次 ### Dubbo 支持哪些序列化方式呢? -![](https://oss.javaguide.cn/github/javaguide/csdn/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MzM3Mjcy,size_16,color_FFFFFF,t_70-20230309234143460.png) +![Dubbo 支持的序列化协议](https://oss.javaguide.cn/github/javaguide/csdn/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0MzM3Mjcy,size_16,color_FFFFFF,t_70-20230309234143460.png) Dubbo 支持多种序列化方式:JDK 自带的序列化、hessian2、JSON、Kryo、FST、Protostuff,ProtoBuf 等等。 @@ -456,4 +456,4 @@ Kryo 和 FST 这两种序列化方式是 Dubbo 后来才引入的,性能非常 Dubbo 官方文档中还有一个关于这些[序列化协议的性能对比图](https://dubbo.apache.org/zh/docs/v2.7/user/serialization/#m-zhdocsv27userserialization)可供参考。 -![](https://oscimg.oschina.net/oscnet/up-00c3ce1e5d222e477ed84310239daa2f6b0.png) +![序列化协议的性能对比](https://oscimg.oschina.net/oscnet/up-00c3ce1e5d222e477ed84310239daa2f6b0.png) diff --git a/docs/distributed-system/rpc/rpc-intro.md b/docs/distributed-system/rpc/rpc-intro.md index 529c5f3d..7a6b1817 100644 --- a/docs/distributed-system/rpc/rpc-intro.md +++ b/docs/distributed-system/rpc/rpc-intro.md @@ -5,9 +5,9 @@ tag: - rpc --- -简单介绍一下 RPC 相关的基础概念。 +这篇文章会简单介绍一下 RPC 相关的基础概念。 -## 何为 RPC? +## RPC 是什么? **RPC(Remote Procedure Call)** 即远程过程调用,通过名字我们就能看出 RPC 关注的是远程调用而非本地调用。 @@ -136,4 +136,5 @@ Dubbo 也是 Spring Cloud Alibaba 里面的一个组件。 ## 既然有了 HTTP 协议,为什么还要有 RPC ? -[HTTP 和 RPC 详细对比](http&rpc.md) 。 +关于这个问题的详细答案,请看这篇文章:[有了 HTTP 协议,为什么还要有 RPC ?](http&rpc.md) 。 + diff --git a/docs/interview-preparation/resume-guide.md b/docs/interview-preparation/resume-guide.md index 31d7d664..28af6e76 100644 --- a/docs/interview-preparation/resume-guide.md +++ b/docs/interview-preparation/resume-guide.md @@ -23,7 +23,7 @@ icon: jianli **2、简历上的内容很大程度上决定了面试官提问的侧重点。** -- 一般情况下你的简历上注明你会的东西才会被问到(Java 基础、集合、并发、MySQL、Redis、Spring、Spring Boot 这些算是每个人必问的),比如写了你熟练使用 Redis,那面试官就很大概率会问你 Redis 的一些问题,再比如你写了你在项目中使用了消息队列,那面试官大概率问很多消息队列相关的问题。 +- 一般情况下你的简历上注明你会的东西才会被问到(Java 基础、集合、并发、MySQL、Redis 、Spring、Spring Boot 这些算是每个人必问的),比如写了你熟练使用 Redis,那面试官就很大概率会问你 Redis 的一些问题,再比如你写了你在项目中使用了消息队列,那面试官大概率问很多消息队列相关的问题。 - 技能熟练度在很大程度上也决定了面试官提问的深度。 在不夸大自己能力的情况下,写出一份好的简历也是一项很棒的能力。 @@ -37,28 +37,28 @@ icon: jianli 下面是我收集的一些还不错的简历模板: - 适合中文的简历模板收集(推荐,免费): -- 木及简历(部分收费): +- 木及简历(部分收费) : - 简单简历(付费): - 站长简历: -- typora+markdown+css 自定义简历模板: -- 极简简历: +- typora+markdown+css 自定义简历模板 : +- 极简简历 : - Markdown 简历排版工具: -- 超级简历(部分收费): +- 超级简历(部分收费) : 上面这些简历模板大多是只有 1 页内容,很难展现足够的信息量。如果你不是顶级大牛(比如 ACM 大赛获奖)的话,我建议还是尽可能多写一点可以突出你自己能力的内容(校招生 2 页之内,社招生 3 页之内,记得精炼语言,不要过多废话)。 再总结几点 **简历排版的注意事项**: - 尽量简洁,不要太花里胡哨。 -- 一些技术名词不要弄错了大小写比如 MySQL 不要写成 mysql,Java 不要写成 java。 +- 技术名词最好规范大小写比较好,比如 java->Java ,spring boot -> Spring Boot 。这个虽然有些面试官不会介意,但是很多面试官都会在意这个细节的。 - 中文和数字英文之间加上空格的话看起来会舒服一点。 ## 简历内容 ### 个人信息 -- 最基本的:姓名(身份证上的那个)、年龄、电话、籍贯、联系方式、邮箱地址 -- 潜在加分项: GitHub 地址、博客地址(如果技术博客和 GitHub 上没有什么内容的话,就不要写了) +- 最基本的 :姓名(身份证上的那个)、年龄、电话、籍贯、联系方式、邮箱地址 +- 潜在加分项 : Github 地址、博客地址(如果技术博客和 Github 上没有什么内容的话,就不要写了) 示例: @@ -129,7 +129,7 @@ icon: jianli > 2017-05~2018-06 淘宝 Java 后端开发工程师 > > - **项目描述** : 简单描述项目是做什么的。 -> - **技术栈**:用了什么技术(如 Spring Boot + MySQL + Redis + Mybatis-plus + Spring Security + Oauth2) +> - **技术栈** :用了什么技术(如 Spring Boot + MySQL + Redis + Mybatis-plus + Spring Security + Oauth2) > - **工作内容/个人职责** : 简单描述自己做了什么,解决了什么问题,带来了什么实质性的改善。突出自己的能力,不要过于平淡的叙述。 > - **个人收获(可选)** : 从这个项目中你学会了那些东西,使用到了那些技术,学会了那些新技术的使用。通常是可以不用写个人收获的,因为你在个人职责介绍中写的东西已经表明了自己的主要收获。 > - **项目成果(可选)** :简单描述这个项目取得了什么成绩。 @@ -162,10 +162,6 @@ icon: jianli - 热门数据(如首页、热门博客)使用 Redis+Caffeine 两级缓存,解决了缓存击穿和穿透问题,查询速度毫秒级,QPS 30w+。 - 使用 CompletableFuture 优化购物车查询模块,对获取用户信息、商品详情、优惠券信息等异步 RPC 调用进行编排,响应时间从 2s 降低 0.2s。 -可以参考下面这位同学的介绍(依然还可以继续优化,参考上面我介绍的方法论): - -![](https://oss.javaguide.cn/zhishixingqiu/395c10e0dc9440c8961cbe203d8a022e~tplv-k3u1fbpfcp-zoom-1.png) - **4、如果你觉得你的项目技术比较落后的话,可以自己私下进行改进。重要的是让项目比较有亮点,通过什么方式就无所谓了。** 项目经历这部分对于简历来说非常重要,《Java 面试指北》的面试准备篇有好几篇关于优化项目经历的文章,建议你仔细阅读一下,应该会对你有帮助。 @@ -227,17 +223,37 @@ FAB 法则由下面 3 个单词组成(FAB 法则的名字就是由它们的首 简单来说,**FAB 法则主要是让你的面试官知道你的优势和你能为公司带来的价值。** -## 注意事项和建议 +## 建议 + +### 避免页数过多 + +精简表述,突出亮点。校招简历建议不要超过 2 页,社招简历建议不要超过 3 页。如果内容过多的话,不需要非把内容压缩到一页,保持排版干净整洁就可以了。 + +看了几千份简历,有少部分同学的简历页数都接近10页了,让我头皮发麻。 + +![简历页数过多](https://oss.javaguide.cn/zhishixingqiu/image-20230508223646164.png) + + + +### 避免语义模糊 + +尽量避免主观表述,少一点语义模糊的形容词。表述要简洁明了,简历结构要清晰。 + +举例: + +- 不好的表述:我在团队中扮演了很重要的角色。 +- 好的表述:我作为后端技术负责人,领导团队完成后端项目的设计与开发。 + +### 注意简历样式 + +简历样式同样很重要,一定要注意!不必追求花里胡哨,但要尽量保证结构清晰且易于阅读。 + +### 其他 - 一定要使用 PDF 格式投递,不要使用 Word 或者其他格式投递。这是最基本的! -- 尽量避免主观表述,少一点语义模糊的形容词。表述要简洁明了,简历结构要清晰。 -- 精简表述,突出亮点。校招简历建议不要超过 2 页,社招简历建议不要超过 3 页。如果内容过多的话,不需要非把内容压缩到一页,保持排版干净整洁就可以了。 - 不会的东西就不要写在简历上了。注意简历真实性,适当润色没有问题。 -- 技术博客、GitHub 以及获奖经历等可以直接证明自己能力的东西,能写就尽量写在这里。不过,如果技术博客和 GitHub 上没有什么内容的话,就不要写了。 -- 技术名词最好规范大小写比较好,比如 java->Java ,spring boot -> Spring Boot 。这个虽然有些面试官不会介意,但是很多面试官都会在意这个细节的。 - 工作经历建议采用时间倒序的方式来介绍,实习经历建议将最有价值的放在最前面。 - 将自己的项目经历完美的展示出来非常重要,重点是突出自己做了什么(挖掘亮点),而不是介绍项目是做什么的。 - 项目经历建议以时间倒序排序,另外项目经历不在于多(精选 2~3 即可),而在于有亮点。 -- 个人评价就是对自己的解读,一定要用简洁的语言突出自己的特点和优势,避免废话! 像勤奋、吃苦这些比较虚的东西就不要扯了,面试官看着这种个人评价就烦。 - 准备面试的过程中应该将你写在简历上的东西作为重点,尤其是项目经历上和技能介绍上的。 - 面试和工作是两回事,聪明的人会把面试官往自己擅长的领域领,其他人则被面试官牵着鼻子走。虽说面试和工作是两回事,但是你要想要获得自己满意的 offer ,你自身的实力必须要强。 diff --git a/docs/java/basis/java-basic-questions-01.md b/docs/java/basis/java-basic-questions-01.md index 0d580b64..8f542b60 100644 --- a/docs/java/basis/java-basic-questions-01.md +++ b/docs/java/basis/java-basic-questions-01.md @@ -499,7 +499,7 @@ Double i4 = 1.2; System.out.println(i3 == i4);// 输出 false ``` -下面我们来看一下问题。下面的代码的输出结果是 `true` 还是 `false` 呢? +下面我们来看一个问题:下面的代码的输出结果是 `true` 还是 `false` 呢? ```java Integer i1 = 40; diff --git a/docs/java/concurrent/java-concurrent-questions-03.md b/docs/java/concurrent/java-concurrent-questions-03.md index 98361faa..ba202bf2 100644 --- a/docs/java/concurrent/java-concurrent-questions-03.md +++ b/docs/java/concurrent/java-concurrent-questions-03.md @@ -163,7 +163,7 @@ ThreadLocalMap(ThreadLocal firstKey, Object firstValue) { `ThreadLocalMap` 中使用的 key 为 `ThreadLocal` 的弱引用,而 value 是强引用。所以,如果 `ThreadLocal` 没有被外部强引用的情况下,在垃圾回收的时候,key 会被清理掉,而 value 不会被清理掉。 -这样一来,`ThreadLocalMap` 中就会出现 key 为 null 的 Entry。假如我们不做任何措施的话,value 永远无法被 GC 回收,这个时候就可能会产生内存泄露。`ThreadLocalMap` 实现中已经考虑了这种情况,在调用 `set()`、`get()`、`remove()` 方法的时候,会清理掉 key 为 null 的记录。使用完 `ThreadLocal`方法后 最好手动调用`remove()`方法 +这样一来,`ThreadLocalMap` 中就会出现 key 为 null 的 Entry。假如我们不做任何措施的话,value 永远无法被 GC 回收,这个时候就可能会产生内存泄露。`ThreadLocalMap` 实现中已经考虑了这种情况,在调用 `set()`、`get()`、`remove()` 方法的时候,会清理掉 key 为 null 的记录。使用完 `ThreadLocal`方法后最好手动调用`remove()`方法 ```java static class Entry extends WeakReference> { diff --git a/docs/javaguide/faq.md b/docs/javaguide/faq.md index a995fc72..76ee750e 100644 --- a/docs/javaguide/faq.md +++ b/docs/javaguide/faq.md @@ -36,10 +36,23 @@ JavaGuide 这个项目诞生一年左右就有出版社的老师联系我了, **出书既能博名又能赚点钱,我为啥不考虑出书呢?** -- JavaGuide 的很多内容我还不是很满意,也一直在维护中,细心的小伙伴看我的提交记录就明白了。 +- JavaGuide 的很多内容我还不是很满意,也一直在维护中,细心的小伙伴看我的[提交记录](https://github.com/Snailclimb/JavaGuide/commits/main)就明白了。 - 开源版本更容易维护和修改,也能让更多人更方便地参与到项目的建设中,这也是我最初做这个项目的初衷。 - 我觉得出书是一件神圣的事情,自认能力还不够。 - 个人精力有限,不光有本职工作,还弄了一个[知识星球](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)赚点外快,还要维护完善 JavaGuide。 - ...... 这几年一直在默默完善,真心希望 JavaGuide 越来越好,帮助到更多朋友!也欢迎大家参与进来! + +## JavaGuide 上为什么有一些付费文章? + +是这样的,JavaGuide 上确实有非常非常少的付费文章,差不多 10 篇不到吧,这对于整个网站的内容来说算是微不足道了。 + +这些付费文章属于[知识星球](https://javaguide.cn/about-the-author/zhishixingqiu-two-years.html)专属,是我用来引流知识星球的,对整体阅读其实并没有什么影响的。 + +我也知道大家不喜欢营销,所以我会让自己控制好一个度。我一不割韭菜,二不贩卖焦虑,仅仅赚一份小钱提升家人生活品质。 + +**用心做内容,真心希望能帮助到其他人。** + + + diff --git a/docs/javaguide/intro.md b/docs/javaguide/intro.md index 47349aa0..58e95ea4 100644 --- a/docs/javaguide/intro.md +++ b/docs/javaguide/intro.md @@ -6,14 +6,16 @@ icon: about 我是 19 年大学毕业的,在大三准备面试的时候,我开源了 JavaGuide 。我把自己准备面试过程中的一些总结都毫不保留地通过 JavaGuide 分享了出来。 -开源 JavaGuide 初始想法源于自己的个人那一段比较迷茫的学习经历。主要目的是为了通过这个开源平台来帮助一些在学习 Java 或者面试过程中遇到问题的小伙伴。 +开源 JavaGuide 初始想法源于自己的个人那一段比较迷茫的学习经历,主要目的是为了通过这个开源平台来帮助一些在学习 Java 或者面试过程中遇到问题的小伙伴。 -- **对于 Java 初学者来说:** 本文档倾向于给你提供一个比较详细的学习路径,让你对于 Java 整体的知识体系有一个初步认识。另外,本文的一些文章也是你学习和复习 Java 知识不错的实践; -- **对于非 Java 初学者来说:** 本文档更适合回顾知识,准备面试,搞清面试应该把重心放在那些问题上。要搞清楚这个道理:提前知道那些面试常见,不是为了背下来应付面试,而是为了让你可以更有针对的学习重点。 +- **对于 Java 初学者来说:** 本文档倾向于给你提供一个比较详细的学习路径,目录清晰,让你对于 Java 整体的知识体系有一个清晰认识。你可以跟着视频或者书籍学习完某个知识点之后,然后来这里找对应的总结,帮助你更好地掌握对应的知识点。 +- **对于非 Java 初学者来说:** 本文档更适合回顾知识,准备面试,让你搞清面试应该把重心放在哪些问题上。 + +**由于本网站的内容完全开源,由大家共同维护完善,因此内容质量比较高。** 如果你也想要参与 JavaGuide 的维护建设工作,请查阅[贡献指南](./contribution-guideline.md)。 相比于其他通过 JavaGuide 学到东西或者说助力获得 offer 的朋友来说 , JavaGuide 对我的意义更加重大。不夸张的说,有时候真的感觉像是自己的孩子一点一点长大一样,我一直用心呵护着它。虽然,我花了很长时间来维护它,但是,我觉得非常值得!非常有意义! -希望大家对面试不要抱有侥幸的心理,打铁还需自身硬! 我希望这个文档是为你学习 Java 指明方向,而不仅仅是用来应付面试用的。 +不过,希望大家对面试不要抱有侥幸的心理,打铁还需自身硬! **我希望这个文档是为你学习 Java 指明方向,而不仅仅是用来应付面试用的。** 另外,JavaGuide 不可能把面试中的所有内容都给涵盖住,尤其是阿里、美团这种挖的比较深入的面试。你可以根据你的目标公司进行针对性的深入学习,多看一些目标公司的面经进行查漏补缺,没事就自测一下,多多思考总结。