<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>避风港</title>
  
  
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://yoursite.com/"/>
  <updated>2023-04-08T05:47:09.977Z</updated>
  <id>http://yoursite.com/</id>
  
  <author>
    <name>Sympa</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>2023蓝桥杯广东省赛个人题解</title>
    <link href="http://yoursite.com/2023/04/08/ACM/2023%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%B9%BF%E4%B8%9C%E7%9C%81%E8%B5%9B%E4%B8%AA%E4%BA%BA%E9%A2%98%E8%A7%A3/"/>
    <id>http://yoursite.com/2023/04/08/ACM/2023%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%B9%BF%E4%B8%9C%E7%9C%81%E8%B5%9B%E4%B8%AA%E4%BA%BA%E9%A2%98%E8%A7%A3/</id>
    <published>2023-04-08T05:27:00.000Z</published>
    <updated>2023-04-08T05:47:09.977Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h1 id="2023蓝桥杯广东省赛个人题解"><a href="#2023蓝桥杯广东省赛个人题解" class="headerlink" title="2023蓝桥杯广东省赛个人题解"></a>2023蓝桥杯广东省赛个人题解</h1><p>仅供参考，不保证思路和代码的正确性。</p><h2 id="试题-A-日期统计"><a href="#试题-A-日期统计" class="headerlink" title="试题 A: 日期统计"></a>试题 A: 日期统计</h2><p>暴力，忘记判重，白给</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> a[<span class="number">101</span>] = &#123; <span class="number">5</span>,<span class="number">6</span>,<span class="number">8</span>,<span class="number">6</span>,<span class="number">9</span>,<span class="number">1</span>,<span class="number">6</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">4</span>,<span class="number">9</span>,<span class="number">1</span>,<span class="number">9</span>,<span class="number">8</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">6</span>,<span class="number">4</span>,<span class="number">7</span>,<span class="number">7</span>,<span class="number">5</span>,<span class="number">9</span>,<span class="number">5</span>,<span class="number">0</span>,<span class="number">3</span>,<span class="number">8</span>,<span class="number">7</span>,<span class="number">5</span>,<span class="number">8</span>,<span class="number">1</span>,<span class="number">5</span>,<span class="number">8</span>,<span class="number">6</span>,<span class="number">1</span>,<span class="number">8</span>,<span class="number">3</span>,<span class="number">0</span>,<span class="number">3</span>,<span class="number">7</span>,<span class="number">9</span>,<span class="number">2</span>,<span class="number">7</span>,<span class="number">0</span>,<span class="number">5</span>,<span class="number">8</span>,<span class="number">8</span>,<span class="number">5</span>,<span class="number">7</span>,<span class="number">0</span>,<span class="number">9</span>,<span class="number">9</span>,<span class="number">1</span>,<span class="number">9</span>,<span class="number">4</span>,<span class="number">4</span>,<span class="number">6</span>,<span class="number">8</span>,<span class="number">6</span>,<span class="number">3</span>,<span class="number">3</span>,<span class="number">8</span>,<span class="number">5</span>,<span class="number">1</span>,<span class="number">6</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">6</span>,<span class="number">7</span>,<span class="number">0</span>,<span class="number">7</span>,<span class="number">8</span>,<span class="number">2</span>,<span class="number">7</span>,<span class="number">6</span>,<span class="number">8</span>,<span class="number">9</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">1</span>,<span class="number">4</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">9</span>,<span class="number">4</span>,<span class="number">8</span>,<span class="number">0</span>,<span class="number">9</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">8</span>,<span class="number">5</span>,<span class="number">0</span>,<span class="number">2</span>,<span class="number">5</span>,<span class="number">3</span>,<span class="number">3</span> &#125;;</span><br><span class="line"><span class="keyword">long</span> <span class="keyword">long</span> ans = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">int</span> b[<span class="number">20</span>];</span><br><span class="line"><span class="keyword">int</span> c[<span class="number">20</span>] = &#123; <span class="number">0</span>, <span class="number">31</span>, <span class="number">28</span>, <span class="number">31</span>, <span class="number">30</span>, <span class="number">31</span>, <span class="number">30</span>, <span class="number">31</span>, <span class="number">31</span>, <span class="number">30</span>, <span class="number">31</span>, <span class="number">30</span>, <span class="number">31</span> &#125;;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">dfs</span><span class="params">(<span class="keyword">int</span> x, <span class="keyword">int</span> pos)</span> </span>&#123;</span><br><span class="line"><span class="keyword">if</span> (pos == <span class="number">1</span> &amp;&amp; a[x] != <span class="number">2</span>) <span class="keyword">return</span>;</span><br><span class="line"><span class="keyword">if</span> (pos == <span class="number">2</span> &amp;&amp; a[x] != <span class="number">0</span>) <span class="keyword">return</span>;</span><br><span class="line"><span class="keyword">if</span> (pos == <span class="number">3</span> &amp;&amp; a[x] != <span class="number">2</span>) <span class="keyword">return</span>;</span><br><span class="line"><span class="keyword">if</span> (pos == <span class="number">4</span> &amp;&amp; a[x] != <span class="number">3</span>) <span class="keyword">return</span>;</span><br><span class="line">b[pos] = a[x];</span><br><span class="line"><span class="keyword">if</span> (pos != <span class="number">8</span>) &#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = x + <span class="number">1</span>; i &lt; <span class="number">100</span>; i++) &#123;</span><br><span class="line">dfs(i, pos + <span class="number">1</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span> &#123;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> m = b[<span class="number">5</span>] * <span class="number">10</span> + b[<span class="number">6</span>];</span><br><span class="line"><span class="keyword">int</span> d = b[<span class="number">7</span>] * <span class="number">10</span> + b[<span class="number">8</span>];</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (m &lt; <span class="number">1</span> || m &gt; <span class="number">12</span>) <span class="keyword">return</span>;</span><br><span class="line"><span class="keyword">if</span> (d &lt; <span class="number">1</span> || d &gt; c[m]) <span class="keyword">return</span>;</span><br><span class="line"></span><br><span class="line"><span class="built_in">cout</span> &lt;&lt; b[<span class="number">1</span>] &lt;&lt; b[<span class="number">2</span>] &lt;&lt; b[<span class="number">3</span>] &lt;&lt; b[<span class="number">4</span>] &lt;&lt; <span class="string">"-"</span> &lt;&lt; b[<span class="number">5</span>] &lt;&lt; b[<span class="number">6</span>] &lt;&lt; <span class="string">"-"</span> &lt;&lt; b[<span class="number">7</span>] &lt;&lt; b[<span class="number">8</span>] &lt;&lt; <span class="built_in">endl</span>;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">ans++;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">100</span>; i++) &#123;</span><br><span class="line">dfs(i, <span class="number">1</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">cout</span> &lt;&lt; ans &lt;&lt; <span class="built_in">endl</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="试题-B-01-串的熵"><a href="#试题-B-01-串的熵" class="headerlink" title="试题 B: 01 串的熵"></a>试题 B: 01 串的熵</h2><p>暴力，记得处理四舍五入，11027421</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> a = <span class="number">23333333</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> mid = a / <span class="number">2</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = mid; i &gt;= <span class="number">0</span>; i--) &#123;</span><br><span class="line"><span class="keyword">double</span> x = <span class="number">-1.0</span> * i / a * log2(<span class="number">1.0</span> * i / a);</span><br><span class="line"><span class="keyword">double</span> y = <span class="number">-1.0</span> * (a - i) / a * log2(<span class="number">1.0</span> * (a - i) / a);</span><br><span class="line"><span class="keyword">long</span> <span class="keyword">long</span> ans = (x * i + y * (a - i)) * <span class="number">100000</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (ans % <span class="number">10</span> &gt;= <span class="number">5</span>) ans = ans / <span class="number">10</span> + <span class="number">1</span>;</span><br><span class="line"><span class="keyword">else</span> ans = ans / <span class="number">10</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (ans == <span class="number">116259075798</span>) <span class="built_in">cout</span> &lt;&lt; i &lt;&lt; <span class="built_in">endl</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="试题-C-冶炼金属"><a href="#试题-C-冶炼金属" class="headerlink" title="试题 C: 冶炼金属"></a>试题 C: 冶炼金属</h2><p>思维，注意处理边界情况</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> n;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">ios::sync_with_stdio(<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">cin</span> &gt;&gt; n;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> maxx = <span class="number">-1</span>;</span><br><span class="line"><span class="keyword">int</span> minn = <span class="number">1e9</span> + <span class="number">7</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> a, b;</span><br><span class="line"><span class="built_in">cin</span> &gt;&gt; a &gt;&gt; b;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (a == b) &#123;</span><br><span class="line">maxx = <span class="number">1</span>;</span><br><span class="line">minn = <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span> &#123;</span><br><span class="line">minn = a / (b + <span class="number">1</span>) + <span class="number">1</span>;</span><br><span class="line">maxx = a / b;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">2</span>; i &lt;= n; i++) &#123;</span><br><span class="line"><span class="built_in">cin</span> &gt;&gt; a &gt;&gt; b;</span><br><span class="line"><span class="keyword">if</span> (a == b) &#123;</span><br><span class="line">maxx = <span class="number">1</span>;</span><br><span class="line">minn = <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span> &#123;</span><br><span class="line">minn = <span class="built_in">max</span>(minn, a / (b + <span class="number">1</span>) + <span class="number">1</span>);</span><br><span class="line">maxx = <span class="built_in">min</span>(maxx, a / b);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">cout</span> &lt;&lt; minn &lt;&lt; <span class="string">" "</span> &lt;&lt; maxx &lt;&lt; <span class="built_in">endl</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="试题-D-飞机降落"><a href="#试题-D-飞机降落" class="headerlink" title="试题 D: 飞机降落"></a>试题 D: 飞机降落</h2><p>全排列处理，复杂度为10! * 10，可能不是最优解</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> n;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> a[<span class="number">12</span>];</span><br><span class="line"><span class="keyword">int</span> t[<span class="number">12</span>], d[<span class="number">12</span>], l[<span class="number">12</span>];</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">ios::sync_with_stdio(<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> T;</span><br><span class="line"><span class="built_in">cin</span> &gt;&gt; T;</span><br><span class="line"><span class="keyword">while</span> (T--) &#123;</span><br><span class="line"><span class="built_in">cin</span> &gt;&gt; n;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= n; i++) a[i] = i;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= n; i++) &#123;</span><br><span class="line"><span class="built_in">cin</span> &gt;&gt; t[i] &gt;&gt; d[i] &gt;&gt; l[i];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> flag = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">do</span> &#123;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> now = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= n; i++) &#123;</span><br><span class="line"><span class="keyword">if</span> (d[a[i]] + t[a[i]] &lt; now) <span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (t[a[i]] &gt; now) &#123;</span><br><span class="line">now = t[a[i]] + l[a[i]];</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span> &#123;</span><br><span class="line">now = now + l[a[i]];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (i == n) flag = <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (flag) <span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line">&#125; <span class="keyword">while</span> (next_permutation(a + <span class="number">1</span>, a + <span class="number">1</span> + n));</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (flag) <span class="built_in">cout</span> &lt;&lt; <span class="string">"YES"</span>;</span><br><span class="line"><span class="keyword">else</span> <span class="built_in">cout</span> &lt;&lt; <span class="string">"NO"</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (T != <span class="number">0</span>) <span class="built_in">cout</span> &lt;&lt; <span class="built_in">endl</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="试题-E-接龙数列"><a href="#试题-E-接龙数列" class="headerlink" title="试题 E: 接龙数列"></a>试题 E: 接龙数列</h2><p>简单动态规划</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> n;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> a[<span class="number">100010</span>];</span><br><span class="line"><span class="keyword">int</span> dp[<span class="number">100010</span>];</span><br><span class="line"><span class="keyword">int</span> h[<span class="number">100010</span>];</span><br><span class="line"><span class="keyword">int</span> last[<span class="number">11</span>];</span><br><span class="line"><span class="keyword">int</span> maxi[<span class="number">11</span>];</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">ios::sync_with_stdio(<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">cin</span> &gt;&gt; n;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= n; i++) &#123;</span><br><span class="line"><span class="built_in">cin</span> &gt;&gt; a[i];</span><br><span class="line"><span class="keyword">int</span> k = a[i];</span><br><span class="line"><span class="keyword">while</span> (k) &#123;</span><br><span class="line"><span class="keyword">if</span> (k &lt; <span class="number">10</span>) h[i] = k;</span><br><span class="line">k /= <span class="number">10</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt;= <span class="number">9</span>; i++) &#123;</span><br><span class="line">last[i] = <span class="number">0</span>;</span><br><span class="line">maxi[i] = <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= n; i++) &#123;</span><br><span class="line">dp[i] = maxi[h[i]] + <span class="number">1</span>;</span><br><span class="line">maxi[a[i] % <span class="number">10</span>] = <span class="built_in">max</span>(maxi[a[i] % <span class="number">10</span>], dp[i]);</span><br><span class="line">last[a[i] % <span class="number">10</span>] = i;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> ans = n;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt;= <span class="number">9</span>; i++) &#123;</span><br><span class="line">ans = <span class="built_in">min</span>(ans, n - maxi[i]);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">cout</span> &lt;&lt; ans;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="试题-F-岛屿个数"><a href="#试题-F-岛屿个数" class="headerlink" title="试题 F: 岛屿个数"></a>试题 F: 岛屿个数</h2><p>首先bfs每个点，判断是否能通过0到达岛外，可以斜着走，无法到达就说明是子岛屿，记得剪枝。第二次bfs判断连通块个数，即为答案。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> n, m;</span><br><span class="line"><span class="keyword">int</span> a[<span class="number">60</span>][<span class="number">60</span>];</span><br><span class="line"><span class="keyword">int</span> flag;</span><br><span class="line"><span class="keyword">int</span> xi[<span class="number">8</span>] = &#123; <span class="number">1</span>, <span class="number">0</span>, <span class="number">-1</span>, <span class="number">0</span>, <span class="number">1</span>, <span class="number">-1</span>, <span class="number">1</span>, <span class="number">-1</span>&#125;;</span><br><span class="line"><span class="keyword">int</span> yi[<span class="number">8</span>] = &#123; <span class="number">0</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">-1</span>, <span class="number">-1</span>, <span class="number">1</span>, <span class="number">1</span>, <span class="number">-1</span>&#125;;</span><br><span class="line"><span class="keyword">int</span> ans;</span><br><span class="line"><span class="keyword">int</span> ch[<span class="number">60</span>][<span class="number">60</span>];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">check</span><span class="params">(<span class="keyword">int</span> x, <span class="keyword">int</span> y)</span> </span>&#123;</span><br><span class="line"><span class="keyword">if</span> (x &lt; <span class="number">1</span> || x &gt; n || y &lt; <span class="number">1</span> || y &gt; m) <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"><span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">init_bfs</span><span class="params">(<span class="keyword">int</span> x, <span class="keyword">int</span> y)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="built_in">queue</span>&lt;pair&lt;<span class="keyword">int</span>, <span class="keyword">int</span>&gt;&gt;q;</span><br><span class="line">q.push(make_pair(x, y));</span><br><span class="line"><span class="keyword">int</span> c[<span class="number">60</span>][<span class="number">60</span>];</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= n; i++) &#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">1</span>; j &lt;= m; j++) &#123;</span><br><span class="line">c[i][j] = <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">c[x][y] = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">while</span> (!q.empty()) &#123;</span><br><span class="line"><span class="keyword">auto</span> p = q.front();</span><br><span class="line">q.pop();</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">8</span>; i++) &#123;</span><br><span class="line"><span class="keyword">int</span> xn = p.first + xi[i];</span><br><span class="line"><span class="keyword">int</span> yn = p.second + yi[i];</span><br><span class="line"><span class="keyword">if</span> (check(xn, yn)) &#123;</span><br><span class="line"><span class="keyword">if</span> (c[xn][yn])<span class="keyword">continue</span>;</span><br><span class="line">c[xn][yn] = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (a[xn][yn] == <span class="number">2</span>) &#123;</span><br><span class="line"></span><br><span class="line">flag = <span class="number">2</span>;</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span> <span class="keyword">if</span> (a[xn][yn] == <span class="number">1</span>) &#123;</span><br><span class="line"><span class="keyword">continue</span>;</span><br><span class="line">&#125;</span><br><span class="line">q.push(make_pair(xn, yn));</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span> &#123;</span><br><span class="line"></span><br><span class="line">flag = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (flag != <span class="number">0</span>) <span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">bfs</span><span class="params">(<span class="keyword">int</span> x, <span class="keyword">int</span> y)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="built_in">queue</span>&lt;pair&lt;<span class="keyword">int</span>, <span class="keyword">int</span>&gt;&gt;q;</span><br><span class="line">q.push(make_pair(x, y));</span><br><span class="line">ch[x][y] = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">while</span> (!q.empty()) &#123;</span><br><span class="line"><span class="keyword">auto</span> p = q.front();</span><br><span class="line">q.pop();</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">4</span>; i++) &#123;</span><br><span class="line"><span class="keyword">int</span> xn = p.first + xi[i];</span><br><span class="line"><span class="keyword">int</span> yn = p.second + yi[i];</span><br><span class="line"><span class="keyword">if</span> (check(xn, yn)) &#123;</span><br><span class="line"><span class="keyword">if</span> (ch[xn][yn])<span class="keyword">continue</span>;</span><br><span class="line">ch[xn][yn] = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (a[xn][yn] == <span class="number">0</span>) &#123;</span><br><span class="line"><span class="keyword">continue</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">q.push(make_pair(xn, yn));</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">ios::sync_with_stdio(<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> T;</span><br><span class="line"><span class="built_in">cin</span> &gt;&gt; T;</span><br><span class="line"><span class="keyword">while</span> (T--) &#123;</span><br><span class="line"><span class="built_in">cin</span> &gt;&gt; n &gt;&gt; m;</span><br><span class="line"><span class="built_in">string</span> s;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= n; i++) &#123;</span><br><span class="line"><span class="built_in">cin</span> &gt;&gt; s;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">0</span>; j &lt; m; j++) &#123;</span><br><span class="line">a[i][j + <span class="number">1</span>] = s[j] - <span class="string">'0'</span>;</span><br><span class="line">ch[i][j + <span class="number">1</span>] = <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= n; i++) &#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">1</span>; j &lt;= m; j++) &#123;</span><br><span class="line"><span class="keyword">if</span> (a[i][j] == <span class="number">0</span>) <span class="keyword">continue</span>;</span><br><span class="line">flag = <span class="number">0</span>;</span><br><span class="line">init_bfs(i, j);</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (flag != <span class="number">1</span>) a[i][j] = <span class="number">2</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">ans = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= n; i++) &#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">1</span>; j &lt;= m; j++) &#123;</span><br><span class="line"><span class="keyword">if</span> (ch[i][j] == <span class="number">1</span> || a[i][j] != <span class="number">1</span>) <span class="keyword">continue</span>;</span><br><span class="line">ans++;</span><br><span class="line">bfs(i, j);</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">cout</span> &lt;&lt; ans;</span><br><span class="line"><span class="keyword">if</span> (T != <span class="number">0</span>) <span class="built_in">cout</span> &lt;&lt; <span class="built_in">endl</span>;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="试题-G-子串简写"><a href="#试题-G-子串简写" class="headerlink" title="试题 G: 子串简写"></a>试题 G: 子串简写</h2><p>前缀和，但这个位置的题目真的这么简单么，怀疑可能读错题。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> k;</span><br><span class="line"><span class="built_in">string</span> s;</span><br><span class="line"><span class="keyword">char</span> a, b;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> pre[<span class="number">1000010</span>];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">ios::sync_with_stdio(<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">cin</span> &gt;&gt; k;</span><br><span class="line"><span class="built_in">cin</span> &gt;&gt; s &gt;&gt; a &gt;&gt; b;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> n = s.length();</span><br><span class="line"><span class="keyword">long</span> <span class="keyword">long</span> ans = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; n; i++) &#123;</span><br><span class="line"><span class="keyword">if</span> (i != <span class="number">0</span>) pre[i] = pre[i - <span class="number">1</span>];</span><br><span class="line"><span class="keyword">else</span> pre[i] = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">if</span> (s[i] == a) pre[i]++;</span><br><span class="line"><span class="keyword">if</span> (s[i] == b &amp;&amp; i - k + <span class="number">1</span> &gt;= <span class="number">0</span>) ans += pre[i - k + <span class="number">1</span>];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">cout</span> &lt;&lt; ans;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="试题-H-整数删除"><a href="#试题-H-整数删除" class="headerlink" title="试题 H: 整数删除"></a>试题 H: 整数删除</h2><p>维护链表和一个set，每次取出set中最小的，判断是否合法，并对链表节点和值进行修改。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> c[<span class="number">1000010</span>];</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> n, k;</span><br><span class="line"><span class="keyword">long</span> <span class="keyword">long</span> a[<span class="number">500010</span>];</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> l[<span class="number">500010</span>], r[<span class="number">500010</span>];</span><br><span class="line"></span><br><span class="line"><span class="built_in">set</span>&lt;pair&lt;<span class="keyword">int</span>, <span class="keyword">int</span>&gt;&gt; s;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">ios::sync_with_stdio(<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">cin</span> &gt;&gt; n &gt;&gt; k;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> w = n - k;</span><br><span class="line"></span><br><span class="line">l[<span class="number">0</span>] = r[<span class="number">0</span>] = l[n + <span class="number">1</span>] = r[n + <span class="number">1</span>] = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= n; i++) &#123;</span><br><span class="line"><span class="built_in">cin</span> &gt;&gt; a[i];</span><br><span class="line">l[i] = i - <span class="number">1</span>;</span><br><span class="line">r[i] = i + <span class="number">1</span>;</span><br><span class="line">s.insert(make_pair(a[i], i));</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">while</span> (<span class="number">1</span>) &#123;</span><br><span class="line"><span class="keyword">if</span> (k == <span class="number">0</span>) <span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">auto</span> it = s.<span class="built_in">begin</span>();</span><br><span class="line"><span class="keyword">auto</span> p = *it;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> val = p.first, pos = p.second;</span><br><span class="line"><span class="keyword">if</span> (c[pos] || a[pos] != val) &#123;</span><br><span class="line">s.erase(it);</span><br><span class="line"><span class="keyword">continue</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">k--;</span><br><span class="line">c[pos] = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">int</span> pl = l[pos], pr = r[pos];</span><br><span class="line"><span class="keyword">if</span> (pl &gt; <span class="number">0</span> &amp;&amp; pl &lt;= n) &#123;</span><br><span class="line">a[pl] += a[pos];</span><br><span class="line">r[pl] = pr;</span><br><span class="line">s.insert(make_pair(a[pl], pl));</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (pr &gt; <span class="number">0</span> &amp;&amp; pr &lt;= n) &#123;</span><br><span class="line">a[pr] += a[pos];</span><br><span class="line">l[pr] = pl;</span><br><span class="line">s.insert(make_pair(a[pr], pr));</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= n; i++) &#123;</span><br><span class="line"><span class="keyword">if</span> (c[i]) <span class="keyword">continue</span>;</span><br><span class="line"><span class="built_in">cout</span> &lt;&lt; a[i];</span><br><span class="line"><span class="keyword">if</span> (w != <span class="number">0</span>) <span class="built_in">cout</span> &lt;&lt; <span class="string">" "</span>;</span><br><span class="line">w--;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="试题-I-景区导游"><a href="#试题-I-景区导游" class="headerlink" title="试题 I: 景区导游"></a>试题 I: 景区导游</h2><p>最近公共祖先+简单容斥，LCA边想边敲，敲的很烂，思路应该问题不大。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> pow2[<span class="number">21</span>];</span><br><span class="line"><span class="keyword">int</span> n, k;</span><br><span class="line"><span class="built_in">vector</span>&lt;pair&lt;<span class="keyword">int</span>, <span class="keyword">int</span>&gt;&gt;edge[<span class="number">100010</span>];</span><br><span class="line"><span class="keyword">long</span> <span class="keyword">long</span> st[<span class="number">100010</span>][<span class="number">21</span>];</span><br><span class="line"><span class="keyword">int</span> stt[<span class="number">100010</span>][<span class="number">21</span>];</span><br><span class="line"><span class="keyword">int</span> fa[<span class="number">100010</span>];</span><br><span class="line"><span class="keyword">int</span> dep[<span class="number">100010</span>];</span><br><span class="line"><span class="keyword">int</span> kk[<span class="number">100010</span>];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">init</span><span class="params">(<span class="keyword">int</span> x, <span class="keyword">int</span> f)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; edge[x].<span class="built_in">size</span>(); i++) &#123;</span><br><span class="line"><span class="keyword">auto</span> p = edge[x][i];</span><br><span class="line"><span class="keyword">int</span> to = p.first;</span><br><span class="line"><span class="keyword">int</span> val = p.second;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (to == f) <span class="keyword">continue</span>;</span><br><span class="line">dep[to] = dep[x] + <span class="number">1</span>;</span><br><span class="line">fa[to] = x;</span><br><span class="line">st[to][<span class="number">0</span>] = val;</span><br><span class="line">stt[to][<span class="number">0</span>] = x;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">1</span>; j &lt;= <span class="number">20</span>; j++) &#123;</span><br><span class="line"><span class="keyword">int</span> now = x;</span><br><span class="line">st[to][j] = val;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> k = j - <span class="number">1</span>; k &gt;= <span class="number">0</span>; k--) &#123;</span><br><span class="line">st[to][j] += st[now][k];</span><br><span class="line">now = stt[now][k];</span><br><span class="line">&#125;</span><br><span class="line">stt[to][j] = now;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">init(to, x);</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">long</span> <span class="keyword">long</span> <span class="title">solve</span><span class="params">(<span class="keyword">int</span> x, <span class="keyword">int</span> y)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (dep[x] &gt; dep[y]) swap(x, y);</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> cha = dep[y] - dep[x];</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> now = y;</span><br><span class="line"><span class="keyword">long</span> <span class="keyword">long</span> ans = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">20</span>; i &gt;= <span class="number">0</span>; i--) &#123;</span><br><span class="line"><span class="keyword">if</span> (pow2[i] &lt;= cha) &#123;</span><br><span class="line">ans += st[now][i];</span><br><span class="line">cha -= pow2[i];</span><br><span class="line">now = stt[now][i];</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> lpos = x, rpos = now;</span><br><span class="line"><span class="keyword">while</span> (<span class="number">1</span>) &#123;</span><br><span class="line"><span class="keyword">if</span> (lpos == rpos) <span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">if</span> (stt[lpos][<span class="number">0</span>] == stt[rpos][<span class="number">0</span>]) &#123;</span><br><span class="line">ans += st[lpos][<span class="number">0</span>] + st[rpos][<span class="number">0</span>];</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">20</span>; i &gt;= <span class="number">0</span>; i--) &#123;</span><br><span class="line"><span class="keyword">if</span> (stt[lpos][i] == stt[rpos][i]) <span class="keyword">continue</span>;</span><br><span class="line">ans += st[lpos][i] + st[rpos][i];</span><br><span class="line">lpos = stt[lpos][i];</span><br><span class="line">rpos = stt[rpos][i];</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> ans;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">ios::sync_with_stdio(<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">pow2[<span class="number">0</span>] = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= <span class="number">20</span>; i++) pow2[i] = pow2[i - <span class="number">1</span>] * <span class="number">2</span>;</span><br><span class="line"></span><br><span class="line"><span class="built_in">cin</span> &gt;&gt; n &gt;&gt; k;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt; n; i++) &#123;</span><br><span class="line"><span class="keyword">int</span> u, v, t;</span><br><span class="line"><span class="built_in">cin</span> &gt;&gt; u &gt;&gt; v &gt;&gt; t;</span><br><span class="line">edge[u].push_back(make_pair(v, t));</span><br><span class="line">edge[v].push_back(make_pair(u, t));</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line">dep[<span class="number">1</span>] = <span class="number">1</span>;</span><br><span class="line">init(<span class="number">1</span>, <span class="number">0</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= k; i++) <span class="built_in">cin</span> &gt;&gt; kk[i];</span><br><span class="line"></span><br><span class="line"><span class="keyword">long</span> <span class="keyword">long</span> ans = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">2</span>; i &lt;= k; i++) &#123;</span><br><span class="line">ans += solve(kk[i - <span class="number">1</span>], kk[i]);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= k; i++) &#123;</span><br><span class="line"><span class="keyword">long</span> <span class="keyword">long</span> ff = ans;</span><br><span class="line"><span class="keyword">if</span> (i == <span class="number">1</span>) &#123;</span><br><span class="line">ff -= solve(kk[i], kk[i + <span class="number">1</span>]);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span> <span class="keyword">if</span> (i == k) &#123;</span><br><span class="line">ff -= solve(kk[i - <span class="number">1</span>], kk[i]);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span> &#123;</span><br><span class="line">ff -= solve(kk[i], kk[i + <span class="number">1</span>]);</span><br><span class="line">ff -= solve(kk[i - <span class="number">1</span>], kk[i]);</span><br><span class="line">ff += solve(kk[i - <span class="number">1</span>], kk[i + <span class="number">1</span>]);</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">cout</span> &lt;&lt; ff;</span><br><span class="line"><span class="keyword">if</span> (i != k) <span class="built_in">cout</span> &lt;&lt; <span class="string">" "</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="试题-J-砍树"><a href="#试题-J-砍树" class="headerlink" title="试题 J: 砍树"></a>试题 J: 砍树</h2><p>正解没有想到，枚举砍掉的边，用LCA判断是否在一颗子树上，可以通过30%样例。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> pow2[<span class="number">21</span>];</span><br><span class="line"><span class="keyword">int</span> n, k;</span><br><span class="line"><span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt;edge[<span class="number">100010</span>];</span><br><span class="line"><span class="keyword">int</span> stt[<span class="number">100010</span>][<span class="number">21</span>];</span><br><span class="line"><span class="keyword">int</span> fa[<span class="number">100010</span>];</span><br><span class="line"><span class="keyword">int</span> dep[<span class="number">100010</span>];</span><br><span class="line"><span class="keyword">int</span> kl[<span class="number">100010</span>], kr[<span class="number">100010</span>];</span><br><span class="line"><span class="keyword">int</span> ledge[<span class="number">100010</span>], redge[<span class="number">100010</span>];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">init</span><span class="params">(<span class="keyword">int</span> x, <span class="keyword">int</span> f)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; edge[x].<span class="built_in">size</span>(); i++) &#123;</span><br><span class="line"><span class="keyword">int</span> to = edge[x][i];</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (to == f) <span class="keyword">continue</span>;</span><br><span class="line">dep[to] = dep[x] + <span class="number">1</span>;</span><br><span class="line">fa[to] = x;</span><br><span class="line">stt[to][<span class="number">0</span>] = x;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">1</span>; j &lt;= <span class="number">20</span>; j++) &#123;</span><br><span class="line"><span class="keyword">int</span> now = x;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> k = j - <span class="number">1</span>; k &gt;= <span class="number">0</span>; k--) &#123;</span><br><span class="line">now = stt[now][k];</span><br><span class="line">&#125;</span><br><span class="line">stt[to][j] = now;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">init(to, x);</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">solve</span><span class="params">(<span class="keyword">int</span> x, <span class="keyword">int</span> y)</span> </span>&#123;</span><br><span class="line"><span class="keyword">if</span> (dep[x] &gt; dep[y]) swap(x, y);</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> cha = dep[y] - dep[x];</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> now = y;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">20</span>; i &gt;= <span class="number">0</span>; i--) &#123;</span><br><span class="line"><span class="keyword">if</span> (pow2[i] &lt;= cha) &#123;</span><br><span class="line">cha -= pow2[i];</span><br><span class="line">now = stt[now][i];</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> lpos = x, rpos = now;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">while</span> (<span class="number">1</span>) &#123;</span><br><span class="line"><span class="keyword">if</span> (lpos == rpos) <span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">if</span> (stt[lpos][<span class="number">0</span>] == stt[rpos][<span class="number">0</span>]) &#123;</span><br><span class="line">lpos = stt[lpos][<span class="number">0</span>];</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">20</span>; i &gt;= <span class="number">0</span>; i--) &#123;</span><br><span class="line"><span class="keyword">if</span> (stt[lpos][i] == stt[rpos][i]) <span class="keyword">continue</span>;</span><br><span class="line">lpos = stt[lpos][i];</span><br><span class="line">rpos = stt[rpos][i];</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> lpos;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">ios::sync_with_stdio(<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">pow2[<span class="number">0</span>] = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= <span class="number">20</span>; i++) pow2[i] = pow2[i - <span class="number">1</span>] * <span class="number">2</span>;</span><br><span class="line"></span><br><span class="line"><span class="built_in">cin</span> &gt;&gt; n &gt;&gt; k;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt; n; i++) &#123;</span><br><span class="line"><span class="keyword">int</span> u, v, t;</span><br><span class="line"><span class="built_in">cin</span> &gt;&gt; u &gt;&gt; v;</span><br><span class="line">edge[u].push_back(v);</span><br><span class="line">edge[v].push_back(u);</span><br><span class="line">ledge[i] = u;</span><br><span class="line">redge[i] = v;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line">dep[<span class="number">1</span>] = <span class="number">1</span>;</span><br><span class="line">init(<span class="number">1</span>, <span class="number">0</span>);</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= k; i++) &#123;</span><br><span class="line"><span class="built_in">cin</span> &gt;&gt; kl[i] &gt;&gt; kr[i];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> ans = <span class="number">-1</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt; n; i++) &#123;</span><br><span class="line"><span class="keyword">if</span> (dep[ledge[i]] &lt; dep[redge[i]]) swap(ledge[i], redge[i]);</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> flag = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">1</span>; j &lt;= k; j++) &#123;</span><br><span class="line"><span class="keyword">int</span> ansa = solve(kl[j], ledge[i]);</span><br><span class="line"><span class="keyword">int</span> ansb = solve(kr[j], ledge[i]);</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> ((ansa == ledge[i] || ansb == ledge[i]) &amp;&amp; ansa != ansb) <span class="keyword">continue</span>;</span><br><span class="line">flag = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (!flag) ans = i;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">cout</span> &lt;&lt; ans;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla
      
    
    </summary>
    
    
      <category term="题解" scheme="http://yoursite.com/categories/%E9%A2%98%E8%A7%A3/"/>
    
    
  </entry>
  
  <entry>
    <title>分布式锁</title>
    <link href="http://yoursite.com/2022/07/27/%E4%B8%AD%E9%97%B4%E4%BB%B6/Redis/%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81/"/>
    <id>http://yoursite.com/2022/07/27/%E4%B8%AD%E9%97%B4%E4%BB%B6/Redis/%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81/</id>
    <published>2022-07-27T08:50:10.000Z</published>
    <updated>2022-07-27T13:34:48.478Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h4 id="死锁问题"><a href="#死锁问题" class="headerlink" title="死锁问题"></a>死锁问题</h4><p>获取锁的进程在锁未释放时终止，其他进程无法获取到锁，形成死锁</p><h5 id="解决死锁问题？"><a href="#解决死锁问题？" class="headerlink" title="解决死锁问题？"></a>解决死锁问题？</h5><p>原子操作设置过期时间</p><h5 id="过期时间的两个问题"><a href="#过期时间的两个问题" class="headerlink" title="过期时间的两个问题"></a>过期时间的两个问题</h5><ul><li>未执行完key就过期，导致其他进程获取到锁：锁续期</li><li>删除到其他线程的锁：设定不冲突的key值</li></ul><h4 id="提升redis锁性能"><a href="#提升redis锁性能" class="headerlink" title="提升redis锁性能"></a>提升redis锁性能</h4><h5 id="分段锁"><a href="#分段锁" class="headerlink" title="分段锁"></a>分段锁</h5><p>比如把相同的商品的id分段</p><h4 id="集群引发的问题"><a href="#集群引发的问题" class="headerlink" title="集群引发的问题"></a>集群引发的问题</h4><p>主服务器加锁，未同步到从服务器就挂掉，选举的新的主服务器没有加锁</p><h5 id="Redis红锁方案"><a href="#Redis红锁方案" class="headerlink" title="Redis红锁方案"></a>Redis红锁方案</h5><ul><li>存活的Redis服务器有一半加锁成功，才算成功</li><li>实现工具：redission</li></ul><h4 id="JVM的STW对Redis影响"><a href="#JVM的STW对Redis影响" class="headerlink" title="JVM的STW对Redis影响"></a>JVM的STW对Redis影响</h4><p>拿到锁后，JVM发生STW，锁无法续期，其他进程可以拿到锁</p><h5 id="使用zookeeper解决"><a href="#使用zookeeper解决" class="headerlink" title="使用zookeeper解决"></a>使用zookeeper解决</h5>]]></content>
    
    <summary type="html">
    
      
      
        &lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla
      
    
    </summary>
    
    
      <category term="中间件" scheme="http://yoursite.com/categories/%E4%B8%AD%E9%97%B4%E4%BB%B6/"/>
    
    
  </entry>
  
  <entry>
    <title>Java并发编程的艺术</title>
    <link href="http://yoursite.com/2022/07/21/%E4%B9%A6%E7%AD%BE/Java%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E7%9A%84%E8%89%BA%E6%9C%AF/"/>
    <id>http://yoursite.com/2022/07/21/%E4%B9%A6%E7%AD%BE/Java%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B%E7%9A%84%E8%89%BA%E6%9C%AF/</id>
    <published>2022-07-21T08:43:23.000Z</published>
    <updated>2022-07-22T08:13:26.256Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h4 id="第一章-并发编程的挑战"><a href="#第一章-并发编程的挑战" class="headerlink" title="第一章 并发编程的挑战"></a>第一章 并发编程的挑战</h4><h5 id="减少上下文切换的四种方法-p3"><a href="#减少上下文切换的四种方法-p3" class="headerlink" title="减少上下文切换的四种方法   p3"></a>减少上下文切换的四种方法   p3</h5><h4 id><a href="#" class="headerlink" title=" "></a> </h4><h4 id="第二章-Java并发机制的底层实现原理"><a href="#第二章-Java并发机制的底层实现原理" class="headerlink" title="第二章 Java并发机制的底层实现原理"></a>第二章 Java并发机制的底层实现原理</h4><h5 id="volatile如何保证可见性-p9"><a href="#volatile如何保证可见性-p9" class="headerlink" title="volatile如何保证可见性 p9"></a>volatile如何保证可见性 p9</h5><h5 id="synchronized实现原理-p12"><a href="#synchronized实现原理-p12" class="headerlink" title="synchronized实现原理 p12"></a>synchronized实现原理 p12</h5><h5 id="锁的升级-p13"><a href="#锁的升级-p13" class="headerlink" title="锁的升级 p13"></a>锁的升级 p13</h5><h5 id="处理器实现原子操作的两种方式-p17"><a href="#处理器实现原子操作的两种方式-p17" class="headerlink" title="处理器实现原子操作的两种方式 p17"></a>处理器实现原子操作的两种方式 p17</h5><h5 id="java实现原子操作-p18"><a href="#java实现原子操作-p18" class="headerlink" title="java实现原子操作 p18"></a>java实现原子操作 p18</h5><h5 id="CAS实现原子操作的三大问题-p19"><a href="#CAS实现原子操作的三大问题-p19" class="headerlink" title="CAS实现原子操作的三大问题 p19"></a>CAS实现原子操作的三大问题 p19</h5><h4 id="第三章-Java内存模型"><a href="#第三章-Java内存模型" class="headerlink" title="第三章 Java内存模型"></a>第三章 Java内存模型</h4><h5 id="volatile两大特性的含义（可见性与原子性）-p39"><a href="#volatile两大特性的含义（可见性与原子性）-p39" class="headerlink" title="volatile两大特性的含义（可见性与原子性） p39"></a>volatile两大特性的含义（可见性与原子性） p39</h5><h5 id="双重检查锁定（单例模式）-p67"><a href="#双重检查锁定（单例模式）-p67" class="headerlink" title="双重检查锁定（单例模式） p67"></a>双重检查锁定（单例模式） p67</h5><h5 id="类初始化的5个阶段-p74"><a href="#类初始化的5个阶段-p74" class="headerlink" title="类初始化的5个阶段 p74"></a>类初始化的5个阶段 p74</h5><h4 id="第四章-Java并发编程基础"><a href="#第四章-Java并发编程基础" class="headerlink" title="第四章 Java并发编程基础"></a>第四章 Java并发编程基础</h4><h5 id="线程的状态-p87"><a href="#线程的状态-p87" class="headerlink" title="线程的状态 p87"></a>线程的状态 p87</h5><h5 id="队列同步器AQS-p121"><a href="#队列同步器AQS-p121" class="headerlink" title="队列同步器AQS p121"></a>队列同步器AQS p121</h5><h5 id="重入锁-p136"><a href="#重入锁-p136" class="headerlink" title="重入锁 p136"></a>重入锁 p136</h5><h5 id="公平锁与非公平锁-p137"><a href="#公平锁与非公平锁-p137" class="headerlink" title="公平锁与非公平锁 p137"></a>公平锁与非公平锁 p137</h5><h5 id="读写锁-p140"><a href="#读写锁-p140" class="headerlink" title="读写锁 p140"></a>读写锁 p140</h5>]]></content>
    
    <summary type="html">
    
      
      
        &lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla
      
    
    </summary>
    
    
      <category term="Bookmark" scheme="http://yoursite.com/categories/Bookmark/"/>
    
    
  </entry>
  
  <entry>
    <title>RDB与AOF持久化对比</title>
    <link href="http://yoursite.com/2022/07/20/%E4%B8%AD%E9%97%B4%E4%BB%B6/Redis/RDB%E4%B8%8EAOF%E6%8C%81%E4%B9%85%E5%8C%96%E5%AF%B9%E6%AF%94/"/>
    <id>http://yoursite.com/2022/07/20/%E4%B8%AD%E9%97%B4%E4%BB%B6/Redis/RDB%E4%B8%8EAOF%E6%8C%81%E4%B9%85%E5%8C%96%E5%AF%B9%E6%AF%94/</id>
    <published>2022-07-20T07:27:10.000Z</published>
    <updated>2022-07-20T07:30:56.738Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><div class="table-container"><table><thead><tr><th></th><th>RDB</th><th>AOF</th></tr></thead><tbody><tr><td>持久化方式</td><td>定时对整个内存做快照</td><td>记录每一次执行的命令</td></tr><tr><td>数据完整性</td><td>不完整，两次备份之间会有数据丢失</td><td>相对完整，取决于刷盘策略</td></tr><tr><td>文件大小</td><td>会有压缩，体积小</td><td>记录命令，体积大</td></tr><tr><td>宕机恢复速度</td><td>很快</td><td>慢</td></tr><tr><td>数据恢复优先级</td><td>低，因为完整性不如AOF</td><td>高</td></tr><tr><td>系统资源占用</td><td>高，大量CPU与内存消耗</td><td>低，主要是磁盘IO资源，重写时占用高</td></tr><tr><td>使用场景</td><td>容忍数分钟数据丢失，追求更快启动速度</td><td>对数据安全性要求较高</td></tr></tbody></table></div>]]></content>
    
    <summary type="html">
    
      
      
        &lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla
      
    
    </summary>
    
    
      <category term="中间件" scheme="http://yoursite.com/categories/%E4%B8%AD%E9%97%B4%E4%BB%B6/"/>
    
    
  </entry>
  
  <entry>
    <title>Seata</title>
    <link href="http://yoursite.com/2022/07/19/%E5%BE%AE%E6%9C%8D%E5%8A%A1/%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1/Seata/"/>
    <id>http://yoursite.com/2022/07/19/%E5%BE%AE%E6%9C%8D%E5%8A%A1/%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1/Seata/</id>
    <published>2022-07-19T07:14:23.000Z</published>
    <updated>2022-07-21T08:42:02.994Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h4 id="Seata是什么？"><a href="#Seata是什么？" class="headerlink" title="Seata是什么？"></a>Seata是什么？</h4><p>Seata是2019年1月蚂蚁金服和阿里巴巴共同开源的分布式事务解决方案。致力于提供高性能和简单易用的分布式事务服务，为用户打造一站式的分布式解决方案。</p><h4 id="Seata架构"><a href="#Seata架构" class="headerlink" title="Seata架构"></a>Seata架构</h4><h5 id="Seata事务管理中有三个重要角色"><a href="#Seata事务管理中有三个重要角色" class="headerlink" title="Seata事务管理中有三个重要角色"></a>Seata事务管理中有三个重要角色</h5><ul><li>TC - 事务协调者：维护全局和分支事务的状态，协调全局事务提交或回滚</li><li>TM - 事务管理器：定义全局事务的范围、开始全局事务、提交或回滚全局事务</li><li>RM - 资源管理器：管理分支事务处理的资源，与TC交谈以注册分支事务和报告分支事务的状态，并驱动分支事务提交或回滚</li></ul><h5 id="Seata提供了四种不同的分布式事务解决方案"><a href="#Seata提供了四种不同的分布式事务解决方案" class="headerlink" title="Seata提供了四种不同的分布式事务解决方案"></a>Seata提供了四种不同的分布式事务解决方案</h5><ul><li>XA模式：强一致分阶段事务模式，牺牲了一定的可用性，无业务侵入</li><li>TCC模式：最终一致的分阶段事务模式，有业务侵入</li><li>AT模式：最终一致的分阶段事务模式，无业务侵入，也是Seata的默认模式</li><li>SAGA模式：长事务模式，有业务侵入</li></ul><h4 id="XA模式"><a href="#XA模式" class="headerlink" title="XA模式"></a>XA模式</h4><h5 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h5><p>XA规范是X/Open组织定义的分布式事务处理(DTP)标准，XA规范描述了全局的TM与局部RM之间的接口，几乎所有主流的数据库都对XA规范提供了支持</p><ul><li>RM一阶段工作：<ul><li>注册分支事务到TC</li><li>执行分支事务sql但不提交</li><li>报告执行状态到TC</li></ul></li><li>TC二阶段工作：<ul><li>TC检测各分支事务执行状态</li><li>判断提交或回滚</li></ul></li><li>RM二阶段工作：<ul><li>接收TC指令，提交或回滚事务</li></ul></li></ul><h5 id="实现XA模式"><a href="#实现XA模式" class="headerlink" title="实现XA模式"></a>实现XA模式</h5><p>Seata的starter已经完成了XA模式的自动装配</p><ul><li>修改配置文件</li></ul><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">seata:</span></span><br><span class="line">    <span class="attr">data-source-proxy-mode:</span> <span class="string">XA</span></span><br></pre></td></tr></table></figure><ul><li>发起全局事务的入口添加@GlobalTransactional注解</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Override</span></span><br><span class="line"><span class="meta">@GlobalTransactional</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> Long <span class="title">create</span><span class="params">(Order order)</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 创建订单</span></span><br><span class="line">    orderMapper.insert(order);</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">// 扣用户余额</span></span><br><span class="line">        accountClient.deduct(order.getUserId(), order.getMoney());</span><br><span class="line">        <span class="comment">// 扣库存</span></span><br><span class="line">        storageClient.deduct(order.getCommodityCode(), order.getCount());</span><br><span class="line"></span><br><span class="line">    &#125; <span class="keyword">catch</span> (FeignException e) &#123;</span><br><span class="line">        log.error(<span class="string">"下单失败，原因:&#123;&#125;"</span>, e.contentUTF8(), e);</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException(e.contentUTF8(), e);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> order.getId();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="AT模式"><a href="#AT模式" class="headerlink" title="AT模式"></a>AT模式</h4><h5 id="原理-1"><a href="#原理-1" class="headerlink" title="原理"></a>原理</h5><p>AT模式同样是分阶段提交的事务模型，不过弥补了XA模型中资源锁定周期过长的缺陷</p><ul><li>RM一阶段工作：<ul><li>注册分支事务到TC</li><li><strong>记录undo-log（数据快照）</strong></li><li>执行分支事务sql并<strong>提交</strong></li><li>报告执行状态到TC</li></ul></li><li>TC二阶段工作：<ul><li>TC检测各分支事务执行状态</li><li>判断提交或回滚，提交删除快照，回滚读取快照</li></ul></li><li>RM二阶段回滚工作：<ul><li>根据undo-log恢复数据</li></ul></li></ul><h5 id="AT模式的写隔离"><a href="#AT模式的写隔离" class="headerlink" title="AT模式的写隔离"></a>AT模式的写隔离</h5><p>全局锁：由TC（在数据库中）记录当前正在操作某行数据的事务，该事务持有全局锁，具备执行权</p><ul><li>事务1获取了全局锁，准备回滚，等待事务2释放DB锁（读写隔离）</li><li>事务2持有DB锁，等待全局锁，重试默认30次，间隔10毫秒，超时释放（避免死锁）</li><li>事务1获取DB锁，将数据库当前数据和更新后undo-log数据对比，判断是否一致</li></ul><h4 id="TCC模式"><a href="#TCC模式" class="headerlink" title="TCC模式"></a>TCC模式</h4><p>与AT模式相似，每阶段都是独立事务，但不加锁。不同的是TCC通过人工编码来实现数据恢复，需要实现三个方法</p><ul><li>Try：资源的检测和预留，比如可用余额预留为冻结余额，不同的操作冻结的余额相互隔离</li><li>Confirm：完成资源操作业务；要求Try成功Confirm一定要成功</li><li>Cancel：预留资源释放，try的反向操作</li></ul><h5 id="优点"><a href="#优点" class="headerlink" title="优点"></a>优点</h5><ul><li>一阶段完成直接提交事务，释放数据库资源，性能好</li><li>相比AT模型，无需生成快照，无需使用全局锁，性能最强</li><li>不依赖数据库事务，而是依赖补偿操作，可以用非事务数据库</li></ul><h5 id="缺点"><a href="#缺点" class="headerlink" title="缺点"></a>缺点</h5><ul><li>有代码侵入，需要人为编写try、Confirm和Cancel接口</li><li>软状态，最终一致</li><li>需要考虑Confirm和Cancel失败情况，做好幂等处理</li></ul><h5 id="空回滚"><a href="#空回滚" class="headerlink" title="空回滚"></a>空回滚</h5><p>当某分支事务的try阶段阻塞时，可能导致全局事务超时而触发二阶段的cancel操作，在未执行try操作时先执行了cancel操作，这时cancel不能做回滚，就是空回滚</p><h5 id="业务悬挂"><a href="#业务悬挂" class="headerlink" title="业务悬挂"></a>业务悬挂</h5><p>对于已经空回滚的业务，如果以后继续执行try，就永远不可能confirm或cancel，这就是业务悬挂。应当组织执行空回滚后try操作，避免悬挂</p><h5 id="业务分析"><a href="#业务分析" class="headerlink" title="业务分析"></a>业务分析</h5><p>为了实现空回滚，防止业务悬挂，以及幂等性要求。我们必须在数据库记录预留资源信息同时，记录当前事务id和执行状态</p><h5 id="声明TCC接口，并实现三个方法"><a href="#声明TCC接口，并实现三个方法" class="headerlink" title="声明TCC接口，并实现三个方法"></a>声明TCC接口，并实现三个方法</h5><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">AccountTCCServiceImpl</span> <span class="keyword">implements</span> <span class="title">AccountTCCService</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> AccountMapper accountMapper;</span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> AccountFreezeMapper accountFreezeMapper;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="meta">@Transactional</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">deduct</span><span class="params">(String userId, <span class="keyword">int</span> money)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//获取事务id</span></span><br><span class="line">        String xid = RootContext.getXID();</span><br><span class="line"></span><br><span class="line">        <span class="comment">//业务悬挂判断</span></span><br><span class="line">        AccountFreeze oldFreeze = accountFreezeMapper.selectById(xid);</span><br><span class="line">        <span class="keyword">if</span>(oldFreeze != <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//扣减可用余额</span></span><br><span class="line">        accountMapper.deduct(userId, money);</span><br><span class="line">        <span class="comment">//记录冻结余额与事务状态</span></span><br><span class="line">        AccountFreeze freeze = <span class="keyword">new</span> AccountFreeze();</span><br><span class="line">        freeze.setUserId(userId);</span><br><span class="line">        freeze.setFreezeMoney(money);</span><br><span class="line">        freeze.setState(AccountFreeze.State.TRY);</span><br><span class="line">        freeze.setXid(xid);</span><br><span class="line">        accountFreezeMapper.insert(freeze);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">confirm</span><span class="params">(BusinessActionContext ctx)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//获取事务id</span></span><br><span class="line">        String xid = ctx.getXid();</span><br><span class="line">        <span class="comment">//根据id删除冻结记录</span></span><br><span class="line">        <span class="keyword">int</span> count = accountFreezeMapper.deleteById(xid);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> count == <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">cancel</span><span class="params">(BusinessActionContext ctx)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//获取事务id,查询freeze对象</span></span><br><span class="line">        String xid = ctx.getXid();</span><br><span class="line">        String userId = ctx.getActionContext(<span class="string">"userId"</span>).toString();</span><br><span class="line">        AccountFreeze freeze = accountFreezeMapper.selectById(xid);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//空回滚判断，判断freeze是否为null</span></span><br><span class="line">        <span class="keyword">if</span>(freeze == <span class="keyword">null</span>) &#123;</span><br><span class="line">            AccountFreeze newFreeze = <span class="keyword">new</span> AccountFreeze();</span><br><span class="line">            freeze.setUserId(userId);</span><br><span class="line">            freeze.setFreezeMoney(<span class="number">0</span>);</span><br><span class="line">            freeze.setState(AccountFreeze.State.CANCEL);</span><br><span class="line">            freeze.setXid(xid);</span><br><span class="line">            <span class="keyword">int</span> count = accountFreezeMapper.insert(newFreeze);</span><br><span class="line"></span><br><span class="line">            <span class="keyword">return</span> count == <span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//幂等判断</span></span><br><span class="line">        <span class="keyword">if</span>(freeze.getState().equals(AccountFreeze.State.CANCEL)) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//恢复可用余额</span></span><br><span class="line">        accountMapper.refund(freeze.getUserId(), freeze.getFreezeMoney());</span><br><span class="line"></span><br><span class="line">        <span class="comment">//将冻结金额清零，状态改为CANCEL</span></span><br><span class="line">        freeze.setFreezeMoney(<span class="number">0</span>);</span><br><span class="line">        freeze.setState(AccountFreeze.State.CANCEL);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">int</span> count = accountFreezeMapper.updateById(freeze);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> count == <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="Saga模式"><a href="#Saga模式" class="headerlink" title="Saga模式"></a>Saga模式</h4><p>Saga模式时SEATA提供的长事务解决方案。也分为两个阶段</p><ul><li>一阶段：直接提交事务，与TCC不同的是不做预留操作</li><li>二阶段：失败则通过编写补偿业务来回滚</li></ul><h5 id="优点-1"><a href="#优点-1" class="headerlink" title="优点"></a>优点</h5><ul><li>事务参与者可以基于事件驱动实现异步调用，吞吐高</li><li>一阶段直接提交事务，无锁，性能好</li><li>不用编写TCC中三个阶段，实现简单</li></ul><h5 id="缺点-1"><a href="#缺点-1" class="headerlink" title="缺点"></a>缺点</h5><ul><li>软状态持续时间不确定，时效性差</li><li>无锁，无事务隔离，会有脏写</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla
      
    
    </summary>
    
    
      <category term="微服务" scheme="http://yoursite.com/categories/%E5%BE%AE%E6%9C%8D%E5%8A%A1/"/>
    
    
      <category term="seata" scheme="http://yoursite.com/tags/seata/"/>
    
  </entry>
  
  <entry>
    <title>分布式事务</title>
    <link href="http://yoursite.com/2022/07/19/%E5%BE%AE%E6%9C%8D%E5%8A%A1/%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1/%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1/"/>
    <id>http://yoursite.com/2022/07/19/%E5%BE%AE%E6%9C%8D%E5%8A%A1/%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1/%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1/</id>
    <published>2022-07-19T02:44:23.000Z</published>
    <updated>2022-07-23T08:19:28.967Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><p>在分布式系统下，一个业务跨越多个服务或数据源，每个服务都是一个分支事务，要保证所有分支事务最终状态一致，这样的事务就是分布式事务。</p><h4 id="CAP定理"><a href="#CAP定理" class="headerlink" title="CAP定理"></a>CAP定理</h4><p>分布式系统三个指标：</p><ul><li>Consistency（一致性）：用户访问分布式系统中的任意节点，得到的数据必须一致</li><li>Availability（可用性）：用户访问集群中的任意健康节点，必须能得到响应，而不是超时或拒绝</li><li>Partition tolerance（分区容错性）：出现分区问题，C和A无法同时满足<ul><li>分区：因为网络故障或其它原因导致分布式系统中的部分节点与其它节点失去连接，形成独立分区</li><li>容错：在集群出现分区时，整个系统也要持续对外提供服务</li></ul></li></ul><p>Eric Brewer认为，分布式系统<strong>无法同时满足</strong>三个指标，这个结论就是CAP定理</p><h4 id="BASE理论"><a href="#BASE理论" class="headerlink" title="BASE理论"></a>BASE理论</h4><p>BASE理论时对CAP的一种解决思路</p><ul><li>Basically Available（基本可用）：分布式系统出现故障时，允许损失部分可用性，即保证核心可用</li><li>Soft State（软状态）：在一定时间内，允许出现中间状态，比如临时的不一致状态</li><li>Eventually Consistent（最终一致性）：虽然无法保证强一致，但是在软状态结束后，最终达到数据一直</li></ul><h4 id="AP模式"><a href="#AP模式" class="headerlink" title="AP模式"></a>AP模式</h4><p>各子事务分别执行和提交，允许出现结果不一致，然后采用弥补措施恢复数据即可，实现<strong>最终一致</strong></p><h4 id="CP模式"><a href="#CP模式" class="headerlink" title="CP模式"></a>CP模式</h4><p>各个子事务执行后互相等待，同时提交，同时回滚，达成<strong>强一致</strong>，但事务等待过程中，处于弱可用状态</p><h4 id="事务协调者"><a href="#事务协调者" class="headerlink" title="事务协调者"></a>事务协调者</h4><p>各个子系统之间必须能感知到彼此的事务状态，才能保证状态一致，因此需要一个事务协调者来协调每一个事务的参与者（子系统事务）</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla
      
    
    </summary>
    
    
      <category term="微服务" scheme="http://yoursite.com/categories/%E5%BE%AE%E6%9C%8D%E5%8A%A1/"/>
    
    
      <category term="seata" scheme="http://yoursite.com/tags/seata/"/>
    
  </entry>
  
  <entry>
    <title>授权规则</title>
    <link href="http://yoursite.com/2022/07/18/%E5%BE%AE%E6%9C%8D%E5%8A%A1/%E5%BE%AE%E6%9C%8D%E5%8A%A1%E4%BF%9D%E6%8A%A4/%E6%8E%88%E6%9D%83%E8%A7%84%E5%88%99/"/>
    <id>http://yoursite.com/2022/07/18/%E5%BE%AE%E6%9C%8D%E5%8A%A1/%E5%BE%AE%E6%9C%8D%E5%8A%A1%E4%BF%9D%E6%8A%A4/%E6%8E%88%E6%9D%83%E8%A7%84%E5%88%99/</id>
    <published>2022-07-18T09:03:23.000Z</published>
    <updated>2022-07-19T02:43:38.045Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><p>授权规则可以对调用方的来源做控制，有白名单和黑名单两种方式</p><ul><li>白名单：来源在白名单内的调用者允许访问</li><li>黑名单：来源在黑名单内的调用者不允许访问</li></ul><p>可以解决绕过网关直接访问微服务的问题</p><h4 id="授权方法"><a href="#授权方法" class="headerlink" title="授权方法"></a>授权方法</h4><ul><li>实现RequestOriginParser接口，自定义处理逻辑</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">HeaderOriginParser</span> <span class="keyword">implements</span> <span class="title">RequestOriginParser</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">parseOrigin</span><span class="params">(HttpServletRequest request)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">        String origin = request.getHeader(<span class="string">"origin"</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span>(StringUtils.isEmpty(origin)) &#123;</span><br><span class="line">            origin = <span class="string">"blank"</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> origin;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>在gateway服务中，利用过滤器添加指定请求头</li></ul><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">default-filters:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">AddRequestHeader=Truth,Itcast</span> <span class="string">is</span> <span class="string">freaking</span> <span class="string">awesome!</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">AddRequestHeader=origin,gateway</span></span><br></pre></td></tr></table></figure><ul><li>在sentinel中添加约定好的授权规则</li></ul><h4 id="自定义异常"><a href="#自定义异常" class="headerlink" title="自定义异常"></a>自定义异常</h4><p>实现BlockExceptionHandler接口</p><p>BlockException包含多个子类：</p><div class="table-container"><table><thead><tr><th>异常</th><th>说明</th></tr></thead><tbody><tr><td>FlowException</td><td>限流异常</td></tr><tr><td>ParamFlowException</td><td>热点参数限流的异常</td></tr><tr><td>DegradeException</td><td>降级异常</td></tr><tr><td>AuthorityException</td><td>授权规则异常</td></tr><tr><td>SystemBlockException</td><td>系统规则异常</td></tr></tbody></table></div><h4 id="规则持久化"><a href="#规则持久化" class="headerlink" title="规则持久化"></a>规则持久化</h4><h5 id="规则管理模式"><a href="#规则管理模式" class="headerlink" title="规则管理模式"></a>规则管理模式</h5><ul><li>原始模式：默认模式，将规则保存在内存，重启服务丢失</li><li>pull模式：控制台将配置的规则推送给Sentinel客户端，客户端会保存到本地文件或数据库中。之后定时<strong>轮询</strong>更新</li><li>push模式：控制台将配置规则推送到远程配置中心，例如Nacos。Sentinel客户端<strong>监听</strong>Nacos，获取配置变更的推送消息，完成本地更新</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla
      
    
    </summary>
    
    
      <category term="微服务保护" scheme="http://yoursite.com/categories/%E5%BE%AE%E6%9C%8D%E5%8A%A1%E4%BF%9D%E6%8A%A4/"/>
    
    
  </entry>
  
  <entry>
    <title>隔离和降级</title>
    <link href="http://yoursite.com/2022/07/18/%E5%BE%AE%E6%9C%8D%E5%8A%A1/%E5%BE%AE%E6%9C%8D%E5%8A%A1%E4%BF%9D%E6%8A%A4/%E9%9A%94%E7%A6%BB%E5%92%8C%E9%99%8D%E7%BA%A7/"/>
    <id>http://yoursite.com/2022/07/18/%E5%BE%AE%E6%9C%8D%E5%8A%A1/%E5%BE%AE%E6%9C%8D%E5%8A%A1%E4%BF%9D%E6%8A%A4/%E9%9A%94%E7%A6%BB%E5%92%8C%E9%99%8D%E7%BA%A7/</id>
    <published>2022-07-18T07:41:23.000Z</published>
    <updated>2022-07-18T09:03:31.865Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><p>虽然限流可以尽量避免因高并发而引起的服务故障，但服务还会因为其它原因而故障。而要将这些故障控制在一定范围，避免雪崩，就要靠线程隔离（舱壁模式）和熔断降级的手段。</p><h4 id="Feign整合Sentinel"><a href="#Feign整合Sentinel" class="headerlink" title="Feign整合Sentinel"></a>Feign整合Sentinel</h4><p>SpringCloud中，微服务调用都是通过Feign来实现的，因此做客户端保护必须整合Feign和Sentinel</p><ul><li>修改配置文件，开启Feign的Sentinel功能</li><li>给FeignClient编写失败后的降级逻辑<ul><li>方式一：FallbackClass，无法对远程调用的异常做处理</li><li>方式二：FallbackFactory，可以对远程调用的异常做处理</li></ul></li></ul><h5 id="使用FallbackFactory实现降级逻辑"><a href="#使用FallbackFactory实现降级逻辑" class="headerlink" title="使用FallbackFactory实现降级逻辑"></a>使用FallbackFactory实现降级逻辑</h5><ul><li>定义类，实现FallbackFactory接口的create方法</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Slf</span>4j</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UserClientFallBackFactory</span> <span class="keyword">implements</span> <span class="title">FallbackFactory</span>&lt;<span class="title">UserClient</span>&gt; </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> UserClient <span class="title">create</span><span class="params">(Throwable throwable)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> UserClient() &#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="function"><span class="keyword">public</span> User <span class="title">findById</span><span class="params">(Long id)</span> </span>&#123;</span><br><span class="line">                log.error(<span class="string">"查询用户异常"</span>, throwable);</span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">new</span> User();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>将实现的FallbackFactory注册为一个Bean</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> UserClientFallBackFactory <span class="title">userClientFallBackFactory</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> UserClientFallBackFactory();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>在Client接口中使用FallbackFactory（注解添加）</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@FeignClient</span>(value = <span class="string">"userservice"</span>, fallbackFactory = UserClientFallBackFactory<span class="class">.<span class="keyword">class</span>)</span></span><br></pre></td></tr></table></figure><h4 id="线程隔离"><a href="#线程隔离" class="headerlink" title="线程隔离"></a>线程隔离</h4><ul><li>线程池隔离<ul><li>支持主动超时和异步调用</li><li>但线程额外开销较大</li><li>场景：低扇出</li></ul></li><li>信号量隔离（Sentinel默认）<ul><li>轻量级，无额外开销</li><li>不支持主动超时、异步调用</li><li>场景：高频调用，高扇出</li></ul></li></ul><h4 id="熔断降级"><a href="#熔断降级" class="headerlink" title="熔断降级"></a>熔断降级</h4><p>也是解决雪崩问题的重要手段。由断路器统计服务调用的异常比例、慢请求比例，如果超出阈值则会熔断该服务。即拦截访问该服务的一切请求；而当服务恢复时，断路器会放行访问该服务的请求</p><h5 id="断路器三种状态"><a href="#断路器三种状态" class="headerlink" title="断路器三种状态"></a>断路器三种状态</h5><ul><li>Closed：不会拦截任何请求</li><li>Open：熔断，拦截进入该服务的请求，有持续时间</li><li>Half-Open：Open状态时间结束，会放行请求，根据结果切换状态</li></ul><h5 id="熔断策略-慢调用"><a href="#熔断策略-慢调用" class="headerlink" title="熔断策略-慢调用"></a>熔断策略-慢调用</h5><p>业务响应时长（RT）大于指定时长的请求认定为慢调用请求。在指定时间内，如果<strong>请求数量超过设定的最小数量且慢调用比例大于设定的阈值</strong>，则触发熔断</p><h5 id="熔断策略-异常比例"><a href="#熔断策略-异常比例" class="headerlink" title="熔断策略-异常比例"></a>熔断策略-异常比例</h5><p>慢调用比例换成抛出异常比例即可</p><h5 id="熔断策略-异常数"><a href="#熔断策略-异常数" class="headerlink" title="熔断策略-异常数"></a>熔断策略-异常数</h5><p>指定异常次数</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla
      
    
    </summary>
    
    
      <category term="微服务保护" scheme="http://yoursite.com/categories/%E5%BE%AE%E6%9C%8D%E5%8A%A1%E4%BF%9D%E6%8A%A4/"/>
    
    
  </entry>
  
  <entry>
    <title>Sentinel入门与限流</title>
    <link href="http://yoursite.com/2022/07/17/%E5%BE%AE%E6%9C%8D%E5%8A%A1/%E5%BE%AE%E6%9C%8D%E5%8A%A1%E4%BF%9D%E6%8A%A4/Sentinel%E5%85%A5%E9%97%A8%E4%B8%8E%E9%99%90%E6%B5%81/"/>
    <id>http://yoursite.com/2022/07/17/%E5%BE%AE%E6%9C%8D%E5%8A%A1/%E5%BE%AE%E6%9C%8D%E5%8A%A1%E4%BF%9D%E6%8A%A4/Sentinel%E5%85%A5%E9%97%A8%E4%B8%8E%E9%99%90%E6%B5%81/</id>
    <published>2022-07-17T09:42:23.000Z</published>
    <updated>2022-07-18T07:40:35.446Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h4 id="雪崩问题"><a href="#雪崩问题" class="headerlink" title="雪崩问题"></a>雪崩问题</h4><p>微服务调用链路中的某个服务故障，引起整个链路中的所有微服务都不可用</p><p>解决雪崩问题的常见方式有四种（前三种避免故障传递，流量控制预防故障发生）：</p><ul><li>超时处理：设定超时时间，请求超过一定时间没有响应就返回错误信息，不会无休止等待</li><li><strong>舱壁模式</strong>：限定每个业务能使用的线程数，避免耗尽整个tomcat资源，因此也叫线程隔离</li><li><strong>熔断降级</strong>：由<strong>断路器</strong>统计业务执行的异常比例，如果超出<strong>阈值</strong>则会熔断该业务，拦截访问该业务的一切请求</li><li><strong>流量控制</strong>：限制业务访问的QPS（每秒钟请求数量），避免服务因流量的突增而故障</li></ul><h4 id="服务保护技术对比-Sentinel与Hystrix"><a href="#服务保护技术对比-Sentinel与Hystrix" class="headerlink" title="服务保护技术对比(Sentinel与Hystrix)"></a>服务保护技术对比(Sentinel与Hystrix)</h4><div class="table-container"><table><thead><tr><th></th><th>Sentinel</th><th>Hystrix</th></tr></thead><tbody><tr><td>隔离策略</td><td>信号量隔离</td><td>线程池隔离/信号量隔离</td></tr><tr><td>熔断降级策略</td><td>基于慢调用比例或异常比例</td><td>基于失败比率</td></tr><tr><td>实时指标实现</td><td>滑动窗口</td><td>滑动窗口（基于RxJava）</td></tr><tr><td>规则配置</td><td>支持多种数据源</td><td>支持多种数据源</td></tr><tr><td>扩展性</td><td>多个扩展点</td><td>插件的形式</td></tr><tr><td>基于注解的支持</td><td>支持</td><td>支持</td></tr><tr><td>限流</td><td>基于QPS，支持基于调用关系的限流</td><td>有限的支持</td></tr><tr><td>流量整形</td><td>支持慢启动、匀速排队模式</td><td>不支持</td></tr><tr><td>系统自适应保护</td><td>支持</td><td>不支持</td></tr><tr><td>控制台</td><td>开箱即用，可配置规则、查看秒级监控、机器发现等</td><td>不完善</td></tr><tr><td>常见框架适配</td><td>Servlet、Spring Cloud、Dubbo、gRPC等</td><td>Servlet、Spring Cloud Netflix</td></tr></tbody></table></div><h4 id="安装Sentinel控制台"><a href="#安装Sentinel控制台" class="headerlink" title="安装Sentinel控制台"></a>安装Sentinel控制台</h4><ul><li>运行jar包</li><li>访问页面，默认账号密码为sentinel</li><li>通过配置修改</li></ul><div class="table-container"><table><thead><tr><th>配置项</th><th>默认值</th><th>说明</th></tr></thead><tbody><tr><td>server.port</td><td>8080</td><td>服务端口</td></tr><tr><td>sentinel.dashboard.auth.username</td><td>sentinel</td><td>默认用户名</td></tr><tr><td>sentinel.dashboard.auth.password</td><td>sentinel</td><td>默认密码</td></tr></tbody></table></div><ul><li>启动时修改</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">java -jar sentinel-dashboard-1.8.1.jar -Dserver.port&#x3D;8090</span><br></pre></td></tr></table></figure><h4 id="微服务整合Sentinel"><a href="#微服务整合Sentinel" class="headerlink" title="微服务整合Sentinel"></a>微服务整合Sentinel</h4><ul><li>引入sentinel依赖</li></ul><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-alibaba-sentinel<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure><ul><li>配置控制台地址</li></ul><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">sentinel:</span></span><br><span class="line">      <span class="attr">transport:</span></span><br><span class="line">        <span class="attr">dashboard:</span> <span class="string">localhost:8080</span></span><br></pre></td></tr></table></figure><ul><li>访问微服务任意端点，触发sentinel监控</li></ul><h4 id="Sentinel限流规则"><a href="#Sentinel限流规则" class="headerlink" title="Sentinel限流规则"></a>Sentinel限流规则</h4><h5 id="簇点链路"><a href="#簇点链路" class="headerlink" title="簇点链路"></a>簇点链路</h5><p>项目内的调用链路，链路中被监控的每个接口就是一个资源。默认情况下Sentinel会监控SpringMVC每一个端点</p><h5 id="在Sentinel控制台设置流控规则"><a href="#在Sentinel控制台设置流控规则" class="headerlink" title="在Sentinel控制台设置流控规则"></a>在Sentinel控制台设置流控规则</h5><ul><li>设置QPS，并使用Apache JMeter测试</li><li>高级配置：流控模式、流控效果</li><li><p>流控模式：直接、关联、链路</p><ul><li>直接：默认模式，统计当前资源请求，触发阈值对当前资源限流</li><li>关联：统计与当前资源相关的<strong>另一个资源</strong>，触发阈值对当前资源限流(A触发阈值对B限流)，如触发修改订单阈值，对查询订单限流</li><li>链路：只统计从<strong>指定链路</strong>访问到本地的资源的请求，触发阈值时，对指定链路限流</li></ul></li><li><p>流控效果，请求达到流控阈值时应该采取的措施，包括三种：快速失败、warm up、排队等待</p><ul><li>快速失败：达到阈值后，新的请求立即被拒绝抛出FlowException异常</li><li>warm up：预热模式，对超出阈值的请求同样拒绝，但这种模式的阈值会动态变化，从小增大到最大阈值</li><li>排队等待：让所有请求按照先后次序排队执行，间隔不小于指定时常</li></ul></li></ul><h5 id="添加限流方法"><a href="#添加限流方法" class="headerlink" title="添加限流方法"></a>添加限流方法</h5><ul><li><p>Sentinel默认只标记Controller中的方法为资源，如果要标记其它方法，需要利用@SentinelResource注解</p></li><li><p>Sentinel默认会将Controller方法做context整合，导致链路模式的流控失效，需要修改application.yml</p></li></ul><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">sentinel:</span></span><br><span class="line">      <span class="attr">web-context-unify:</span> <span class="literal">false</span> <span class="comment">#关闭context整合</span></span><br></pre></td></tr></table></figure><h5 id="流控效果-warm-up"><a href="#流控效果-warm-up" class="headerlink" title="流控效果-warm up"></a>流控效果-warm up</h5><p>应对服务冷启动的一种方案，请求阈值初始值为threshold/coldFactor，持续指定时长后，逐渐提高到threshold，coldFactor（冷启动因子）默认值为3</p><h5 id="流控效果-排队等待"><a href="#流控效果-排队等待" class="headerlink" title="流控效果-排队等待"></a>流控效果-排队等待</h5><p>让所有请求进入一个队列中，然后按着阈值允许的时间间隔依次执行。后来的请求必须等待前面执行完成，如果请求预期时间超出最大时长，则会被拒绝</p><ul><li>例如，QPS=5，也就是每200ms处理一个请求。timeout=2000，意味着等待超过2000ms就会抛出异常</li></ul><h5 id="热点参数限流"><a href="#热点参数限流" class="headerlink" title="热点参数限流"></a>热点参数限流</h5><p>分别统计与设定<strong>参数值相同</strong>的请求，判断是否超过QPS阈值</p><ul><li>例如参数索引为0，单机阈值为5，统计窗口时长为1，含义为：对当前资源0号参数（<strong>第一个参数</strong>）的请求做统计，每1秒的请求数量不超过5</li><li>高级选项可以对部分参数做例外配置</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla
      
    
    </summary>
    
    
      <category term="微服务保护" scheme="http://yoursite.com/categories/%E5%BE%AE%E6%9C%8D%E5%8A%A1%E4%BF%9D%E6%8A%A4/"/>
    
    
      <category term="雪崩问题" scheme="http://yoursite.com/tags/%E9%9B%AA%E5%B4%A9%E9%97%AE%E9%A2%98/"/>
    
      <category term="限流规则" scheme="http://yoursite.com/tags/%E9%99%90%E6%B5%81%E8%A7%84%E5%88%99/"/>
    
  </entry>
  
  <entry>
    <title>分布式定时任务Spring Quartz</title>
    <link href="http://yoursite.com/2022/06/24/%E5%B7%A5%E5%85%B7/%E5%88%86%E5%B8%83%E5%BC%8F%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1Spring%20Quartz/"/>
    <id>http://yoursite.com/2022/06/24/%E5%B7%A5%E5%85%B7/%E5%88%86%E5%B8%83%E5%BC%8F%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1Spring%20Quartz/</id>
    <published>2022-06-24T06:23:45.000Z</published>
    <updated>2022-06-24T13:17:00.987Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><ul><li>服务器之间通过数据库进行数据共享</li><li>用加锁的方式抢夺资源</li></ul><h4 id="核心组件"><a href="#核心组件" class="headerlink" title="核心组件"></a>核心组件</h4><ul><li>核心调度工具类：Scheduler</li><li>定义任务接口：Job</li><li>配置Job的接口：JobDetail(Job信息)、Trigger(触发器)</li></ul><h4 id="核心数据库表"><a href="#核心数据库表" class="headerlink" title="核心数据库表"></a>核心数据库表</h4><ul><li>qrtz_job_details表：job相关信息</li><li>qrtz_simple_triggers表：trigger简单内容</li><li>qrtz_triggers表：trigger详细内容</li><li>qrtz_scheduler_state表：定时器的信息状态</li><li>qrtz_locks表：锁信息</li></ul><h4 id="定时任务创建基本步骤"><a href="#定时任务创建基本步骤" class="headerlink" title="定时任务创建基本步骤"></a>定时任务创建基本步骤</h4><ul><li><p>创建工具类，用于将创建的jobDetail和trigger存储到数据库，实现二者FactoryBean</p><ul><li>FactoryBean作用：简化Bean的实例化过程<ul><li>Spring通过FactoryBean封装Bean实例化过程</li><li>将FactoryBean装配到Spring容器里</li><li>将FactoryBean注入给其它Bean</li><li>该Bean就得到了FactoryBean所管理对象的实例</li></ul></li></ul></li><li><p>创建Job实体类，实现Job接口的execute方法</p></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla
      
    
    </summary>
    
    
      <category term="工具" scheme="http://yoursite.com/categories/%E5%B7%A5%E5%85%B7/"/>
    
    
  </entry>
  
  <entry>
    <title>SpringAMQP</title>
    <link href="http://yoursite.com/2022/06/21/%E4%B8%AD%E9%97%B4%E4%BB%B6/MQ/AMQP/"/>
    <id>http://yoursite.com/2022/06/21/%E4%B8%AD%E9%97%B4%E4%BB%B6/MQ/AMQP/</id>
    <published>2022-06-21T02:50:13.000Z</published>
    <updated>2022-07-17T09:41:15.820Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h4 id="什么是SpringAMQP"><a href="#什么是SpringAMQP" class="headerlink" title="什么是SpringAMQP"></a>什么是SpringAMQP</h4><h5 id="AMQP（高级消息队列协议）"><a href="#AMQP（高级消息队列协议）" class="headerlink" title="AMQP（高级消息队列协议）"></a>AMQP（高级消息队列协议）</h5><p>是用于在应用程序或之间传递业务消息的开放标准。该协议与语言和平台无关，更符合微服务中独立性的要求</p><h5 id="Spirng-AMQP"><a href="#Spirng-AMQP" class="headerlink" title="Spirng AMQP"></a>Spirng AMQP</h5><p>基于AMQP协议定义的一套API规范，提供了模板来发送和接收消息。包含两部分，其中spring-amqp是基础抽象，spring-rabbit是底层的默认实现</p><h4 id="利用SpringAMQP实现基础消息队列功能"><a href="#利用SpringAMQP实现基础消息队列功能" class="headerlink" title="利用SpringAMQP实现基础消息队列功能"></a>利用SpringAMQP实现基础消息队列功能</h4><h5 id="发送消息"><a href="#发送消息" class="headerlink" title="发送消息"></a>发送消息</h5><ul><li>在父工程中引入spring-amqp依赖</li><li>在publisher服务中利用RabbitTemplate发送消息到simple.queue这个队列</li></ul><h5 id="接受消息"><a href="#接受消息" class="headerlink" title="接受消息"></a>接受消息</h5><ul><li>引入amqp的starter依赖</li><li>配置RabbitMQ地址</li><li>定义类，添加@Component注解</li><li>类中声明方法，添加@RabbitListener注解，方法参数就是消息</li></ul><h4 id="Work-Queue-工作队列"><a href="#Work-Queue-工作队列" class="headerlink" title="Work Queue 工作队列"></a>Work Queue 工作队列</h4><p>与基础消息队列区别：多个消费者，可以提高消息处理速度，避免队列消息堆积</p><h5 id="消费预取限制"><a href="#消费预取限制" class="headerlink" title="消费预取限制"></a>消费预取限制</h5><p>配置文件设置preFetch值，可以控制预取消息上限</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">rabbitmq:</span></span><br><span class="line">    <span class="attr">listener:</span></span><br><span class="line">      <span class="attr">simple:</span></span><br><span class="line">        <span class="attr">prefetch:</span> <span class="number">1</span> <span class="comment">#每次只能获取一条消息，处理完才能获取下一条,默认无限</span></span><br></pre></td></tr></table></figure><h4 id="发布、订阅模型（Publish-amp-Subscribe）"><a href="#发布、订阅模型（Publish-amp-Subscribe）" class="headerlink" title="发布、订阅模型（Publish&amp;Subscribe）"></a>发布、订阅模型（Publish&amp;Subscribe）</h4><p>允许将同一消息发送给多个消费者，实现方式是加入了交换机（exchange）</p><p>实现方式：通过交换机发送给多个队列</p><p>常见交换机类型：</p><ul><li>Fanout：广播</li><li>Direct：路由</li><li>Topic：话题</li></ul><p>注意：exchange负责消息路由，只负责转发消息，路由失败则消息丢失</p><h5 id="发布订阅-FanoutExchange"><a href="#发布订阅-FanoutExchange" class="headerlink" title="发布订阅-FanoutExchange"></a>发布订阅-FanoutExchange</h5><p>会将接收到的消息路由到每一个与其绑定的queue</p><p>实现思路如下：</p><ul><li>在cunsumer服务中，声明队列、交换机，并将两者绑定</li><li>在consumer服务中，编写消费者方法，分别监听各个队列</li><li>在publisher中编写测试方法，发送消息</li></ul><h5 id="发布订阅-DirectExchange"><a href="#发布订阅-DirectExchange" class="headerlink" title="发布订阅-DirectExchange"></a>发布订阅-DirectExchange</h5><p>会将接收到的消息<strong>根据规则</strong>路由到指定的Queue，因此称为路由模式</p><ul><li>每一个Queue都与Exchange设置一个BindingKey，可以绑定多个</li><li>发布者发送消息时，指定<strong>消息</strong>的RoutingKey</li><li>Exchange将消息路由到BindingKey宇RoutingKey一致的队列</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RabbitListener</span>(bindings = <span class="meta">@QueueBinding</span>(</span><br><span class="line">        value = <span class="meta">@Queue</span>(name = <span class="string">"direct.queue1"</span>),</span><br><span class="line">        exchange = <span class="meta">@Exchange</span>(name = <span class="string">"itcast.direct"</span>, type = ExchangeTypes.DIRECT),</span><br><span class="line">        key = &#123;<span class="string">"red"</span>, <span class="string">"blue"</span>&#125;</span><br><span class="line">))</span><br></pre></td></tr></table></figure><h5 id="发布订阅-TopicExchange"><a href="#发布订阅-TopicExchange" class="headerlink" title="发布订阅-TopicExchange"></a>发布订阅-TopicExchange</h5><p>与DirectExchange类似，区别在于routingKey必须是多个单词的列表，并且以.分割</p><p>Queue与Exchange指定BindingKey时可以使用通配符：</p><ul><li><h1 id="：代指0个或多个单词"><a href="#：代指0个或多个单词" class="headerlink" title="：代指0个或多个单词"></a>：代指0个或多个单词</h1></li><li>*：代指一个单词</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RabbitListener</span>(bindings = <span class="meta">@QueueBinding</span>(</span><br><span class="line">        value = <span class="meta">@Queue</span>(name = <span class="string">"topic.queue2"</span>),</span><br><span class="line">        exchange = <span class="meta">@Exchange</span>(name = <span class="string">"itcast.topic"</span>, type = ExchangeTypes.TOPIC),</span><br><span class="line">        key = <span class="string">"#.news"</span></span><br><span class="line">))</span><br></pre></td></tr></table></figure><h4 id="消息转换器"><a href="#消息转换器" class="headerlink" title="消息转换器"></a>消息转换器</h4><p>消息发送Java对象时，SpringAMQP会帮我们序列化为字节后发送，基于JDK的ObjectOutputStream完成序列化</p><p>如果要修改只需要定义一个MessageConverter的Bean即可。推荐使用JSON方式序列化，步骤如下：</p><h5 id="发送消息-1"><a href="#发送消息-1" class="headerlink" title="发送消息"></a>发送消息</h5><ul><li>在publisher服务引入依赖</li></ul><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.fasterxml.jackson.dataformat<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>jackson-dataformat-xml<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.9.10<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure><ul><li>在publisher服务声明MessageConverter</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> MessageConverter <span class="title">jsonMessageConverter</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> Jackson2JsonMessageConverter();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>发送消息即可</li></ul><h5 id="接收消息"><a href="#接收消息" class="headerlink" title="接收消息"></a>接收消息</h5><ul><li>在consumer服务引入Jackson依赖</li></ul><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.fasterxml.jackson.dataformat<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>jackson-dataformat-xml<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.9.10<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure><ul><li>在consumer服务定义MessageConverter：</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> MessageConverter <span class="title">jsonMessageConverter</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> Jackson2JsonMessageConverter();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>接收消息即可</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla
      
    
    </summary>
    
    
      <category term="中间件" scheme="http://yoursite.com/categories/%E4%B8%AD%E9%97%B4%E4%BB%B6/"/>
    
    
      <category term="MQ" scheme="http://yoursite.com/tags/MQ/"/>
    
  </entry>
  
  <entry>
    <title>RabbitMQ消息模型</title>
    <link href="http://yoursite.com/2022/06/20/%E4%B8%AD%E9%97%B4%E4%BB%B6/MQ/RabbitMQ%E6%B6%88%E6%81%AF%E6%A8%A1%E5%9E%8B/"/>
    <id>http://yoursite.com/2022/06/20/%E4%B8%AD%E9%97%B4%E4%BB%B6/MQ/RabbitMQ%E6%B6%88%E6%81%AF%E6%A8%A1%E5%9E%8B/</id>
    <published>2022-06-20T03:24:13.000Z</published>
    <updated>2022-06-21T02:49:48.455Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h4 id="常见消息模型"><a href="#常见消息模型" class="headerlink" title="常见消息模型"></a>常见消息模型</h4><p>MQ的官方文档中给出了5个MQ的Demo示例，对应了几种不同的用法：</p><ul><li>基本消息队列（BasicQueue）</li><li>工作消息队列（WorkQueue）</li><li>发布订阅（Publish、Subscribe），又根据交换机类型不同分为三种：<ul><li>Fanout Exchange：广播</li><li>Direct Exchange：路由</li><li>Topic Exchange：主题</li></ul></li></ul><h4 id="基本消息队列（官方提供API）"><a href="#基本消息队列（官方提供API）" class="headerlink" title="基本消息队列（官方提供API）"></a>基本消息队列（官方提供API）</h4><h5 id="消息发送流程"><a href="#消息发送流程" class="headerlink" title="消息发送流程"></a>消息发送流程</h5><ul><li>建立connection</li><li>创建channel</li><li>利用channel声明队列</li><li>利用channel向队列发送消息</li></ul><h5 id="基本消息队列的消息接收流程"><a href="#基本消息队列的消息接收流程" class="headerlink" title="基本消息队列的消息接收流程"></a>基本消息队列的消息接收流程</h5><ul><li>建立connection</li><li>创建channel</li><li>利用channel声明队列</li><li>定义consumer的消费行为handleDelivery()</li><li>利用channel将消费者与队列绑定</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla
      
    
    </summary>
    
    
      <category term="中间件" scheme="http://yoursite.com/categories/%E4%B8%AD%E9%97%B4%E4%BB%B6/"/>
    
    
      <category term="MQ" scheme="http://yoursite.com/tags/MQ/"/>
    
  </entry>
  
  <entry>
    <title>RabbitMQ的安装与基本概念</title>
    <link href="http://yoursite.com/2022/06/20/%E4%B8%AD%E9%97%B4%E4%BB%B6/MQ/RabbitMQ%E7%9A%84%E5%AE%89%E8%A3%85/"/>
    <id>http://yoursite.com/2022/06/20/%E4%B8%AD%E9%97%B4%E4%BB%B6/MQ/RabbitMQ%E7%9A%84%E5%AE%89%E8%A3%85/</id>
    <published>2022-06-20T02:37:13.000Z</published>
    <updated>2022-06-20T03:20:57.959Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">docker run \</span><br><span class="line">-e RABBITMQ_DEFAULT_USER=用户名 \</span><br><span class="line">-e RABBITMQ_DEFAULT_PASS=密码\</span><br><span class="line">--name mq \</span><br><span class="line">--hostname mq1 \</span><br><span class="line"><span class="meta">&gt;</span><span class="bash">p 15672:15672 \</span></span><br><span class="line">-p 5672:5672 \</span><br><span class="line">-d \</span><br><span class="line">rabbitmq:3-management</span><br></pre></td></tr></table></figure><h4 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h4><ul><li>channel：操作MQ的工具</li><li>exchange：路由消息到队列中</li><li>queue：缓存消息</li><li>virtual host：虚拟主机，是对queue、exchange等资源的逻辑分组</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla
      
    
    </summary>
    
    
      <category term="中间件" scheme="http://yoursite.com/categories/%E4%B8%AD%E9%97%B4%E4%BB%B6/"/>
    
    
      <category term="MQ" scheme="http://yoursite.com/tags/MQ/"/>
    
  </entry>
  
  <entry>
    <title>网站数据统计</title>
    <link href="http://yoursite.com/2022/06/16/%E7%89%9B%E5%AE%A2%E8%AE%A8%E8%AE%BA%E5%8C%BA%E9%A1%B9%E7%9B%AE/%E7%BD%91%E7%AB%99%E6%95%B0%E6%8D%AE%E7%BB%9F%E8%AE%A1/"/>
    <id>http://yoursite.com/2022/06/16/%E7%89%9B%E5%AE%A2%E8%AE%A8%E8%AE%BA%E5%8C%BA%E9%A1%B9%E7%9B%AE/%E7%BD%91%E7%AB%99%E6%95%B0%E6%8D%AE%E7%BB%9F%E8%AE%A1/</id>
    <published>2022-06-16T02:39:11.000Z</published>
    <updated>2022-06-16T10:41:14.501Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><ul><li>UV(Unique Visitor)<ul><li>独立访客，需通过用户IP排重统计数据</li><li>每次访问都要进行统计</li><li>HyperLogLog，性能好，存储空间小</li></ul></li><li>DAU(Daily Active User)<ul><li>日活跃用户，需通过用户ID排重统计数据</li><li>访问过一次，则认为其活跃</li><li>Bitmap，性能好、且可以精确统计结果</li></ul></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla
      
    
    </summary>
    
    
      <category term="牛客讨论区项目" scheme="http://yoursite.com/categories/%E7%89%9B%E5%AE%A2%E8%AE%A8%E8%AE%BA%E5%8C%BA%E9%A1%B9%E7%9B%AE/"/>
    
    
  </entry>
  
  <entry>
    <title>置顶、加精、删除</title>
    <link href="http://yoursite.com/2022/06/15/%E7%89%9B%E5%AE%A2%E8%AE%A8%E8%AE%BA%E5%8C%BA%E9%A1%B9%E7%9B%AE/%E7%BD%AE%E9%A1%B6%E3%80%81%E5%8A%A0%E7%B2%BE%E3%80%81%E5%88%A0%E9%99%A4/"/>
    <id>http://yoursite.com/2022/06/15/%E7%89%9B%E5%AE%A2%E8%AE%A8%E8%AE%BA%E5%8C%BA%E9%A1%B9%E7%9B%AE/%E7%BD%AE%E9%A1%B6%E3%80%81%E5%8A%A0%E7%B2%BE%E3%80%81%E5%88%A0%E9%99%A4/</id>
    <published>2022-06-15T08:52:11.000Z</published>
    <updated>2022-06-16T02:38:06.800Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><ul><li>功能实现<ul><li>点击置顶，修改帖子类型</li><li>点击加精、删除，修改帖子状态</li></ul></li><li>权限管理<ul><li>版主可以执行置顶、加精操作</li><li>管理员可以执行删除操作</li></ul></li><li>按钮显示<ul><li>版主可以看到置顶、加精按钮</li><li>管理员可以看到删除按钮</li></ul></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla
      
    
    </summary>
    
    
      <category term="牛客讨论区项目" scheme="http://yoursite.com/categories/%E7%89%9B%E5%AE%A2%E8%AE%A8%E8%AE%BA%E5%8C%BA%E9%A1%B9%E7%9B%AE/"/>
    
    
  </entry>
  
  <entry>
    <title>SpringSecurity入门</title>
    <link href="http://yoursite.com/2022/06/13/%E6%A1%86%E6%9E%B6/SpringSecurity/SpringSecurity%E5%85%A5%E9%97%A8/"/>
    <id>http://yoursite.com/2022/06/13/%E6%A1%86%E6%9E%B6/SpringSecurity/SpringSecurity%E5%85%A5%E9%97%A8/</id>
    <published>2022-06-13T08:57:30.000Z</published>
    <updated>2022-07-01T03:04:28.114Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h4 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h4><p>SpringSecurity是一个专注于为Java应用程序提供身份认证和授权的框架，它的强大之处在于它可以轻松扩展以满足自定义的需求</p><h4 id="特征"><a href="#特征" class="headerlink" title="特征"></a>特征</h4><ul><li>对身份的认证和授权提供全面的、可扩展的支持</li><li>防止各种攻击，如会话固定攻击、点击劫持、csrf攻击等</li><li>支持与Servlet API、Spring MVC等Web技术集成</li></ul><h4 id="用户权限管理"><a href="#用户权限管理" class="headerlink" title="用户权限管理"></a>用户权限管理</h4><ul><li><p>User实体类实现UserDetails接口</p><ul><li>isAccountNonExpired()方法：返回true，账号未过期</li><li>isAccountNonLocked()方法：返回true，账号未锁定</li><li>isCredentialsNonExpired()方法：返回true，凭证未过期</li><li>isEnabled()方法：返回true，账号可用</li><li>getAuthorities()方法：返回用户的权限集合，权限实现GrantedAuthority接口</li></ul></li><li><p>UserService实现UserDetailsService接口</p><ul><li>loudUserByUsername()方法：通过用户名查找用户</li></ul></li><li><p>SecurityConfig配置类，要求继承于WebSecurityConfigurerAdapter类</p><ul><li><p>configure(WebSecurity web)方法</p><ul><li>web.ignoring(),antMatchers(“资源路径”)：忽略静态资源访问</li></ul></li><li><p>configure(AuthenticationManagerBuilder auth)方法</p><ul><li>AuthenticationManager：认证核心接口</li><li>AuthenticationManagerBuilder：用于构建AuthenticationManager实例</li><li>ProviderManager：AuthenticationManager接口的默认实现类</li><li>AuthenticationProvider：每个ProviderManager持有一组AuthenticationProvider，每个AuthenticationProvider负责一种认证（委托模式）</li><li>Aythentication：用于封装认证信息的接口，不同实现类代表不同认证信息</li><li>内置认证规则：auth.userDetailsService(xxxService).passwordEncoder(内置密码加密方式);</li><li><strong>自定义认证规则：auth.authenticationProvider(new AuthenticationProvider())，实现 AuthenticationProvider的接口</strong><ul><li>authenticate()方法：实现认证逻辑，reutrn UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities())，信息、证书、权限</li><li>supports()方法：返回当前接口支持哪种认证类型，例如return UsernamePasswordAuthenticationToken.class.equals(aClass)。UsernamePasswordAuthenticationToken：Aythentication常用实现类，代表账号密码认证</li></ul></li></ul></li><li><p>configure(HttpSecurity http)方法，登陆相关配置</p><ul><li><p>http.formLogin().loginPage()</p><p>.loginProcessingUrl()</p><p>.successHandler(new AuthenticationSuccessHandler())</p><p>.failureHandler(new AuthenticationFailureHandler())</p></li><li><p>退出相关配置：</p></li></ul><p>​     http.logout().logoutUrl().logoutSuccessHandler()</p><ul><li>授权配置</li></ul><p>​     http.authorizeRequests()</p><p>​     .antMatchers(“路径”).hasAnyAuthority(权限，权限)</p><p>​     .and().exceptionHandling().accessDeniedPage(“权限不足页面”)</p><ul><li>增加Filter，处理验证码</li></ul><p>​     http.addFilterBefore(new Filter())</p><ul><li>记住我功能</li></ul><p>​     http.rememberMe()</p></li></ul></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla
      
    
    </summary>
    
    
      <category term="框架" scheme="http://yoursite.com/categories/%E6%A1%86%E6%9E%B6/"/>
    
      <category term="SpringSecurity" scheme="http://yoursite.com/categories/%E6%A1%86%E6%9E%B6/SpringSecurity/"/>
    
    
  </entry>
  
  <entry>
    <title>常见MQ</title>
    <link href="http://yoursite.com/2022/06/12/%E4%B8%AD%E9%97%B4%E4%BB%B6/MQ/%E5%B8%B8%E8%A7%81MQ/"/>
    <id>http://yoursite.com/2022/06/12/%E4%B8%AD%E9%97%B4%E4%BB%B6/MQ/%E5%B8%B8%E8%A7%81MQ/</id>
    <published>2022-06-12T06:03:13.000Z</published>
    <updated>2022-06-12T06:09:15.176Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><div class="table-container"><table><thead><tr><th></th><th>RabbitMQ</th><th>ActiveMQ</th><th>RocketMQ</th><th>Kafka</th></tr></thead><tbody><tr><td>公司/社区</td><td>Rabbit</td><td>Apache</td><td>阿里/Apache</td><td>Apache</td></tr><tr><td>开发语言</td><td>Erlang</td><td>Java</td><td>Java</td><td>Scala&amp;Java</td></tr><tr><td>协议支持</td><td>AMQP,XMPP,SMTP,STOMP</td><td>OpenWire,STOMP,REST,XMPP,AMQP</td><td>自定义协议</td><td>自定义协议</td></tr><tr><td>可用性</td><td>高</td><td>一般</td><td>高</td><td>高</td></tr><tr><td>单机吞吐量</td><td>一般</td><td>差</td><td>高</td><td>非常高</td></tr><tr><td>消息延迟</td><td>微秒级</td><td>毫秒级</td><td>毫秒级</td><td>毫秒以内</td></tr><tr><td>消息可靠性</td><td>高</td><td>一般</td><td>高</td><td>一般</td></tr></tbody></table></div>]]></content>
    
    <summary type="html">
    
      
      
        &lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla
      
    
    </summary>
    
    
      <category term="中间件" scheme="http://yoursite.com/categories/%E4%B8%AD%E9%97%B4%E4%BB%B6/"/>
    
    
      <category term="MQ" scheme="http://yoursite.com/tags/MQ/"/>
    
  </entry>
  
  <entry>
    <title>同步调用与异步调用</title>
    <link href="http://yoursite.com/2022/06/12/%E4%B8%AD%E9%97%B4%E4%BB%B6/MQ/%E5%90%8C%E6%AD%A5%E8%B0%83%E7%94%A8%E4%B8%8E%E5%BC%82%E6%AD%A5%E8%B0%83%E7%94%A8/"/>
    <id>http://yoursite.com/2022/06/12/%E4%B8%AD%E9%97%B4%E4%BB%B6/MQ/%E5%90%8C%E6%AD%A5%E8%B0%83%E7%94%A8%E4%B8%8E%E5%BC%82%E6%AD%A5%E8%B0%83%E7%94%A8/</id>
    <published>2022-06-12T05:47:13.000Z</published>
    <updated>2022-06-12T06:01:56.666Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h4 id="同步调用存在的问题"><a href="#同步调用存在的问题" class="headerlink" title="同步调用存在的问题"></a>同步调用存在的问题</h4><ul><li>耦合度高</li><li>性能下降</li><li>资源浪费</li><li>级联失败</li></ul><h4 id="异步调用"><a href="#异步调用" class="headerlink" title="异步调用"></a>异步调用</h4><ul><li>异步调用常见实现是事件驱动模式</li><li>优势<ul><li>服务解耦</li><li>性能提升，吞吐量提高</li><li>服务没有强依赖，不担心级联失败问题，故障隔离</li><li>流量削峰（缓冲）</li></ul></li><li>缺点<ul><li>依赖于Broker的可靠性、安全性、吞吐能力</li><li>架构复杂，业务没有明显的流程线，不好追踪管理</li></ul></li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla
      
    
    </summary>
    
    
      <category term="中间件" scheme="http://yoursite.com/categories/%E4%B8%AD%E9%97%B4%E4%BB%B6/"/>
    
    
      <category term="MQ" scheme="http://yoursite.com/tags/MQ/"/>
    
  </entry>
  
  <entry>
    <title>Docker镜像仓库</title>
    <link href="http://yoursite.com/2022/06/11/%E5%B7%A5%E5%85%B7/Docker/Docker%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93/"/>
    <id>http://yoursite.com/2022/06/11/%E5%B7%A5%E5%85%B7/Docker/Docker%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93/</id>
    <published>2022-06-11T14:10:42.000Z</published>
    <updated>2022-06-12T05:39:20.237Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h4 id="常见镜像仓库服务"><a href="#常见镜像仓库服务" class="headerlink" title="常见镜像仓库服务"></a>常见镜像仓库服务</h4><p>镜像仓库有公有和私有的两种形式</p><ul><li>公共仓库：官方的Docker Hub，网易云镜像，DaoCloud镜像，阿里云镜像等。</li><li>本地搭建私有Docker Registry</li></ul><h4 id="创建私有镜像仓库（可视化界面）"><a href="#创建私有镜像仓库（可视化界面）" class="headerlink" title="创建私有镜像仓库（可视化界面）"></a>创建私有镜像仓库（可视化界面）</h4><h5 id="配置Docker信任地址"><a href="#配置Docker信任地址" class="headerlink" title="配置Docker信任地址"></a>配置Docker信任地址</h5><p>我们的私服采用的是http协议，默认不被Docker信任，所以需要做一个配置：</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 打开要修改的文件</span></span><br><span class="line">vi /etc/docker/daemon.json</span><br><span class="line"><span class="comment"># 添加内容：</span></span><br><span class="line"><span class="string">"insecure-registries"</span>:[<span class="string">"http://&#123;ip地址&#125;:8080"</span>]</span><br><span class="line"><span class="comment"># 重加载</span></span><br><span class="line">systemctl daemon-reload</span><br><span class="line"><span class="comment"># 重启docker</span></span><br><span class="line">systemctl restart docker</span><br></pre></td></tr></table></figure><h5 id="使用DockerCompose部署带有图象界面的DockerRegistry"><a href="#使用DockerCompose部署带有图象界面的DockerRegistry" class="headerlink" title="使用DockerCompose部署带有图象界面的DockerRegistry"></a>使用DockerCompose部署带有图象界面的DockerRegistry</h5><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">version:</span> <span class="string">'3.0'</span></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">registry:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">registry</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./registry-data:/var/lib/registry</span></span><br><span class="line">  <span class="attr">ui:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">joxit/docker-registry-ui:static</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="number">8080</span><span class="string">:80</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">REGISTRY_TITLE=私有仓库1</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">REGISTRY_URL=http://registry:5000</span></span><br><span class="line">    <span class="attr">depends_on:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">registry</span></span><br></pre></td></tr></table></figure><h5 id="在私有镜像仓库推送或拉取镜像"><a href="#在私有镜像仓库推送或拉取镜像" class="headerlink" title="在私有镜像仓库推送或拉取镜像"></a>在私有镜像仓库推送或拉取镜像</h5><ul><li>重新tag本地镜像，名称前缀为私有仓库地址</li></ul><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker tag nginx:latest 116.62.168.80:8081/nginx:1.0</span><br></pre></td></tr></table></figure><ul><li>推送镜像</li></ul><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker push 116.62.168.80:8081/nginx:1.0</span><br></pre></td></tr></table></figure><ul><li>拉取镜像</li></ul><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker pull 116.62.168.80:8081/nginx:1.0</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla
      
    
    </summary>
    
    
      <category term="工具" scheme="http://yoursite.com/categories/%E5%B7%A5%E5%85%B7/"/>
    
    
  </entry>
  
  <entry>
    <title>DockerCompose</title>
    <link href="http://yoursite.com/2022/06/11/%E5%B7%A5%E5%85%B7/Docker/DockerCompose/"/>
    <id>http://yoursite.com/2022/06/11/%E5%B7%A5%E5%85%B7/Docker/DockerCompose/</id>
    <published>2022-06-11T10:18:42.000Z</published>
    <updated>2022-06-11T14:10:19.360Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" class="aplayer-secondary-style-marker" href="\assets\css\APlayer.min.css"><script src="\assets\js\APlayer.min.js" class="aplayer-secondary-script-marker"></script><script class="meting-secondary-script-marker" src="\assets\js\Meting.min.js"></script><h4 id="什么是DockerCompose"><a href="#什么是DockerCompose" class="headerlink" title="什么是DockerCompose"></a>什么是DockerCompose</h4><ul><li>DockerCompose可以基于Compose文件帮用户快速部署分布式应用，而无需手动一个个创建和运行容器</li><li>Compose文件是一个文本文件，通过指令定义集群中每个容器如何运行</li></ul><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">version:</span> <span class="string">"3.2"</span></span><br><span class="line"></span><br><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">nacos:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">nacos/nacos-server</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">MODE:</span> <span class="string">standalone</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">"8848:8848"</span></span><br><span class="line">  <span class="attr">mysql:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">mysql:5.7.25</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="attr">MYSQL_ROOT_PASSWORD:</span> <span class="number">123456</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">"$PWD/mysql/data:/var/lib/mysql"</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">"$PWD/mysql/conf:/etc/mysql/conf.d/"</span></span><br><span class="line">  <span class="attr">userservice:</span></span><br><span class="line">    <span class="attr">build:</span> <span class="string">./user-service</span></span><br><span class="line">  <span class="attr">orderservice:</span></span><br><span class="line">    <span class="attr">build:</span> <span class="string">./order-service</span></span><br><span class="line">  <span class="attr">gateway:</span></span><br><span class="line">    <span class="attr">build:</span> <span class="string">./gateway</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">"10010:10010"</span></span><br></pre></td></tr></table></figure><h4 id="可以看到，其中包含5个service服务："><a href="#可以看到，其中包含5个service服务：" class="headerlink" title="可以看到，其中包含5个service服务："></a>可以看到，其中包含5个service服务：</h4><ul><li><code>nacos</code>：作为注册中心和配置中心<ul><li><code>image: nacos/nacos-server</code>： 基于nacos/nacos-server镜像构建</li><li><code>environment</code>：环境变量<ul><li><code>MODE: standalone</code>：单点模式启动</li></ul></li><li><code>ports</code>：端口映射，这里暴露了8848端口</li></ul></li><li><code>mysql</code>：数据库<ul><li><code>image: mysql:5.7.25</code>：镜像版本是mysql:5.7.25</li><li><code>environment</code>：环境变量<ul><li><code>MYSQL_ROOT_PASSWORD: 123456</code>：设置数据库root账户的密码</li></ul></li><li><code>volumes</code>：数据卷挂载，这里挂载了mysql的data、conf目录，其中有我提前准备好的数据</li></ul></li><li><code>userservice</code>、<code>orderservice</code>、<code>gateway</code>：都是基于Dockerfile临时构建的</li></ul><ul><li>修改cloud-demo项目，将数据库、nacos地址都命名为docker-compose中的服务名</li><li>使用maven打包工具，将项目中的每个微服务都打包为app.jar</li><li>将打包好的app.jar拷贝到cloud-demo中的每一个对应子目录中</li><li>将cloud-demo上传至虚拟机，利用docker-compose up -d来部署</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;link rel=&quot;stylesheet&quot; class=&quot;aplayer-secondary-style-marker&quot; href=&quot;\assets\css\APlayer.min.css&quot;&gt;&lt;script src=&quot;\assets\js\APlayer.min.js&quot; cla
      
    
    </summary>
    
    
      <category term="工具" scheme="http://yoursite.com/categories/%E5%B7%A5%E5%85%B7/"/>
    
    
  </entry>
  
</feed>
