作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;padding-right: 10px;padding-left: 10px;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: PingFangSC-Light;"> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-family: STHeitiSC-Light;color: rgb(14, 136, 235);font-weight: bolder;display: inline-block;padding-left: 10px;border-left: 5px solid rgb(14, 136, 235);">前言</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">面试官问:您熟悉redis?搭建过redis集群?rediscluster底层的主从复制rdb如何工作的?……</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">接下来,就是一轮迫击炮,犹如把面试者按在砧板上,轮番炮击……</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-family: STHeitiSC-Light;color: rgb(14, 136, 235);font-weight: bolder;display: inline-block;padding-left: 10px;border-left: 5px solid rgb(14, 136, 235);">您目前用redis那种集群模式?</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">采用Redis Cluster无中心结构集群模式</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;color: rgb(14, 136, 235);"><span style="display: none;"></span>拓展<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">master-slave模式模式存在的问题是,master宕机之后,从机只能读,不可写,不能保证高可用。Redis Cluster每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。节点之间使用gossip协议传播信息以及发现新节点。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> Redis 集群是一个分布式(distributed)、容错(fault-tolerant)的 Redis 实现,集群可以使用的功能是普通单机 Redis 所能使用的功能的一个子集(subset)。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> Redis 集群中不存在中心(central)节点或者代理(proxy)节点,集群的其中一个主要设计目标是,达到线性可扩展性(linear scalability)。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> Redis 集群为了保证一致性(consistency),而牺牲了一部分容错性:系统会在保证对网络断线(net split)和节点失效(node failure)具有有限(limited)抵抗力的前提下,尽可能地保持数据的一致性。 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">redis集群技术,是构建高性能网站架构的重要手段,试想在网站承受高并发访问压力的同时,还需要从海量数据中查询出满足条件的数据,并快速响应,在单个 redis 内存不足时,使用 Cluster 进行分片存储,把数据根据某种规则放入多个不同的服务器节点,来降低单节点服务器的压力。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-family: STHeitiSC-Light;color: rgb(14, 136, 235);font-weight: bolder;display: inline-block;padding-left: 10px;border-left: 5px solid rgb(14, 136, 235);">Redis集群中的节点如何保证数据一致?</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">采用异步复制,进行数据同步,保持各个节点数据一致。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.5055555555555555" src="/upload/6991f33d25eaa0fe4c5c3b77fe8a370d.png" data-type="png" data-w="1080" style="border-radius: 0px 0px 5px 5px;display: block;margin: 20px auto;width: 85%;height: 100%;object-fit: contain;box-shadow: rgb(132, 161, 168) 0px 10px 15px;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 图片 </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">当客户端向从S服务器发送SLAVEOF命令,要求从S服务器复制主M服务器时,从S服务器首先需要执行同步操作,也即是,将从S服务器的数据库状态更新至主M服务器当前所处的数据库状态。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">从S服务器对主M服务器的同步操作,需要通过向主M服务器发送SYNC命令来完成,以下是SYNC命令的执行步骤:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 从S服务器向主M服务器发送SYNC命令。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 收到SYNC命令的主M服务器执行BGSAVE命令,在后台生成一个RDB文件,并使用一个缓冲区,记录从现在开始执行的所有写命令。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 当主M服务器的BGSAVE命令执行完毕时,主M服务器会将BGSAVE命令生成的RDB文件,发送给从S服务器,从S服务器接收并载入这个RDB文件,将自己的数据库状态更新至主M服务器,执行BGSAVE命令时的数据库状态。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 主M服务器将记录在缓冲区里面的所有写命令,发送给从S服务器,从S服务器执行这些写命令,将自己的数据库状态更新至主M服务器数据库当前所处的状态。 </section></li> </ol> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-family: STHeitiSC-Light;color: rgb(14, 136, 235);font-weight: bolder;display: inline-block;padding-left: 10px;border-left: 5px solid rgb(14, 136, 235);">Redis有哪些适合的场景?</span></h2> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> Session共享(单点登录) </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 页面缓存 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 队列 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 排行榜/计数器 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 发布/订阅 </section></li> </ul> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-family: STHeitiSC-Light;color: rgb(14, 136, 235);font-weight: bolder;display: inline-block;padding-left: 10px;border-left: 5px solid rgb(14, 136, 235);">Redis如何做内存优化?</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">尽可能使用散列c表(hash)----是说散列表里面存储的数少,使用的内存非常小,所以尽可能的,将你的数据模型抽象到一个散列表里面。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">比如你的web系统中有一个用户对象,不要为这个用户的名称,姓氏,邮箱,密码设置单独的key,而是应该把这个用户的所有信息存储到一张散列表里面.</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-family: STHeitiSC-Light;color: rgb(14, 136, 235);font-weight: bolder;display: inline-block;padding-left: 10px;border-left: 5px solid rgb(14, 136, 235);">Redis回收进程如何工作的?</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">一个客户端运行了新的命令,添加了新的数据。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">Redi检查内存使用情况,如果大于maxmemory的限制, 则根据设定好的LRU算法策略进行回收。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-family: STHeitiSC-Light;color: rgb(14, 136, 235);font-weight: bolder;display: inline-block;padding-left: 10px;border-left: 5px solid rgb(14, 136, 235);">Redis 的持久化机制是什么?各自的优缺点?</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">Redis提供两种持久化机制 RDB 和 AOF 机制:</p> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;"><span style="display: none;"></span>1、RDB(Redis DataBase)持久化方式:<span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">是指用数据集快照的方式,半持久化模式记录 redis 数据库的所有键值对,在某个时间点,将数据写入一个临时文件,持久化结束后,用这个临时文件替换上次持久化的文件,达到数据恢复。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;"><strong style="font-weight: border;color: #0e88eb;">优点:</strong></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 只有一个文件 dump.rdb,方便持久化。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 容灾性好,一个文件可以保存到安全的磁盘。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 性能最大化,fork 子进程来完成写操作,让主进程继续处理命令,所以是 IO最大化。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 redis的高性能。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 相对于数据集大时,比 AOF 的启动效率更高。 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;"><strong style="font-weight: border;color: #0e88eb;">缺点:</strong></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 数据安全性低。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> RDB 是间隔一段时间进行持久化,如果持久化期间 ,redis 发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候 </section></li> </ul> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;"><span style="display: none;"></span>2、AOF(Append-only file)持久化方式:<span style="display: none;"></span></h4> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">是指所有的命令行记录,以 redis 命令请求协议的格式,完全持久化存储,保存为 aof 文件。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;"><strong style="font-weight: border;color: #0e88eb;">优点:</strong></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 数据安全,aof持久化,可以配置appendfsync属性,有always,每进行一次命令操作就记录到aof文件中一次。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 通过append模式写文件,即使中途服务器宕机,可以通过redis-check-aof工具解决数据一致性问题。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> AOF机制的rewrite模式。AOF文件没被rewrite之前(文件过大时,会对命令进行合并重写),可以删除其中的某些命令(比如误操作的flushall)) </section></li> </ul> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.16434540389972144" src="/upload/e8dd56dad6cfe0e76fd16e484e313ee3.png" data-type="png" data-w="1077" style="border-radius: 0px 0px 5px 5px;display: block;margin: 20px auto;width: 85%;height: 100%;object-fit: contain;box-shadow: rgb(132, 161, 168) 0px 10px 15px;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 图片 </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;"><strong style="font-weight: border;color: #0e88eb;">缺点:</strong></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> AOF 文件比 RDB 文件大,且恢复速度慢。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 数据集大的时候,比 rdb 启动效率低。 </section></li> </ul> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-family: STHeitiSC-Light;color: rgb(14, 136, 235);font-weight: bolder;display: inline-block;padding-left: 10px;border-left: 5px solid rgb(14, 136, 235);">Redis是单线程的,那它为什么这么快?</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">Redis的单线程,其实是指执行Redis命令的核心模块是单线程的,也就是文件事件处理器,主要由四个部分组成:套接字、IO多路复用、文件事件分派器和事件处理器。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">Redis6.0其实已经支持多线程来提高性能了。而Redis之所以快主要原因:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> Redis是基于内存的,数据都存放在内存中,速度非常快 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> Redis的IO模型是非阻塞IO </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> Redis核心模块的单线程使得可以避免线程切换带来的开销 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> Redis是单线程的,可以通过开启多个Redis实例来利用多核 </section></li> </ul> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.3972222222222222" src="/upload/4c88c6821f1884ea36dd46394b6f9ce9.png" data-type="png" data-w="1080" style="border-radius: 0px 0px 5px 5px;display: block;margin: 20px auto;width: 85%;height: 100%;object-fit: contain;box-shadow: rgb(132, 161, 168) 0px 10px 15px;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 图片 </figcaption> </figure> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-family: STHeitiSC-Light;color: rgb(14, 136, 235);font-weight: bolder;display: inline-block;padding-left: 10px;border-left: 5px solid rgb(14, 136, 235);">Redis支持哪几种数据类型?优势是什么?比其他key-value存储数据库有什么不同?</span></h2> <h4 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;"><span style="display: none;"></span>支持多种类型的数据结构<span style="display: none;"></span></h4> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.30265486725663715" src="/upload/5d91a401fca7db625020d2563138fa51.png" data-type="png" data-w="565" style="border-radius: 0px 0px 5px 5px;display: block;margin: 20px auto;width: 85%;height: 100%;object-fit: contain;box-shadow: rgb(132, 161, 168) 0px 10px 15px;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 图片 </figcaption> </figure> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.4783861671469741" src="/upload/30ca1aa636f6ecbba33a53509efd0ae8.png" data-type="png" data-w="1041" style="border-radius: 0px 0px 5px 5px;display: block;margin: 20px auto;width: 85%;height: 100%;object-fit: contain;box-shadow: rgb(132, 161, 168) 0px 10px 15px;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 图片 </figcaption> </figure> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-family: STHeitiSC-Light;color: rgb(14, 136, 235);font-weight: bolder;display: inline-block;padding-left: 10px;border-left: 5px solid rgb(14, 136, 235);">Redis优势</span></h2> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> <strong style="font-weight: border;color: #0e88eb;">性能极高</strong>--------Redis能读的速度是11万次/s,写的速度是8.1万次/s。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> <strong style="font-weight: border;color: #0e88eb;">丰富的数据类型</strong>--------Redis支持二进制案例的Strings,Lists,Hashes,Sets及OrderedSets数据类型操作。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> <strong style="font-weight: border;color: #0e88eb;">原子</strong>--------Redis的所有操作都是原子性的,意思就是要么成功执行,要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,结合lua脚本,用MULTI和EXEC指令包起来。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> <strong style="font-weight: border;color: #0e88eb;">丰富的特性</strong>--------Redis还支持publish/subscribe,通知,key过期等等特性。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> <strong style="font-weight: border;color: #0e88eb;">Redis单点吞吐量</strong>--------单点TPS达到8万/秒,QPS达到10万/秒。 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">可以复制脚本生成的单个写入命令,而不是复制整个脚本,我们称之为【脚本影响复制】(script effects replication)。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 在这种复制模式下,当执行Lua脚本时,Redis会收集由Lua脚本引擎执行的所有实际修改数据集的命令。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 当脚本执行完成后,由脚本生成的命令序列,将被包装到 MULTI/EXEC 事务中,并发送到从节点,和进行AOF持久化保存。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 当我们加了 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">replicate_commands()</code>以后,到AOF备份文件里面查看,发现会把写命令转换为MULTI...EXEC命令: </section></li> </ul> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.8102409638554217" src="/upload/5edc45c57117686f045bea02fd607415.png" data-type="png" data-w="332" style="border-radius: 0px 0px 5px 5px;display: block;margin: 20px auto;width: 85%;height: 100%;object-fit: contain;box-shadow: rgb(132, 161, 168) 0px 10px 15px;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 图片 </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;margin: 10px;line-height: 1.75;letter-spacing: 0.2em;font-size: 15px;word-spacing: 0.1em;">结合lua脚本,用MULTI和EXEC指令包起来,并且在Lua脚本中读多写少的情况下,只持久化和复制写命令,可以节省重启和备库的CPU时间。 <mpcpc js_editor_cpcad="" class="js_cpc_area cpc_iframe" src="/cgi-bin/readtemplate?t=tmpl/cpc_tmpl#1642757120181" data-category_id_list="1|16|17|2|21|24|28|29|31|35|36|37|39|41|42|43|46|47|48|5|50|51|55|56|57|58|59|6|60|61|62|63|64|65|66|7|8" data-id="1642757120181"></mpcpc></p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-family: STHeitiSC-Light;color: rgb(14, 136, 235);font-weight: bolder;display: inline-block;padding-left: 10px;border-left: 5px solid rgb(14, 136, 235);">Redis与其他key-value存储NOSQL数据库有什么不同?</span></h2> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> Memcached是一个自由开源的,高性能,分布式内存对象缓存系统。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> MongoDB是一个基于分布式文件存储的数据库,文档型的非关系型数据库,与上面两者不同, MongoDB不支持事务。 </section></li> </ul> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;color: rgb(14, 136, 235);"><span style="display: none;"></span>性能上:<span style="display: none;"></span></h3> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> Memcached单个key-value大小有限,一个value最大只支持1MB,而Redis最大支持512MB。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 而在100k以上的数据中,Memcached性能要高于Redis,虽然Redis最近也在存储大数据的性能上进行优化,但是比起 Memcached,还是稍有逊色。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> Memcached只是个内存缓存,对可靠性无要求;而Redis更倾向于内存数据库,因此对对可靠性方面要求比较高。 </section></li> </ul> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;color: rgb(14, 136, 235);"><span style="display: none;"></span>内存空间和数据量大小:<span style="display: none;"></span></h3> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> MemCached可以修改最大内存,采用LRU算法。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> Redis增加了VM的特性,突破了物理内存的限制。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> MongoDB 适合大数据量的存储,依赖操作系统 VM 做内存管理,吃内存也比较厉害。 </section></li> </ul> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;color: rgb(14, 136, 235);"><span style="display: none;"></span>操作便利上:<span style="display: none;"></span></h3> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> MemCached数据结构单一,仅用来缓存数据。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> 而Redis支持更加丰富的数据类型,也可以在服务器端直接对数据进行丰富的操作,这样可以减少网络IO次数和数据体积。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> Mongodb 支持丰富的数据表达,索引,最类似关系型数据库,支持的查询语言非常丰富。 </section></li> </ul> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;color: rgb(14, 136, 235);"><span style="display: none;"></span>可靠性上:<span style="display: none;"></span></h3> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> MemCached不支持数据持久化,断电或重启后数据消失,但其稳定性是有保证的。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> Redis支持数据持久化和数据恢复,允许单点故障,但是同时也会付出性能的代价。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> MongoDB 从 1.8 版本开始采用 binlog 方式支持持久化的可靠性。 </section></li> </ul> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 18px;color: rgb(14, 136, 235);"><span style="display: none;"></span>应用场景:<span style="display: none;"></span></h3> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> Memcached:动态系统中减轻数据库负载,提升性能;做缓存,适合多读少写,大数据量的情况(如人人网大量查询用户信息、好友信息、文章信息等)。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> Redis:适用于对读写效率要求都很高,数据处理业务复杂和对安全性要求较高的系统(如新浪微博的计数和微博发布部分系统,对数据安全性、读写要求都很高)。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;"> MongoDB:主要解决海量数据的访问效率问题(没有事务性要求的,适合kv存储,评论,文章,邮件存储,文本存储,json存储,爬虫存储,游戏领域,tb级以上的大数据存储,这种数据用mongodb存储,mongodb更容易实现水平扩展,可以存储比数据库更多的数据)。 </section></li> </ul> </section>
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="line-height: 1.6;word-break: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;padding: 5px;font-size: 16px;color: rgb(53, 53, 53);word-spacing: 0.8px;letter-spacing: 0.8px;border-radius: 16px;" data-mpa-powered-by="yiban.io"> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">大家好,我是<span style="font-weight: 700;color: rgb(248, 57, 41);">飘渺</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Redis是面试中绕不过的槛,只要在简历中写了用过Redis,肯定逃不过。今天我们就来模拟一下面试官在Redis这个话题上是如何一步一步深入,全面考察候选人对于Redis的掌握情况。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">小张:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">面试官,你好。我是来参加面试的。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">面试官:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">你好,小张。我看了你的简历,熟练掌握Redis,那么我就随便问你几个Redis相关的问题吧。首先我的问题是,<span style="font-weight: 700;color: rgb(248, 57, 41);">Redis是单线程还是多线程呢?</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">小张:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Redis不同版本之间采用的线程模型是不一样的,在Redis4.0版本之前使用的是单线程模型,在4.0版本之后增加了多线程的支持。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">在4.0之前虽然我们说Redis是单线程,也只是说它的网络I/O线程以及Set 和 Get操作是由一个线程完成的。但是Redis的持久化、集群同步还是使用其他线程来完成。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">4.0之后添加了多线程的支持,主要是体现在大数据的异步删除功能上,例如 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">unlink key</code>、<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">flushdb async</code>、<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">flushall async</code> 等</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">面试官:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">回答的很好,<span style="font-weight: 700;color: rgb(248, 57, 41);">那为什么Redis在4.0之前会选择使用单线程?而且使用单线程还那么快?</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">小张:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">选择单线程个人觉得主要是使用简单,不存在锁竞争,可以在无锁的情况下完成所有操作,不存在死锁和线程切换带来的性能和时间上的开销,但同时单线程也不能完全发挥出多核CPU的性能。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">至于为什么单线程那么快我觉得主要有以下几个原因:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Redis 的大部分操作都在内存中完成,内存中的执行效率本身就很快,并且采用了高效的数据结构,比如哈希表和跳表。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 使用单线程避免了多线程的竞争,省去了多线程切换带来的时间和性能开销,并且不会出现死锁。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 采用 I/O 多路复用机制处理大量客户端的Socket请求,因为这是基于非阻塞的 I/O 模型,这就让Redis可以高效地进行网络通信,I/O的读写流程也不再阻塞。 </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">面试官:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">不错,<span style="font-weight: 700;color: rgb(248, 57, 41);">那Redis是如何实现数据不丢失的呢?</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">小张:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Redis数据是存储在内存中的,为了保证Redis数据不丢失,那就要把数据从内存存储到磁盘上,以便在服务器重启后还能够从磁盘中恢复原有数据,这就是Redis的数据持久化。Redis数据持久化有三种方式。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">AOF 日志(Append Only File,文件追加方式):记录所有的操作命令,并以文本的形式追加到文件中。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">RDB 快照(Redis DataBase):将某一个时刻的内存数据,以二进制的方式写入磁盘。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">混合持久化方式:Redis 4.0 新增了混合持久化的方式,集成了 RDB 和 AOF 的优点。</p> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">面试官:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">那你分别说说 <span style="font-weight: 700;color: rgb(248, 57, 41);">AOF和 RDB的实现原理吧。</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">小张:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">AOF采用的是写后日志的方式,Redis先执行命令把数据写入内存,然后再记录日志到文件中。AOF日志记录的是操作命令,不是实际的数据,如果采用AOF方法做故障恢复时需要将全量日志都执行一遍。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.4425" src="/upload/b62a6f04d68fffd6b66e88ca2cd0feec.png" data-type="png" data-w="800" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">RDB采用的是内存快照的方式,它记录的是某一时刻的数据,而不是操作,所以采用RDB方法做故障恢复时只需要直接把RDB文件读入内存即可,实现快速恢复。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">面试官:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">你刚提到了AOF采用的是 “写后日志” 的方式,我们平时用的MySQL则采用的是 “写前日志”,那 <span style="font-weight: 700;color: rgb(248, 57, 41);">Redis为什么要先执行命令,再把数据写入日志呢?</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">小张:额头开始冒汗,问的是些啥问题呀。。。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">额,这个主要是由于Redis在写入日志之前,不对命令进行语法检查,所以只记录执行成功的命令,避免出现记录错误命令的情况,而且在命令执行后再写日志不会阻塞当前的写操作。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">面试官:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">那 <span style="font-weight: 700;color: rgb(248, 57, 41);">后写日志又有什么风险呢?</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">小张:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">我... 这个我不会。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">面试官:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">好吧,后写日志主要有两个风险可能会发生:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 数据可能会丢失:如果 Redis 刚执行完命令,此时发生故障宕机,会导致这条命令存在丢失的风险。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 可能阻塞其他操作:AOF 日志其实也是在主线程中执行,所以当 Redis 把日志文件写入磁盘的时候,还是会阻塞后续的操作无法执行。 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">我还有个问题是 <span style="font-weight: 700;color: rgb(248, 57, 41);">RDB做快照时会阻塞线程吗?</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">小张:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Redis 提供了两个命令来生成 RDB 快照文件,分别是 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">save</code> 和 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">bgsave</code>。<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">save</code> 命令在主线程中执行,会导致阻塞。而 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">bgsave</code> 命令则会创建一个子进程,用于写入 RDB 文件的操作,避免了对主线程的阻塞,这也是 Redis RDB 的默认配置。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">面试官:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">RDB 做快照的时候数据能修改吗?</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">小张:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">save是同步的会阻塞客户端命令,bgsave的时候是可以修改的。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">面试官:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">那Redis是怎么解决在bgsave做快照的时候允许数据修改呢?</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">小张:(你咋还问。。。我™不会啊!)</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">额,这个我不太清楚...</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.8897849462365591" src="/upload/7d11c42f44c24420ceddc4193bc694dd.png" data-type="png" data-w="372" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">面试官:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这里主要是利用<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">bgsave</code>的子线程实现的,具体操作如下:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">如果主线程执行读操作,则主线程和 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">bgsave</code> 子进程互相不影响;</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">如果主线程执行写操作,则被修改的数据会复制一份副本,然后 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">bgsave</code>子进程会把该副本数据写入 RDB 文件,在这个过程中,主线程仍然可以直接修改原来的数据。</p> </section></li> </ul> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.38875" src="/upload/9d3a111dcc8a8f24e737be0c6d67d6bf.png" data-type="png" data-w="800" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">要注意,Redis 对 RDB 的执行频率非常重要,因为这会影响快照数据的完整性以及 Redis 的稳定性,所以在 Redis 4.0 后,<span style="font-weight: 700;color: rgb(248, 57, 41);">增加了 AOF 和 RDB 混合的数据持久化机制:</span> 把数据以 RDB 的方式写入文件,再将后续的操作命令以 AOF 的格式存入文件,既保证了 Redis 重启速度,又降低数据丢失风险。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">小张:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">学到了学到了。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">面试官:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">那你再跟我说说Redis如何实现高可用吧?</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">小张:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Redis实现高可用主要有三种方式:主从复制、哨兵模式,以及 Redis 集群。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">主从复制</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">将从前的一台 Redis 服务器,同步数据到多台从 Redis 服务器上,即一主多从的模式,这个跟MySQL主从复制的原理一样。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.5723684210526315" src="/upload/1dd2ccd8599d72dcabf13792e906d5ce.png" data-type="png" data-w="608" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">哨兵模式</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">使用 Redis 主从服务的时候,会有一个问题,就是当 Redis 的主从服务器出现故障宕机时,需要手动进行恢复,为了解决这个问题,Redis 增加了哨兵模式(因为哨兵模式做到了可以监控主从服务器,并且提供自动容灾恢复的功能)。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.84125" src="/upload/9f744a6670041958c2d2881bedffbbf4.png" data-type="png" data-w="800" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">Redis Cluster(集群)</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Redis Cluster 是一种分布式去中心化的运行模式,是在 Redis 3.0 版本中推出的 Redis 集群方案,它将数据分布在不同的服务器上,以此来降低系统对单主节点的依赖,从而提高 Redis 服务的读写性能。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.325" src="/upload/859b78c807f6b6dac17f6de2f2543b95.png" data-type="png" data-w="800" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">面试官:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">使用哨兵模式在数据上有副本数据做保证,在可用性上又有哨兵监控,一旦master宕机会选举salve节点为master节点,这种已经满足了我们的生产环境需要,<span style="font-weight: 700;color: rgb(248, 57, 41);">那为什么还需要使用集群模式呢?</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">小张:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">额,哨兵模式归根节点还是主从模式,在主从模式下我们可以通过增加salve节点来扩展读并发能力,但是没办法扩展写能力和存储能力,存储能力只能是master节点能够承载的上限。所以为了扩展写能力和存储能力,我们就需要引入集群模式。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">面试官:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">集群中那么多Master节点,redis cluster在存储的时候如何确定选择哪个节点呢?</span></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">小张:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这应该是使用了某种hash算法,但是我不太清楚。。。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.6432291666666666" src="/upload/fa6e158654e8611356f8cdfac59ae931.png" data-type="png" data-w="384" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">面试官:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">那好,今天的面试就到这里吧,你先回去等我们的面试通知。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">小张:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">好的,谢谢面试官,你能告诉我redis cluster怎么实现节点选择的吗?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">面试官:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Redis Cluster采用的是<span style="font-weight: 700;color: rgb(248, 57, 41);">类一致性哈希算法实现节点选择的</span>,至于什么是一致性哈希算法你自己回去看看。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">Redis Cluster将自己分成了16384个<span style="font-weight: 700;color: rgb(248, 57, 41);">Slot</span>(槽位),哈希槽类似于数据分区,每个键值对都会根据它的 key,被映射到一个哈希槽中,具体执行过程分为两大步。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">根据键值对的 key,按照 CRC16 算法计算一个 16 bit 的值。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">再用 16bit 值对 16384 取模,得到 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">0~16383</code> 范围内的模数,每个模数代表一个相应编号的哈希槽。</p> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">每个Redis节点负责处理一部分槽位,加入你有三个master节点 ABC,每个节点负责的槽位如下:</p> <section data-tool="mdnice编辑器" style="overflow-x: auto;"> <table> <thead> <tr style="border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: white;"> <th style="border-top-width: 1px;border-color: rgb(204, 204, 204);background-color: rgb(219, 217, 216);min-width: 85px;text-align: center;" width="19">节点</th> <th style="border-top-width: 1px;border-color: rgb(204, 204, 204);background-color: rgb(219, 217, 216);min-width: 85px;text-align: center;" width="248">处理槽位</th> </tr> </thead> <tbody style="border-width: 0px;border-style: initial;border-color: initial;"> <tr style="border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: white;"> <td style="border-color: rgb(204, 204, 204);color: rgb(100, 86, 71);min-width: 85px;text-align: center;" width="104">A</td> <td style="border-color: rgb(204, 204, 204);color: rgb(100, 86, 71);min-width: 85px;text-align: center;" width="248">0-5000</td> </tr> <tr style="border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: rgb(248, 248, 248);"> <td style="border-color: rgb(204, 204, 204);color: rgb(100, 86, 71);min-width: 85px;text-align: center;" width="19">B</td> <td style="border-color: rgb(204, 204, 204);color: rgb(100, 86, 71);min-width: 85px;text-align: center;" width="248">5001 - 10000</td> </tr> <tr style="border-width: 1px 0px 0px;border-right-style: initial;border-bottom-style: initial;border-left-style: initial;border-right-color: initial;border-bottom-color: initial;border-left-color: initial;border-top-style: solid;border-top-color: rgb(204, 204, 204);background-color: white;"> <td style="border-color: rgb(204, 204, 204);color: rgb(100, 86, 71);min-width: 85px;text-align: center;" width="19">C</td> <td style="border-color: rgb(204, 204, 204);color: rgb(100, 86, 71);min-width: 85px;text-align: center;" width="248">10001 - 16383</td> </tr> </tbody> </table> </section> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这样就实现了cluster节点的选择。</p> </section>
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;padding-right: 10px;padding-left: 10px;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;" data-mpa-powered-by="yiban.io"> <h3 data-tool="mdnice编辑器" style="margin-top: 40px;margin-bottom: 20px;font-weight: bold;line-height: 1.5;color: rgb(63, 63, 63);font-size: 120%;">一、Nginx安装<span style="display: none;"></span></h3> <h5 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;"><span style="display: none;"></span>1、去官网http://nginx.org/下载对应的nginx包,推荐使用稳定版本<span style="display: none;"></span></h5> <h5 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;"><span style="display: none;"></span>2、上传nginx到linux系统<span style="display: none;"></span></h5> <h5 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;"><span style="display: none;"></span>3、安装依赖环境<span style="display: none;"></span></h5> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">(1)安装gcc环境</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">yum install gcc-c++<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">(2)安装PCRE库,用于解析正则表达式</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">yum install -y pcre pcre-devel<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">(3)zlib压缩和解压缩依赖</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">yum install -y zlib zlib-devel<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">(4)SSL 安全的加密的套接字协议层,用于HTTP安全传输,也就是https</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">yum install -y openssl openssl-devel<br></code></pre> <h5 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;"><span style="display: none;"></span>4、解压,需要注意,解压后得到的是源码,源码需要编译后才能安装<span style="display: none;"></span></h5> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">tar -zxvf nginx-1.16.1.tar.gz<br></code></pre> <h5 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;"><span style="display: none;"></span>5、编译之前,先创建nginx临时目录,如果不创建,在启动nginx的过程中会报错<span style="display: none;"></span></h5> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">mkdir /var/temp/nginx -p<br></code></pre> <h5 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;"><span style="display: none;"></span>6、在nginx目录,输入如下命令进行配置,目的是为了创建makefile文件<span style="display: none;"></span></h5> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">./configure \ <br>--prefix=/usr/<span style="color: #e6c07b;line-height: 26px;">local</span>/nginx \ <br>--pid-path=/var/run/nginx/nginx.pid \ <br>--lock-path=/var/lock/nginx.lock \ <br>--error-log-path=/var/<span style="color: #e6c07b;line-height: 26px;">log</span>/nginx/error.log \ <br>--http-log-path=/var/<span style="color: #e6c07b;line-height: 26px;">log</span>/nginx/access.log \ <br>--with-http_gzip_static_module \ <br>--http-client-body-temp-path=/var/temp/nginx/client \ <br>--http-proxy-temp-path=/var/temp/nginx/proxy \ <br>--http-fastcgi-temp-path=/var/temp/nginx/fastcgi \ <br>--http-uwsgi-temp-path=/var/temp/nginx/uwsgi \ <br>--http-scgi-temp-path=/var/temp/nginx/scgi<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">注:代表在命令行中换行,用于提高可读性配置命令:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.4864864864864865" src="/upload/6735708fccd953f2a1a062f026a2ff69.png" data-type="png" data-w="962" style="display: block;margin-right: auto;margin-left: auto;height: auto !important;"> </figure> <h5 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;"><span style="display: none;"></span>7、make编译&安装<span style="display: none;"></span></h5> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">make<br>make install<br></code></pre> <h5 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;"><span style="display: none;"></span>8、进入sbin目录启动nginx<span style="display: none;"></span></h5> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">启动:nginx<br>停止:./nginx -s stop<br>重新加载:./nginx -s reload<br></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 40px;margin-bottom: 20px;font-weight: bold;line-height: 1.5;color: rgb(63, 63, 63);font-size: 120%;"><span style="display: none;"></span>二、配置反向代理<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">1、配置upstream</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">upstream [proxyName] {<br> server 192.168.1.173:8080;<br> server 192.168.1.174:8080;<br> server 192.168.1.175:8080;<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">2、配置server</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">server {<br> listem 80;<br> server_name www.tomcats.com;<br><br> location / {<br> proxy_pass http://tomcats;<br> }<br>}<br></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 40px;margin-bottom: 20px;font-weight: bold;line-height: 1.5;color: rgb(63, 63, 63);font-size: 120%;"><span style="display: none;"></span>三、配置负载均衡<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">nginx默认采用轮训的方式进行负载均衡</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">1、使用加权轮询</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">upstream [proxyName] {<br> server 192.168.1.173:8080 weight=1;<br> server 192.168.1.174:8080 weight=5;<br> server 192.168.1.175:8080 weight=2;<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">2、hash负载均衡</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">upstream [proxyName] {<br> ip_hash<br><br> server 192.168.1.173:8080;<br> server 192.168.1.174:8080;<br> server 192.168.1.175:8080;<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzU2MTI4MjI0MQ==&mid=2247510238&idx=2&sn=ddb826f3ee3f0c6f3457361ddce23cae&chksm=fc79c570cb0e4c66d374e3511c454bc4c9ae7eb273dbce75b3b7efba548b5acc5ed3ed00f980&scene=21#wechat_redirect" textvalue="hash算法" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" style="text-decoration: underline;" data-linktype="2">hash算法</a>实际上只会计算 192.168.1这段做哈希</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">使用ip_hash的注意点:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 不能把后台服务器直接移除,只能标记down. </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">3、url hash负载均衡</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">upstream [proxyName] {<br> <span style="color: #e6c07b;line-height: 26px;">hash</span> <span style="color: #d19a66;line-height: 26px;">$request_url</span>;<br><br> server 192.168.1.173:8080;<br> server 192.168.1.174:8080;<br> server 192.168.1.175:8080;<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">4、最小连接负载均衡</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">upstream [proxyName] {<br> least_conn;<br><br> server 192.168.1.173:8080;<br> server 192.168.1.174:8080;<br> server 192.168.1.175:8080;<br>}<br></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 40px;margin-bottom: 20px;font-weight: bold;line-height: 1.5;color: rgb(63, 63, 63);font-size: 120%;"><span style="display: none;"></span>四、upstream指令参数<span style="display: none;"></span></h3> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;"><code style="margin-right: 2px;margin-left: 2px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 90%;padding: 3px 5px;border-radius: 2px;">max_conns</code>:限制最大同时连接数 1.11.5之前只能用于商业版</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;"><code style="margin-right: 2px;margin-left: 2px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 90%;padding: 3px 5px;border-radius: 2px;">slow_start</code>:单位秒,权重在指定时间内从1上升到指定值,不适用与hash负载均衡、随机负载均衡 如果在 upstream 中只有一台 server,则该参数失效(商业版才有)</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;"><code style="margin-right: 2px;margin-left: 2px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 90%;padding: 3px 5px;border-radius: 2px;">down</code>:禁止访问</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;"><code style="margin-right: 2px;margin-left: 2px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 90%;padding: 3px 5px;border-radius: 2px;">backup</code>:备用机 只有在其他服务器无法访问的时候才能访问到 不适用与hash负载均衡、随机负载均衡</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;"><code style="margin-right: 2px;margin-left: 2px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 90%;padding: 3px 5px;border-radius: 2px;">max_fails</code>:表示失败几次,则标记server已宕机,剔出上游服务 默认值1</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;"><code style="margin-right: 2px;margin-left: 2px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 90%;padding: 3px 5px;border-radius: 2px;">fail_timeout</code>:表示失败的重试时间 默认值10</p> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">1、keepalived</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">upstream [proxyName] {<br> server 192.168.1.173:8080 weight=1;<br> server 192.168.1.174:8080 weight=5;<br> server 192.168.1.175:8080 weight=2;<br><br> keepalive 32; <span style="color: #5c6370;font-style: italic;line-height: 26px;">#保持的连接数</span><br>}<br><br>server {<br> listem 80;<br> server_name www.tomcats.com;<br><br> location / {<br> proxy_pass http://tomcats;<br> proxy_http_version 1.1; <span style="color: #5c6370;font-style: italic;line-height: 26px;">#连接的协议版本</span><br> proxy_set_header Connection <span style="color: #98c379;line-height: 26px;">""</span>; 清空连接请求头<br> }<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">2、控制浏览器缓存</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">server {<br> listem 80;<br> server_name www.tomcats.com;<br><br> location / {<br> proxy_pass http://tomcats;<br> expires 10s; <span style="color: #5c6370;font-style: italic;line-height: 26px;">#浏览器缓存10秒钟</span><br> <span style="color: #5c6370;font-style: italic;line-height: 26px;">#expires @22h30m #在晚上10点30的时候过期</span><br> <span style="color: #5c6370;font-style: italic;line-height: 26px;">#expires -1h #缓存在一小时前时效</span><br> <span style="color: #5c6370;font-style: italic;line-height: 26px;">#expires epoch #不设置缓存</span><br> <span style="color: #5c6370;font-style: italic;line-height: 26px;">#expires off #缓存关闭,浏览器自己控制缓存</span><br> <span style="color: #5c6370;font-style: italic;line-height: 26px;">#expires max #最大过期时间</span><br> }<br>}<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">3、反向代理缓存</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">upstream [proxyName] {<br> server 192.168.1.173:8080 weight=1;<br> server 192.168.1.174:8080 weight=5;<br> server 192.168.1.175:8080 weight=2;<br>}<br><br><span style="color: #5c6370;font-style: italic;line-height: 26px;">#proxy_cache_path 设置缓存保存的目录的位置</span><br><span style="color: #5c6370;font-style: italic;line-height: 26px;">#keys_zone设置共享内以及占用的空间大小</span><br><span style="color: #5c6370;font-style: italic;line-height: 26px;">#mas_size 设置缓存最大空间</span><br><span style="color: #5c6370;font-style: italic;line-height: 26px;">#inactive 缓存过期时间,错过此时间自动清理</span><br><span style="color: #5c6370;font-style: italic;line-height: 26px;">#use_temp_path 关闭零时目录</span><br>proxy_cache_path /usr/<span style="color: #e6c07b;line-height: 26px;">local</span>/nginx/upsteam_cache keys_zone=mycache:5m max_size=1g inactive=8h use_temp_path=off;<br><br>server {<br> listem 80;<br> server_name www.tomcats.com;<br> <span style="color: #5c6370;font-style: italic;line-height: 26px;">#开启并使用缓存</span><br> proxy_cache mycache;<br> <span style="color: #5c6370;font-style: italic;line-height: 26px;">#针对200和304响应码的缓存过期时间</span><br> proxy_cache_valid 200 304 8h; <br><br> location / {<br> proxy_pass http://tomcats;<br> }<br>}<br></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 40px;margin-bottom: 20px;font-weight: bold;line-height: 1.5;color: rgb(63, 63, 63);font-size: 120%;"><span style="display: none;"></span>五、配置ssl证书提供https访问<span style="display: none;"></span></h3> <h5 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;"><span style="display: none;"></span>1. 安装SSL模块<span style="display: none;"></span></h5> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">要在nginx中配置https,就必须安装ssl模块,也就是: <code style="margin-right: 2px;margin-left: 2px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 90%;padding: 3px 5px;border-radius: 2px;">http_ssl_module</code>。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">进入到nginx的解压目录:<code style="margin-right: 2px;margin-left: 2px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 90%;padding: 3px 5px;border-radius: 2px;">/home/software/nginx-1.16.1</code></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">新增ssl模块(原来的那些模块需要保留)</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">./configure \<br>--prefix=/usr/<span style="color: #e6c07b;line-height: 26px;">local</span>/nginx \<br>--pid-path=/var/run/nginx/nginx.pid \<br>--lock-path=/var/lock/nginx.lock \<br>--error-log-path=/var/<span style="color: #e6c07b;line-height: 26px;">log</span>/nginx/error.log \<br>--http-log-path=/var/<span style="color: #e6c07b;line-height: 26px;">log</span>/nginx/access.log \<br>--with-http_gzip_static_module \<br>--http-client-body-temp-path=/var/temp/nginx/client \<br>--http-proxy-temp-path=/var/temp/nginx/proxy \<br>--http-fastcgi-temp-path=/var/temp/nginx/fastcgi \<br>--http-uwsgi-temp-path=/var/temp/nginx/uwsgi \<br>--http-scgi-temp-path=/var/temp/nginx/scgi \<br>--with-http_ssl_module<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">编译和安装</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">make<br>make install<br></code></pre> <h5 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;"><span style="display: none;"></span>2、配置HTTPS<span style="display: none;"></span></h5> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">把ssl证书 <code style="margin-right: 2px;margin-left: 2px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 90%;padding: 3px 5px;border-radius: 2px;">*.crt</code> 和 私钥 <code style="margin-right: 2px;margin-left: 2px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 90%;padding: 3px 5px;border-radius: 2px;">*.key</code> 拷贝到<code style="margin-right: 2px;margin-left: 2px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 90%;padding: 3px 5px;border-radius: 2px;">/usr/local/nginx/conf</code>目录中。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">新增 server 监听 443 端口:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">server {<br> listen 443;<br> server_name www.imoocdsp.com;<br> <span style="color: #5c6370;font-style: italic;line-height: 26px;"># 开启ssl</span><br> ssl on;<br> <span style="color: #5c6370;font-style: italic;line-height: 26px;"># 配置ssl证书</span><br> ssl_certificate 1_www.imoocdsp.com_bundle.crt;<br> <span style="color: #5c6370;font-style: italic;line-height: 26px;"># 配置证书秘钥</span><br> ssl_certificate_key 2_www.imoocdsp.com.key;<br> <span style="color: #5c6370;font-style: italic;line-height: 26px;"># ssl会话cache</span><br> ssl_session_cache shared:SSL:1m;<br> <span style="color: #5c6370;font-style: italic;line-height: 26px;"># ssl会话超时时间</span><br> ssl_session_timeout 5m;<br> <span style="color: #5c6370;font-style: italic;line-height: 26px;"># 配置加密套件,写法遵循 openssl 标准</span><br> ssl_protocols TLSv1 TLSv1.1 TLSv1.2;<br> ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;<br> ssl_prefer_server_ciphers on;<br> <br> location / {<br> proxy_pass http://tomcats/;<br> index index.html index.htm;<br> }<br>}<br></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 40px;margin-bottom: 20px;font-weight: bold;line-height: 1.5;color: rgb(63, 63, 63);font-size: 120%;"><span style="display: none;"></span>六、配置ha nginx<span style="display: none;"></span></h3> <h5 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;"><span style="display: none;"></span>1、安装keepalived<span style="display: none;"></span></h5> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">(1)下载</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">https://www.keepalived.org/download.html<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">(2)解压</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">tar -zxvf keepalived-2.0.18.tar.gz<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">(3)使用configure命令配置安装目录与核心配置文件所在位置:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">./configure --prefix=/usr/<span style="color: #e6c07b;line-height: 26px;">local</span>/keepalived --sysconf=/etc<br></code></pre> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;"><strong style="color: rgb(255, 53, 2);line-height: 1.5;">prefix</strong>:keepalived安装的位置sysconf:keepalived核心配置文件所在位置,固定位置,改成其他位置则keepalived启动不了,<code style="margin-right: 2px;margin-left: 2px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 90%;padding: 3px 5px;border-radius: 2px;">/var/log/messages</code>中会报错</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;"><strong style="color: rgb(255, 53, 2);line-height: 1.5;">sysconf</strong>:keepalived核心配置文件所在位置,固定位置,改成其他位置则keepalived启动不了,<code style="margin-right: 2px;margin-left: 2px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 90%;padding: 3px 5px;border-radius: 2px;">/var/log/messages</code>中会报错</p> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">配置过程中可能会出现警告信息,如下所示:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">*** WARNING - this build will not support IPVS with IPv6. Please install libnl/libnl-3 dev libraries to support IPv6 with IPVS.<br><br><span style="color: #5c6370;font-style: italic;line-height: 26px;"># 安装libnl/libnl-3依赖</span><br>yum -y install libnl libnl-devel <br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">(4)安装keepalived</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">make && make install<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">(5)配置文件 在<code style="margin-right: 2px;margin-left: 2px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 90%;padding: 3px 5px;border-radius: 2px;">/etc/keepalived/keepalived.conf</code></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">(6)忘记安装配置的目录,则通过如下命令找到:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">whereis keepalived<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">(7)启动keepalived</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">进入sbin目录</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">./keepalived<br></code></pre> <h5 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;"><span style="display: none;"></span>2、配置keepalived 主机<span style="display: none;"></span></h5> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.6;color: rgb(63, 63, 63);margin-top: 10px;margin-bottom: 10px;">(1)通过命令 <code style="margin-right: 2px;margin-left: 2px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgb(248, 245, 236);color: rgb(255, 53, 2);line-height: 1.5;font-size: 90%;padding: 3px 5px;border-radius: 2px;">vim keepalived.conf</code> 打开配置文件</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;background: #282c34;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">global_defs { <br> <span style="color: #5c6370;font-style: italic;line-height: 26px;"># 路�
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;padding-right: 10px;padding-left: 10px;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;counter-reset: counterh1 0 counterh2 0 counterh3 0;"> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 24px;line-height: 28px;border-bottom: 1px solid rgb(37, 132, 181);"><span style="background: rgb(37,132,181);color: white;counter-increment: counterh1;padding: 2px 8px;">Part1</span><span style="color: rgb(37,132,181);margin-left: 8px;font-size: 20px;">困惑</span></h1> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">最近遇到个问题,有个表的要加个user_id字段,user_id字段可能很大,于是我提mysql工单<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">alter table xxx ADD user_id int(1)</code>。领导看到我的sql工单,于是说:这<code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">int(1)</code>怕是不够用吧,接下来是一通解释。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzIxMzQzNzMwMw==&mid=2247499749&idx=1&sn=4c3fcce19c7c87a350903d52615b88ca&chksm=97b461fda0c3e8eb08f00a4cefc51c95a583c76dc02184ce425b13fbae9b52c241c392d5ed9d&scene=21#wechat_redirect" textvalue="其实这不是我第一次遇到这样的问题了,其中不乏有工作5年以上的老司机。包括我经常在也看到同事也一直使用int(10),感觉用了int(1),字段的上限就被限制,真实情况肯定不是这样。" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" style="color: rgb(0, 0, 0);" data-linktype="2"><span style="color: rgb(0, 0, 0);">其实这不是我第一次遇到这样的问题了,其中不乏有工作5年以上的老司机。包括我经常在也看到同事也一直使用int(10),感觉用了int(1),字段的上限就被限制,真实情况肯定不是这样。</span></a></p> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 24px;line-height: 28px;border-bottom: 1px solid rgb(37, 132, 181);"><span style="background: rgb(37,132,181);color: white;counter-increment: counterh1;padding: 2px 8px;">Part2</span><span style="color: rgb(37,132,181);margin-left: 8px;font-size: 20px;">数据说话</span></h1> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzIxMzQzNzMwMw==&mid=2247499749&idx=1&sn=4c3fcce19c7c87a350903d52615b88ca&chksm=97b461fda0c3e8eb08f00a4cefc51c95a583c76dc02184ce425b13fbae9b52c241c392d5ed9d&scene=21#wechat_redirect" textvalue="我们知道在mysql中 int占4个字节,那么对于无符号的int,最大值是2^32-1 = 4294967295,将近40亿,难道用了int(1),就不能达到这个最大值吗?" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" style="color: rgb(0, 0, 0);" data-linktype="2"><span style="color: rgb(0, 0, 0);">我们知道在mysql中 int占4个字节,那么对于无符号的int,最大值是2^32-1 = 4294967295,将近40亿,难道用了int(1),就不能达到这个最大值吗?</span></a></p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">CREATE TABLE `user` (<br> `id` int(1) unsigned NOT NULL AUTO_INCREMENT,<br> PRIMARY KEY (`id`)<br>) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">id字段为无符号的int(1),我来插入一个最大值看看。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">mysql> INSERT INTO `user` (`id`) VALUES (4294967295);<br>Query OK, 1 row affected (0.00 sec)<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzIxMzQzNzMwMw==&mid=2247499749&idx=1&sn=4c3fcce19c7c87a350903d52615b88ca&chksm=97b461fda0c3e8eb08f00a4cefc51c95a583c76dc02184ce425b13fbae9b52c241c392d5ed9d&scene=21#wechat_redirect" textvalue="可以看到成功了,说明int后面的数字,不影响int本身支持的大小,int(1)、int(2)...int(10)没什么区别。" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" style="color: rgb(0, 0, 0);" data-linktype="2"><span style="color: rgb(0, 0, 0);">可以看到成功了,说明int后面的数字,不影响int本身支持的大小,int(1)、int(2)...int(10)没什么区别。</span></a></p> <p style="min-height: 24px;">对了,如果您正在学习Spring Boot,那么推荐一个连载多年还在继续更新的免费教程:http://blog.didispace.com/spring-boot-learning-2x/</p> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 24px;line-height: 28px;border-bottom: 1px solid rgb(37, 132, 181);"><span style="background: rgb(37,132,181);color: white;counter-increment: counterh1;padding: 2px 8px;">Part3</span><span style="color: rgb(37,132,181);margin-left: 8px;font-size: 20px;">零填充</span></h1> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">一般int后面的数字,配合zerofill一起使用才有效。先看个例子:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">CREATE TABLE `user` (<br> `id` int(4) unsigned zerofill NOT NULL AUTO_INCREMENT,<br> PRIMARY KEY (`id`)<br>) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">注意int(4)后面加了个zerofill,我们先来插入4条数据。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">mysql> INSERT INTO `user` (`id`) VALUES (1),(10),(100),(1000);<br>Query OK, 4 rows affected (0.00 sec)<br>Records: 4 Duplicates: 0 Warnings: 0<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">分别插入1、10、100、1000 4条数据,然后我们来查询下:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><code style="overflow-x: auto;padding: 16px;color: #abb2bf;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #282c34;border-radius: 5px;">mysql> select * from user;<br>+------+<br>| id |<br>+------+<br>| 0001 |<br>| 0010 |<br>| 0100 |<br>| 1000 |<br>+------+<br>4 rows <span style="color: #c678dd;line-height: 26px;">in</span> <span style="color: #e6c07b;line-height: 26px;">set</span> (0.00 sec)<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzIxMzQzNzMwMw==&mid=2247499749&idx=1&sn=4c3fcce19c7c87a350903d52615b88ca&chksm=97b461fda0c3e8eb08f00a4cefc51c95a583c76dc02184ce425b13fbae9b52c241c392d5ed9d&scene=21#wechat_redirect" textvalue="通过数据可以发现 int(4) + zerofill实现了不足4位补0的现象,单单int(4)是没有用的。而且对于0001这种,底层存储的还是1,只是在展示的会补0。" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" style="color: rgb(0, 0, 0);" data-linktype="2"><span style="color: rgb(0, 0, 0);">通过数据可以发现 int(4) + zerofill实现了不足4位补0的现象,单单int(4)是没有用的。而且对于0001这种,底层存储的还是1,只是在展示的会补0。</span></a> <mpcpc js_editor_cpcad="" class="js_cpc_area cpc_iframe" src="/cgi-bin/readtemplate?t=tmpl/cpc_tmpl#1642992380619" data-category_id_list="1|16|17|2|21|24|28|29|31|35|36|37|39|41|42|43|46|47|48|5|50|51|55|56|57|58|59|6|60|61|62|63|64|65|66|7|8" data-id="1642992380619"></mpcpc><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzIxMzQzNzMwMw==&mid=2247499749&idx=1&sn=4c3fcce19c7c87a350903d52615b88ca&chksm=97b461fda0c3e8eb08f00a4cefc51c95a583c76dc02184ce425b13fbae9b52c241c392d5ed9d&scene=21#wechat_redirect" textvalue="通过数据可以发现 int(4) + zerofill实现了不足4位补0的现象,单单int(4)是没有用的。而且对于0001这种,底层存储的还是1,只是在展示的会补0。" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" style="color: rgb(0, 0, 0);" data-linktype="2"><span style="color: rgb(0, 0, 0);"></span></a></p> <h1 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 24px;line-height: 28px;border-bottom: 1px solid rgb(37, 132, 181);"><span style="background: rgb(37,132,181);color: white;counter-increment: counterh1;padding: 2px 8px;">Part4</span><span style="color: rgb(37,132,181);margin-left: 8px;font-size: 20px;">总结</span></h1> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzIxMzQzNzMwMw==&mid=2247499749&idx=1&sn=4c3fcce19c7c87a350903d52615b88ca&chksm=97b461fda0c3e8eb08f00a4cefc51c95a583c76dc02184ce425b13fbae9b52c241c392d5ed9d&scene=21#wechat_redirect" textvalue="int后面的数字不能表示字段的长度,int(num)一般加上zerofill,才有效果。" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" style="color: rgb(0, 0, 0);" data-linktype="2"><span style="color: rgb(0, 0, 0);">int后面的数字不能表示字段的长度,int(num)一般加上zerofill,才有效果。</span></a></p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzIxMzQzNzMwMw==&mid=2247499749&idx=1&sn=4c3fcce19c7c87a350903d52615b88ca&chksm=97b461fda0c3e8eb08f00a4cefc51c95a583c76dc02184ce425b13fbae9b52c241c392d5ed9d&scene=21#wechat_redirect" textvalue="zerofill的作用一般可以用在一些编号相关的数字中,比如学生的编号 001 002 ... 999这种,如果mysql没有零填充的功能,但是你又要格式化输出等长的数字编号时,那么你只能自己处理了。" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" data-linktype="2"><span style="color: rgb(0, 0, 0);">zerofill的作用一般可以用在一些编号相关的数字中,比如学生的编号 001 002 ... 999这种,如果mysql没有零填充的功能,但是你又要格式化输出等长的数字编号时,那么你只能自己处理了。</span></a></p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <figcaption style="margin-top: 5px;text-align: center;color: #888;font-size: 14px;"></figcaption> </figure> </section>
作者:微信小助手
<section style="font-size: 16px;" data-mpa-powered-by="yiban.io"> <section style="line-height: 1.5em;"> <span style="letter-spacing: 0.5px;font-size: 16px;">一个真实案例,我把业务细节去掉,只给大家分享一下技术的部分。</span> </section> <section style="line-height: 1.5em;"> <span style="letter-spacing: 0.5px;font-size: 16px;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">先直接说复现方式。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">引入 lombok 和 jackson 的 maven 配置。</span> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="color: black;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: PingFangSC-Light;font-size: 16px;padding: 10px;"> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #333;background: #f8f8f8;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="color: rgb(0, 0, 128);line-height: 26px;"><<span style="line-height: 26px;">dependencies</span>></span><br> <span style="color: rgb(0, 0, 128);line-height: 26px;"><<span style="line-height: 26px;">dependency</span>></span><br> <span style="color: rgb(0, 0, 128);line-height: 26px;"><<span style="line-height: 26px;">groupId</span>></span>org.projectlombok<span style="color: rgb(0, 0, 128);line-height: 26px;"></<span style="line-height: 26px;">groupId</span>></span><br> <span style="color: rgb(0, 0, 128);line-height: 26px;"><<span style="line-height: 26px;">artifactId</span>></span>lombok<span style="color: rgb(0, 0, 128);line-height: 26px;"></<span style="line-height: 26px;">artifactId</span>></span><br> <span style="color: rgb(0, 0, 128);line-height: 26px;"><<span style="line-height: 26px;">version</span>></span>1.16.18<span style="color: rgb(0, 0, 128);line-height: 26px;"></<span style="line-height: 26px;">version</span>></span><br> <span style="color: rgb(0, 0, 128);line-height: 26px;"></<span style="line-height: 26px;">dependency</span>></span><br> <span style="color: rgb(0, 0, 128);line-height: 26px;"><<span style="line-height: 26px;">dependency</span>></span><br> <span style="color: rgb(0, 0, 128);line-height: 26px;"><<span style="line-height: 26px;">groupId</span>></span>com.fasterxml.jackson.core<span style="color: rgb(0, 0, 128);line-height: 26px;"></<span style="line-height: 26px;">groupId</span>></span><br> <span style="color: rgb(0, 0, 128);line-height: 26px;"><<span style="line-height: 26px;">artifactId</span>></span>jackson-databind<span style="color: rgb(0, 0, 128);line-height: 26px;"></<span style="line-height: 26px;">artifactId</span>></span><br> <span style="color: rgb(0, 0, 128);line-height: 26px;"><<span style="line-height: 26px;">version</span>></span>2.9.3<span style="color: rgb(0, 0, 128);line-height: 26px;"></<span style="line-height: 26px;">version</span>></span><br> <span style="color: rgb(0, 0, 128);line-height: 26px;"></<span style="line-height: 26px;">dependency</span>></span><br><span style="color: rgb(0, 0, 128);line-height: 26px;"></<span style="line-height: 26px;">dependencies</span>></span><br></code></pre> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">随便写一个类 Student,上面标注 @AllArgsConstructor 注解。</span> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="color: black;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: PingFangSC-Light;font-size: 16px;padding: 10px;"> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #333;background: #f8f8f8;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="font-weight: bold;line-height: 26px;">package</span> com.flash;<br><span style="font-weight: bold;line-height: 26px;">import</span> lombok.AllArgsConstructor;<br><br><span style="color: #999;font-weight: bold;line-height: 26px;">@ToString</span><br><span style="color: #999;font-weight: bold;line-height: 26px;">@AllArgsConstructor</span><br><span style="font-weight: bold;line-height: 26px;">public</span> <span style="line-height: 26px;"><span style="font-weight: bold;line-height: 26px;">class</span> <span style="color: #458;font-weight: bold;line-height: 26px;">Student</span> </span>{<br> <span style="font-weight: bold;line-height: 26px;">private</span> <span style="font-weight: bold;line-height: 26px;">int</span> age;<br>}<br></code></pre> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">尝试用 jackson 解析一个 json 字符串,并反序列化为 Student 类。</span> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="color: black;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: PingFangSC-Light;font-size: 16px;padding: 10px;"> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #333;background: #f8f8f8;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="font-weight: bold;line-height: 26px;">package</span> com.flash;<br><span style="font-weight: bold;line-height: 26px;">import</span> com.fasterxml.jackson.databind.ObjectMapper;<br><span style="font-weight: bold;line-height: 26px;">import</span> java.io.IOException;<br><br><span style="font-weight: bold;line-height: 26px;">public</span> <span style="line-height: 26px;"><span style="font-weight: bold;line-height: 26px;">class</span> <span style="color: #458;font-weight: bold;line-height: 26px;">TestLombokJackson</span> </span>{<br> <span style="line-height: 26px;"><span style="font-weight: bold;line-height: 26px;">public</span> <span style="font-weight: bold;line-height: 26px;">static</span> <span style="font-weight: bold;line-height: 26px;">void</span> <span style="color: #900;font-weight: bold;line-height: 26px;">main</span><span style="line-height: 26px;">(String[] args)</span> <span style="font-weight: bold;line-height: 26px;">throws</span> IOException </span>{<br> String json = <span style="color: #d14;line-height: 26px;">"{\"age\":1}"</span>;<br> Student s = <span style="font-weight: bold;line-height: 26px;">new</span> ObjectMapper().readValue(json, Student<span style="line-height: 26px;">.<span style="font-weight: bold;line-height: 26px;">class</span>)</span>;<br> System.out.println(s);<br> }<br>}<br></code></pre> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">结果没有任何问题。</span> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="color: black;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: PingFangSC-Light;font-size: 16px;padding: 10px;"> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;background: #272822;color: #ddd;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">Student(age=<span style="line-height: 26px;">1</span>)<br></code></pre> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">升级一下 lombok 版本,从 1.16.18 升级到 1.16.20,其他什么都不动。</span> </section> <pre> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="padding: 10px;letter-spacing: 0px;white-space: normal;color: black;line-height: 1.6;word-break: break-word;text-align: left;font-family: PingFangSC-Light;font-size: 16px;"> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="padding: 16px;overflow-x: auto;color: rgb(51, 51, 51);background: rgb(248, 248, 248);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;"><span style="color: rgb(0, 0, 128);line-height: 26px;"><<span style="line-height: 26px;">dependencies</span>></span><br> <span style="color: rgb(0, 0, 128);line-height: 26px;"><<span style="line-height: 26px;">dependency</span>></span><br> <span style="color: rgb(0, 0, 128);line-height: 26px;"><<span style="line-height: 26px;">groupId</span>></span>org.projectlombok<span style="color: rgb(0, 0, 128);line-height: 26px;"></<span style="line-height: 26px;">groupId</span>></span><br> <span style="color: rgb(0, 0, 128);line-height: 26px;"><<span style="line-height: 26px;">artifactId</span>></span>lombok<span style="color: rgb(0, 0, 128);line-height: 26px;"></<span style="line-height: 26px;">artifactId</span>></span><br> <strong><span style="color: rgb(0, 0, 128);line-height: 26px;"><<span style="line-height: 26px;">version</span>></span>1.16.20<span style="color: rgb(0, 0, 128);line-height: 26px;"></<span style="line-height: 26px;">version</span>></span></strong><br> <span style="color: rgb(0, 0, 128);line-height: 26px;"></<span style="line-height: 26px;">dependency</span>></span><br> <span style="color: rgb(0, 0, 128);line-height: 26px;"><<span style="line-height: 26px;">dependency</span>></span><br> <span style="color: rgb(0, 0, 128);line-height: 26px;"><<span style="line-height: 26px;">groupId</span>></span>com.fasterxml.jackson.core<span style="color: rgb(0, 0, 128);line-height: 26px;"></<span style="line-height: 26px;">groupId</span>></span><br> <span style="color: rgb(0, 0, 128);line-height: 26px;"><<span style="line-height: 26px;">artifactId</span>></span>jackson-databind<span style="color: rgb(0, 0, 128);line-height: 26px;"></<span style="line-height: 26px;">artifactId</span>></span><br> <span style="color: rgb(0, 0, 128);line-height: 26px;"><<span style="line-height: 26px;">version</span>></span>2.9.3<span style="color: rgb(0, 0, 128);line-height: 26px;"></<span style="line-height: 26px;">version</span>></span><br> <span style="color: rgb(0, 0, 128);line-height: 26px;"></<span style="line-height: 26px;">dependency</span>></span><br><span style="color: rgb(0, 0, 128);line-height: 26px;"></<span style="line-height: 26px;">dependencies</span>></span><br></code></pre> </section> <section style="white-space: normal;line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;">再次运行程序,结果报错。</span> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="color: black;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: PingFangSC-Light;font-size: 16px;padding: 10px;"> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;background: #272822;color: #ddd;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="color: rgb(255, 76, 65);">Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.flash.Student` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)<br> at [Source: (String)"{"age":1}"; line: 1, column: 2]<br> at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)<br> at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1342)<br> at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1031)<br> at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1275)<br> at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:325)<br> at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)<br> at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)<br> at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2992)<br> at com.flash.TestLombokJackson.main(TestLombokJackson.java:10)<br><br>Process finished with exit code 1</span><br></code></pre> </section> <section style="white-space: normal;line-height: 1.5em;"> <br> </section> <section style="white-space: normal;line-height: 1.5em;"> <br> </section> <section style="white-space: normal;line-height: 1.5em;"> <strong><span style="font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.5px;font-size: 20px;">猜测一下为什么报错</span></strong> <br> </section></pre> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">先不看具体错误信息,我们仅仅升级了一下 lombok 版本,就导致了错误出现,说明大概率是 lombok 有了什么变化导致的。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">这里 lombok 的作用就是编译期为这个 Student 类添加一个有参构造方法,免去了手写的麻烦。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">所以,第一想到的是由 lombok 在编译期改造的这个 Student 类有什么不同。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">反编译由 <strong>1.16.18</strong> 版本生成的 Student.class 如下</span> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="color: black;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: PingFangSC-Light;font-size: 16px;padding: 10px;"> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #333;background: #f8f8f8;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="font-weight: bold;line-height: 26px;">package</span> com.flash;<br><span style="font-weight: bold;line-height: 26px;">import</span> java.beans.ConstructorProperties;<br><br><span style="font-weight: bold;line-height: 26px;">public</span> <span style="line-height: 26px;"><span style="font-weight: bold;line-height: 26px;">class</span> <span style="color: #458;font-weight: bold;line-height: 26px;">Student</span> </span>{<br> <span style="font-weight: bold;line-height: 26px;">private</span> <span style="font-weight: bold;line-height: 26px;">int</span> age;<br> <span style="line-height: 26px;"><span style="font-weight: bold;line-height: 26px;">public</span> String <span style="color: #900;font-weight: bold;line-height: 26px;">toString</span><span style="line-height: 26px;">()</span> </span>{<br> <span style="font-weight: bold;line-height: 26px;">return</span> <span style="color: #d14;line-height: 26px;">"Student(age="</span> + <span style="font-weight: bold;line-height: 26px;">this</span>.age + <span style="color: #d14;line-height: 26px;">")"</span>;<br> }<br> <span style="color: #999;font-weight: bold;line-height: 26px;">@ConstructorProperties</span>({<span style="color: #d14;line-height: 26px;">"age"</span>})<br> <span style="line-height: 26px;"><span style="font-weight: bold;line-height: 26px;">public</span> <span style="color: #900;font-weight: bold;line-height: 26px;">Student</span><span style="line-height: 26px;">(<span style="font-weight: bold;line-height: 26px;">int</span> age)</span> </span>{<br> <span style="font-weight: bold;line-height: 26px;">this</span>.age = age;<br> }<br>}<br></code></pre> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">反编译由 <strong>1.16.20</strong> 版本生成的 Student.class 如下</span> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="color: black;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: PingFangSC-Light;font-size: 16px;padding: 10px;"> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #333;background: #f8f8f8;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="font-weight: bold;line-height: 26px;">package</span> com.flash;<br><br><span style="font-weight: bold;line-height: 26px;">public</span> <span style="line-height: 26px;"><span style="font-weight: bold;line-height: 26px;">class</span> <span style="color: #458;font-weight: bold;line-height: 26px;">Student</span> </span>{<br> <span style="font-weight: bold;line-height: 26px;">private</span> <span style="font-weight: bold;line-height: 26px;">int</span> age;<br> <span style="line-height: 26px;"><span style="font-weight: bold;line-height: 26px;">public</span> String <span style="color: #900;font-weight: bold;line-height: 26px;">toString</span><span style="line-height: 26px;">()</span> </span>{<br> <span style="font-weight: bold;line-height: 26px;">return</span> <span style="color: #d14;line-height: 26px;">"Student(age="</span> + <span style="font-weight: bold;line-height: 26px;">this</span>.age + <span style="color: #d14;line-height: 26px;">")"</span>;<br> }<br> <span style="line-height: 26px;"><span style="font-weight: bold;line-height: 26px;">public</span> <span style="color: #900;font-weight: bold;line-height: 26px;">Student</span><span style="line-height: 26px;">(<span style="font-weight: bold;line-height: 26px;">int</span> age)</span> </span>{<br> <span style="font-weight: bold;line-height: 26px;">this</span>.age = age;<br> }<br>}<br></code></pre> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">很明显,20 版本去掉了 18 版本在有参构造方法上的一个注解。</span> </section> <section style="line-height: 1.5em;"> <strong><span style="font-size: 16px;letter-spacing: 0.5px;">@ConstructorProperties({"age"})</span></strong> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">去掉了它,导致了 Jackson 报错,也就是说,Jackson 在反序列化时,用到了这个注解去寻找有参构造方法。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">当然,目前仅仅是猜测。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <h2 data-foldable-wrapper=""> <section style="line-height: 1.5em;"> <strong><span style="letter-spacing: 0.5px;font-size: 20px;">Jackson 是不是用到了这个注解?</span></strong> </section></h2> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">整个反序列化过程细节很多,我们只看两个关键节点。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">第一,这个方法里获取了 ConstructorProperties 注解,如果没有这个注解,将会返回 null。</span> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="color: black;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: PingFangSC-Light;font-size: 16px;padding: 10px;"> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #333;background: #f8f8f8;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="color: #999;font-weight: bold;line-height: 26px;">@Override</span><br><span style="line-height: 26px;"><span style="font-weight: bold;line-height: 26px;">public</span> Boolean <span style="color: #900;font-weight: bold;line-height: 26px;">hasCreatorAnnotation</span><span style="line-height: 26px;">(Annotated a)</span> </span>{<br> ConstructorProperties props = <br> a.getAnnotation(ConstructorProperties<span style="line-height: 26px;">.<span style="font-weight: bold;line-height: 26px;">class</span>)</span>;<br> <span style="font-weight: bold;line-height: 26px;">if</span> (props != <span style="font-weight: bold;line-height: 26px;">null</span>) {<br> <span style="font-weight: bold;line-height: 26px;">return</span> Boolean.TRUE;<br> }<br> <span style="font-weight: bold;line-height: 26px;">return</span> <span style="font-weight: bold;line-height: 26px;">null</span>;<br>}<br></code></pre> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">假如上一个方法返回了 null,就会导致下面这个方法的 if 判断失效,走到最后一行。</span> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="color: black;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: PingFangSC-Light;font-size: 16px;padding: 10px;"> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #333;background: #f8f8f8;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="line-height: 26px;"><span style="font-weight: bold;line-height: 26px;">protected</span> Object <span style="color: #900;font-weight: bold;line-height: 26px;">deserializeFromObjectUsingNonDefault</span><span style="line-height: 26px;">(JsonParser p,<br> DeserializationContext ctxt)</span> <span style="font-weight: bold;line-height: 26px;">throws</span> IOException </span>{<br> ...<br> <span style="font-weight: bold;line-height: 26px;">if</span> (_propertyBasedCreator != <span style="font-weight: bold;line-height: 26px;">null</span>) {<br> <span style="font-weight: bold;line-height: 26px;">return</span> _deserializeUsingPropertyBased(p, ctxt);<br> }<br> ...<br> <span style="font-weight: bold;line-height: 26px;">return</span> ctxt.handleMissingInstantiator(raw, getValueInstantiator(), p,<br> <span style="color: #d14;line-height: 26px;">"cannot deserialize from Object value (no delegate- or property-based Creator)"</span>);<br>}<br></code></pre> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">看最后一行的报错信息,和我们实验的报错信息,就完全一样了。</span> <br> </section> <section style="line-height: 1.5em;"> <span style="letter-spacing: 0.5px;font-size: 15px;color: rgb(136, 136, 136);">cannot deserialize from Object value</span> </section> <section style="line-height: 1.5em;"> <span style="letter-spacing: 0.5px;font-size: 15px;color: rgb(136, 136, 136);">(no delegate- or property-based Creator)</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">jackson 反序列化的过程大概是这样的:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <p style="line-height: 1.5em;margin-left: 8px;margin-right: 8px;"><span style="letter-spacing: 0.5px;font-size: 18px;"><strong>1</strong></span><span style="letter-spacing: 0.5px;font-size: 15px;">. 先尝试找空参构造方法和 get\set 方法,如果有,直接利用这两个反序列化。</span></p> <p style="line-height: 1.5em;margin-left: 8px;margin-right: 8px;"><span style="font-size: 18px;"><strong><span style="letter-spacing: 0.5px;">2</span></strong></span><span style="letter-spacing: 0.5px;font-size: 15px;">. 如果没有,尝试找有参构造方法,但需要通过 @ConstructorProperties 来寻找。</span></p> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">所以,正是因为:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;margin-left: 8px;margin-right: 8px;"> <span style="font-size: 18px;"><strong><span style="letter-spacing: 0.5px;">1</span></strong></span> <span style="letter-spacing: 0.5px;font-size: 15px;">. 我们代码中又没有空参构造方法(默认的空参构造由于写了 @AllArgsConstructor 被有参构造给覆盖了)。</span> </section> <section style="line-height: 1.5em;margin-left: 8px;margin-right: 8px;"> <span style="font-size: 18px;"><strong><span style="letter-spacing: 0.5px;">2</span></strong></span> <span style="letter-spacing: 0.5px;font-size: 15px;">. 新版的 lombok 所生成的有参构造函数,没有生成一个叫 ConstructorProperties 的注解。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">导致上述两个条件均没有命中,进而导致 jackson 反序列化失败。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">所以解决办法也很简单,加一个空参构造或者用 @NoArgsConstructor 注解即可,要么就降级 lombok 或在新版 lombok 修改默认配置项,要么就换一个不以这个参数寻找有参构造方法的 json 框架。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"><br></span> </section> <h2 data-foldable-wrapper=""> <section style="line-height: 1.5em;"> <strong><span style="letter-spacing: 0.5px;font-size: 20px;">新版 lombok 为什么不生成这个注解了?</span></strong> </section></h2> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">此时我们自然想到一个问题,既然 jackson 这么大名鼎鼎的框架都用到了这个注解,那 lombok 新版本为什么要做这么一件多余的事情,把它去掉呢?</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">一般开源软件的新版本发布,都会有 <strong>changelog</strong>,来表示它修改了什么内容,又是为什么修改。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">我们看 lombok 的 changelog。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <img class="rich_pages wxw-img" data-ratio="0.4832807570977918" src="/upload/1a674a4e2dba36f54259b6e2206ea3d5.png" data-type="png" data-w="1585" height="auto" style="height: auto !important;" width="1585"> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">看到 20 版本的改变一共有 9 个,我们只关心第三个,是一个 BREAKING CHANGE,表示突破性的改变。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="letter-spacing: 0.5px;font-size: 15px;color: rgb(136, 136, 136);">BREAKING CHANGE: _lombok config_ key `lombok.anyConstructor.suppressConstructorProperties` is now deprecated and defaults to `true`, that is, by default lombok no longer automatically generates `@ConstructorProperties` annotations. New config key `lombok.anyConstructor.addConstructorProperties` now exists; set it to `true` if you want the old behavior. Oracle more or less broke this annotation with the release of JDK9, necessitating this breaking change.</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">这里可以看出,从 20 版本开始,lombok 果然不再默认添加 @ConstructorProperties 注解了,原因是最后一句话:<strong>JDK9 或多或少破坏了这个注解,从而需要进行这一突破性的更改。</strong></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">具体看 18 ~ 20 版本的一大堆 commit 信息,也的确有一个 commit 是修改这个地方的。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="letter-spacing: 0.5px;font-size: 15px;color: rgb(64, 118, 0);">commit:d7c019c07c3851fa0c89b3080da6c08d021fd272</span> </section> <section style="line-height: 1.5em;"> <span style="letter-spacing: 0.5px;font-size: 15px;color: rgb(64, 118, 0);">for lombok v2, make generation of ConstructorProperties an optional extra, instead of default on. Reinier Zwitserloot 2017/12/5 4:35</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">那看来,就是 lombok 新版本的这个改动,再加上 jackson 反序列化时又非要用到这个注解,导致的这个问题发生。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"><br></span> </section> <h2 data-foldable-wrapper=""> <section style="line-height: 1.5em;"> <span style="font-size: 20px;"><strong><span style="letter-spacing: 0.5px;">fastjson 也需要有这个注解么?</span></strong></span> </section></h2> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">既然 jackson 是这么玩的,那 fastjson 会不会也是这样呢?我印象中用 fastjson 好像从来没有因为 lombok 发生过什么错误。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">我先尝试了低版本的 fastjson,代码还是原来的代码。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">Student 类</span> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="color: black;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: PingFangSC-Light;font-size: 16px;padding: 10px;"> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #333;background: #f8f8f8;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="font-weight: bold;line-height: 26px;">package</span> com.flash;<br><span style="font-weight: bold;line-height: 26px;">import</span> lombok.AllArgsConstructor;<br><br><span style="color: #999;font-weight: bold;line-height: 26px;">@ToString</span><br><span style="color: #999;font-weight: bold;line-height: 26px;">@AllArgsConstructor</span><br><span style="font-weight: bold;line-height: 26px;">public</span> <span style="line-height: 26px;"><span style="font-weight: bold;line-height: 26px;">class</span> <span style="color: #458;font-weight: bold;line-height: 26px;">Student</span> </span>{<br> <span style="font-weight: bold;line-height: 26px;">private</span> <span style="font-weight: bold;line-height: 26px;">int</span> age;<br>}<br></code></pre> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">测试类</span> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="color: black;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: PingFangSC-Light;font-size: 16px;padding: 10px;"> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #333;background: #f8f8f8;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="font-weight: bold;line-height: 26px;">package</span> com.flash;<br><span style="font-weight: bold;line-height: 26px;">import</span> com.alibaba.fastjson.JSONObject;<br><span style="font-weight: bold;line-height: 26px;">import</span> java.io.IOException;<br><br><span style="font-weight: bold;line-height: 26px;">public</span> <span style="line-height: 26px;"><span style="font-weight: bold;line-height: 26px;">class</span> <span style="color: #458;font-weight: bold;line-height: 26px;">TestLombokJackson</span> </span>{<br> <span style="line-height: 26px;"><span style="font-weight: bold;line-height: 26px;">public</span> <span style="font-weight: bold;line-height: 26px;">static</span> <span style="font-weight: bold;line-height: 26px;">void</span> <span style="color: #900;font-weight: bold;line-height: 26px;">main</span><span style="line-height: 26px;">(String[] args)</span> <span style="font-weight: bold;line-height: 26px;">throws</span> IOException </span>{<br> String json = <span style="color: #d14;line-height: 26px;">"{\"age\":1}"</span>;<br> Student s = JSONObject.parseObject(json, Student<span style="line-height: 26px;">.<span style="font-weight: bold;line-height: 26px;">class</span>)</span>;<br> System.out.println(s);<br> }<br>}<br></code></pre> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">结果报出了这个错。</span> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="color: black;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: PingFangSC-Light;font-size: 16px;padding: 10px;"> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;background: #272822;color: #ddd;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="color: rgb(255, 76, 65);">Exception in thread "main" com.alibaba.fastjson.JSONException: default constructor not found. class com.flash.Student<br> at com.alibaba.fastjson.util.JavaBeanInfo.build(JavaBeanInfo.java:224)<br> at com.alibaba.fastjson.parser.ParserConfig.createJavaBeanDeserializer(ParserConfig.java:574)<br> at com.alibaba.fastjson.parser.ParserConfig.getDeserializer(ParserConfig.java:491)<br> at com.alibaba.fastjson.parser.ParserConfig.getDeserializer(ParserConfig.java:348)<br> at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:639)<br> at com.alibaba.fastjson.JSON.parseObject(JSON.java:350)<br> at com.alibaba.fastjson.JSON.parseObject(JSON.java:254)<br> at com.alibaba.fastjson.JSON.parseObject(JSON.java:467)<br> at com.flash.TestLombokJackson.main(TestLombokJackson.java:12)</span><br></code></pre> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">关键信息是这个</span> <br> </section> <section style="line-height: 1.5em;"> <strong><span style="font-size: 16px;letter-spacing: 0.5px;">default constructor not found</span></strong> <span style="font-size: 16px;letter-spacing: 0.5px;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">看来,低版本 fastjson 在尝试寻找默认空参构造失败后,并不会去寻找那个 @ConstructorProperties 注解,所以直接在空参构造这里就把错误报出来了。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">我又试了一下高版本的 fastjson,解析成功了!</span> </section> <pre> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="padding: 10px;letter-spacing: 0px;white-space: normal;color: black;line-height: 1.6;word-break: break-word;text-align: left;font-family: PingFangSC-Light;font-size: 16px;"> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="padding: 16px;overflow-x: auto;background: rgb(39, 40, 34);color: rgb(221, 221, 221);display: -webkit-box;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;">Student(age=<span style="line-height: 26px;">1</span>)<br></code></pre> </section> <section style="white-space: normal;line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;">也就是说,高版本的 fastjson 可以不必非要有空参构造了,而且,也不需要有 @ConstructorProperties 注解,也能反序列化成功。</span> <br> </section></pre> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"><br></span> </section> <h2 data-foldable-wrapper=""> <section style="line-height: 1.5em;"> <strong><span style="letter-spacing: 0.5px;font-size: 20px;">那 fastjson 是怎么做到的呢?</span></strong> </section></h2> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">这是怎么做到的呢?为啥比 jackson 厉害。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">发生这一改变,肯定是在某个版本之间,我努力寻找到了这两个版本,<strong>1.2.35</strong> 版本的会报错,而 <strong>1.2.36</strong> 版本的不会报错,那我们看看区别吧。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <img class="rich_pages wxw-img" data-ratio="0.531129476584022" src="/upload/7181ff6b921583f6f4b0254c23f32949.png" data-type="png" data-w="1815" height="auto" style="height: auto !important;" width="1815"> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">我只看了关键节点,注意到原来直接报错的那个地方,前面多了好多行代码,那看来就是这些代码,导致情况有些不同。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">我截取关键片段,并做了一定程度的简化,比如省略了通过 JSONCreator 来寻找构造方法的过程。</span> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="color: black;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: PingFangSC-Light;font-size: 16px;padding: 10px;"> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #333;background: #f8f8f8;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="line-height: 26px;"><span style="font-weight: bold;line-height: 26px;">public</span> <span style="font-weight: bold;line-height: 26px;">static</span> JavaBeanInfo <span style="color: #900;font-weight: bold;line-height: 26px;">build</span><span style="line-height: 26px;">(...)</span> </span>{<br> ...<br> <span style="color: #998;font-style: italic;line-height: 26px;">// 直接获取默认空参构造</span><br> Constructor[] constructors = clazz.getDeclaredConstructors();<br> defaultConstructor = getDefaultConstructor(clazz, constructors);<br> ...<br> <span style="color: #998;font-style: italic;line-height: 26px;">// 默认空参不存在的话</span><br> <span style="font-weight: bold;line-height: 26px;">if</span> (defaultConstructor == <span style="font-weight: bold;line-height: 26px;">null</span>){<br> ...<br> <span style="font-weight: bold;line-height: 26px;">for</span> (Constructor constructor : constructors) {<br> ...<br> <span style="color: #998;font-style: italic;line-height: 26px;">// 通过 asm 方式寻找参数名</span><br> paramNames = ASMUtils.lookupParameterNames(constructor);<br> ...<br> }<br> ...<br> <span style="color: #998;font-style: italic;line-height: 26px;">// 找到了就可以正常返回了</span><br> <span style="font-weight: bold;line-height: 26px;">if</span> (paramNames != <span style="font-weight: bold;line-height: 26px;">null</span> && ...) {<br> ...<br> <span style="font-weight: bold;line-height: 26px;">return</span> <span style="font-weight: bold;line-height: 26px;">new</span> JavaBeanInfo(...);<br> }<br> <span style="color: #998;font-style: italic;line-height: 26px;">// 原来是直接到下面这句,不经过上面 asm 寻找名的过程</span><br> <span style="font-weight: bold;line-height: 26px;">throw</span> <span style="font-weight: bold;line-height: 26px;">new</span> JSONException(<span style="color: #d14;line-height: 26px;">"default constructor not found. "</span> + clazz);<br> }<br> ...<br>}<br></code></pre> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">注释已经很明确了,就是通过一个 ASM 工具类,在字节码层面把参数名找出来,这样就不用开发者手动把参数名写在注解上了。</span> <br> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">总结起来就是:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <p style="line-height: 1.5em;margin-left: 8px;margin-right: 8px;"><strong><span style="letter-spacing: 0.5px;font-size: 18px;">1</span></strong><span style="letter-spacing: 0.5px;font-size: 15px;">. 老版本的 fastjson 是不尝试寻找合适的有参构造,除非写了 JSONCreator 注解。</span></p> <p style="line-height: 1.5em;margin-left: 8px;margin-right: 8px;"><strong><span style="letter-spacing: 0.5px;font-size: 18px;">2</span></strong><span style="letter-spacing: 0.5px;font-size: 15px;">. jackson 也是不尝试自己寻找,但可以借助 lombok 或用户自己写的 ConstructorProperties 注解。</span></p> <p style="line-height: 1.5em;margin-left: 8px;margin-right: 8px;"><strong><span style="letter-spacing: 0.5px;font-size: 18px;">3</span></strong><span style="letter-spacing: 0.5px;font-size: 15px;">. 新版本的 fastjson 比较卷,还会自己尝试通过 asm 的方式强行帮你找到。</span></p> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">所以,新版的 fastjson 用在这里,就不会报错。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">但是新版本的 fastjson 仍然会先找空参构造,没找到,又去找加了 JSONCreator 注解的方法,又没找到,最后尝试用 ASMUtil 强行读取 class 文件把参数名揪出来,这过程一听就很麻烦。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">找到这行关键代码 <strong>ASMUtils.lookupParameterNames</strong> 的 <strong>commit </strong>信息,提交者也明确说明了它的作用,就是解决无默认空参构造的问题。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="letter-spacing: 0.5px;font-size: 15px;color: rgb(64, 118, 0);">improved non default constructor bean deserialize support. based on asm bytecode class reader lookup parameters.</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">从这个角度看,人家考虑的真全面。但换个角度,哪个开发者能管你这么细节的东西啊,假如我用 fastjson 好好的,结果换成了 jackson 报错了,谁能立刻想到居然是 lombok 生成注解以及 fastjson “超强大”的 ASM 取参数名这段代码导致的连锁</span> <span style="font-size: 16px;letter-spacing: 0.5px;">反应。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">或者,看似 lombok 为了 JDK9 的一个隐患而突破性地升级了自己的代码,但谁又能想到这东西配合 jackson 居然能产生这种“化学反应”。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">所有的框架,都在卷,增加功能,适配老版本,适应新时代,对开发者友好。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;"> </span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">但也正是这些过度设计,导致现在排查一个问题十分头疼,一个简简单单的 json 解析工具,搞得如此复杂,而且升级速度还特别快,根本不知道过几天又加了哪些“友好”的设计。</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="font-size: 16px;letter-spacing: 0.5px;">不过,咱作为开发者,就老老实实给实体类加上<strong>空参构造方法</strong>和 <strong>get\set</strong> 方法吧,标配就完事了。这么搞无论什么版本的 jackson 和 fastjson,就都不会报错了。</span> </section> <section class="mp_profile_iframe_wrp"> <mpprofile class="js_uneditable custom_select_card mp_profile_iframe" data-pluginname="mpprofile" data-id="Mzk0MjE3NDE0Ng==" data-headimg="http://mmbiz.qpic.cn/mmbiz_png/GLeh42uInXRVh3YhnV9yvZK9TGpSsFykUQPtHm4TuNAOUOr5qtPyZlg4DNciaYWiasRx1Fgt6UFTDjaK9qc08Llw/0?wx_fmt=png" data-nickname="低并发编程" data-alias="dibingfa" data-signature="战略上藐视技术,战术上重视技术" data-from="0"></mpprofile> </section> </section>
作者:微信小助手
<section style="font-size: 16px;" data-mpa-powered-by="yiban.io"> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="line-height: 1.6;word-break: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;padding: 5px;font-size: 16px;color: rgb(53, 53, 53);word-spacing: 0.8px;letter-spacing: 0.8px;border-radius: 16px;"> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">大家好,我是飘渺。<br>马上过完年又到了面试的高峰期,而一般情况下JVM在面试中是跑不掉的,所以特意给大家整理了一份JVM的常见面试题,刚好趁着过年的时候卷起来。话不多说,咱们直接开卷。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">1.说说 JVM 内存区域</span></h2> <img class="rich_pages wxw-img" data-ratio="0.75" src="/upload/b5fbde5606c788184fbef08dccf0c78b.png" data-type="png" data-w="948" style="margin: 20px auto;outline: 0px;vertical-align: middle;border-style: none;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangTC-Light, PingFangSC-light, PingFangTC-light;font-size: 16px;letter-spacing: 2px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);border-radius: 6px;display: block;object-fit: contain;box-shadow: rgb(153, 153, 153) 2px 4px 7px;box-sizing: border-box !important;width: 677px !important;visibility: visible !important;height: auto !important;"> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> JVM 内存区域 </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这张图就是一个 JVM 运行时数据图, <span style="font-weight: 700;color: rgb(248, 57, 41);">紫色区域代表是线程共享的区域</span> ,JAVA 程序在运行的过程中会把他管理的内存划分为若干个不同的数据区域, <span style="font-weight: 700;color: rgb(248, 57, 41);">每一块儿的数据区域所负责的功能都是不同的,他们也有不同的创建时间和销毁时间</span> 。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">1.程序计数器</span></p> </section></li> <ul style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);list-style-type: square;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 程序计数器是 <span style="font-weight: 700;color: rgb(248, 57, 41);">程序控制流的指示器,循环,跳转,异常处理,线程的恢复等工作都需要依赖程序计数器去完成</span> 。程序计数器是 <span style="font-weight: 700;color: rgb(248, 57, 41);">线程私有</span> 的,它的 <span style="font-weight: 700;color: rgb(248, 57, 41);">生命周期是和线程保持一致</span> 的,我们知道,N 个核心数的 CPU 在同一时刻,最多有 N个线程同时运行,在我们真实的使用过程中可能会创建很多线程,JVM 的多线程其实是通过线程轮流切换,分配处理器执行时间来实现的。既然涉及的线程切换,所以每条线程必须有一个独立的程序计数器。 </section></li> </ul> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">2.虚拟机栈</span></p> </section></li> <ul style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);list-style-type: square;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 虚拟机栈,其描述的就是线程内存模型, <span style="font-weight: 700;color: rgb(248, 57, 41);">也可以称作线程栈</span> ,也是每个 <span style="font-weight: 700;color: rgb(248, 57, 41);">线程私有</span> 的, <span style="font-weight: 700;color: rgb(248, 57, 41);">生命周期与线程保持一致</span> 。在每个方法执行的时候,jvm 都会同步创建一个栈帧去存储局部变量表,操作数栈,动态连接,方法出口等信息。一个方法的生命周期就贯彻了一个栈帧从入栈到出栈的全部过程。 </section></li> </ul> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">3.本地方法栈</span> 本地方法栈的概念很好理解,我们知道,java底层用了很多c的代码去实现,而其调用c端的方法上都会有native,代表本地方法服务,而本地方法栈就是为其服务的。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">4.堆</span> 堆可以说是jvm中最大的一块儿内存区域了,它是所有线程共享的,不管你是初学者还是资深开发,多少都会听说过堆,毕竟几乎所有的对象都会在堆中分配。</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">5.方法区</span></p> </section></li> <ul style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);list-style-type: square;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 方法区也是所有 <span style="font-weight: 700;color: rgb(248, 57, 41);">线程共享</span> 的区域,它 <span style="font-weight: 700;color: rgb(248, 57, 41);">存储</span> 了被 jvm 加载的 <span style="font-weight: 700;color: rgb(248, 57, 41);">类型信息、常量、静态变量等数据</span> 。运行时常量池就是方法区的一部分,编译期生成的各种字面量与符号引用就存储在其中。 </section></li> </ul> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">6.直接内存</span></p> </section></li> <ul style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);list-style-type: square;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 这部分数据并 <span style="font-weight: 700;color: rgb(248, 57, 41);">不是 jvm 运行时数据区的一部分</span> ,nio 就会使用到直接内存,也可以说 <span style="font-weight: 700;color: rgb(248, 57, 41);">堆外内存</span> ,通常会 <span style="font-weight: 700;color: rgb(248, 57, 41);">配合虚引用一起去使用</span> ,就是为了资源释放,会将堆外内存开辟空间的信息存储到一个队列中,然后GC会去清理这部分空间。堆外内存优势在 IO 操作上,对于网络 IO,使用 Socket 发送数据时,能够节省堆内存到堆外内存的数据拷贝,所以性能更高。看过 Netty 源码的同学应该了解,Netty 使用堆外内存池来实现零拷贝技术。对于磁盘 IO 时,也可以使用内存映射,来提升性能。另外,更重要的几乎不用考虑堆内存烦人的 GC 问题。但是既然是内存。也会受到本机总内存的限制, </section></li> </ul> </ul> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">2.垃圾对象是怎么找到的?</span></h2> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">1.引用计数算法</span> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">就是给对象添加一个计数器</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 每当有一个地方引用它的时候,计数器就加1 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 每当有一个引用失效的时候,计数器就减1 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">当计数器的值为0的时候,那么该对象就是垃圾了</span> 这种方案的原理很简单,而且判定的效率也非常高,但是却可能会有其他的额外情况需要考虑。</p> <img class="rich_pages wxw-img" data-ratio="0.2742409402546523" src="/upload/e0f195a33d020cc4601a6163e3e61c9b.png" data-type="png" data-w="1021" style="margin: 20px auto;outline: 0px;vertical-align: middle;border-style: none;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangTC-Light, PingFangSC-light, PingFangTC-light;font-size: 16px;letter-spacing: 2px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);border-radius: 6px;display: block;object-fit: contain;box-shadow: rgb(153, 153, 153) 2px 4px 7px;box-sizing: border-box !important;width: 677px !important;visibility: visible !important;height: auto !important;"> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 相互引用 </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">比如两个<span style="font-weight: 700;color: rgb(248, 57, 41);">对象循环引用</span> ,a 对象引用了 b 对象,b 对象也引用了 a 对象,a、b 对象却没有再被其他对象所引用了,其实正常来说这两个对象已经是垃圾了,因为没有其他对象在使用了,但是计数器内的数值却不是 0,所以引用计数算法就无法回收它们。这种算法是比较<span style="font-weight: 700;color: rgb(248, 57, 41);">直接的找到垃圾</span> ,然后去回收,也被称为"直接垃圾收集"。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">2.根可达算法</span> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这也是 <span style="font-weight: 700;color: rgb(248, 57, 41);">JVM 默认使用</span> 的寻找垃圾算法它的原理就是定义了一系列的根,我们把它称为 <span style="font-weight: 700;color: rgb(248, 57, 41);">"GC Roots"</span> ,从 <span style="font-weight: 700;color: rgb(248, 57, 41);">"GC Roots"</span> 开始往下进行搜索,走过的路径我们把它称为 <span style="font-weight: 700;color: rgb(248, 57, 41);">"引用链"</span> ,当一个对象到 <span style="font-weight: 700;color: rgb(248, 57, 41);">"GC Roots"</span> 之间没有任何引用链相连时,那么这个对象就可以被当做垃圾回收了。</p> <img class="rich_pages wxw-img" data-ratio="0.600990099009901" src="/upload/83d389e659ef31672ccc30afda68708b.png" data-type="png" data-w="1010" style="margin: 20px auto;outline: 0px;vertical-align: middle;border-style: none;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangTC-Light, PingFangSC-light, PingFangTC-light;font-size: 16px;letter-spacing: 2px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);border-radius: 6px;display: block;object-fit: contain;box-shadow: rgb(153, 153, 153) 2px 4px 7px;box-sizing: border-box !important;width: 677px !important;visibility: visible !important;height: auto !important;"> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> root search </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">如图, <span style="font-weight: 700;color: rgb(248, 57, 41);">根可达算法</span> 就可以 <span style="font-weight: 700;color: rgb(248, 57, 41);">避免</span> 计数器算法不好解决的 <span style="font-weight: 700;color: rgb(248, 57, 41);">循环引用问题</span> ,Object 6、Object 7、Object 8彼此之前有引用关系,但是 <span style="font-weight: 700;color: rgb(248, 57, 41);">没有与"GC Roots" 相连,那么就会被当做垃圾所回收</span> 。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">3.GC Roots 有哪些?</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">在java中,有<span style="font-weight: 700;color: rgb(248, 57, 41);">固定的GC Roots 对象</span> 和 <span style="font-weight: 700;color: rgb(248, 57, 41);">不固定的临时GC Roots对象</span> :</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">固定的GC Roots:</span></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 1.在 <span style="font-weight: 700;color: rgb(248, 57, 41);">虚拟机栈(栈帧的本地变量表)中所引用的对象</span> ,譬如各个线程被调用的方法堆栈中使用到的参数、局部变量、临时变量等。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 在方法区中类静态属性引用的对象,譬如 Java 类的 <span style="font-weight: 700;color: rgb(248, 57, 41);">引用静态变量</span> 。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 在方法区中 <span style="font-weight: 700;color: rgb(248, 57, 41);">常量引用的对象</span> ,譬如字符串常量池中的引用。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 在方法区栈中 <span style="font-weight: 700;color: rgb(248, 57, 41);">JNI (譬如 Native 方法)引用的对象</span> 。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Java <span style="font-weight: 700;color: rgb(248, 57, 41);">虚拟机内部的引用</span> ,如基本数据类型对应的 Class 对象,一些常驻的异常对象(空指针异常、OOM等),还有类加载器。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 所有 <span style="font-weight: 700;color: rgb(248, 57, 41);">被 Synchronized 持有的对象</span> 。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 反应 Java 虚拟机内部情况的 <span style="font-weight: 700;color: rgb(248, 57, 41);">JMXBean、JVMTI 中注册的回调本地代码缓存等</span> 。 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">临时GC Roots:</span></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">为什么会有临时的 GC Roots ?</span> :目前的垃圾回收大部分都是 <span style="font-weight: 700;color: rgb(248, 57, 41);">分代收集和局部回收</span> ,如果只针对某一部分区域进行局部回收,那么就必须要考虑的 <span style="font-weight: 700;color: rgb(248, 57, 41);">当前区域的对象有可能正被其他区域的对象所引用</span> ,这时候就要将这部分关联的对象也添加到 GC Roots 中去来确保根可达算法的准确性。这种算法是利用了 <span style="font-weight: 700;color: rgb(248, 57, 41);">逆向思维</span> ,找到使用的对象,剩下的就是垃圾,也被称为"间接垃圾收集"。 </section></li> </ul> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">4.java 有哪四种引用类型?</span></h2> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">1.强引用</span> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">"Object o = new Object()" 就是一种强引用关系,这也是我们在代码中最常用的一种引用关系。无论任何情况下,只要强引用关系还存在,垃圾回收器就不会回收掉被引用的对象。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">2.软引用</span> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">当内存空间不足时,就会回收软引用对象。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #383a42;background: #fafafa;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;"><span style="color: #a0a1a7;font-style: italic;line-height: 26px;">// 软引用 </span><br>SoftReference<String> softRef = <span style="color: #a626a4;line-height: 26px;">new</span> SoftReference<String>(str);<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">软引用用来描述那些有用但是没必要的对象。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">3.弱引用</span> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">弱引用要比软引用更弱一点,它 <span style="font-weight: 700;color: rgb(248, 57, 41);">只能够存活到下次垃圾回收之前</span> 。也就是说,垃圾回收器开始工作,会回收掉所有只被弱引用关联的对象。</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"><code style="overflow-x: auto;padding: 16px;color: #383a42;background: #fafafa;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;border-radius: 0px;font-size: 12px;-webkit-overflow-scrolling: touch;">WeakReference<String> weakRef = <span style="color: #a626a4;line-height: 26px;">new</span> WeakReference<String>(str);<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">在 <span style="font-weight: 700;color: rgb(248, 57, 41);">ThreadLocal</span> 中就使用了弱引用来防止内存泄漏。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">4.虚引用</span> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">虚引用是最弱的一种引用关系,它的唯一作用是用来作为一种通知。如零拷贝(Zero Copy),开辟了堆外内存,虚引用在这里使用,会将这部分信息存储到一个队列中,以便于后续对堆外内存的回收管理。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">5.说一说分代收集理论</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">大多数的垃圾回收器都遵循了分代收集的理论进行设计,它建立在两个分代假说之上:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">弱分代假说</span> :绝大多数对象都是朝生夕灭的。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">强分代假说</span> :熬过越多次数垃圾回收过程的对象就越难消亡。 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这两种假说的设计原则都是相同的:垃圾收集器 <span style="font-weight: 700;color: rgb(248, 57, 41);">应该将jvm划分出不同的区域</span> ,把那些较难回收的对象放在一起(一般指老年代),这个区域的垃圾回收频率就可以降低,减少垃圾回收的开销。剩下的区域(一般指新生代)可以用较高的频率去回收,并且只需要去关心那些存活的对象,也不用标记出需要回收的垃圾,这样就能够以较低的代价去完成垃圾回收。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">跨代引用假说</span> :如果某个新生代的对象存在了跨代引用,但是老年代的对象是很难消亡的,那么随着时间的推移,这个新生代对象也会慢慢晋升为老年代对象,那么这种跨代引用也就被消除了。 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">由于跨代引用是很少的,所以我们不应该为了少量的跨代引用去扫描整个老年代的数据,只需要在新生代对象建立一个 <span style="font-weight: 700;color: rgb(248, 57, 41);">记忆集</span> 来记录引用信息。记忆集: <span style="font-weight: 700;color: rgb(248, 57, 41);">将老年代分为若干个小块,每块区域中有 N 个对象</span> ,在对象引用信息发生变动的时候来维护记忆集数据的准确性,这样每次发生了 <span style="font-weight: 700;color: rgb(248, 57, 41);">"Minor GC"</span> 的时候只需要将记忆集中的对象添加到 <span style="font-weight: 700;color: rgb(248, 57, 41);">"GC Roots"</span> 中就可以了。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">6.垃圾收集算法有哪些?</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">总共有三种</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <span style="font-weight: 700;color: rgb(248, 57, 41);">1.标记清除算法</span> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这种算法的实现是很简单的,有两种方式</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 1.标记出垃圾,然后清理掉 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 2.标记出存货的对象,回收其他空间 </section></li> </ul> <img class="rich_pages wxw-img" data-ratio="0.67384916748286" src="/upload/d5f034effa40dfc75b7548efc9b01544.png" data-type="png" data-w="1021" style="margin: 20px auto;outline: 0px;vertical-align: middle;border-style: none;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangTC-Light, PingFangSC-light, PingFangTC-light;font-size: 16px;letter-spacing: 2px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);border-radius: 6px;display: block;object-fit: contain;box-shadow: rgb(153, 153, 153) 2px 4px 7px;box-sizing: border-box !important;width: 677px !important;visibility: visible !important;height: auto !important;"> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 标记清除算法 </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这种算法有两个<span style="font-weight: 700;color: rgb(248, 57, 41);">缺点</span></p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">1.随着对象越来越多,那么所需要消耗的时间就会越来越多</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">2.标记清除后会导致碎片化,如果有大对象分配很有可能分配不下而出发另一次的垃圾收集动作</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">2.标记复制算法</span></p> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这种算法解决了第一种算法碎片化的问题。就是 <span style="font-weight: 700;color: rgb(248, 57, 41);">开辟两块完全相同的区域</span> ,对象只在其中一篇区域内分配,然后 <span style="font-weight: 700;color: rgb(248, 57, 41);">标记</span> 出那些 <span style="font-weight: 700;color: rgb(248, 57, 41);">存活的对象,按顺序整体移到另外一个空间</span> ,如下图,可以看到回收后的对象是排列有序的,这种操作只需要移动指针就可以完成,效率很高, <span style="font-weight: 700;color: rgb(248, 57, 41);">之后就回收移除前的空间</span> 。</p> <img class="rich_pages wxw-img" data-ratio="0.593320235756385" src="/upload/c10cc58041975b6f1edaaeb96390739f.png" data-type="png" data-w="1018" style="margin: 20px auto;outline: 0px;vertical-align: middle;border-style: none;color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangTC-Light, PingFangSC-light, PingFangTC-light;font-size: 16px;letter-spacing: 2px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);border-radius: 6px;display: block;object-fit: contain;box-shadow: rgb(153, 153, 153) 2px 4px 7px;box-sizing: border-box !important;width: 677px !important;visibility: visible !important;height: auto !important;"> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <figcaption style="margin-top: 5px;text-align: center;color: rgb(136, 136, 136);font-size: 12px;"> 标记复制算法 </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">这种算法的缺点也是很明显的</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;">浪费过多的内存,使现有的 <span style="font-weight: 700;color: rgb(248, 57, 41);">可用空间变为</span> 原先的 <span style="font-weight: 700;color: rgb(248, 57, 41);">一半</span></p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> <p style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0.8em;margin-bottom: 0.8em;"><span style="font-weight: 700;color: rgb(248, 57, 41);">3.标记整理算法</span></p> </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8
作者:微信小助手
<p style="white-space: normal;text-align: center;" data-mpa-powered-by="yiban.io"><img class="rich_pages wxw-img" data-galleryid="" data-ratio="0.42577777777777776" data-s="300,640" src="/upload/d135b8784f9bc37b39b7ce47acf7bec8.png" data-type="png" data-w="2250" style="font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;"><br></p> <p data-darkmode-color-15906764299112="rgb(230, 230, 230)" data-darkmode-original-color-15906764299112="rgb(0, 0, 0)" data-darkmode-bgcolor-15906764299112="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15906764299112="rgb(255, 255, 255)" data-style="margin-top: 10px; margin-bottom: 10px; background-color: rgb(255, 255, 255); color: rgb(0, 0, 0); font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif; font-size: 16px; white-space: normal; word-spacing: 0.8px; letter-spacing: 0.75px; text-align: center; visibility: visible;" class="js_darkmode__1" data-darkmode-color-15958675267961="rgb(163, 163, 163)" data-darkmode-original-color-15958675267961="rgb(0, 0, 0)" data-darkmode-bgcolor-15958675267961="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15958675267961="rgb(255, 255, 255)" data-darkmode-color-15965526125846="rgb(163, 163, 163)" data-darkmode-original-color-15965526125846="rgb(0, 0, 0)" data-darkmode-bgcolor-15965526125846="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15965526125846="rgb(255, 255, 255)" data-darkmode-bgcolor-15969880239317="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15969880239317="rgb(255, 255, 255)" data-darkmode-color-15969880239317="rgb(163, 163, 163)" data-darkmode-original-color-15969880239317="rgb(0, 0, 0)" data-darkmode-color-15976750929548="rgb(163, 163, 163)" data-darkmode-original-color-15976750929548="rgb(0, 0, 0)" data-darkmode-bgcolor-15976750929548="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15976750929548="rgb(255, 255, 255)" data-darkmode-color-15982803404507="rgb(163, 163, 163)" data-darkmode-original-color-15982803404507="rgb(0, 0, 0)" data-darkmode-bgcolor-15982803404507="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15982803404507="rgb(255, 255, 255)" style="margin-top: 10px;margin-bottom: 10px;white-space: normal;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;background-color: rgb(255, 255, 255);font-size: 16px;word-spacing: 0.8px;text-align: right;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span data-darkmode-color-15906764299112="rgb(230, 230, 230)" data-darkmode-original-color-15906764299112="rgb(0, 0, 0)" data-darkmode-bgcolor-15906764299112="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15906764299112="rgb(255, 255, 255)" data-darkmode-color-15958675267961="rgb(163, 163, 163)" data-darkmode-original-color-15958675267961="rgb(0, 0, 0)" data-darkmode-bgcolor-15958675267961="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15958675267961="rgb(255, 255, 255)" data-darkmode-color-15965526125846="rgb(163, 163, 163)" data-darkmode-original-color-15965526125846="rgb(0, 0, 0)" data-darkmode-bgcolor-15965526125846="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15965526125846="rgb(255, 255, 255)" data-darkmode-bgcolor-15969880239317="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15969880239317="rgb(255, 255, 255)" data-darkmode-color-15969880239317="rgb(163, 163, 163)" data-darkmode-original-color-15969880239317="rgb(0, 0, 0)" data-darkmode-color-15976750929548="rgb(163, 163, 163)" data-darkmode-original-color-15976750929548="rgb(0, 0, 0)" data-darkmode-bgcolor-15976750929548="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15976750929548="rgb(255, 255, 255)" data-darkmode-color-15982803404507="rgb(163, 163, 163)" data-darkmode-original-color-15982803404507="rgb(0, 0, 0)" data-darkmode-bgcolor-15982803404507="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15982803404507="rgb(255, 255, 255)" style="max-width: 100%;font-size: 14px;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="color: rgb(0, 0, 0);">这是悟空的第 </span><span style="color: rgb(255, 104, 39);">140</span></span><span data-darkmode-color-15906764299112="rgb(230, 230, 230)" data-darkmode-original-color-15906764299112="rgb(0, 0, 0)" data-darkmode-bgcolor-15906764299112="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15906764299112="rgb(255, 255, 255)" data-darkmode-color-15958675267961="rgb(163, 163, 163)" data-darkmode-original-color-15958675267961="rgb(0, 0, 0)" data-darkmode-bgcolor-15958675267961="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15958675267961="rgb(255, 255, 255)" data-darkmode-color-15965526125846="rgb(163, 163, 163)" data-darkmode-original-color-15965526125846="rgb(0, 0, 0)" data-darkmode-bgcolor-15965526125846="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15965526125846="rgb(255, 255, 255)" data-darkmode-bgcolor-15969880239317="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15969880239317="rgb(255, 255, 255)" data-darkmode-color-15969880239317="rgb(163, 163, 163)" data-darkmode-original-color-15969880239317="rgb(0, 0, 0)" data-darkmode-color-15976750929548="rgb(163, 163, 163)" data-darkmode-original-color-15976750929548="rgb(0, 0, 0)" data-darkmode-bgcolor-15976750929548="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15976750929548="rgb(255, 255, 255)" data-darkmode-color-15982803404507="rgb(163, 163, 163)" data-darkmode-original-color-15982803404507="rgb(0, 0, 0)" data-darkmode-bgcolor-15982803404507="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15982803404507="rgb(255, 255, 255)" style="color: rgb(0, 0, 0);max-width: 100%;font-size: 14px;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"> 篇原创文章</span><br data-darkmode-color-15982803404507="rgb(163, 163, 163)" data-darkmode-original-color-15982803404507="rgb(0, 0, 0)" data-darkmode-bgcolor-15982803404507="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15982803404507="rgb(255, 255, 255)" style="max-width: 100%;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p data-tool="mdnice编辑器" data-darkmode-color-15906764299112="rgb(230, 230, 230)" data-darkmode-original-color-15906764299112="rgb(0, 0, 0)" data-darkmode-bgcolor-15906764299112="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15906764299112="rgb(255, 255, 255)" data-style="background-color: rgb(255, 255, 255); color: rgb(0, 0, 0); font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif; font-size: 16px; white-space: normal; word-spacing: 0.8px; letter-spacing: 0.75px; text-align: center; visibility: visible;" class="js_darkmode__2" data-darkmode-color-15958675267961="rgb(163, 163, 163)" data-darkmode-original-color-15958675267961="rgb(0, 0, 0)" data-darkmode-bgcolor-15958675267961="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15958675267961="rgb(255, 255, 255)" data-darkmode-color-15965526125846="rgb(163, 163, 163)" data-darkmode-original-color-15965526125846="rgb(0, 0, 0)" data-darkmode-bgcolor-15965526125846="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15965526125846="rgb(255, 255, 255)" data-darkmode-bgcolor-15969880239317="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15969880239317="rgb(255, 255, 255)" data-darkmode-color-15969880239317="rgb(163, 163, 163)" data-darkmode-original-color-15969880239317="rgb(0, 0, 0)" data-darkmode-color-15976750929548="rgb(163, 163, 163)" data-darkmode-original-color-15976750929548="rgb(0, 0, 0)" data-darkmode-bgcolor-15976750929548="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15976750929548="rgb(255, 255, 255)" data-darkmode-color-15982803404507="rgb(163, 163, 163)" data-darkmode-original-color-15982803404507="rgb(0, 0, 0)" data-darkmode-bgcolor-15982803404507="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15982803404507="rgb(255, 255, 255)" style="margin-top: 10px;margin-bottom: 10px;white-space: normal;max-width: 100%;min-height: 1em;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;letter-spacing: 0.75px;background-color: rgb(255, 255, 255);font-size: 16px;word-spacing: 0.8px;text-align: right;visibility: visible;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span data-darkmode-color-15906764299112="rgb(230, 230, 230)" data-darkmode-original-color-15906764299112="rgb(0, 0, 0)" data-darkmode-bgcolor-15906764299112="rgb(36, 36, 36)" data-darkmode-original-bgcolor-15906764299112="rgb(255, 255, 255)" data-darkmode-color-15958675267961="rgb(163, 163, 163)" data-darkmode-original-color-15958675267961="rgb(0, 0, 0)" data-darkmode-bgcolor-15958675267961="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15958675267961="rgb(255, 255, 255)" data-darkmode-color-15965526125846="rgb(163, 163, 163)" data-darkmode-original-color-15965526125846="rgb(0, 0, 0)" data-darkmode-bgcolor-15965526125846="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15965526125846="rgb(255, 255, 255)" data-darkmode-bgcolor-15969880239317="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15969880239317="rgb(255, 255, 255)" data-darkmode-color-15969880239317="rgb(163, 163, 163)" data-darkmode-original-color-15969880239317="rgb(0, 0, 0)" data-darkmode-color-15976750929548="rgb(163, 163, 163)" data-darkmode-original-color-15976750929548="rgb(0, 0, 0)" data-darkmode-bgcolor-15976750929548="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15976750929548="rgb(255, 255, 255)" data-darkmode-color-15982803404507="rgb(163, 163, 163)" data-darkmode-original-color-15982803404507="rgb(0, 0, 0)" data-darkmode-bgcolor-15982803404507="rgb(25, 25, 25)" data-darkmode-original-bgcolor-15982803404507="rgb(255, 255, 255)" style="max-width: 100%;font-size: 14px;visibility: visible;color: rgb(0, 0, 0);box-sizing: border-box !important;overflow-wrap: break-word !important;">官网:www.passjava.cn</span></p> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="line-height: 1.6;word-break: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 15px;color: rgb(53, 53, 53);word-spacing: 0.8px;letter-spacing: 0.8px;border-radius: 16px;"> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">大家好,我是悟空呀。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">上次我们讲解了 <a href="https://mp.weixin.qq.com/s?__biz=MzAwMjI0ODk0NA==&mid=2451961986&idx=1&sn=f805fc10fd08353f2b1916ae0beec5fd&scene=21#wechat_redirect" style="color: rgb(248, 57, 41);border-bottom: 1px solid rgb(248, 57, 41);" data-linktype="2">OpenFeign 的架构原理</a>,这次我们要来进入 Nacos 帝国了,Nacos 作为服务注册中心、配置中心,已经非常成熟了,业界的标杆,在讲解 Nacos 的架构原理之前,我先给大家来一篇开胃菜:讲解 Nacos 如何使用。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">涉及到如下两个话题:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);font-size: 16px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 用 Nacos 作为 <span style="color: rgb(255, 104, 39);">注册</span>中心。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 用 Nacos 作为 <span style="color: rgb(255, 104, 39);">配置</span>中心。 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">由于本篇是针对 Nacos 的使用和配置教程,可能会略显枯燥,建议大家快速浏览一遍,然后收藏转发下,以后说不定就会用上了~~</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">本篇主要内容如下:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.7327327327327328" src="/upload/d58b55b03001a87381d8618c5657cb1f.png" data-type="png" data-w="1332" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">老规矩,本篇所有示例代码都是用我的开源 SpringCloud 项目 PassJava 作为示例。</p> <blockquote data-tool="mdnice编辑器" style="border-top: none;border-right: none;border-bottom: none;font-size: 0.9em;overflow: auto;color: rgb(106, 115, 125);padding: 10px 10px 10px 20px;margin-bottom: 20px;margin-top: 20px;border-left-color: rgb(255, 177, 27);background: rgb(255, 245, 227);"> <p style="padding-top: 8px;padding-bottom: 8px;font-size: 15px;color: black;line-height: 26px;">开源地址: https://github.com/Jackson0714/PassJava-Platform</p> <p style="padding-top: 8px;padding-bottom: 8px;font-size: 15px;color: black;line-height: 26px;">喜欢的小伙伴来点个 Star 吧,冲 2K Star。</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">PassJava 架构图如下所示:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;border-radius: 16px;overflow: hidden;"> <img class="rich_pages wxw-img" data-ratio="0.56768038163387" src="/upload/327eaf3fdc7dcd7f6c34cbbb442aed62.png" data-type="png" data-w="1677" style="border-radius: 6px;display: block;margin: 20px auto;max-width: 95%;object-fit: contain;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">Nacos 是阿里巴巴开源的一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;color: black;font-size: 22px;margin-top: 20px;margin-right: 10px;"><span style="display: none;"></span><span style="font-size: 18px;color: rgb(34, 34, 34);display: inline-block;padding-left: 10px;border-left: 5px solid rgb(248, 57, 41);">一、Nacos 作为注册中心</span></h2> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;"><span style="display: none;"></span><span style="font-size: 16px;color: #222;">1.1 引入 Nacos 服务发现组件</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">passjava-common模块的pom.xml文件引入Nacos 服务发现组件</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/ibKHP1TZZeXLuuibODqFs5MjCkf6wj1YMvrUzxlf4Ffna9kXhYtGDgacT4NtFOKa4zMxhSBrgEesPIJRprCdh0se0huue820so/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(250, 250, 250);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #383a42;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #fafafa;border-radius: 5px;"><span style="color: #a0a1a7;font-style: italic;line-height: 26px;"><!-- nacos discovery 服务发现组件--></span><br><span style="line-height: 26px;"><<span style="color: #e45649;line-height: 26px;">dependency</span>></span><br> <span style="line-height: 26px;"><<span style="color: #e45649;line-height: 26px;">groupId</span>></span>com.alibaba.cloud<span style="line-height: 26px;"></<span style="color: #e45649;line-height: 26px;">groupId</span>></span><br> <span style="line-height: 26px;"><<span style="color: #e45649;line-height: 26px;">artifactId</span>></span>spring-cloud-starter-alibaba-nacos-discovery<span style="line-height: 26px;"></<span style="color: #e45649;line-height: 26px;">artifactId</span>></span><br><span style="line-height: 26px;"></<span style="color: #e45649;line-height: 26px;">dependency</span>></span><br></code></pre> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;color: black;font-size: 20px;"><span style="display: none;"></span><span style="font-size: 16px;color: #222;">1.2 下载 Nacos Server 工具包并启动</span><span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">注意:我在 Windows 和 Mac 上都测试过,都可以正常使用。</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);font-size: 16px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> 下载Nacos Server 压缩包 </section></li> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">https://github.com/alibaba/nacos/releases</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 1.75;margin-top: 0em;margin-bottom: 0em;">启动 Server,进入解压后文件夹或编译打包好的文件夹,找到如下相对文件夹 nacos/bin,并对照操作系统实际情况之下如下命令。</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;color: rgb(248, 57, 41);font-size: 16px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Linux/Unix/Mac 操作系统,执行命令 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 93, 108);">sh startup.sh -m standalone</code> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(53, 53, 53);"> Windows 操作系统,执行命令 <code style=
作者:微信小助手
<blockquote style="white-space: normal;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;border-left: none;padding: 1em;border-radius: 8px;color: rgba(0, 0, 0, 0.5);background: rgb(247, 247, 247);margin: 0px 8px 2em;"> <p style="line-height: 1.75;font-size: 1em;letter-spacing: 0.1em;color: rgb(80, 80, 80);">本文摘自 Doocs 开源社区《<strong style="line-height: 1.75;color: rgb(24, 204, 162);">互联网 Java 工程师进阶知识完全扫盲</strong>》手册,方便读者在手机上阅读学习。<br><br>也欢迎读者们关注 GitHub 项目:<strong style="line-height: 1.75;color: rgb(24, 204, 162);">https://github.com/doocs/advanced-java</strong></p> </blockquote> <h2 style="white-space: normal;text-align: center;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 16.5px;font-weight: bold;display: table;margin: 4em auto 2em;padding-right: 0.2em;padding-left: 0.2em;background: rgb(24, 204, 162);color: rgb(255, 255, 255);">面试题</h2> <p style="white-space: normal;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;margin: 1.5em 8px;letter-spacing: 0.1em;color: rgb(63, 63, 63);">你们有没有做 MySQL 读写分离?如何实现 MySQL 的读写分离?MySQL 主从复制原理的是啥?如何解决 MySQL 主从同步的延时问题?</p> <h2 style="white-space: normal;text-align: center;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 16.5px;font-weight: bold;display: table;margin: 4em auto 2em;padding-right: 0.2em;padding-left: 0.2em;background: rgb(24, 204, 162);color: rgb(255, 255, 255);">面试官心理分析</h2> <p style="white-space: normal;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;margin: 1.5em 8px;letter-spacing: 0.1em;color: rgb(63, 63, 63);">高并发这个阶段,肯定是需要做读写分离的,啥意思?因为实际上大部分的互联网公司,一些网站,或者是 app,其实都是读多写少。所以针对这个情况,就是写一个主库,但是主库挂多个从库,然后从多个从库来读,那不就可以支撑更高的读并发压力了吗?</p> <h2 style="white-space: normal;text-align: center;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 16.5px;font-weight: bold;display: table;margin: 4em auto 2em;padding-right: 0.2em;padding-left: 0.2em;background: rgb(24, 204, 162);color: rgb(255, 255, 255);">面试题剖析</h2> <h3 style="white-space: normal;text-align: left;line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;font-weight: bold;margin-top: 2em;margin-right: 8px;margin-bottom: 0.75em;padding-left: 8px;border-left: 3px solid rgb(24, 204, 162);color: rgb(63, 63, 63);">如何实现 MySQL 的读写分离?</h3> <p style="white-space: normal;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;margin: 1.5em 8px;letter-spacing: 0.1em;color: rgb(63, 63, 63);">其实很简单,就是基于主从复制架构,简单来说,就搞一个主库,挂多个从库,然后我们就单单只是写主库,然后主库会自动把数据给同步到从库上去。</p> <h3 style="white-space: normal;text-align: left;line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;font-weight: bold;margin-top: 2em;margin-right: 8px;margin-bottom: 0.75em;padding-left: 8px;border-left: 3px solid rgb(24, 204, 162);color: rgb(63, 63, 63);">MySQL 主从复制原理的是啥?</h3> <p style="white-space: normal;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;margin: 1.5em 8px;letter-spacing: 0.1em;color: rgb(63, 63, 63);">主库将变更写入 binlog 日志,然后从库连接到主库之后,从库有一个 IO 线程,将主库的 binlog 日志拷贝到自己本地,写入一个 relay 中继日志中。接着从库中有一个 SQL 线程会从中继日志读取 binlog,然后执行 binlog 日志中的内容,也就是在自己本地再次执行一遍 SQL,这样就可以保证自己跟主库的数据是一样的。</p> <p style="text-align: center;"><img class="rich_pages wxw-img js_insertlocalimg" data-ratio="0.5988857938718662" data-s="300,640" src="/upload/c11a0fd7be742e763e77849f4e6405d9.png" data-type="png" data-w="718" style=""></p> <figure style="white-space: normal;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;margin: 1.5em 8px;color: rgb(63, 63, 63);"> <figcaption style="text-align: center;line-height: 1.75;color: rgb(136, 136, 136);font-size: 0.8em;"> mysql-master-slave </figcaption> </figure> <p style="white-space: normal;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;margin: 1.5em 8px;letter-spacing: 0.1em;color: rgb(63, 63, 63);">这里有一个非常重要的一点,就是从库同步主库数据的过程是串行化的,也就是说主库上并行的操作,在从库上会串行执行。所以这就是一个非常重要的点了,由于从库从主库拷贝日志以及串行执行 SQL 的特点,在高并发场景下,从库的数据一定会比主库慢一些,是<strong style="line-height: 1.75;color: rgb(24, 204, 162);">有延时</strong>的。所以经常出现,刚写入主库的数据可能是读不到的,要过几十毫秒,甚至几百毫秒才能读取到。</p> <p style="white-space: normal;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;margin: 1.5em 8px;letter-spacing: 0.1em;color: rgb(63, 63, 63);">而且这里还有另外一个问题,就是如果主库突然宕机,然后恰好数据还没同步到从库,那么有些数据可能在从库上是没有的,有些数据可能就丢失了。</p> <p style="white-space: normal;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;margin: 1.5em 8px;letter-spacing: 0.1em;color: rgb(63, 63, 63);">所以 MySQL 实际上在这一块有两个机制,一个是<strong style="line-height: 1.75;color: rgb(24, 204, 162);">半同步复制</strong>,用来解决主库数据丢失问题;一个是<strong style="line-height: 1.75;color: rgb(24, 204, 162);">并行复制</strong>,用来解决主从同步延时问题。</p> <p style="white-space: normal;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;margin: 1.5em 8px;letter-spacing: 0.1em;color: rgb(63, 63, 63);">这个所谓<strong style="line-height: 1.75;color: rgb(24, 204, 162);">半同步复制</strong>,也叫 <code style="white-space:pre-wrap;line-height: 1.75;font-size: 13.5px;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;">semi-sync</code> 复制,指的就是主库写入 binlog 日志之后,就会将<strong style="line-height: 1.75;color: rgb(24, 204, 162);">强制</strong>此时立即将数据同步到从库,从库将日志写入自己本地的 relay log 之后,接着会返回一个 ack 给主库,主库接收到<strong style="line-height: 1.75;color: rgb(24, 204, 162);">至少一个从库</strong>的 ack 之后才会认为写操作完成了。</p> <p style="white-space: normal;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;margin: 1.5em 8px;letter-spacing: 0.1em;color: rgb(63, 63, 63);">所谓<strong style="line-height: 1.75;color: rgb(24, 204, 162);">并行复制</strong>,指的是从库开启多个线程,并行读取 relay log 中不同库的日志,然后<strong style="line-height: 1.75;color: rgb(24, 204, 162);">并行重放不同库的日志</strong>,这是库级别的并行。</p> <h3 style="white-space: normal;text-align: left;line-height: 1.2;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;font-weight: bold;margin-top: 2em;margin-right: 8px;margin-bottom: 0.75em;padding-left: 8px;border-left: 3px solid rgb(24, 204, 162);color: rgb(63, 63, 63);">MySQL 主从同步延时问题(精华)</h3> <p style="white-space: normal;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;margin: 1.5em 8px;letter-spacing: 0.1em;color: rgb(63, 63, 63);">以前线上确实处理过因为主从同步延时问题而导致的线上的 bug,属于小型的生产事故。</p> <p style="white-space: normal;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;margin: 1.5em 8px;letter-spacing: 0.1em;color: rgb(63, 63, 63);">是这个么场景。有个同学是这样写代码逻辑的。先插入一条数据,再把它查出来,然后更新这条数据。在生产环境高峰期,写并发达到了 2000/s,这个时候,主从复制延时大概是在小几十毫秒。线上会发现,每天总有那么一些数据,我们期望更新一些重要的数据状态,但在高峰期时候却没更新。用户跟客服反馈,而客服就会反馈给我们。</p> <p style="white-space: normal;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;margin: 1.5em 8px;letter-spacing: 0.1em;color: rgb(63, 63, 63);">我们通过 MySQL 命令:</p> <pre style="color: rgb(171, 178, 191);background: rgb(40, 44, 52);font-size: 14px;text-align: left;line-height: 1.5;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;overflow-x: auto;border-radius: 8px;padding: 1em;margin: 10px 8px;"><code style="line-height: 1.75;font-family: Menlo, "Operator Mono", Consolas, Monaco, monospace;font-size: 15px;white-space: nowrap;"><span style="color: rgb(198, 120, 221);">show</span> slave status</code></pre> <p style="white-space: normal;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;margin: 1.5em 8px;letter-spacing: 0.1em;color: rgb(63, 63, 63);">查看 <code style="white-space:pre-wrap;line-height: 1.75;font-size: 13.5px;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;">Seconds_Behind_Master</code> ,可以看到从库复制主库的数据落后了几 ms。</p> <p style="white-space: normal;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;margin: 1.5em 8px;letter-spacing: 0.1em;color: rgb(63, 63, 63);">一般来说,如果主从延迟较为严重,有以下解决方案:</p> <p style="white-space: normal;text-align: left;line-height: 1.75;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 15px;padding-left: 1em;list-style: circle;color: rgb(63, 63, 63);"><span style="line-height: 1.75;text-indent: -1em;display: block;margin: 0.2em 8px;"><span style="margin-right: 10px;">•</span>分库,将一个主库拆分为多个主库,每个主库的写并发就减少了几倍,此时主从延迟可以忽略不计。</span><span style="line-height: 1.75;text-indent: -1em;display: block;margin: 0.2em 8px;"><span style="margin-right: 10px;">•</span>打开 MySQL 支持的并行复制,多个库并行复制。如果说某个库的写入并发就是特别高,单库写并发达到了 2000/s,并行复制还是没意义。</span><span style="line-height: 1.75;text-indent: -1em;display: block;margin: 0.2em 8px;"><span style="margin-right: 10px;">•</span>重写代码,写代码的同学,要慎重,插入数据时立马查询可能查不到。</span><span style="line-height: 1.75;text-indent: -1em;display: block;margin: 0.2em 8px;"><span style="margin-right: 10px;">•</span>如果确实是存在必须先插入,立马要求就查询到,然后立马就要反过来执行一些操作,对这个查询<strong style="line-height: 1.75;color: rgb(24, 204, 162);">设置直连主库</strong>。<strong style="line-height: 1.75;color: rgb(24, 204, 162);">不推荐</strong>这种方法,你要是这么搞,读写分离的意义就丧失了。</span></p>
作者:微信小助手
<p style="white-space: normal;" data-mpa-powered-by="yiban.io"><span style="font-size: 15px;">我是一个 Linux 服务器上的进程,名叫小进。</span><br></p> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">老是有人说我最多只能创建 65535 个 TCP 连接。</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">我不信这个邪,今天我要亲自去实践一下。</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">我走到操作系统老大的跟前,说:</span> <span style="font-size: 15px;text-align: justify;">“老操,我要建立一个 TCP 连接!</span> <span style="font-size: 15px;text-align: justify;">”</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">老操不慌不忙,拿出一个表格递给我,"</span> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);">小进,先填表吧</span> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">"</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <img class="rich_pages wxw-img" data-ratio="0.1990521327014218" src="/upload/54457b0c34154d44ecb27938db1314e8.jpg" data-type="jpeg" data-w="844" height="auto" width="844"> </section> <section style="white-space: normal;text-align: left;"> <br> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">我一看这个表,这不就是经典的 </span> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);">socket 四元组</span> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">嘛。我只有一块网卡,其 IP 地址是 123.126.45.68,我想要与 110.242.68.3 的 80 端口建立一个 TCP 连接,我将这些信息填写在了表中。</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: center;"> <img class="rich_pages wxw-img" data-ratio="0.1990521327014218" src="/upload/f84fc374cc8fa6d64862518783ae2780.jpg" data-type="jpeg" data-w="844" height="auto" style="width: 417px;height: 83px;" width="844"> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">源端口号填什么呢?我记得端口号是 16 位的,可以有 0 ~ 65535 这个范围的数字,那我随便选一个吧!</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">正当我犹豫到底选什么数字的时候,老操一把抢过我的表格。</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">“</span> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);">你墨迹个啥呢小进?源端口号不用你填,我会给你分配一个可用的数字。源IP也不用你填,我知道都有哪些网卡,并且会帮你选个合适的。真是个新手,回去等消息吧。</span> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">”</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">"哦"</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">老操带着我的表格,走了。</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">过了很长时间,老操终于回来了,并且带着一个纸条。</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: center;"> <img class="rich_pages wxw-img" data-ratio="0.7760416666666666" src="/upload/797a195daab6dada36fb23b653608887.jpg" data-type="jpeg" data-w="192" height="auto" style="height: 98px;width: 126px;" width="192"> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">“</span> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);">小进,你把这个收好了。</span> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">”</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">我问道,“这是啥呀?”</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">老操不耐烦地说道,“</span> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);">刚刚说你是新手你还不服,这个 5 表示文件描述符,linux 下一切皆文件,你待会和你那个目标 IP 进行 TCP 通信的时候,就对着这个文件描述符读写就好啦。</span> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">”</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">“这么方便!好的,谢谢老操。”</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">我拿着这个文件描述符,把它放到属于我的内存中裱起来了,反正我只是想看看最多能创建多少 TCP 连接,又不是去真的用它,嘻嘻。</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"> </span> </section> <h2 style="white-space: normal;text-align: left;"> <section style="white-space: normal;text-align: left;"> <strong><span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);">端口号</span></strong> </section></h2> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"> </span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">过了一分钟,我又去找老操了。</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">“老操,我要建立一个 TCP 连接!”</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">老操不慌不忙,拿出一个表格递给我,“小进,先填表吧”</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: center;"> <img class="rich_pages wxw-img" data-ratio="0.1990521327014218" src="/upload/64fe5a8d2cfe8d5dd2e8dd5e4f13043b.png" data-type="png" data-w="844" height="auto" style="width: 407px;height: 81px;" width="844"> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">这回我熟悉了,只把目标IP和目标端口填好。</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: center;"> <img class="rich_pages wxw-img" data-ratio="0.1990521327014218" src="/upload/4866f9c104498ba4043edf3b350f6021.jpg" data-type="jpeg" data-w="844" height="auto" style="width: 413px;height: 82px;" width="844"> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">老操办好事之后,又带着一个纸条回来,上面写着数字“6”。</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">就这样,我每隔一分钟都去找老操建立一个新的 TCP 连接,目标 IP 都是110.242.68.3,目标端口都是 80。</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">老操也很奇怪,不知道我在这折腾啥,他虽然权力大,但无权拒绝我的指令,每次都兢兢业业地把事情办好,并给我一张一张写着文件描述符的纸条。</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">直到有一次,我收到的纸条有些不同。</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: center;"> <img class="rich_pages wxw-img" data-ratio="0.34452296819787986" src="/upload/5785a85301b775deb854e1c33b0dab85.jpg" data-type="jpeg" data-w="566" height="154px" style="height: 107px;width: 311px;" width="448px"> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">我带着些许责怪的语气问,“老操,这是怎么回事呀?”</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">老操也没好气地说,“</span> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);">这表示端口号不够用啦!早就觉得你小子不对劲了,一个劲地对着同一个 IP 和端口创建 TCP 连接,之前没办法必须执行你给的指令,现在不行了,端口号不够用了,源端口那里我没法给你填了。</span> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">”</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">我也不是那么好骗的,质疑道。“老操,你也别欺负我这个新手,我可是知道端口号是 16 位的,范围是 1~65535,一共可以创建 65535 个 TCP 连接,我现在才创建了 63977 个,怎么就不够了!”</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">老操鄙视地看了我一眼,“</span> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);">你小子可真是闲的蛋疼啊,还真一个个数,来我告诉你吧,Linux 对可使用的端口范围是有具体限制的,具体可以用如下命令查看。</span> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">”</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="white-space: normal;text-align: left;"> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js" data-lang="cs"><code><span class="code-snippet_outer">[<span class="code-snippet__meta">root</span>]<span class="code-snippet__meta"># cat /proc/sys/net/ipv4/ip_local_port_range </span></span></code><code><span class="code-snippet_outer"><span class="code-snippet__number">1024</span> <span class="code-snippet__number">65000</span></span></code></pre> </section> <pre data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><br></pre> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">“</span> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);">看到没,当前的限制是1024~65000,所以你就只能有63977个端口号可以使用。</span> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">”</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: center;"> <img class="rich_pages wxw-img" data-ratio="0.5454545454545454" src="/upload/b9d9b9bb396b88d15d02e88d9fe991d7.png" data-type="png" data-w="550" height="auto" style="height: 161px;width: 295px;" width="550"> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">我赶紧像老操道歉,"哎哟真是抱歉,还是我见识太少,那这个数可以修改么?"</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">老操也没跟我一般见识,还是耐心地回答我,“</span> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);">可以的,具体可以 vim /etc/sysctl.conf 这个文件进行修改,我们在这个文件里添加一行记录</span> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">”。</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="white-space: normal;text-align: left;"> <section class="code-snippet__fix code-snippet__js"> <ul class="code-snippet__line-index code-snippet__js"> </ul> <pre class="code-snippet__js"><code><span class="code-snippet_outer">net.ipv4.ip_local_port_range = 60000 60009</span></code></pre> </section> <pre data-tool="mdnice编辑器" style="white-space: normal;text-align: left;"><br></pre> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">“</span> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);">保存好后执行 sysctl -p /etc/sysctl.conf 使其生效。这样你就只有 10 个端口号可以用了,就会更快报出端口号不够用的错误</span> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">”。</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">"原来如此,谢谢老操又给我上了一课。"</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;">哎不对,建立一个 TCP 连接,需要将通信两端的套接字(socket)进行绑定,如下:</span> </section> <section style="white-space: normal;text-align: left;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;"><br></span> </section> <section style="white-space: normal;text-align: center;"> <span style="font-size: 15px;font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;text-align: justify;color: rgb(171, 25, 66);">源 IP 地址:源
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;padding-right: 10px;padding-left: 10px;line-height: 1.6;letter-spacing: 0px;word-break: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;" data-mpa-powered-by="yiban.io"> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">前言</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">大家好,最近有位读者去虾皮面试啦,分享一下面试的真题~</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 排序链表 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 对称与非对称加密算法的区别 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> TCP如何保证可靠性 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 聊聊五种IO模型 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> hystrix 工作原理 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 延时场景处理 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> https请求过程 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 聊聊事务隔离级别,以及可重复读实现原理 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 聊聊索引在哪些场景下会失效? </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 什么是虚拟内存 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 排行榜的实现,比如高考成绩排序 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 分布式锁实现 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 聊聊零拷贝 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 聊聊synchronized </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 分布式ID生成方案 </section></li> </ol> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;border-bottom: 2px solid rgb(239, 112, 96);font-size: 1.3em;"><span style="display: none;"></span><span style="display: inline-block;background: rgb(239, 112, 96);color: rgb(255, 255, 255);padding: 3px 10px 1px;border-top-right-radius: 3px;border-top-left-radius: 3px;margin-right: 3px;">1. 排序链表</span><span style="display: inline-block;vertical-align: bottom;border-bottom: 36px solid #efebe9;border-right: 20px solid transparent;"> </span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">给你链表的头结点head ,请将其按升序排列并返回排序后的链表 。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.4306049822064057" src="/upload/e5c387fbf0bf86349850c2387216862e.png" data-type="png" data-w="562" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>实例1:</strong></p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/eytJa9K5jkpeFJOg5WzX3ZgRE2egNicoUY2fbEM1uvPU4ckwUUmJ4N0d1G6QdmZJBTCjaEVF7eP5QfVU8GicgicZWkdqGXCX0G6/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #ddd;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #272822;border-radius: 5px;">输入:head = [4,2,1,3]<br>输出:[1,2,3,4]<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;"><strong>实例2:</strong></p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;display: flex;flex-direction: column;justify-content: center;align-items: center;"> <img class="rich_pages wxw-img" data-ratio="0.33518005540166207" src="/upload/ad73c6971c8513538a33e16265232d2b.png" data-type="png" data-w="722" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/eytJa9K5jkpeFJOg5WzX3ZgRE2egNicoUY2fbEM1uvPU4ckwUUmJ4N0d1G6QdmZJBTCjaEVF7eP5QfVU8GicgicZWkdqGXCX0G6/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #ddd;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #272822;border-radius: 5px;">输入:head = [-1,5,3,4,0]<br>输出:[-1,0,3,4,5]<br></code></pre> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">这道题可以用<strong>双指针+归并排序</strong>算法解决,主要以下四个步骤</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 1. 快慢指针法,遍历链表找到中间节点 </section> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 2. 中间节点切断链表 </section> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 3. 分别用归并排序排左右子链表 </section> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 4. 合并子链表 </section> </ul> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;">完整代码如下:</p> <pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: block;background: url("https://mmbiz.qpic.cn/mmbiz_svg/eytJa9K5jkpeFJOg5WzX3ZgRE2egNicoUY2fbEM1uvPU4ckwUUmJ4N0d1G6QdmZJBTCjaEVF7eP5QfVU8GicgicZWkdqGXCX0G6/640?wx_fmt=svg") 10px 10px / 40px no-repeat rgb(39, 40, 34);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;padding: 16px;color: #ddd;display: -webkit-box;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;font-size: 12px;-webkit-overflow-scrolling: touch;padding-top: 15px;background: #272822;border-radius: 5px;">class Solution {<br> public ListNode sortList(ListNode head) {<br> //如果链表为空,或者只有一个节点,直接返回即可,不用排序<br> <span style="color: #f92672;font-weight: bold;line-height: 26px;">if</span> (head == null || head.next == null)<br> <span style="color: #a6e22e;line-height: 26px;">return</span> head;<br> <br> //快慢指针移动,以寻找到中间节点<br> ListNode slow = head;<br> ListNode fast = head;<br> <span style="color: #f92672;font-weight: bold;line-height: 26px;">while</span>(fast.n