<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Kyson&apos;s Blog</title><description>A blog for Kyson</description><link>https://blog.xoxxo18.icu/</link><templateTheme>Firefly</templateTheme><templateThemeVersion>6.8.11</templateThemeVersion><templateThemeUrl>https://github.com/CuteLeaf/Firefly</templateThemeUrl><lastBuildDate>2026年4月10日 18:48:15</lastBuildDate><item><title>一次 Redisson 升级排查</title><link>https://blog.xoxxo18.icu/posts/redisson-setretrydelay/</link><guid isPermaLink="true">https://blog.xoxxo18.icu/posts/redisson-setretrydelay/</guid><description>setRetryDelay 为何从常数变成策略类</description><pubDate>Fri, 03 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Redisson版本：4.3.0&lt;/p&gt;
&lt;p&gt;起因是在配置 Redisson 的 Config 的设置重试延迟时间方法 &lt;code&gt;setRetryDelay&lt;/code&gt; 时，
发现原本的 &lt;code&gt;setRetryInterval(int retryInterval)&lt;/code&gt; 变成了 &lt;code&gt;setRetryInterval(int retryInterval)&lt;/code&gt;,&lt;/p&gt;
&lt;p&gt;点进源码一看：&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;* Use {&lt;/span&gt;&lt;span&gt;@link&lt;/span&gt;&lt;span&gt; #&lt;/span&gt;&lt;span&gt;setRetryDelay(DelayStrategy)&lt;/span&gt;&lt;span&gt;} instead.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@param&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;retryInterval&lt;/span&gt;&lt;span&gt; - time in milliseconds&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@return&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Deprecated&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;setRetryInterval&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; retryInterval)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;原来是官方废弃了这个方法，让我用一个叫做 &lt;code&gt;setRetryDelay(DelayStrategy)&lt;/code&gt; 的新方法，
那么我们直接跳转到这个新方法的定义，看看它的注释：&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Defines the delay strategy for a new attempt to send a command.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &amp;lt;p&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Default is &amp;lt;code&amp;gt;EqualJitterDelay(Duration.ofSeconds(1), Duration.ofSeconds(2))&amp;lt;/code&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@see&lt;/span&gt;&lt;span&gt; DecorrelatedJitterDelay&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@see&lt;/span&gt;&lt;span&gt; EqualJitterDelay&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@see&lt;/span&gt;&lt;span&gt; FullJitterDelay&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@see&lt;/span&gt;&lt;span&gt; ConstantDelay&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@param&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;retryDelay&lt;/span&gt;&lt;span&gt; delay strategy implementation&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@return&lt;/span&gt;&lt;span&gt; options instance&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;setRetryDelay&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;DelayStrategy&lt;/span&gt;&lt;span&gt; retryDelay)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;看来是 &lt;code&gt;setRetryDelay&lt;/code&gt; 不让我直接传 &lt;code&gt;int&lt;/code&gt; 参数了，而是要我传 &lt;code&gt;DelayStrategy&lt;/code&gt; 参数，而且这个参数还是个接口，
说明我得传一个实现类进去，注释里还说目前这个接口有以下四种实现类&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ConstantDelay&lt;/code&gt;：固定延迟，每次重试都等同样长时间&lt;/li&gt;
&lt;li&gt;&lt;code&gt;EqualJitterDelay&lt;/code&gt;：等分抖动延迟，Redisson 当前默认策略。保留一半的指数退避值，再给另一半加随机抖动值&lt;/li&gt;
&lt;li&gt;&lt;code&gt;FullJitterDelay&lt;/code&gt;：完全随机抖动延迟，对指数退避结果做完全随机抖动化&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DecorrelatedJitterDelay&lt;/code&gt;：相关抖动延迟，延迟会指数式增长，但抖动值会受前一次退避时长影响&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;上面的描述来自官方文档，除了 &lt;code&gt;ConstantDelay&lt;/code&gt; 非常的简单易懂，其他三个都有点抽象，
不过我注意到，这三个重试策略中的前两个都提到了一个词：&lt;strong&gt;指数退避&lt;/strong&gt;，那我高低得从这里切入。&lt;/p&gt;
&lt;section&gt;&lt;h1&gt;指数退避&lt;a href=&quot;#指数退避&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;指数退避，是一种失败后逐步拉长重试等待时间的机制。可以把它理解成：&lt;/p&gt;&lt;p&gt;第一次失败，等 1 秒&lt;/p&gt;&lt;p&gt;第二次失败，等 2 秒&lt;/p&gt;&lt;p&gt;第三次失败，等 4 秒&lt;/p&gt;&lt;p&gt;第四次失败，等 8 秒&lt;/p&gt;&lt;p&gt;…&lt;/p&gt;&lt;p&gt;也就是等待时间不是线性增加，而是按 &lt;strong&gt;2 的幂&lt;/strong&gt; 这样越来越大，所以叫“指数”退避。&lt;/p&gt;&lt;section&gt;&lt;h2&gt;为什么要这样做呢？&lt;a href=&quot;#为什么要这样做呢&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;因为如果一个服务已经出问题了，客户端还用很高频率不断重试，就容易出现两个问题：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;把服务压得更厉害：服务本来就在抖动、切换、恢复，客户端越频繁重试，它越难缓过来。&lt;/li&gt;
&lt;li&gt;大量客户端同时重试：会形成“重试风暴”，一下子又把 Redis、数据库、接口打满。&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;指数退避的核心目的，就是&lt;strong&gt;失败越多，说明问题越可能不是服务器瞬时抖动，而是真故障，那客户端就应该等得更久一点&lt;/strong&gt;。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;一个直观的例子&lt;a href=&quot;#一个直观的例子&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;假设程序访问 Redis 失败了。而你设置重试策略为固定每隔 1 秒重试一次，&lt;/p&gt;&lt;p&gt;如果有 100 台机器都这样干，就可能每秒一起冲 Redis 一次。&lt;/p&gt;&lt;p&gt;但如果用指数退避，这样重试频率会越来越低，系统就有恢复空间。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;在代码中，这个指数退避值的计算是如何实现的？&lt;a href=&quot;#在代码中这个指数退避值的计算是如何实现的&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;首先从 &lt;code&gt;DelayStrategy&lt;/code&gt; 接口看起&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;interface&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;DelayStrategy&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* Calculates the delay duration to wait before the next retry attempt.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@param&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;attempt&lt;/span&gt;&lt;span&gt; the zero-based retry attempt number (0 = first retry)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;* &lt;/span&gt;&lt;span&gt;@return&lt;/span&gt;&lt;span&gt; the duration to wait before the next retry attempt&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;     &lt;/span&gt;&lt;/span&gt;&lt;span&gt;*/&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;Duration&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;calcDelay&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;attempt&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;可以看到，这个接口里只有一个 &lt;code&gt;calcDelay&lt;/code&gt; 方法，接收一个 &lt;code&gt;attempt&lt;/code&gt; 参数，表示重试的次数。
返回一个 &lt;code&gt;Duration&lt;/code&gt; 类型，表示等待时间，另外三种策略都是通过实现这个方法来计算等待时间的。&lt;/p&gt;&lt;p&gt;在 &lt;code&gt;calcDelay&lt;/code&gt; 方法中，首先需要显式指定延迟时间的最小值（baseMs/minDelay）和最大值（maxMs/maxDelay），
然后，定义一个 &lt;code&gt;exponentialDelay&lt;/code&gt; 变量，用来存放计算好的指数退避值，计算方法如下：&lt;/p&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;exponentialDelayMs=min(baseMs×attempt,maxMs);exponentialDelayMs = min(baseMs \times attempt, maxMs);&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;o&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;ia&lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt;D&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;M&lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;min&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ba&lt;/span&gt;&lt;span&gt;se&lt;/span&gt;&lt;span&gt;M&lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;×&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;tt&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span&gt;pt&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;ma&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;M&lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h1&gt;随机抖动&lt;a href=&quot;#随机抖动&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;真实系统里，往往不是只做指数退避，还会再加一个 jitter（随机抖动值）。&lt;/p&gt;&lt;p&gt;原因在于，如果所有客户端都严格按 1、2、4、8 秒去重试，它们还是可能在同一时刻一起打过去。&lt;/p&gt;&lt;p&gt;所以更常见的是：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;大方向按指数增长&lt;/li&gt;
&lt;li&gt;具体每次等待再加一点随机性&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;当按照上面计算出指数退避值后，接下来就是对指数退避值进行抖动处理，这里 Redisson 提出了两种策略：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;code&gt;EqualJitterDelay&lt;/code&gt;：等分抖动延迟，Redisson 当前默认策略。保留一半的指数退避值，再给另一半加随机抖动值&lt;/li&gt;
&lt;li&gt;&lt;code&gt;FullJitterDelay&lt;/code&gt;：完全随机抖动延迟，对指数退避结果做完全随机抖动化&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;首先来看下 &lt;code&gt;EqualJitterDelay&lt;/code&gt;，它的核心逻辑如下：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 保留一半的指数退避值&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;long&lt;/span&gt;&lt;span&gt; halfDelay &lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; exponentialDelayMs &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 在 [0, halfDelay] 之间生成一个随机抖动值&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;long&lt;/span&gt;&lt;span&gt; randomComponent &lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;random&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; halfDelay &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 将保留的一半指数退避值和随机抖动值相加，得到最终的等待时间&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;&lt;span&gt; halfDelay &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; randomComponent&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;另一种策略 &lt;code&gt;FullJitterDelay&lt;/code&gt; 的实现如下：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 在 [0, exponentialDelayMs] 之间生成一个随机抖动值&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;long&lt;/span&gt;&lt;span&gt; jitteredDelayMs &lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;random&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; exponentialDelayMs &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 直接返回这个随机抖动值&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;&lt;span&gt; jitteredDelayMs&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;最终，&lt;code&gt;EqualJitterDelay&lt;/code&gt; 的等待时间范围为&lt;span&gt;&lt;span&gt;[halfDelay,exponentialDelay][halfDelay, exponentialDelay]&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;ha&lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;D&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;o&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;ia&lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt;D&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;，
而 &lt;code&gt;FullJitterDelay&lt;/code&gt; 的等待时间范围为&lt;span&gt;&lt;span&gt;[0,exponentialDelayMs][0, exponentialDelayMs]&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;span&gt;o&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;ia&lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt;D&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;M&lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;这两种策略分别适用于什么场景呢？&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;如果你想追求稳定性，可以选择 &lt;code&gt;EqualJitterDelay&lt;/code&gt; 策略，因为它会保留一半的指数退避值，再给另一半加随机抖动值，所以等待时间会比较稳定。&lt;/li&gt;
&lt;li&gt;如果你想追求随机性，可以选择 &lt;code&gt;FullJitterDelay&lt;/code&gt; 策略，因为它会对指数退避结果做完全随机抖动化，所以等待时间会比较随机。&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h1&gt;基于前一次结果的随机退避&lt;a href=&quot;#基于前一次结果的随机退避&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;现在来看最后一个策略：&lt;code&gt;DecorrelatedJitterDelay&lt;/code&gt;。&lt;/p&gt;&lt;p&gt;这个策略和前两个策略最大的不同在于，它的退避时间不跟重试次数 &lt;code&gt;attempt&lt;/code&gt; 挂钩了，而是只跟上一次重试时间 &lt;code&gt;previousDelay&lt;/code&gt; 挂钩，&lt;/p&gt;&lt;p&gt;前两个策略计算退避时间时，使用的是 &lt;span&gt;&lt;span&gt;min(baseMs×attempt,maxMs)min(baseMs \times attempt, maxMs)&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;min&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ba&lt;/span&gt;&lt;span&gt;se&lt;/span&gt;&lt;span&gt;M&lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;×&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;tt&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span&gt;pt&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;ma&lt;/span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;M&lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;，而该策略计算退避时间，使用的是如下核心逻辑：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 1. 第一次调用时，因为 previousDelay 还是 0，系统会先把 prev 取成 minDelay；&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;//    之后调用时，将prev设置为上一次重试时间&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;long&lt;/span&gt;&lt;span&gt; prev &lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (previousDelay &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; minDelay &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; previousDelay)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 2. 在 [0, 3倍上次重试时间] 之间生成一个随机值&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;long&lt;/span&gt;&lt;span&gt; randomComponent &lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;random&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; prev &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 3. 在随机值上加一个最小重试时间，然后和最大重试时间取最小值&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;long&lt;/span&gt;&lt;span&gt; newDelay &lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;min&lt;/span&gt;&lt;span&gt;&lt;span&gt;(minDelay &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; randomComponent&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; maxDelay)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 4. 更新上次重试时间&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;previousDelay &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; newDelay&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; newDelay&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;按照如此逻辑执行，第一次重试时间会落在 &lt;span&gt;&lt;span&gt;[minDelay,4×minDelay)[minDelay, 4 \times minDelay)&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;min&lt;/span&gt;&lt;span&gt;D&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;×&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;min&lt;/span&gt;&lt;span&gt;D&lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;l&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;y&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 这个区间内；
后面每次都会在 &lt;strong&gt;0和上一次结果的 3 倍&lt;/strong&gt; 随机滚动。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>Leetcode 406 - Queue Reconstruction by Height</title><link>https://blog.xoxxo18.icu/posts/leetcode-406/</link><guid isPermaLink="true">https://blog.xoxxo18.icu/posts/leetcode-406/</guid><description>根据身高重建队列</description><pubDate>Sun, 22 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;耗时：1h&lt;/p&gt;
&lt;p&gt;瞟了一眼题解看到要先对people中的每个元素做排序，然后尝试了按&lt;strong&gt;身高&lt;/strong&gt;排和按&lt;strong&gt;前面有几个人的身高&amp;gt;=自己&lt;/strong&gt;排，
发现按&lt;strong&gt;身高从高到低&lt;/strong&gt;排能解决前两个用例：[[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]和[[6,0],[5,0],[4,0],[3,2],[2,2],[1,4]]，&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Arrays&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;sort&lt;/span&gt;&lt;span&gt;(people, &lt;/span&gt;&lt;span&gt;Comparator&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;comparingInt&lt;/span&gt;&lt;span&gt;((&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;[] a) &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; a[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]).&lt;/span&gt;&lt;span&gt;reversed&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;于是愉快的进行提交：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/L0406_error.CHiEcutU_Z275DWj.webp&quot; srcset=&quot;/_astro/L0406_error.CHiEcutU_19mLMV.webp 640w, /_astro/L0406_error.CHiEcutU_RKyza.webp 750w, /_astro/L0406_error.CHiEcutU_vTlOy.webp 828w, /_astro/L0406_error.CHiEcutU_Z275DWj.webp 1018w&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1018&quot; height=&quot;564&quot; /&gt;&lt;/p&gt;
&lt;p&gt;针对出错的用例逐行debug，发现还得加一个排序规则：按&lt;strong&gt;前面有几个人的身高&amp;gt;=自己 从低到高&lt;/strong&gt;排&lt;/p&gt;
&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;Arrays&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;sort&lt;/span&gt;&lt;span&gt;(people, (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;[] a, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;[] b) &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; a[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; b[&lt;/span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; a[&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; b[&lt;/span&gt;&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; b[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; a[&lt;/span&gt;&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;]);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;再次进行提交：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/_astro/L0406_success.7_8mWuFa_Z5g3bS.webp&quot; srcset=&quot;/_astro/L0406_success.7_8mWuFa_xSPi6.webp 640w, /_astro/L0406_success.7_8mWuFa_2poFDI.webp 750w, /_astro/L0406_success.7_8mWuFa_1bnmsr.webp 828w, /_astro/L0406_success.7_8mWuFa_ZijJQe.webp 1080w, /_astro/L0406_success.7_8mWuFa_Z5g3bS.webp 1111w&quot; alt=&quot;&quot; loading=&quot;lazy&quot; width=&quot;1111&quot; height=&quot;570&quot; /&gt;&lt;/p&gt;
&lt;p&gt;🎉🎉&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://gitee.com/xoxxo18/algorithm/blob/Java/leetcode/src/main/java/greedy/L0406.java&quot; target=&quot;_blank&quot;&gt;code&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title>第一篇博客</title><link>https://blog.xoxxo18.icu/posts/first-post/</link><guid isPermaLink="true">https://blog.xoxxo18.icu/posts/first-post/</guid><description>就从高考考完说起好了</description><pubDate>Mon, 02 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;高考考完了，我也不知道自己要干什么，稀里糊涂进了信息管理与信息系统专业，开始在一个所谓的“计算机”、“经济学”、“管理学”交叉学科里浑浑噩噩度日。
三年下来倒也学了不少编程课程，C、Pyhton、Java、R都跟着过了一遍。&lt;/p&gt;
&lt;p&gt;第一次认真开始学习编程，是在大三下学期，我开始考虑毕设的事情，粗略定下用Java写一个管理系统，于是开始看网课，跟敲代码。
也发现原来学校里教的那些东西，和企业招聘时需要你会的，差的不是一点半点。
当我看了一些招聘信息后，我开始慌了，我学历一般，实习经历为0，专业也不对口，我该怎么办？&lt;/p&gt;
&lt;p&gt;此时，差不多进入了考研备考期，我原本打算随大流考本专业的研，但在听说一个金融专业的初中同学准备跨考计算机的时候，我就下定了决心，
人家金融专业的同学都能跨考计算机，我一个距离计算机专业比较近的人，凭什么不能跨考？跨，跨TMD！&lt;/p&gt;
&lt;p&gt;于是我折腾了半年的数一英一408，却没想到，由于前两年绩点还算不错，我竟然获得了一个保研名额。虽然我得知这个消息的时候，科研、竞赛经历都没有，
注定只能保本校，但我当时已经被考研的重压压的喘不过气了，果断抓住了救命稻草，提前上岸。
当我和考研搭子（就是前文那个金融跨考）说我要半路开溜的时候，我其实心里是有点愧疚的，抱歉不能配兄弟负重前行了（抱拳）。&lt;/p&gt;
&lt;p&gt;保研后，我趁着难得的空窗期，狠狠地学了一手Java全栈开发，从JavaSE开始，SpringBoot、MyBatis、MySQL、Vue都过了一遍。
也跟着网上一些教程，写了一个项目作为自己的毕设。说实话，搞毕设的时候我抱着的想法挺天真的，
我只需要做一个项目，既能锻炼自己的能力，又能满足毕业条件，说不定还能直接写进简历，提升自己的求职竞争力，
到时候读研再跟着导师做一些更有含金量的项目写进简历，直接就是一个咸鱼翻身进大厂，把之前成绩差、考不进好学校的履历一笔勾销，岂不美哉？&lt;/p&gt;
&lt;p&gt;这样的幻想，在转到计算机读研后，被狠狠打脸了。&lt;/p&gt;
&lt;p&gt;第一次感到无所适从是在挑选导师的时候，我发现，计算机学院导师的研究方向我一个都没听说过，而且似乎需要很强的数学功底，
关键是，我学全栈开发的时候，压根没学到这些东西，我该怎么办？只能矮子里挑高个，找了一个可视化方向的老师。&lt;/p&gt;
&lt;p&gt;为了能够笨鸟先飞，我决定提前学习一些可视化方面的知识，于是开始学习D3.js这个可视化库，结果没想到，网上关于它的视频教程少的可怜，
大部分都是英文的，而且讲的也不够详细。最后好不容易给我找到一个中文教程（这里也&lt;a href=&quot;https://www.bilibili.com/video/BV1LX4y197qZ&quot; target=&quot;_blank&quot;&gt;推荐一下&lt;/a&gt;，就当给后面的人撑一把伞），算是完整地过了一遍。&lt;/p&gt;
&lt;p&gt;附上一张我用D3.js画出来的图，说实话画这些图还挺有意思的。&lt;/p&gt;

&lt;div&gt;重新播放动画&lt;/div&gt; 
&lt;p&gt;万万没想到，我导明明主页上写的是可视化，科研经历也全是可视化，但我进组的时候，他一开始给我分配的方向居然是搞大模型？!
那我的D3.js不是白学了，而且我后来才意识到，这对于我们组来说是一个全新的方向，根本没有科研积累可言。
在稀里糊涂、吭哧吭哧尝试了微调、RAG后，我无奈的发现，自己的水平做做工程还行，想在科研算法方面有所创新简直是痴人说梦，
就这么白白浪费了研一的时间，在研二悲催地转了方向。&lt;/p&gt;
&lt;p&gt;更让人崩溃的是，我转的新方向，仍然和可视化没有一丁点关系，就连导师分配来带我的博士师兄也说，自己之前没搞过这方面的，
得让你们自己尝试了，我嘞个。。。你一个博士，让我一个硕士搞，诗人啊。&lt;/p&gt;
&lt;p&gt;而且站在现在回望之前，我发现自己其实被导师安排了很多杂活，包括但不限于接一些小公司的难上天又没有含金量的需求、
写项目结题报告和出差当外包的外包的外包（TMD搁这剥洋葱呢，你愿意一层一层一层地剥开我的心~），最EX的是，
我甚至大年三十还要熬夜赶一份项目结题报告，整个新年都没能好好过。&lt;/p&gt;
&lt;p&gt;总之，我现在的状态就是科研没进度，找工作也没着落，已经是金三银四的时间了，要是现在不找到大厂实习，我的大厂梦就要破碎了。&lt;/p&gt;</content:encoded></item></channel></rss>