<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Ruofeng's Blog]]></title><description><![CDATA[Ruofeng's Blog]]></description><link>https://ruofeng.me/</link><image><url>https://ruofeng.me/favicon.png</url><title>Ruofeng&apos;s Blog</title><link>https://ruofeng.me/</link></image><generator>Ghost 4.19</generator><lastBuildDate>Tue, 10 Mar 2026 15:12:02 GMT</lastBuildDate><atom:link href="https://ruofeng.me/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Kubernetes 源码阅读 - HPA 原理]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>K8s &#x7684; HPA (Horizontal Pod Autoscaler) &#x81EA;&#x52A8;&#x6269;&#x7F29;&#x5BB9;&#x5728; kube-controller-manager &#x4E2D;&#x7684; HPA Controller &#x4E2D;&#x5B9E;&#x73B0;&#xFF0C;&#x5B83;&#x901A;&#x8FC7; APIServer &#x7684; <code>*metrics.k8s.io</code> APISerice &#x8BBF;&#x95EE; &#x5404;&#x79CD; metrics &#x63D0;&#x4F9B;&#x8005;&#xFF0C;&#x5176;&#x4E2D;&#x57FA;&#x7840; CPU &#x5185;&#x5B58; &#x7684; resource metrics &#x7531;</p>]]></description><link>https://ruofeng.me/2021/07/28/k8s-hpa-controller/</link><guid isPermaLink="false">61121dda74599b0001da31a6</guid><category><![CDATA[k8s]]></category><category><![CDATA[autoscaling]]></category><dc:creator><![CDATA[Ruofeng Lei]]></dc:creator><pubDate>Wed, 28 Jul 2021 06:34:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>K8s &#x7684; HPA (Horizontal Pod Autoscaler) &#x81EA;&#x52A8;&#x6269;&#x7F29;&#x5BB9;&#x5728; kube-controller-manager &#x4E2D;&#x7684; HPA Controller &#x4E2D;&#x5B9E;&#x73B0;&#xFF0C;&#x5B83;&#x901A;&#x8FC7; APIServer &#x7684; <code>*metrics.k8s.io</code> APISerice &#x8BBF;&#x95EE; &#x5404;&#x79CD; metrics &#x63D0;&#x4F9B;&#x8005;&#xFF0C;&#x5176;&#x4E2D;&#x57FA;&#x7840; CPU &#x5185;&#x5B58; &#x7684; resource metrics &#x7531; metrics-server &#x7EC4;&#x4EF6;&#x63D0;&#x4F9B;&#xFF0C;&#x5B83;&#x4F1A;&#x5B9A;&#x65F6;&#x67E5;&#x8BE2;&#x5404;&#x4E2A;&#x8282;&#x70B9; kubelet &#x7F29;&#x66B4;&#x9732;&#x7684;&#x5BB9;&#x5668;&#x76D1;&#x63A7;&#x6570;&#x636E;&#x5E76;&#x4FDD;&#x5B58;&#x5230;&#x5185;&#x5B58;&#x4E2D;&#x4EE5;&#x4F9B;&#x83B7;&#x53D6;&#xFF0C;&#x9664; HPA &#x5916;&#xFF0C;<code>kubectl top</code> &#x547D;&#x4EE4;&#x4E5F;&#x4F9D;&#x8D56;&#x5B83;&#x3002;</p>
<p>HPA &#x67B6;&#x6784;&#x56FE;&#x5982;&#x4E0B;&#xFF1A;</p>
<p><img src="https://img.ruofeng.me/file/ruofengimg/2021-08/4dQKCN-qJ4ubu.png" alt="HPA Controller" loading="lazy"></p>
<h2 id="newhorizontalcontroller"><code>NewHorizontalController</code></h2>
<p>HPA Controller &#x4F7F;&#x7528;&#x7684; informer &#x6709;&#x4E24;&#x4E2A;</p>
<ul>
<li><code>hpaInformer</code></li>
<li><code>podInformer</code></li>
</ul>
<p>&#x5176;&#x4E2D; <code>hpaInformer</code> &#x6709; EventHandler&#xFF0C;&#x7528;&#x4E8E;&#x76D1;&#x542C; HPA &#x53D8;&#x5316;&#x5B9A;&#x65F6;&#x6293;&#x53D6; metrics &#x8BA1;&#x7B97;&#x9884;&#x671F;&#x7684;&#x5B9E;&#x4F8B;&#x6570;&#x91CF;&#xFF0C;<code>podInformer</code> &#x4EC5;&#x7528;&#x4E8E; list</p>
<h2 id="run">Run</h2>
<p>&#x548C;&#x5176;&#x4ED6; Controller &#x65E0;&#x5F02;&#xFF0C;&#x542F;&#x52A8; worker &#x5E76;&#x4ECE; workqueue &#x4E2D;&#x53D6;&#x51FA;&#x4EFB;&#x52A1;&#x6267;&#x884C;&#xFF0C;&#x4F46;&#x5BF9;&#x4E8E; HPA Controller&#xFF0C;&#x6709;&#x4E24;&#x70B9;&#x4E0D;&#x540C;&#x4E4B;&#x5904;</p>
<ul>
<li>&#x542F;&#x52A8;&#x7684; worker &#x53EA;&#x6709;&#x4E00;&#x4E2A;</li>
<li>workqueue &#x662F;&#x4E00;&#x4E2A;&#x56FA;&#x5B9A;&#x65F6;&#x95F4;&#x53C2;&#x6570;&#xFF08;&#x9ED8;&#x8BA4; 15s&#xFF0C;&#x4E5F;&#x5C31;&#x662F; HPA &#x7684;&#x8BC4;&#x4F30;&#x8BC4;&#x7387;&#xFF09;&#x7684;&#x9650;&#x901F;&#x961F;&#x5217;&#xFF0C;&#x4EE5;&#x5B9E;&#x73B0;&#x7C7B;&#x4F3C; Ticker &#x5B9A;&#x65F6;&#x6267;&#x884C;&#x7684;&#x6548;&#x679C;</li>
</ul>
<p>worker &#x5DE5;&#x4F5C;&#x903B;&#x8F91;</p>
<pre><code class="language-go">func (a *HorizontalController) processNextWorkItem() bool {
	key, quit := a.queue.Get()
	if quit {
		return false
	}
	defer a.queue.Done(key)
	deleted, err := a.reconcileKey(key.(string))
	if err != nil {
		utilruntime.HandleError(err)
	}
	// &#x5468;&#x671F;&#x6027;&#x5BF9; HPA &#x8FDB;&#x884C;&#x6269;&#x7F29;&#x5BB9;&#x5224;&#x65AD;&#x7684;&#x5B9E;&#x73B0;&#xFF0C;processNextWorkItem &#x6BCF;&#x5904;&#x7406;&#x5B8C;&#x4E00;&#x4E2A; HPA &#x5BF9;&#x8C61;
	// &#x82E5;&#x6B64;&#x5BF9;&#x8C61;&#x672A;&#x88AB;&#x5220;&#x9664;&#xFF0C;&#x5219;&#x7EE7;&#x7EED;&#x6DFB;&#x52A0;&#x5230; RateLimited &#x961F;&#x5217;&#x4E2D;&#x7B49;&#x5F85;&#x4E0B;&#x4E00;&#x6B21;&#x6267;&#x884C;
	if !deleted {
		a.queue.AddRateLimited(key)
	}
	return true
}
</code></pre>
<p>&#x4ECE;&#x961F;&#x5217;&#x4E2D;&#x53D6;&#x5F97;&#x4E00;&#x4E2A; HPA &#x5BF9;&#x8C61;&#x5728;&#x65B9;&#x6CD5; <code>reconcileKey</code> &#x4E2D;&#x8BC4;&#x4F30;&#x6267;&#x884C;&#x6269;&#x7F29;&#x5BB9;&#xFF0C;&#x8FD4;&#x56DE;&#x4E86;&#x4E00;&#x4E2A; delete &#x8868;&#x793A;&#x8BE5; HPA &#x5BF9;&#x8C61;&#x662F;&#x5426;&#x88AB;&#x5220;&#x9664;&#xFF0C;&#x82E5;&#x672A;&#x88AB;&#x5220;&#x9664;&#x5219;<strong>&#x5904;&#x7406;&#x5B8C;&#x540E;&#x7EE7;&#x7EED;&#x6DFB;&#x52A0;</strong>&#x5230;&#x8FD9;&#x4E2A; rateLimit &#x961F;&#x5217;&#x4E2D;&#xFF0C;&#x7B49;&#x5F85;&#x4E0B;&#x4E00;&#x4E2A;&#x65F6;&#x95F4;&#x5468;&#x671F;&#x5230;&#x6765;&#x540E;&#x53D6;&#x51FA;&#x518D;&#x6B21;&#x6267;&#x884C;&#x3002;</p>
<h2 id="hpa">&#x5982;&#x4F55;&#x8BA1;&#x7B97; HPA &#x63A8;&#x8350;&#x7684;&#x5B9E;&#x4F8B;&#x6570;&#x91CF;</h2>
<p>&#x6574;&#x4F53;&#x5224;&#x65AD;&#x903B;&#x8F91;&#x4E3B;&#x8981;&#x6709;&#x56DB;&#x6B65;</p>
<ol>
<li>&#x5B9E;&#x4F8B;&#x6570;&#x91CF;&#x4E3A; 0 &#x65F6;&#x4E0D;&#x8FDB;&#x884C;&#x5224;&#x65AD;&#xFF0C;&#x7981;&#x7528;&#x81EA;&#x52A8;&#x6269;&#x7F29;&#x5BB9;&#xFF0C;&#x56E0;&#x6B64;&#x539F;&#x751F; HPA &#x4E0D;&#x9002;&#x7528;&#x4E8E; Scale From Zero</li>
<li>&#x5B9E;&#x4F8B;&#x6570;&#x91CF;&#x5927;&#x4E8E; max &#x65F6;&#xFF0C;&#x7F29;&#x5BB9;&#x5230;&#x4E0A;&#x9650;</li>
<li>&#x5B9E;&#x4F8B;&#x6570;&#x91CF;&#x5C0F;&#x4E8E; min &#x65F6;&#xFF0C;&#x6269;&#x5BB9;&#x5230;&#x4E0B;&#x9650;</li>
<li>&#x901A;&#x8FC7; HPA &#x6307;&#x5B9A;&#x7684; Metrics &#x8BA1;&#x7B97;&#x671F;&#x671B;&#x5B9E;&#x4F8B;&#x6570;&#x91CF;</li>
</ol>
<pre><code class="language-go">// 1. &#x5F53;&#x524D;&#x5B9E;&#x4F8B;&#x6570;&#x91CF;&#x4E3A; 0&#xFF0C;&#x4F46;&#x662F; HPA min &#x4E0D;&#x4E3A;&#x96F6;&#x65F6;&#xFF0C;&#x7981;&#x7528;&#x6B64; HPA &#x505C;&#x6B62;&#x81EA;&#x52A8;&#x6269;&#x7F29;&#x5BB9;
if scale.Spec.Replicas == 0 &amp;&amp; minReplicas != 0 {
	// Autoscaling is disabled for this resource
	desiredReplicas = 0
	rescale = false
} else if currentReplicas &gt; hpa.Spec.MaxReplicas {
	// 2. &#x5F53;&#x524D;&#x5B9E;&#x4F8B;&#x6570;&#x91CF;&#x5927;&#x4E8E; HPA max &#x65F6;&#xFF0C;&#x7F29;&#x5BB9;&#x5230;&#x4E0A;&#x9650;
	desiredReplicas = hpa.Spec.MaxReplicas
} else if currentReplicas &lt; minReplicas {
	// 3. &#x5F53;&#x524D;&#x5B9E;&#x4F8B;&#x6570;&#x91CF;&#x5C0F;&#x4E8E; HPA min &#x65F6;&#xFF0C;&#x6269;&#x5BB9;&#x5230;&#x4E0B;&#x9650;
	desiredReplicas = minReplicas
} else {
	var metricTimestamp time.Time
	// 4. &#x901A;&#x8FC7;&#x6307;&#x5B9A;&#x7684; metrics &#x8BA1;&#x7B97;&#x51FA;&#x671F;&#x671B;&#x7684;&#x5B9E;&#x4F8B;&#x6570;&#x91CF; metricDesiredReplicas
	// &#x4F46;&#x8FD8;&#x5E76;&#x4E0D;&#x662F;&#x6700;&#x7EC8;&#x51B3;&#x5B9A;&#x671F;&#x671B;&#x7684;&#x6570;&#x91CF;&#xFF0C;&#x76EE;&#x524D;&#x671F;&#x671B;&#x7ED3;&#x679C; desiredReplicas &#x8FD8;&#x662F; 0
	metricDesiredReplicas, metricName, metricStatuses, metricTimestamp, err = a.computeReplicasForMetrics(hpa, scale, hpa.Spec.Metrics)
	//...
}
</code></pre>
<p>&#x901A;&#x8FC7; Metrics &#x8BA1;&#x7B97;&#x671F;&#x671B;&#x5B9E;&#x4F8B;&#x6570;&#x91CF;&#x65F6;&#xFF0C;&#x4F1A;&#x8BA1;&#x7B97; HPA &#x4E2D;&#x5B9A;&#x4E49;&#x7684;&#x6240;&#x6709; Metric &#x7C7B;&#x578B;&#xFF0C;&#x5E76;&#x53D6;&#x51FA;&#x5176;&#x4E2D;&#x5F97;&#x5230;&#x6700;&#x9AD8;&#x6570;&#x91CF;&#x7684;&#x5B9E;&#x4F8B;&#x6570;&#x4F5C;&#x4E3A;&#x672C;&#x6B21;&#x63A8;&#x8350;&#x503C;&#x7684;&#x8BA1;&#x7B97;&#x7ED3;&#x679C;&#xFF1A;</p>
<pre><code class="language-go">for i, metricSpec := range metricSpecs {
	replicaCountProposal, metricNameProposal, timestampProposal, condition, err := a.computeReplicasForMetric(hpa, metricSpec, specReplicas, statusReplicas, selector, &amp;statuses[i])

	if err != nil {
		if invalidMetricsCount &lt;= 0 {
			invalidMetricCondition = condition
			invalidMetricError = err
		}
		invalidMetricsCount++
	}
	// &#x53D6;&#x6240;&#x6709; metrics &#x7ED3;&#x679C;&#x7684;&#x6700;&#x5927;&#x503C;
	if err == nil &amp;&amp; (replicas == 0 || replicaCountProposal &gt; replicas) {
		timestamp = timestampProposal
		replicas = replicaCountProposal
		metric = metricNameProposal
	}
}
</code></pre>
<h2 id>&#x7F29;&#x5BB9;&#x7A33;&#x5B9A;&#x7A97;&#x53E3;</h2>
<p>HPA &#x5728;&#x6267;&#x884C;&#x6269;&#x5BB9;&#x65F6;&#xFF0C;&#x82E5;&#x6B64;&#x6B21;&#x8BA1;&#x7B97;&#x51FA;&#x7684;&#x5B9E;&#x4F8B;&#x6570;&#x91CF;&#x5927;&#x4E8E;&#x5F53;&#x524D;&#x5B9E;&#x4F8B;&#x6570;&#xFF0C;&#x5219;&#x4F1A;&#x7ACB;&#x5373;&#x89E6;&#x53D1;&#x6269;&#x5BB9;&#xFF0C;&#x4F46;&#x7F29;&#x5BB9;&#x5E76;&#x4E0D;&#x662F;&#x4F4E;&#x4E8E;&#x5F53;&#x524D;&#x5B9E;&#x4F8B;&#x6570;&#x91CF;&#x5C31;&#x7ACB;&#x5373;&#x89E6;&#x53D1;&#xFF0C;&#x4E3A;&#x4E86;&#x907F;&#x514D; Pod &#x8D44;&#x6E90;&#x5229;&#x7528;&#x7387;&#x7684;&#x5E38;&#x89C4;&#x6296;&#x52A8;&#x800C;&#x9891;&#x7E41;&#x8FDB;&#x884C;&#x6269;&#x7F29;&#x5BB9;&#xFF0C;&#x53EF;&#x6307;&#x5B9A; <code>downscaleStabilisationWindow</code> <strong>&#x7F29;&#x5BB9;&#x7A33;&#x5B9A;&#x7A97;&#x53E3;</strong> &#x53C2;&#x6570;&#x6765;&#x8FDB;&#x884C;&#x7A33;&#x5B9A;&#x3002;&#x5177;&#x4F53;&#x539F;&#x7406;&#x662F;&#xFF0C;&#x6BCF;&#x6B21;&#x8BC4;&#x4F30;&#x5B8C;&#x63A8;&#x8350;&#x503C;&#x65F6;&#x4E0D;&#x4F1A;&#x76F4;&#x63A5;&#x4F7F;&#x7528;&#x6B64;&#x63A8;&#x8350;&#x503C;&#x8FDB;&#x884C;&#x6269;&#x7F29;&#x5BB9;&#x64CD;&#x4F5C;&#xFF0C;&#x800C;&#x662F;&#x9700;&#x8981;&#x6839;&#x636E;&#x5386;&#x53F2;&#x7684;&#x63A8;&#x8350;&#x503C;&#x8BB0;&#x5F55;&#x91CD;&#x65B0;&#x8BC4;&#x4F30;&#x4E00;&#x904D;&#xFF0C;<strong>&#x4FDD;&#x8BC1;&#x6B64;&#x6B21;&#x4F7F;&#x7528;&#x7684;&#x63A8;&#x8350;&#x5B9E;&#x4F8B;&#x6570;&#x4E0D;&#x4F1A;&#x4F4E;&#x4E8E;&#x5386;&#x53F2;&#x7A33;&#x5B9A;&#x7A97;&#x53E3;&#x5185;&#x4EFB;&#x4F55;&#x4E00;&#x6B21;&#x5386;&#x53F2;&#x63A8;&#x8350;&#x503C;</strong>&#xFF0C;&#x5373;<strong>&#x53D6;&#x7A97;&#x53E3;&#x5185;&#x7684;&#x5386;&#x53F2;&#x6700;&#x9AD8;&#x503C;</strong>&#x3002;</p>
<p>&#x5728; HPA Controller &#x4F7F;&#x7528;&#x4E00;&#x4E2A; <code>recommendations</code> map &#x4FDD;&#x5B58;&#x5386;&#x53F2;&#x7684;&#x6269;&#x7F29;&#x5BB9;&#x8BA1;&#x7B97;&#x63A8;&#x8350;&#x503C;</p>
<pre><code class="language-go">recommendations map[string][]timestampedRecommendation

type timestampedRecommendation struct {
	recommendation int32
	timestamp      time.Time
}
</code></pre>
<p>&#x5B9E;&#x73B0;&#x7A33;&#x5B9A;&#x6269;&#x7F29;&#x5BB9;&#x7684;&#x65B9;&#x6CD5;&#x4E3A; <code>stabilizeRecommendation</code>&#xFF0C;&#x4E3B;&#x8981;&#x6709;&#x4E24;&#x4E2A;&#x903B;&#x8F91;</p>
<ol>
<li>&#x5224;&#x65AD;&#x7A33;&#x5B9A;&#x7A97;&#x53E3;&#x5185;&#x6240;&#x6709;&#x5386;&#x53F2;&#x63A8;&#x8350;&#x503C;&#xFF0C;&#x53D6;&#x6700;&#x5927;&#x503C;&#x4F5C;&#x4E3A;&#x672C;&#x6B21;&#x7684;&#x63A8;&#x8350;</li>
<li>&#x5C06;&#x7A33;&#x5B9A;&#x7A97;&#x53E3;&#x524D;&#x6700;&#x65E7;&#x7684;&#x63A8;&#x8350;&#x503C;&#x66FF;&#x6362;&#x4E3A;&#x8BA1;&#x7B97;&#x51FA;&#x6765;&#x6700;&#x65B0;&#x7684;&#x63A8;&#x8350;&#x503C;&#xFF0C;&#x8F6E;&#x8F6C;&#x907F;&#x514D;&#x5386;&#x53F2;&#x6570;&#x636E;&#x65E0;&#x9650;&#x589E;&#x957F;&#x6D88;&#x8017;&#x5185;&#x5B58;</li>
</ol>
<pre><code class="language-go">func (a *HorizontalController) stabilizeRecommendation(key string, prenormalizedDesiredReplicas int32) int32 {
	maxRecommendation := prenormalizedDesiredReplicas
	foundOldSample := false
	oldSampleIndex := 0
	cutoff := time.Now().Add(-a.downscaleStabilisationWindow)
	for i, rec := range a.recommendations[key] {
		if rec.timestamp.Before(cutoff) {
			// &#x7A97;&#x53E3;&#x65F6;&#x95F4;&#x4E4B;&#x524D;&#x7684;&#x6570;&#x636E;&#xFF08;&#x65E7;&#x6570;&#x636E;&#xFF09;
			foundOldSample = true
			oldSampleIndex = i
		} else if rec.recommendation &gt; maxRecommendation {
			// &#x7A97;&#x53E3;&#x65F6;&#x95F4;&#x5185;&#x7684;&#x6570;&#x636E;&#xFF0C;&#x6BCF;&#x4E00;&#x4E2A;&#x5747;&#x9700;&#x8981;&#x5224;&#x65AD;&#x662F;&#x5426;&#x6BD4;&#x6B64;&#x6B21;&#x63A8;&#x8350;&#x6570;&#x636E;&#x5927;&#xFF0C;&#x82E5;&#x5B58;&#x5728;&#x66F4;&#x5927;&#x7684;&#x5219;&#x53D6;&#x5386;&#x53F2;&#x4E2D;&#x6700;&#x5927;&#x7684;&#x90A3;&#x6761;
			// max(currentRec, historyRec...)
			maxRecommendation = rec.recommendation
		}
	}
	if foundOldSample {
		// &#x66FF;&#x6362;&#x7A97;&#x53E3;&#x5916;&#x4E0D;&#x9700;&#x8981;&#x7684;&#x65E7;&#x6570;&#x636E;&#x4E3A;&#x6700;&#x65B0;&#x4E00;&#x6B21;&#x7684;&#x63A8;&#x8350;&#x503C;
		a.recommendations[key][oldSampleIndex] = timestampedRecommendation{prenormalizedDesiredReplicas, time.Now()}
	} else {
		a.recommendations[key] = append(a.recommendations[key], timestampedRecommendation{prenormalizedDesiredReplicas, time.Now()})
	}
	return maxRecommendation
}
</code></pre>
<h2 id>&#x4E24;&#x4E2A;&#x53C2;&#x6570;</h2>
<p>Pod &#x5728;&#x5176;&#x751F;&#x547D;&#x5468;&#x671F;&#x4E2D;&#x968F;&#x65F6;&#x53EF;&#x80FD;&#x4F1A;&#x6709;&#x5404;&#x79CD;&#x72B6;&#x6001;&#x7684;&#x53D8;&#x5316;&#xFF0C;&#x4EE5;&#x4E0B;&#x4E24;&#x4E2A;&#x53C2;&#x6570;&#x51B3;&#x5B9A;&#x4E86; Pod &#x54EA;&#x4E9B;&#x72B6;&#x6001;&#x7684; Pod &#x4E0D;&#x4F1A;&#x88AB;&#x7EB3;&#x5165; HPA &#x7684;&#x8BA1;&#x7B97;&#x4E2D;</p>
<ul>
<li><code>cpuInitializationPeriod</code> <strong>Default: 5m0s</strong> <em>The period after pod start when CPU samples might be skipped.</em></li>
<li><code>delayOfInitialReadinessStatus</code> <strong>Default: 30s</strong> <em>The period after pod start during which readiness changes will be treated as initial readiness.</em></li>
</ul>
<p>&#x76F8;&#x5173; PR&#xFF1A;<a href="https://github.com/kubernetes/kubernetes/pull/68068">kubernetes/kubernetes#68068</a> &#x4E2D;&#x8BF4;&#x660E;&#xFF0C;&#x5FFD;&#x7565;&#x4EE5;&#x4E0B;&#x60C5;&#x51B5;&#x7684; Pod</p>
<ul>
<li>Pod is beeing initalized - 5 minutes from start defined by flag</li>
<li>Pod is unready</li>
<li>Pod is ready but full window of metric hasn&apos;t been colected since transition</li>
<li>Pod is initialized - 5 minutes from start defined by flag:</li>
<li>Pod has never been ready after initial readiness period.</li>
</ul>
<p>&#x4F46;&#x662F;&#x5176;&#x63CF;&#x8FF0;&#x7684;&#x8BF4;&#x6CD5;&#x5E76;&#x4E0D;&#x592A;&#x51C6;&#x786E;&#xFF0C;&#x901A;&#x8FC7;&#x9605;&#x8BFB;&#x6E90;&#x7801;&#x5F97;&#x77E5;&#xFF0C;<code>cpuInitializationPeriod</code> (5min) &#x53C2;&#x6570;&#x5C06; Pod &#x751F;&#x547D;&#x5468;&#x671F;&#x5206;&#x4E3A;&#x4E24;&#x4E2A;&#x65F6;&#x6BB5;&#x6765;&#x5224;&#x65AD;&#x662F;&#x5426;&#x8981;&#x7EB3;&#x5165;&#x8BA1;&#x7B97;</p>
<h3 id="pod5min">Pod &#x542F;&#x52A8;&#x524D; 5min</h3>
<ul>
<li>&#x82E5; Pod &#x5F53;&#x524D;&#x72B6;&#x6001;&#x662F; Unready &#x5219;&#x76F4;&#x63A5;&#x89C6;&#x4E3A; Unready</li>
<li>&#x82E5; Pod &#x5F53;&#x524D;&#x72B6;&#x6001;&#x662F; Ready &#x4E14;&#x5176; ReadyCondition &#x53D8;&#x4E3A; true &#x7684;&#x65F6;&#x95F4;&#x5DF2;&#x7ECF;&#x8D85;&#x8FC7; <code>metric.Window</code> (30s)&#xFF0C;&#x624D;&#x4F1A;&#x88AB;&#x89C6;&#x4E3A; Ready&#xFF0C;&#x5373;&#x5C31;&#x7B97;&#x77ED;&#x65F6;&#x95F4;&#x5185;&#x7684;&#x63A2;&#x9488;&#x901A;&#x8FC7;&#x4E5F;&#x4E0D;&#x7B97;&#xFF0C;&#x5FC5;&#x987B;&#x8981;&#x4FDD;&#x8BC1;&#x4E0A;&#x6B21;&#x6293;&#x53D6;&#x5230; metric &#x65F6;&#x8BE5; Pod &#x4E5F;&#x9700;&#x8981;&#x662F; Ready &#x72B6;&#x6001;</li>
</ul>
<h3 id="pod5min">Pod &#x542F;&#x52A8; 5min &#x540E;</h3>
<p>&#x8FD9;&#x91CC;&#x5219;&#x7528;&#x5230;&#x4E86; <code>delayOfInitialReadinessStatus</code> (30s) &#x53C2;&#x6570;&#xFF0C;</p>
<ul>
<li>&#x82E5; Pod &#x5F53;&#x524D;&#x72B6;&#x6001;&#x662F; Ready&#xFF0C;&#x76F4;&#x63A5;&#x89C6;&#x4E3A; Ready &#x7EB3;&#x5165;&#x8BA1;&#x7B97;</li>
<li>&#x82E5; Pod &#x5F53;&#x524D;&#x72B6;&#x6001;&#x662F; Unready &#xFF0C;&#x4E14; ReadyCondition &#x4E0A;&#x6B21;&#x53D8;&#x5316;&#x7684;&#x65F6;&#x95F4;&#x5728; Pod &#x542F;&#x52A8;&#x7684; 30s &#x4E4B;&#x540E;&#xFF0C;&#x89C6;&#x4E3A; Ready &#x90FD;&#x9700;&#x8981;&#x7EB3;&#x5165; HPA &#x8BA1;&#x7B97;</li>
<li>&#x82E5; Pod &#x5F53;&#x524D;&#x72B6;&#x6001;&#x662F; Unready &#xFF0C;&#x4E14; ReadyCondition &#x4E0A;&#x6B21;&#x53D8;&#x5316;&#x7684;&#x65F6;&#x95F4;&#x5728; Pod &#x542F;&#x52A8;&#x7684; 30s &#x5185;&#xFF0C;HPA &#x8BA4;&#x4E3A;&#x8FD9;&#x4E2A; Pod &#x4ECE;&#x672A; Ready &#x8FC7;&#xFF0C;&#x6B64;&#x60C5;&#x51B5;&#x89C6;&#x4E3A; Unready &#x9700;&#x8981;&#x5FFD;&#x7565;&#x6389;</li>
</ul>
<p>&#x4F8B;&#x5982;&#x5BF9;&#x4E8E;&#x4EE5;&#x4E0B;&#x4E24;&#x4E2A; Pod</p>
<ul>
<li>POD1: 10min &#x524D;&#x542F;&#x52A8;&#x3001;Unready&#x3001;9min55&#xFF08;&#x542F;&#x52A8;&#x540E; 5s &lt; 30s&#xFF09;&#x524D;&#x53D8;&#x4E3A;&#x7684; Unready&#xFF0C;&#x5219;&#x89C6;&#x4E3A; Unready =&gt; &#x5FFD;&#x7565;</li>
<li>POD2: 10min &#x524D;&#x542F;&#x52A8;&#x3001;Unready&#x3001;9min05&#xFF08;&#x542F;&#x52A8;&#x540E; 55s &gt; 30s&#xFF09;&#x524D;&#x53D8;&#x4E3A;&#x7684; Unready&#xFF0C;&#x5219;&#x89C6;&#x4E3A; Ready =&gt; &#x4E0D;&#x5FFD;&#x7565;</li>
</ul>
<p>&#x53C2;&#x8003;&#x6E90;&#x7801;&#x5982;&#x4E0B;&#xFF1A;</p>
<pre><code class="language-go">if resource == v1.ResourceCPU {
	var unready bool
	_, condition := podutil.GetPodCondition(&amp;pod.Status, v1.PodReady)
	if condition == nil || pod.Status.StartTime == nil {
		unready = true
	} else {
		if pod.Status.StartTime.Add(cpuInitializationPeriod).After(time.Now()) {
			// Pod &#x5728;&#x542F;&#x52A8;&#x524D; cpuInitializationPeriod (&#x9ED8;&#x8BA4;5min) &#x5185;
			// &#x82E5; Pod Unready &#x5219;&#x5FFD;&#x7565;
			// &#x82E5; Pod Ready&#xFF0C;&#x4E14;&#x5728; metric.Window (&#x9ED8;&#x8BA4;30s) &#x65F6;&#x95F4;&#x5185;&#x7684; PodReady &#x72B6;&#x6001;&#x53D8;&#x5316;&#x4E5F;&#x8BA1;&#x4E3A; Unready
			unready = condition.Status == v1.ConditionFalse || metric.Timestamp.Before(condition.LastTransitionTime.Time.Add(metric.Window))
		} else {
			// Pod &#x5728;&#x542F;&#x52A8; cpuInitializationPeriod (&#x9ED8;&#x8BA4;5min)  &#x540E;
			// &#x5F53;&#x524D; Unready&#xFF0C;&#x4E14;&#x662F;&#x4ECE;&#x542F;&#x52A8;&#x540E;&#x7684; delayOfInitialReadinessStatus(&#x9ED8;&#x8BA4;30s) &#x5185;&#x5C31; Unready &#x4E00;&#x76F4;&#x6301;&#x7EED;&#x5230;&#x73B0;&#x5728;&#xFF0C;&#x624D;&#x5FFD;&#x7565;
			// &#x5373;&#x542F;&#x52A8; 5min &#x4E4B;&#x540E;&#xFF0C;&#x5BF9;&#x4E8E; LastTransitionTime &#x5728;&#x542F;&#x52A8; 30s &#x540E;&#x53D8;&#x5316;&#x7684; Pod &#x4E0D;&#x8BBA;&#x73B0;&#x5728;&#x662F;&#x5426;&#x662F; ready &#x5747;&#x89C6;&#x4E3A; ready&#xFF0C;&#x8981;&#x8BA1;&#x5165; HPA &#x8BA1;&#x7B97;&#x4E2D;
			unready = condition.Status == v1.ConditionFalse &amp;&amp; pod.Status.StartTime.Add(delayOfInitialReadinessStatus).After(conditioLastTransitionTime.Time)
		}
	}
	if unready {
		unreadyPods.Insert(pod.Name)
		continue
	}
}
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Kubernetes 控制面组件高可用原理之  Leader Election]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Kubernetes &#x9AD8;&#x53EF;&#x7528;&#x96C6;&#x7FA4;&#x7684;&#x63A7;&#x5236;&#x9762;&#x7EC4;&#x4EF6;&#x91CC;&#xFF0C;&#x9664;&#x4E86; <code>kube-apiserver</code> &#x662F;&#x591A;&#x526F;&#x672C;&#x8D1F;&#x8F7D;&#x5747;&#x8861;&#x540C;&#x65F6;&#x63D0;&#x4F9B;&#x670D;&#x52A1;&#x4E4B;&#x5916;&#xFF0C;&#x8FD8;&#x6709;&#x4E24;&#x4E2A;&#x7EC4;&#x4EF6;&#xFF1A; <code>kube-scheduler</code> &#x548C; <code>kube-controller-manager</code> &#xFF0C;&#x5B83;&#x4EEC;&#x867D;&#x7136;&#x5728;</p>]]></description><link>https://ruofeng.me/2020/07/07/k8s-leader-election/</link><guid isPermaLink="false">5f04a8f0d6384d00014c2a97</guid><category><![CDATA[Kubernetes]]></category><dc:creator><![CDATA[Ruofeng Lei]]></dc:creator><pubDate>Tue, 07 Jul 2020 16:57:06 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Kubernetes &#x9AD8;&#x53EF;&#x7528;&#x96C6;&#x7FA4;&#x7684;&#x63A7;&#x5236;&#x9762;&#x7EC4;&#x4EF6;&#x91CC;&#xFF0C;&#x9664;&#x4E86; <code>kube-apiserver</code> &#x662F;&#x591A;&#x526F;&#x672C;&#x8D1F;&#x8F7D;&#x5747;&#x8861;&#x540C;&#x65F6;&#x63D0;&#x4F9B;&#x670D;&#x52A1;&#x4E4B;&#x5916;&#xFF0C;&#x8FD8;&#x6709;&#x4E24;&#x4E2A;&#x7EC4;&#x4EF6;&#xFF1A; <code>kube-scheduler</code> &#x548C; <code>kube-controller-manager</code> &#xFF0C;&#x5B83;&#x4EEC;&#x867D;&#x7136;&#x5728;&#x4E09;&#x4E2A; master &#x4E2D;&#x5747;&#x90E8;&#x7F72;&#x4E86;&#x4E09;&#x4EFD;&#x526F;&#x672C;&#xFF0C;&#x4F46;&#x662F;&#x5B9E;&#x9645;&#x4E0A;&#x53EA;&#x6709;&#x4E00;&#x4E2A;&#x5728;&#x771F;&#x6B63;&#x5DE5;&#x4F5C;&#x3002;&#x4E09;&#x4E2A;&#x7EC4;&#x4EF6;&#x5982;&#x4F55;&#x5728;&#x96C6;&#x7FA4;&#x4E2D;&#x76F8;&#x4E92;&#x534F;&#x8C03;&#x51B3;&#x5B9A;&#x54EA;&#x4E00;&#x4E2A;&#x771F;&#x6B63;&#x5DE5;&#x4F5C;&#xFF0C;&#x5176;&#x80CC;&#x540E;&#x539F;&#x7406;&#x662F; leader election&#xFF0C;&#x4F7F;&#x7528;&#x4E86; <code>client-go</code> &#x4E2D;&#x7684; <code>tools/leaderelection</code> &#x5305;&#x5B8C;&#x6210;&#x9009;&#x4E3E;&#x7684;&#x884C;&#x4E3A;&#x3002;</p>
<h2 id>&#x57FA;&#x672C;&#x6982;&#x5FF5;</h2>
<p>&#x591A;&#x4E2A;&#x6210;&#x5458;&#x53C2;&#x4E0E; leader election &#x7684;&#x884C;&#x4E3A;&#x4E2D;&#xFF0C;&#x6210;&#x4E3A;&#x5206;&#x4E3A;&#x4E24;&#x7C7B;&#xFF1A;</p>
<ul>
<li>leader</li>
<li>candidate</li>
</ul>
<p>&#x5176;&#x4E2D; leader &#x4E3A;&#x771F;&#x6B63;&#x5DE5;&#x4F5C;&#x7684;&#x6210;&#x5458;&#xFF0C;&#x5176;&#x4ED6;&#x6210;&#x5458;&#x4E3A; candidate &#xFF0C;&#x5B83;&#x4EEC;&#x5E76;&#x6CA1;&#x6709;&#x5728;&#x6267;&#x884C;&#x5DE5;&#x4F5C;&#x800C;&#x662F;&#x968F;&#x65F6;&#x7B49;&#x5F85;&#x6210;&#x4E3A; leader &#x5E76;&#x5F00;&#x59CB;&#x5DE5;&#x4F5C;&#x3002;&#x5728;&#x5B83;&#x4EEC;&#x8FD0;&#x884C;&#x4E4B;&#x521D;&#x90FD;&#x662F; candidate&#xFF0C;&#x521D;&#x59CB;&#x5316;&#x65F6;&#x90FD;&#x4F1A;&#x53BB;&#x83B7;&#x53D6;&#x4E00;&#x4E2A;&#x552F;&#x4E00;&#x7684;&#x9501;&#xFF0C;&#x8C01;&#x62A2;&#x5230;&#x8C01;&#x5C31;&#x6210;&#x4E3A; leader &#x5E76;&#x5F00;&#x59CB;&#x5DE5;&#x4F5C;&#xFF0C;&#x5728; <code>client-go</code> &#x4E2D;&#x8FD9;&#x4E2A;&#x9501;&#x5C31;&#x662F; apiserver &#x4E2D;&#x7684;&#x4E00;&#x4E2A;&#x8D44;&#x6E90;&#xFF0C;&#x8D44;&#x6E90;&#x7C7B;&#x578B;&#x4E00;&#x822C;&#x662F; <code>CoordinationV1()</code> &#x8D44;&#x6E90;&#x7EC4;&#x4E2D;&#x7684; <code>Lease</code> &#x8D44;&#x6E90;&#x3002;</p>
<p>&#x5728; leader &#x88AB;&#x9009;&#x4E3E;&#x6210;&#x529F;&#x4E4B;&#x540E;&#xFF0C;leader &#x4E3A;&#x4E86;&#x4FDD;&#x4F4F;&#x81EA;&#x5DF1;&#x7684;&#x4F4D;&#x7F6E;&#xFF0C;&#x9700;&#x8981;&#x5B9A;&#x65F6;&#x53BB;&#x66F4;&#x65B0;&#x8FD9;&#x4E2A; <code>Lease</code> &#x8D44;&#x6E90;&#x7684;&#x72B6;&#x6001;&#xFF0C;&#x5373;&#x4E00;&#x4E2A;&#x65F6;&#x95F4;&#x6233;&#x4FE1;&#x606F;&#xFF0C;&#x8868;&#x660E;&#x81EA;&#x5DF1;&#x6709;&#x5728;&#x4E00;&#x76F4;&#x5DE5;&#x4F5C;&#x6CA1;&#x6709;&#x51FA;&#x73B0;&#x6545;&#x969C;&#xFF0C;&#x8FD9;&#x4E00;&#x64CD;&#x4F5C;&#x79F0;&#x4E3A;&#x7EED;&#x7EA6;&#x3002;&#x5176;&#x4ED6; candidate &#x4E5F;&#x4E0D;&#x662F;&#x5B8C;&#x5168;&#x95F2;&#x7740;&#xFF0C;&#x800C;&#x662F;&#x4E5F;&#x4F1A;&#x5B9A;&#x671F;&#x5C1D;&#x8BD5;&#x83B7;&#x53D6;&#x8FD9;&#x4E2A;&#x8D44;&#x6E90;&#xFF0C;&#x68C0;&#x67E5;&#x8D44;&#x6E90;&#x7684;&#x4FE1;&#x606F;&#xFF0C;&#x65F6;&#x95F4;&#x6233;&#x6709;&#x6CA1;&#x6709;&#x592A;&#x4E45;&#x6CA1;&#x66F4;&#x65B0;&#xFF0C;&#x5426;&#x5219;&#x8BA4;&#x4E3A;&#x539F;&#x6765;&#x7684; leader &#x6545;&#x969C;&#x5931;&#x8054;&#x65E0;&#x6CD5;&#x6B63;&#x5E38;&#x5DE5;&#x4F5C;&#xFF0C;&#x5E76;&#x66F4;&#x65B0;&#x6B64;&#x8D44;&#x6E90;&#x7684; holder &#x4E3A;&#x81EA;&#x5DF1;&#xFF0C;&#x6210;&#x4E3A; leader &#x5F00;&#x59CB;&#x5DE5;&#x4F5C;&#x5E76;&#x540C;&#x65F6;&#x5B9A;&#x671F;&#x7EED;&#x7EA6;&#x3002;</p>
<h2 id>&#x4E09;&#x4E2A;&#x65F6;&#x95F4;&#x53C2;&#x6570;</h2>
<ul>
<li><code>leaseDuration</code> leader &#x7EED;&#x7EA6;&#x4E00;&#x6B21;&#x7684;&#x6709;&#x6548;&#x671F;</li>
<li><code>RenewDeadline</code> &#x7EED;&#x79DF;&#x8D85;&#x65F6;&#x65F6;&#x95F4;&#xFF0C;leader &#x6BCF;&#x6B21;&#x7EED;&#x79DF;&#x6267;&#x884C;&#x65F6;&#x95F4;&#x8D85;&#x8FC7;&#x6B64;&#x65F6;&#x95F4;&#x8BA4;&#x4E3A;&#x5931;&#x8D25;&#xFF0C;&#x5C06; lease &#x91CA;&#x653E;</li>
<li><code>RetryPeriod</code> leader &#x7EED;&#x7EA6;&#x5468;&#x671F;&#xFF0C;candidate &#x5FAA;&#x73AF;&#x83B7;&#x53D6;&#x9501;&#x7684;&#x5468;&#x671F;</li>
</ul>
<h2 id>&#x6E90;&#x7801;</h2>
<p><code>kube-controller-manager</code> &#x7EC4;&#x4EF6;&#x5728;&#x521D;&#x59CB;&#x5316;&#x65F6;&#x65F6;&#x5982;&#x4F55;&#x4F7F;&#x7528; client-go &#x8FDB;&#x884C;&#x9009;&#x4E3E;&#x7684;&#xFF0C;&#x53C2;&#x8003;&#x4EE3;&#x7801;&#xFF1A; <a href="https://github.com/kubernetes/kubernetes/blob/v1.18.5/cmd/kube-controller-manager/app/controllermanager.go#L245-L285">https://github.com/kubernetes/kubernetes/blob/v1.18.5/cmd/kube-controller-manager/app/controllermanager.go#L245-L285</a></p>
<pre><code class="language-go">// leaderElect &#x53EF;&#x9009;&#x914D;&#x7F6E;&#xFF0C;&#x901A;&#x8FC7;&#x547D;&#x4EE4;&#x884C;&#x53C2;&#x6570;&#x4F20;&#x5165;&#xFF0C;&#x82E5;&#x672A;&#x5F00;&#x542F;&#x76F4;&#x63A5;&#x8FD0;&#x884C;run()&#x5F00;&#x59CB;&#x5DE5;&#x4F5C;
if !c.ComponentConfig.Generic.LeaderElection.LeaderElect {
    run(context.TODO())
    panic(&quot;unreachable&quot;)
}

// &#x5F00;&#x542F; leaderElection&#xFF0C;&#x4E0B;&#x9762;&#x4E3A;&#x4F7F;&#x7528;leaderElection&#x7684;&#x6B65;&#x9AA4;
// &#x9996;&#x5148;&#x4E3A;&#x81EA;&#x5DF1;&#x9009;&#x5B9A;&#x4E00;&#x4E2A;ID&#xFF0C;&#x6B64;ID&#x5FC5;&#x987B;&#x8981;&#x5728;&#x6240;&#x6709;&#x6210;&#x5458;&#x4E2D;&#x662F;&#x552F;&#x4E00;&#x7684;&#xFF0C;&#x8FD9;&#x91CC;&#x4F7F;&#x7528; Hostname + UUID
id, err := os.Hostname()
if err != nil {
    return err
}
id = id + &quot;_&quot; + string(uuid.NewUUID())

// &#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x8D44;&#x6E90;&#x9501;&#xFF0C;resourcelock&#x4E5F;&#x662F;client-go&#x4E2D;&#x7684;&#x5DE5;&#x5177;&#xFF0C;&#x9009;&#x5B9A;&#x54EA;&#x4E2A;&#x8D44;&#x6E90;&#x662F;leaderElection&#x7684;&#x7ADE;&#x4E89;&#x76EE;&#x6807;
rl, err := resourcelock.New(c.ComponentConfig.Generic.LeaderElection.ResourceLock,
    c.ComponentConfig.Generic.LeaderElection.ResourceNamespace,
    c.ComponentConfig.Generic.LeaderElection.ResourceName,
    c.LeaderElectionClient.CoreV1(),
    c.LeaderElectionClient.CoordinationV1(),
    resourcelock.ResourceLockConfig{
        Identity:      id,
        EventRecorder: c.EventRecorder,
    })
if err != nil {
    klog.Fatalf(&quot;error creating lock: %v&quot;, err)
}

// &#x5F00;&#x59CB;&#x8FDB;&#x884C;&#x9009;&#x4E3E;&#xFF0C;&#x5E76;&#x6CE8;&#x518C;&#x56DE;&#x8C03;&#x51FD;&#x6570;
leaderelection.RunOrDie(context.TODO(), leaderelection.LeaderElectionConfig{
    Lock:          rl,
    LeaseDuration: c.ComponentConfig.Generic.LeaderElection.LeaseDuration.Duration,
    RenewDeadline: c.ComponentConfig.Generic.LeaderElection.RenewDeadline.Duration,
    RetryPeriod:   c.ComponentConfig.Generic.LeaderElection.RetryPeriod.Duration,
    Callbacks: leaderelection.LeaderCallbacks{
        OnStartedLeading: run,
        OnStoppedLeading: func() {
            klog.Fatalf(&quot;leaderelection lost&quot;)
        },
    },
    WatchDog: electionChecker,
    Name:     &quot;kube-controller-manager&quot;,
})
</code></pre>
<h2 id="clientgo"><code>client-go</code> &#x5B9E;&#x73B0;&#x7EC6;&#x8282;</h2>
<p>&#x4EE3;&#x7801;&#x4F4D;&#x7F6E; <a href="https://github.com/kubernetes/client-go/blob/v0.18.5/tools/leaderelection/leaderelection.go">https://github.com/kubernetes/client-go/blob/v0.18.5/tools/leaderelection/leaderelection.go</a> &#xFF0C;&#x5F00;&#x59CB;&#x9009;&#x4E3E;&#x7684;&#x5165;&#x53E3;&#x51FD;&#x6570;&#x4E3A;&#xFF1A;</p>
<pre><code class="language-go">leaderelection.RunOrDie(context, cfg)
</code></pre>
<p>Run &#x65B9;&#x6CD5;&#x7684;&#x6838;&#x5FC3;&#x903B;&#x8F91;&#xFF0C;&#x5C1D;&#x8BD5;&#x83B7;&#x53D6;&#x8D44;&#x6E90;&#xFF0C;&#x83B7;&#x53D6;&#x5230;&#x5219;&#x6210;&#x4E3A; leader&#xFF0C;&#x83B7;&#x53D6;&#x5931;&#x8D25;&#x91CD;&#x8BD5;&#xFF1A;</p>
<pre><code class="language-go">func (le *LeaderElector) Run(ctx context.Context) {
	// &#x7ED3;&#x675F;&#x65F6;&#xFF0C;&#x5904;&#x7406;panic&#xFF0C;&#x4EE5;&#x53CA;&#x8C03;&#x7528;StoppedLeading&#x56DE;&#x8C03;&#x51FD;&#x6570;
	defer func() {
		runtime.HandleCrash()
		le.config.Callbacks.OnStoppedLeading()
	}()

	// loop&#xFF0C;&#x5FAA;&#x73AF;&#x5C1D;&#x8BD5;&#x83B7;&#x53D6;&#x9501;&#xFF0C;&#x82E5;&#x5DF2;&#x7ECF;&#x6709;master&#x62FF;&#x5230;&#x9501;&#xFF0C;&#x5219;&#x6B64;candidate&#x59CB;&#x7EC8;&#x5728;&#x6B64;&#x5FAA;&#x73AF;&#x91CC;&#x6CA1;&#x6709;&#x8FD4;&#x56DE;
	if !le.acquire(ctx) {
		return // ctx signalled done
	}

	// &#x5230;&#x8FD9;&#x91CC;&#x8BF4;&#x660E;&#x6B64;candidate&#x5DF2;&#x7ECF;&#x6210;&#x529F;&#x83B7;&#x53D6;&#x5230;&#x9501;&#xFF0C;&#x5E76;&#x6210;&#x4E3A;master&#x6B63;&#x5F0F;&#x5F00;&#x59CB;&#x5DE5;&#x4F5C;
    // &#x8C03;&#x7528;&#x5F00;&#x59CB;&#x7684;&#x56DE;&#x8C03;&#x51FD;&#x6570;&#xFF0C;&#x4E00;&#x822C;&#x63A7;&#x5236;&#x5668;&#x7684;&#x5165;&#x53E3;&#x51FD;&#x6570;&#x4F1A;&#x6CE8;&#x518C;&#x5230;&#x6B64;StartLeading&#x56DE;&#x8C03;&#x51FD;&#x6570;&#x4E2D;
	ctx, cancel := context.WithCancel(ctx)
	defer cancel()
	go le.config.Callbacks.OnStartedLeading(ctx)

    // &#x4E5F;&#x662F;&#x4E00;&#x4E2A;&#x5FAA;&#x73AF;&#xFF0C;master&#x5728;&#x83B7;&#x53D6;&#x5230;&#x9501;&#x4E4B;&#x540E;&#x4E5F;&#x9700;&#x8981;&#x4E0D;&#x505C;&#x5730;&#x53BB;&#x7EED;&#x79DF;&#xFF0C;&#x76F8;&#x5F53;&#x4E8E;&#x662F;&#x53D1;&#x9001;&#x5FC3;&#x8DF3;&#x5305;&#x8868;&#x660E;&#x81EA;&#x5DF1;&#x5728;&#x6B63;&#x5E38;&#x5DE5;&#x4F5C;
	le.renew(ctx)
}
</code></pre>
<p><code>acquire</code> &#x548C; <code>renew</code> &#x4E24;&#x4E2A;&#x65B9;&#x6CD5;&#x7684;&#x5FAA;&#x73AF;&#x5468;&#x671F;&#x90FD;&#x662F;&#x914D;&#x7F6E;&#x4E2D;&#x7684; <code>RetryPeriod</code> &#x53C2;&#x6570;&#xFF0C;&#x5176;&#x4E2D; <code>aquire</code> &#x7684;&#x5FAA;&#x73AF;&#x4E2D;&#x8C03;&#x7528;&#x7684;&#x6838;&#x5FC3;&#x65B9;&#x6CD5;&#x662F; <code>tryAcquireOrRenew</code> &#x8FD4;&#x56DE; true &#x8868;&#x793A;&#x62FF;&#x5230;&#x9501;&#x5E76;&#x6210;&#x4E3A;&#x4E86;&#x65B0;&#x7684; leader&#xFF0C;&#x53CD;&#x4E4B;&#x8FD4;&#x56DE; false&#xFF0C;&#x81EA;&#x5DF1;&#x8FD8;&#x662F; candidate&#xFF0C;&#x6210;&#x529F; aquire &#x4E4B;&#x540E;&#x4FBF;&#x4F1A;&#x9000;&#x51FA;&#x5FAA;&#x73AF;:</p>
<pre><code class="language-go">func (le *LeaderElector) tryAcquireOrRenew(ctx context.Context) bool {
    // &#x5148;&#x5B9E;&#x4F8B;&#x5316;leaderElectionRecord &#x82E5;&#x771F;&#x7684;&#x83B7;&#x53D6;&#x5230;&#x91CC;&#x5C31;&#x5C06;&#x8D44;&#x6E90;&#x66F4;&#x65B0;&#x4E3A;&#x6B64;&#x5B9E;&#x4F8B;
	now := metav1.Now()
	leaderElectionRecord := rl.LeaderElectionRecord{
		HolderIdentity:       le.config.Lock.Identity(),
		LeaseDurationSeconds: int(le.config.LeaseDuration / time.Second),
		RenewTime:            now,
		AcquireTime:          now,
	}

	// 1. &#x5C1D;&#x8BD5;&#x83B7;&#x53D6;&#x76EE;&#x6807;&#x8D44;&#x6E90;&#xFF0C;&#x82E5;&#x6CA1;&#x6709;&#x627E;&#x5230;&#xFF0C;&#x5219;&#x8BF4;&#x660E;&#x8FD8;&#x6CA1;&#x6709;&#x5176;&#x4ED6;&#x6210;&#x5458;&#x5360;&#x7528;&#x5207;&#x6210;&#x4E3A;leader&#xFF0C;&#x76F4;&#x63A5;&#x521B;&#x5EFA;&#x5E76;&#x66F4;&#x65B0;&#x5373;&#x53EF;
	oldLeaderElectionRecord, oldLeaderElectionRawRecord, err := le.config.Lock.Get(ctx)
	if err != nil {
		if !errors.IsNotFound(err) {
			klog.Errorf(&quot;error retrieving resource lock %v: %v&quot;, le.config.Lock.Describe(), err)
			return false
		}
		if err = le.config.Lock.Create(ctx, leaderElectionRecord); err != nil {
			klog.Errorf(&quot;error initially creating leader election record: %v&quot;, err)
			return false
		}
		le.observedRecord = leaderElectionRecord
		le.observedTime = le.clock.Now()
		return true
	}

	// 2. &#x83B7;&#x53D6;&#x5230;&#x76EE;&#x6807;&#x9501;&#x8BB0;&#x5F55;, &#x68C0;&#x67E5;ID&#x548C;&#x65F6;&#x95F4;
	if !bytes.Equal(le.observedRawRecord, oldLeaderElectionRawRecord) {
		le.observedRecord = *oldLeaderElectionRecord
		le.observedRawRecord = oldLeaderElectionRawRecord
		le.observedTime = le.clock.Now()
	}
    // holderID&#x4E0D;&#x4E3A;&#x7A7A; &amp;&amp; &#x76EE;&#x6807;&#x79DF;&#x7EA6;&#x8FD8;&#x6CA1;&#x6709;&#x8FC7;&#x671F; &amp;&amp; ID&#x4E0D;&#x662F;&#x81EA;&#x5DF1;&#xFF0C;&#x4E09;&#x9879;&#x5176;&#x4E2D;&#x4EFB;&#x4F55;&#x4E00;&#x9879;&#x4E0D;&#x6EE1;&#x8DB3;&#x90FD;&#x8868;&#x660E;&#x81EA;&#x5DF1;&#x6709;&#x8D44;&#x683C;&#x6210;&#x4E3A;leader
	if len(oldLeaderElectionRecord.HolderIdentity) &gt; 0 &amp;&amp;
		le.observedTime.Add(le.config.LeaseDuration).After(now.Time) &amp;&amp;
		!le.IsLeader() {
		klog.V(4).Infof(&quot;lock is held by %v and has not yet expired&quot;, oldLeaderElectionRecord.HolderIdentity)
		return false
	}

    // &#x901A;&#x8FC7;&#x83B7;&#x53D6;&#x5230;&#x7684;lease&#x8BB0;&#x5F55;&#x53D1;&#x73B0;&#x81EA;&#x5DF1;&#x53EF;&#x4EE5;&#x6210;&#x4E3A;leader&#xFF0C;&#x4E0B;&#x9762;&#x5F00;&#x59CB;&#x6267;&#x884C;&#x6210;&#x4E3A;leader&#x7684;&#x903B;&#x8F91;
	// 3. &#x82E5;&#x81EA;&#x5DF1;&#x672C;&#x8EAB;&#x4E4B;&#x524D;&#x5C31;&#x662F;leader&#xFF0C;&#x5219;&#x66F4;&#x65B0;acquireTime&#xFF0C;transition&#x8BB0;&#x5F55;leader&#x53D8;&#x5316;&#x7684;&#x6B21;&#x6570;
	if le.IsLeader() {
		leaderElectionRecord.AcquireTime = oldLeaderElectionRecord.AcquireTime
		leaderElectionRecord.LeaderTransitions = oldLeaderElectionRecord.LeaderTransitions
	} else {
		leaderElectionRecord.LeaderTransitions = oldLeaderElectionRecord.LeaderTransitions + 1
	}

	// &#x66F4;&#x65B0;lease&#x8D44;&#x6E90;
	if err = le.config.Lock.Update(ctx, leaderElectionRecord); err != nil {
		klog.Errorf(&quot;Failed to update lock: %v&quot;, err)
		return false
	}

	le.observedRecord = leaderElectionRecord
	le.observedTime = le.clock.Now()
	return true
}
</code></pre>
<p>leader &#x5728; <code>renew</code> &#x65B9;&#x6CD5;&#x7684;&#x5FAA;&#x73AF;&#x4E2D;&#x8C03;&#x7528;&#x7684;&#x5B9E;&#x9645;&#x4E0A;&#x4E5F;&#x662F;&#x4E0A;&#x9762;&#x7684; <code>tryAcquireOrRenew</code> &#x65B9;&#x6CD5;&#xFF0C;&#x53EA;&#x4E0D;&#x8FC7;&#x4E0D;&#x51FA;&#x610F;&#x5916;&#x6BCF;&#x6B21;&#x90FD;&#x5230;&#x7B2C; 3 &#x6B65;&#x66F4;&#x65B0;&#x4E00;&#x4E0B;&#x65F6;&#x95F4;&#x7EED;&#x79DF;&#x5373;&#x53EF;&#x3002;</p>
<h2 id>&#x81EA;&#x5DF1;&#x5C1D;&#x8BD5;&#x4F7F;&#x7528;</h2>
<p>&#x8FD1;&#x671F;&#x5199;&#x4E86;&#x4E00;&#x4E2A;&#x5C0F;&#x7EC4;&#x4EF6;&#xFF0C;&#x6536;&#x96C6; Kubernetes &#x96C6;&#x7FA4;&#x4E2D;&#x7684; Events &#x5E76;&#x5B58;&#x5165;&#x6301;&#x4E45;&#x5316;&#x50A8;&#x5B58;&#x5982; ES &#x4E2D;&#x4EE5;&#x4F9B;&#x5FEB;&#x901F;&#x67E5;&#x8BE2;&#x3002;&#x6B64;&#x7EC4;&#x4EF6;&#x672C;&#x8EAB;&#x5E76;&#x6CA1;&#x6709;&#x4EC0;&#x4E48;&#x590D;&#x6742;&#x5EA6;&#xFF0C;&#x5B9E;&#x9645;&#x4E0A;&#x5C31;&#x662F;&#x4E00;&#x4E2A; informer + watch + workqueue &#x5165;&#x5E93;&#xFF0C;&#x53EF;&#x4EE5;&#x7B97;&#x662F;&#x4E00;&#x4E2A;&#x81EA;&#x5B9A;&#x4E49; controller &#x6700;&#x57FA;&#x672C;&#x7B80;&#x5355;&#x7684;&#x6A21;&#x578B;&#x4E86;&#x3002;&#x7EC4;&#x4EF6;&#x672C;&#x8EAB;&#x6545;&#x969C;&#x6302;&#x6389;&#x4E5F;&#x4E0D;&#x4F1A;&#x6709;&#x592A;&#x5927;&#x7684;&#x5F71;&#x54CD;&#xFF0C;&#x7531; k8s &#x672C;&#x8EAB;&#x6545;&#x969C;&#x81EA;&#x6108;&#x91CD;&#x542F;&#x542F;&#x52A8; Pod &#x5373;&#x53EF;&#xFF0C;&#x867D;&#x7136;&#x8BF4;&#x53EF;&#x80FD;&#x4F1A;&#x4E22;&#x4E00;&#x4E9B;&#x65E5;&#x5FD7;&#xFF0C;&#x4F46;&#x662F;&#x95EE;&#x9898;&#x4E5F;&#x4E0D;&#x7B97;&#x592A;&#x5927;&#x3002;&#x4F46;&#x662F;&#x5F00;&#x59CB;&#x5C1D;&#x8BD5;&#x4F7F;&#x7528;&#x4E86; Leader Election &#x53EF;&#x80FD;&#x6709;&#x4E00;&#x4E9B;&#x5927;&#x6750;&#x5C0F;&#x7528;&#x5427;&#xFF0C;&#x4F46;&#x662F;&#x4E5F;&#x5F53;&#x662F;&#x719F;&#x6089;&#x7EC3;&#x624B;&#x4E86;&#x3002;</p>
<p>&#x7EC4;&#x4EF6;&#x4EE3;&#x7801;&#x5F00;&#x6E90;&#x5728; <a href="https://github.com/abowloflrf/k8s-events-dispatcher">https://github.com/abowloflrf/k8s-events-dispatcher</a> &#xFF0C;Leader Election &#x90E8;&#x5206;&#x5C31;&#x5728;&#x5165;&#x53E3;&#x51FD;&#x6570; <code>main.go</code> &#x4E2D;&#xFF0C;&#x5B9E;&#x73B0;&#x53EF;&#x4F9B;&#x53C2;&#x8003;&#x3002;</p>
<h2 id>&#x53C2;&#x8003;</h2>
<ul>
<li><a href="https://pkg.go.dev/k8s.io/client-go/tools/leaderelection?tab=doc">Package tools/leaderelection Docs</a></li>
<li><a href="https://github.com/kubernetes/client-go/blob/master/examples/leader-election/main.go">kubernetes/client-go Example</a></li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Realtime in Web：Polling/Websocket/SSE]]></title><description><![CDATA[<!--kg-card-begin: markdown--><h2 id>&#x5B9E;&#x65F6;&#x6027;&#x662F;&#x4EC0;&#x4E48;&#xFF1F;</h2>
<p>HTTP &#x534F;&#x8BAE;&#x88AB;&#x8BA4;&#x4E3A;&#x662F;&#x4E00;&#x79CD;&#x65E0;&#x72B6;&#x6001;&#x534F;&#x8BAE;&#xFF1A;&#x5BA2;&#x6237;&#x7AEF;&#x53D1;&#x51FA;&#x8BF7;&#x6C42;&#xFF0C;&#x968F;&#x4E4B;&#x670D;&#x52A1;&#x7AEF;&#x5BF9;&#x8FD9;&#x6B21;&#x8BF7;&#x6C42;&#x8FD4;&#x56DE;&#x54CD;&#x5E94;&#xFF0C;&#x4E00;&#x6765;&#x4E00;&#x56DE;&#x4E3A;</p>]]></description><link>https://ruofeng.me/2019/04/26/realtime-in-web/</link><guid isPermaLink="false">5d8e378da7d96200019ade24</guid><category><![CDATA[HTTP]]></category><category><![CDATA[realtime]]></category><category><![CDATA[Web]]></category><dc:creator><![CDATA[Ruofeng Lei]]></dc:creator><pubDate>Fri, 26 Apr 2019 16:25:29 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h2 id>&#x5B9E;&#x65F6;&#x6027;&#x662F;&#x4EC0;&#x4E48;&#xFF1F;</h2>
<p>HTTP &#x534F;&#x8BAE;&#x88AB;&#x8BA4;&#x4E3A;&#x662F;&#x4E00;&#x79CD;&#x65E0;&#x72B6;&#x6001;&#x534F;&#x8BAE;&#xFF1A;&#x5BA2;&#x6237;&#x7AEF;&#x53D1;&#x51FA;&#x8BF7;&#x6C42;&#xFF0C;&#x968F;&#x4E4B;&#x670D;&#x52A1;&#x7AEF;&#x5BF9;&#x8FD9;&#x6B21;&#x8BF7;&#x6C42;&#x8FD4;&#x56DE;&#x54CD;&#x5E94;&#xFF0C;&#x4E00;&#x6765;&#x4E00;&#x56DE;&#x4E3A;&#x4E00;&#x6B21; HTTP &#x8BF7;&#x6C42;&#x7684;&#x8FC7;&#x7A0B;&#x3002;&#x4F46;&#x662F;&#x57FA;&#x672C;&#x7684; HTTP &#x8BF7;&#x6C42;&#x5F80;&#x5F80;&#x65E0;&#x6CD5;&#x9AD8;&#x6548;&#x4F18;&#x96C5;&#x5730;&#x6EE1;&#x8DB3; Web &#x4E2D;&#x9700;&#x8981;&#x7684;&#x5404;&#x79CD;&#x529F;&#x80FD;&#x3002;&#x4F8B;&#x5982;&#x5404;&#x79CD;&#x5B9E;&#x65F6;&#x6027;&#x8981;&#x6C42;&#x7684;&#x573A;&#x666F;&#xFF0C;&#x5728;&#x7EBF;&#x804A;&#x5929;&#x662F;&#x6700;&#x4E3A;&#x7ECF;&#x5178;&#x7684;&#x4F8B;&#x5B50;&#xFF0C;A &#x53D1;&#x9001;&#x6D88;&#x606F;&#x7ED9; B &#x540E;&#xFF0C;B &#x5982;&#x4F55;&#x80FD;&#x5B9E;&#x65F6;&#x5730;&#x62FF;&#x5230; A &#x53D1;&#x9001;&#x7684;&#x8FD9;&#x6761;&#x6D88;&#x606F;&#xFF1F;&#x6309;&#x6700;&#x7B80;&#x5355;&#x6700;&#x4F20;&#x7EDF;&#x7684;&#x601D;&#x8DEF;&#xFF0C;&#x9700;&#x8981; B &#x7684;&#x6D4F;&#x89C8;&#x5668;&#x7AEF;&#x53BB;&#x8BF7;&#x6C42;&#x670D;&#x52A1;&#x5668;&#x770B;&#x770B;&#x662F;&#x5426;&#x6709;&#x65B0;&#x7684;&#x6D88;&#x606F;&#xFF0C;HTTP &#x63A5;&#x53E3;&#x53EF;&#x80FD;&#x88AB;&#x8BBE;&#x8BA1;&#x6210;&#xFF1A;</p>
<pre><code>POST /send
{
  &quot;to&quot;:&quot;user_b&quot;,
  &quot;msg&quot;:&quot;hello&quot;
}

GET /message
{
  &quot;messages&quot;:[
    {
      &quot;from&quot;:&quot;user_a&quot;,
      &quot;msg&quot;:&quot;hello&quot;
    }
  ]
}
</code></pre>
<p>&#x7528;&#x6237; A &#x8C03;&#x7528; send &#x53D1;&#x9001;&#x6D88;&#x606F;&#xFF0C;&#x7136;&#x540E;&#x7528;&#x6237; B &#x7684;&#x6D4F;&#x89C8;&#x5668;&#x4E2D;&#x6709;&#x4E00;&#x4E2A;&#x6309;&#x94AE; - <strong>&#x83B7;&#x53D6;&#x6700;&#x65B0;&#x6D88;&#x606F;</strong> &#x6765;&#x8C03;&#x7528; message &#x83B7;&#x53D6;&#x6D88;&#x606F;&#x5217;&#x8868;&#xFF0C;&#x8FD9;&#x6837; A &#x53D1;&#x9001;&#x6D88;&#x606F;&#x4E4B;&#x540E; B &#x6CA1;&#x6CD5;&#x76F4;&#x63A5;&#x77E5;&#x9053;&#x8C01;&#x5728;&#x4F55;&#x65F6;&#x53D1;&#x9001;&#x4E86;&#x6D88;&#x606F;&#xFF0C;&#x5FC5;&#x987B;&#x624B;&#x52A8;&#x53BB;&#x70B9;&#x51FB;&#x6309;&#x94AE;&#x53D1;&#x9001;&#x8BF7;&#x6C42;&#x4ECE;&#x670D;&#x52A1;&#x5668;&#x62C9;&#x53D6;&#x6D88;&#x606F;&#xFF0C;&#x663E;&#x7136;&#x8FD9;&#x6837;&#x662F;&#x4E00;&#x4E2A;&#x5F88;&#x4E0D;&#x5408;&#x7406;&#x7684;&#x6280;&#x672F;&#x5B9E;&#x73B0;&#xFF0C;&#x5B8C;&#x5168;&#x4E0D;&#x5177;&#x6709;&#x4EFB;&#x4F55;&#x5B9E;&#x65F6;&#x6027;&#x3002;</p>
<p>&#x8981;&#x5728; Web &#x4E2D;&#x8FBE;&#x5230;&#x5B9E;&#x65F6;&#x6027;&#x9996;&#x5148;&#x9700;&#x8981;&#x9700;&#x8981;&#x601D;&#x8003;&#x5B83;&#x7684;&#x5B9E;&#x65F6;&#x6027;&#x7684;&#x6839;&#x6E90;&#x95EE;&#x9898;&#xFF1A;<strong>&#x670D;&#x52A1;&#x7AEF;&#x662F;&#x77E5;&#x9053;&#x4E00;&#x4E2A;&#x4E8B;&#x4EF6;&#x53D1;&#x751F;&#x7684;&#x7B2C;&#x4E00;&#x4EBA;&#xFF0C;&#x5B83;&#x5982;&#x4F55;&#x5C06;&#x8FD9;&#x4E2A;&#x4E8B;&#x4EF6;&#x5728;&#x7B2C;&#x4E00;&#x65F6;&#x95F4;&#x8BA9;&#x5BA2;&#x6237;&#x7AEF;&#xFF08;&#x6D4F;&#x89C8;&#x5668;&#xFF09;&#x77E5;&#x9053;&#xFF1F;</strong></p>
<p>&#x53EF;&#x4EE5;&#x80AF;&#x5B9A;&#x7684;&#x662F;&#x505A;&#x8FD9;&#x4EF6;&#x4E8B;&#x53EA;&#x6709;&#x4E24;&#x79CD;&#x6700;&#x57FA;&#x672C;&#x7684;&#x65B9;&#x5F0F;&#xFF1A;</p>
<ol>
<li>Client Pull</li>
<li>Server Push</li>
</ol>
<p>&#x5177;&#x4F53;&#x6765;&#x8BF4;&#xFF0C;Web &#x4E2D;&#x6709;&#x5B9E;&#x73B0;&#x5B9E;&#x65F6;&#x6027;&#x7684;&#x51E0;&#x79CD;&#x65B9;&#x5F0F;&#xFF0C;&#x672C;&#x7BC7;&#x6587;&#x7AE0;&#x4F1A;&#x5BF9;&#x8FD9;&#x4E9B;&#x65B9;&#x6CD5;&#x505A;&#x4E00;&#x4E9B;&#x7B80;&#x5355;&#x7684;&#x4ECB;&#x7ECD;&#xFF1A;</p>
<ol>
<li>Polling (Client Pull)</li>
<li>Websocket (Client Pull + Server Push)</li>
<li>SSE (Server Push)</li>
</ol>
<h2 id="polling">Polling</h2>
<p>Polling &#x5373;&#x6240;&#x8C13;&#x7684;&#x8F6E;&#x8BE2;&#xFF0C;&#x662F;&#x6700;&#x57FA;&#x7840;&#x7684;&#x65B9;&#x5F0F;&#xFF0C;&#x5B83;&#x4E0D;&#x9700;&#x8981;&#x989D;&#x5916;&#x7684;&#x517C;&#x5BB9;&#x6027;&#x652F;&#x6301;&#xFF0C;&#x6700;&#x7B80;&#x5355;&#x7684; HTTP &#x534F;&#x8BAE;&#x5C31;&#x80FD;&#x5B8C;&#x6210;&#xFF0C;&#x56E0;&#x6B64;&#x540E;&#x9762;&#x6240;&#x8981;&#x4ECB;&#x7ECD;&#x7684;&#x51E0;&#x79CD;&#x8F83;&#x4E3A;&#x9AD8;&#x7EA7;&#x7684;&#x5B9E;&#x65F6;&#x6027;&#x5B9E;&#x73B0;&#x65B9;&#x5F0F;&#x90FD;&#x4F1A;&#x505A;&#x4E00;&#x4E9B; fallback &#x517C;&#x5BB9;&#x7684;&#x65B9;&#x6CD5;&#x5373;&#x9000;&#x5316;&#x5230; Polling &#x65B9;&#x5F0F;&#x4EE5;&#x517C;&#x5BB9;&#x4E0D;&#x53D7;&#x652F;&#x6301;&#x7684;&#x6D4F;&#x89C8;&#x5668;&#x8BBE;&#x5907;&#x3002;</p>
<p>Polling &#x53C8;&#x53EF;&#x4EE5;&#x7EC6;&#x5206;&#x4E3A;&#x957F;&#x8F6E;&#x8BE2;&#xFF08;Long Polling&#xFF09;&#x548C;&#x77ED;&#x8F6E;&#x8BE2;&#xFF08;Short Polling&#xFF09;&#x3002;&#x5176;&#x4E2D;&#x77ED;&#x8F6E;&#x8BE2;&#x6700;&#x597D;&#x7406;&#x89E3;&#xFF0C;&#x5C31;&#x662F;&#x6BCF;&#x9694;&#x4E00;&#x6BB5;&#x65F6;&#x95F4;&#x6D4F;&#x89C8;&#x5668;&#x81EA;&#x52A8;&#x53D1;&#x9001; HTTP &#x8BF7;&#x6C42;&#x5411;&#x670D;&#x52A1;&#x7AEF;&#x62C9;&#x6570;&#x636E;&#xFF0C;&#x4F46;&#x662F;&#x8FD9;&#x5E76;&#x6CA1;&#x6709;&#x505A;&#x5230;&#x592A;&#x9AD8;&#x7684;&#x5B9E;&#x65F6;&#x6027;&#xFF0C;&#x56E0;&#x4E3A;&#x5B83;&#x53D6;&#x51B3;&#x4E8E;&#x5BA2;&#x6237;&#x7AEF;&#x7684; interval&#xFF0C;&#x82E5; 5 &#x79D2;&#x4E00;&#x6B21;&#x8BF7;&#x6C42;&#xFF0C;&#x90A3;&#x4E48;&#x5728; 3 &#x79D2;&#x65F6; A &#x53D1;&#x9001;&#x7684;&#x6D88;&#x606F;&#x5728; 5s &#x65F6; B &#x624D;&#x4F1A;&#x53BB;&#x8BF7;&#x6C42;&#x62FF;&#x5230;&#x6D88;&#x606F;&#xFF0C;&#x8FD9;&#x6837;&#x5C31;&#x6709;&#x4E86; 2s &#x7684;&#x5EF6;&#x8FDF;&#xFF0C;&#x4F46;&#x662F;&#x76F8;&#x6BD4;&#x5F00;&#x5934;&#x4E2D;&#x6240;&#x8BBE;&#x8BA1;&#x7684;&#x8BA9;&#x7528;&#x6237;&#x50BB;&#x4E4E;&#x4E4E;&#x7684;&#x70B9;&#x6309;&#x94AE;&#x81F3;&#x5C11;&#x8FDB;&#x6B65;&#x4E86;&#xFF0C;&#x5373;&#x6D4F;&#x89C8;&#x5668;&#x53BB;&#x6BCF;&#x9694;&#x4E00;&#x6BB5;&#x65F6;&#x95F4;&#x81EA;&#x52A8;&#x5E2E;&#x7528;&#x6237;&#x53BB;&#x70B9;&#x6309;&#x94AE;&#x3002;&#x957F;&#x8F6E;&#x8BE2;&#x7684;&#x51FA;&#x73B0;&#x5219;&#x89E3;&#x51B3;&#x8FD9;&#x4E2A; 2s &#x7684;&#x5EF6;&#x8FDF;&#xFF0C;&#x63D0;&#x9AD8;&#x5B9E;&#x65F6;&#x6027;&#x3002;&#x8FDE;&#x63A5;&#x5728;&#x4E00;&#x5F00;&#x59CB; B &#x5C31;&#x53D1;&#x9001;&#x4E86;&#x4E00;&#x4E2A; HTTP &#x8BF7;&#x6C42;&#xFF0C;&#x5728; A &#x8FD8;&#x6CA1;&#x6709;&#x53D1;&#x6D88;&#x606F;&#x65F6;&#x8FD9;&#x4E2A;&#x8BF7;&#x6C42;&#x4F1A;&#x4E00;&#x76F4;&#x963B;&#x585E;&#xFF0C;&#x76F4;&#x5230; A &#x53D1;&#x9001;&#x4E86;&#x6D88;&#x606F;&#x670D;&#x52A1;&#x7AEF;&#x5C31;&#x4F1A;&#x7ACB;&#x9A6C;&#x5C06; A &#x53D1;&#x9001;&#x7684;&#x6D88;&#x606F;&#x4F5C;&#x4E3A;&#x90A3;&#x4E2A;&#x963B;&#x585E;&#x7684; HTTP &#x8BF7;&#x6C42;&#x7684;&#x8FD4;&#x56DE;&#x7ED9; B&#x3002;B &#x5728;&#x6536;&#x5230; HTTP &#x54CD;&#x5E94;&#x4E4B;&#x540E;&#x53C8;&#x4F1A;&#x7ACB;&#x523B;&#x518D;&#x53D1;&#x9001; HTTP &#x8BF7;&#x6C42;&#x5982;&#x6B64;&#x5F80;&#x590D;&#x3002;&#x8FD9;&#x6837;&#x5B9E;&#x65F6;&#x6027;&#x5C31;&#x5DF2;&#x7ECF;&#x5F97;&#x5230;&#x4E86;&#x975E;&#x5E38;&#x5927;&#x7684;&#x63D0;&#x9AD8;&#xFF0C;&#x5176;&#x5EF6;&#x65F6;&#x5C31;&#x53EA;&#x5728;&#x7F51;&#x7EDC;&#x5EF6;&#x8FDF;&#x3001;TCP &#x63E1;&#x624B;&#x3001;SSL &#x63E1;&#x624B;&#x7B49;&#x8FDE;&#x63A5;&#x5EFA;&#x7ACB;&#x7684;&#x65F6;&#x95F4;&#x6D88;&#x8017;&#x4E0A;&#x4E86;&#x3002;</p>
<h2 id="websocket">Websocket</h2>
<p>Websocket &#x662F;&#x4E00;&#x4E2A;&#x89E3;&#x51B3; Web &#x4E2D;&#x5B9E;&#x65F6;&#x6027;&#x6570;&#x636E;&#x4F20;&#x8F93;&#x95EE;&#x9898;&#x7684;&#x6700;&#x4E3A;&#x5E7F;&#x6CDB;&#x4F7F;&#x7528;&#x7684;&#x65B9;&#x5F0F;&#x3002;&#x5B83;&#x4F7F;&#x7528; HTTP &#x534F;&#x8BAE;&#x8FDB;&#x884C;&#x63E1;&#x624B;&#xFF0C;&#x6D4F;&#x89C8;&#x5668;&#x5EFA;&#x7ACB; Websocket &#x901A;&#x4FE1;&#x7684; HTTP &#x8BF7;&#x6C42;&#x5934;&#x90E8;&#x5982;&#x4E0B;&#xFF1A;</p>
<pre><code>GET /websocket HTTP/1.1
Host: 127.0.0.1:8000
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Origin: http://127.0.0.1:8000
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
Sec-WebSocket-Key: umeTOPSdULFnza3ucv1Izw==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

</code></pre>
<p>&#x5176;&#x4E2D;&#x4E3B;&#x8981;&#x5728; <code>Connection:Upgrade</code> &#x8FD9;&#x4E2A;&#x5B57;&#x6BB5;&#xFF0C;&#x544A;&#x8BC9;&#x670D;&#x52A1;&#x7AEF;&#x8981;&#x8FDB;&#x884C;&#x4E00;&#x6B21;&#x8FDE;&#x63A5;&#x7684;<strong>&#x5347;&#x7EA7;</strong>&#xFF0C;&#x4F46;&#x662F;&#x6240;&#x8C13;&#x5347;&#x7EA7;&#xFF0C;&#x4ECE;&#x7F51;&#x7EDC;&#x534F;&#x8BAE;&#x6808;&#x4E0A;&#x6765;&#x770B;&#x5B9E;&#x9645;&#x4E0A;&#x662F;&#x4E00;&#x6B21;<strong>&#x964D;&#x7EA7;</strong>&#xFF1A;&#x4ECE; 7 &#x5C42;&#x7684; HTTP &#x534F;&#x8BAE;<strong>&#x964D;&#x7EA7;</strong>&#x4E3A;&#x539F;&#x59CB;&#x7684; TCP &#x534F;&#x8BAE;&#x3002;&#x670D;&#x52A1;&#x7AEF;&#x8FD4;&#x56DE;&#x7684;&#x72B6;&#x6001;&#x7801;&#x4E3A; <code>101</code> :</p>
<pre><code>HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: 96PLAgW2q+VO9O7ubrmfQB6jhyY=
</code></pre>
<p>&#x968F;&#x540E;&#x6D4F;&#x89C8;&#x5668;&#x548C;&#x670D;&#x52A1;&#x7AEF;&#x5C31;&#x4EE5; Websocket &#x534F;&#x8BAE;&#xFF08;<a href="https://tools.ietf.org/html/rfc6455">https://tools.ietf.org/html/rfc6455</a>&#xFF09;&#x5728;&#x8FD9;&#x4E2A; TCP &#x8FDE;&#x63A5;&#x4E0A;&#x8FDB;&#x884C;&#x901A;&#x4FE1;&#xFF0C;&#x4E0D;&#x518D;&#x662F; HTTP &#x7684;&#x5F62;&#x5F0F;&#x800C;&#x662F; TCP &#x7684;&#x5F62;&#x5F0F;&#x8FDB;&#x884C;&#x6570;&#x636E;&#x4F20;&#x8F93;&#x3002;&#x800C;&#x4E14;&#x8FD9;&#x4E2A; TCP &#x8FDE;&#x63A5;&#x53EF;&#x4EE5;&#x662F;&#x5168;&#x53CC;&#x5DE5;&#x7684;&#xFF0C;&#x4E5F;&#x5C31;&#x662F;&#x8BF4;&#x4E0D;&#x4EC5;&#x5BA2;&#x6237;&#x7AEF;&#x53EF;&#x4EE5;&#x53D1;&#x9001; Frame&#xFF0C;&#x670D;&#x52A1;&#x7AEF;&#x8FD8;&#x53EF;&#x4EE5;&#x5728;&#x8FD9;&#x4E2A; TCP &#x8FDE;&#x63A5;&#x4E0A;&#x5411;&#x6D4F;&#x89C8;&#x5668;&#x63A8;&#x9001;&#x6570;&#x636E;&#x3002;&#x76F8;&#x6BD4; Polling&#xFF0C;&#x5B83;&#x7684;&#x4F18;&#x52BF;&#x63D0;&#x5347;&#x5728;&#xFF1A;</p>
<ol>
<li>&#x63D0;&#x4F9B;&#x4E00;&#x4E2A;&#x53CC;&#x5411;&#x6D41;&#x540C;&#x65F6;&#x652F;&#x6301; Server Push &#x548C; Client Push</li>
<li>&#x4E00;&#x6B21; HTTP &#x63E1;&#x624B;&#x540E;&#x5C31;&#x5EFA;&#x7ACB;&#x4E86; TCP &#x8FDE;&#x63A5;&#xFF0C;&#x51CF;&#x5C11;&#x4E86; Polling &#x4E2D;&#x91CD;&#x590D;&#x7684; HTTP &#x5EFA;&#x7ACB;&#x8FC7;&#x7A0B;</li>
<li>&#x76F4;&#x63A5;&#x4F7F;&#x7528; TCP &#x8FDE;&#x63A5;&#x4F20;&#x8F93;&#x6570;&#x636E;&#xFF0C;&#x6CA1;&#x6709; HTTP &#x591A;&#x4F59;&#x7684;&#x5934;&#x90E8;&#x4FE1;&#x606F;&#xFF0C;&#x6570;&#x636E;&#x91CF;&#x5C0F;&#x4F20;&#x8F93;&#x5FEB;</li>
</ol>
<p>&#x4F7F;&#x7528; Python &#x7684; Sanic &#x6846;&#x67B6;&#x4E2D;&#x63D0;&#x4F9B;&#x7684; Webscoket&#xFF1A;</p>
<pre><code class="language-python">@app.websocket(&quot;/websocket&quot;)
async def feed(req, ws):
    while True:
        now = datetime.datetime.now().isoformat()
        await ws.send(json.dumps({&quot;now&quot;: now}))
        await asyncio.sleep(5)
</code></pre>
<p>&#x6D4F;&#x89C8;&#x5668;&#x5BA2;&#x6237;&#x7AEF;&#x4E2D;&#x7684;&#x4F7F;&#x7528;&#x4E5F;&#x5F88;&#x65B9;&#x4FBF;&#xFF0C;new &#x4E00;&#x4E2A;&#x539F;&#x751F;&#x7684; <code>Websocket</code> &#x7C7B;&#x7136;&#x540E;&#x4F20;&#x5165;&#x51E0;&#x4E2A; on &#x4E8B;&#x4EF6;&#x7684;&#x51FD;&#x6570;&#x5373;&#x53EF;&#xFF1A;</p>
<pre><code class="language-javascript">//&#x70B9;&#x51FB;&#x6309;&#x94AE;&#x4E0E;&#x670D;&#x52A1;&#x7AEF;&#x5EFA;&#x7ACB;Websocket&#x8FDE;&#x63A5;
document.getElementById(&quot;btn-ws&quot;).onclick = () =&gt; {
    var loc = window.location
    var ws_protocol = loc.protocol === &quot;https&quot; ? &quot;wss://&quot; : &quot;ws://&quot;
    var ws = new WebSocket(ws_protocol + loc.host + &quot;/websocket&quot;)
    ws.onopen = ev =&gt; {
        console.log(&quot;Websocket open&quot;)
    }
    ws.onclose = ev =&gt; {
        console.log(&quot;Websocket close&quot;)
    }
    ws.onmessage = ev =&gt; {
        console.log(ev.data)
    }
}
</code></pre>
<p>&#x4F7F;&#x7528; Chrome &#x5F00;&#x53D1;&#x8005;&#x5DE5;&#x5177;&#x53EF;&#x76F4;&#x89C2;&#x770B;&#x5230; Websocket &#x7684;&#x6570;&#x636E;&#x4F20;&#x8F93;&#x60C5;&#x51B5;&#xFF1A;</p>
<img src="https://cdn.nlark.com/yuque/0/2019/png/110142/1556295570122-8e3fa857-1cf5-4dba-ad02-1203a3e8a607.png#align=left&amp;display=inline&amp;height=473&amp;name=image.png&amp;originHeight=946&amp;originWidth=1092&amp;size=161784&amp;status=done&amp;width=546" referrerpolicy="no-referrer">
<h2 id="sseserversendevents">SSE(Server-Send-Events)</h2>
<p>SSE &#x662F;&#x4E00;&#x4E2A;&#x6BD4;&#x8F83;&#x5C11;&#x89C1;&#x7684;&#x5B9E;&#x73B0;&#x65B9;&#x6848;&#xFF0C;&#x8FD9;&#x662F;&#x6211;&#x6700;&#x8FD1;&#x5728;&#x505A;&#x6784;&#x5EFA;&#x65E5;&#x5FD7;&#x5C55;&#x793A;&#x76F8;&#x5173;&#x4E1A;&#x52A1;&#x65F6;&#x60F3;&#x5B9E;&#x65F6;&#x5C55;&#x793A;&#x6784;&#x5EFA;&#x65E5;&#x5FD7;&#x4E8E;&#x662F;&#x53BB;&#x770B;&#x4E86;&#x6211;&#x4EEC;&#x6240;&#x4F7F;&#x7528;&#x7684;&#x6784;&#x5EFA;&#x7CFB;&#x7EDF; DroneCI &#x600E;&#x4E48;&#x5B9E;&#x73B0;&#x7684;&#xFF0C;&#x624D;&#x53D1;&#x73B0;&#x4ED6;&#x4EEC;&#x5B9E;&#x65F6;&#x5C55;&#x793A;&#x65E5;&#x5FD7;&#x662F;&#x4F7F;&#x7528;&#x7684;&#x8FD9;&#x4E2A;&#x65B9;&#x6848;&#x3002;&#x76F8;&#x6BD4; Websocket &#x5B83;&#x4EC5;&#x652F;&#x6301; Server Push&#xFF0C;&#x7406;&#x89E3;&#x5B83;&#x7684;&#x539F;&#x7406;&#x4E5F;&#x6BD4;&#x8F83;&#x7B80;&#x5355;&#xFF0C;&#x5B83;&#x8FD8;&#x662F;&#x57FA;&#x4E8E;&#x4E00;&#x4E2A;&#x6B63;&#x5E38;&#x7684; HTTP &#x7684;&#x8BF7;&#x6C42;&#xFF0C;&#x5B83;&#x5229;&#x7528; HTTP &#x534F;&#x8BAE;&#x4F20;&#x8F93;&#x6570;&#x636E;&#x662F;&#x6D41;&#x5F0F;&#x7684;&#x7279;&#x5F81;&#xFF0C;&#x670D;&#x52A1;&#x7AEF;&#x5728;&#x54CD;&#x5E94;&#x4E2D;&#x53BB;&#x5B9E;&#x65F6;&#x5199;&#x5185;&#x5BB9;&#xFF0C;&#x4E3A;&#x4E86;&#x5728;&#x8FD9;&#x4E2A;&#x6D41;&#x4E0A;&#x533A;&#x5206;&#x6D88;&#x606F;&#x548C;&#x6807;&#x793A;&#x4E00;&#x4E9B;&#x4FE1;&#x606F;&#xFF0C;&#x8FD9;&#x4E2A;&#x6807;&#x51C6;&#x53EA;&#x505A;&#x4E86;&#x4E00;&#x4E9B;&#x7B80;&#x5355;&#x7684;&#x7EA6;&#x675F;&#xFF1A;</p>
<p>&#x4EE5; <code>data: xxxx\n\n</code> &#x7684;&#x5F62;&#x5F0F;&#x4F20;&#x8F93;&#x6570;&#x636E;&#xFF0C;&#x5176;&#x4E2D; xxxx &#x662F;&#x5185;&#x5BB9;&#xFF0C; <code>\n\n</code> &#x6765;&#x5206;&#x5272;&#x4E0D;&#x540C;&#x7684;&#x6D88;&#x606F;&#xFF0C;&#x53E6;&#x5916;&#x8FD8;&#x63D0;&#x4F9B;&#x4E24;&#x4E2A;&#x53EF;&#x9009;&#x7684;&#x6807;&#x793A; <code>id: 1\n</code> &#x6807;&#x8BC6;&#x6D88;&#x606F; id&#xFF0C; <code>event: xxx\n</code> &#x6807;&#x8BC6;&#x65F6;&#x95F4;&#x7C7B;&#x578B;&#xFF0C;&#x8FD9;&#x6837;&#x5728; HTTP &#x6D41;&#x4E2D;&#x4E00;&#x4E2A;&#x5B8C;&#x6574;&#x7684;&#x6D88;&#x606F;&#x53EF;&#x80FD;&#x957F;&#x8FD9;&#x6837;&#xFF1A;</p>
<pre><code>id:1\n
event:message\n
data:helloworld\n\n
</code></pre>
<p>&#x4F7F;&#x7528; Python &#x7684; Sanic &#x6846;&#x67B6;&#x7684;&#x4E00;&#x4E2A;&#x7B80;&#x5355;&#x7684;&#x5199;&#x6CD5;&#x5982;&#x4E0B;&#xFF1A;</p>
<pre><code class="language-python">@app.get(&quot;/sse&quot;)
async def sse_handler(req):
    &quot;&quot;&quot;
    Server-Send-Event
    &quot;&quot;&quot;

    def sse_data(data: str, event: str = None, id: int = None) -&gt; str:
        &quot;&quot;&quot;
        &#x7EC4;&#x88C5;sse&#x4FE1;&#x606F;
        &quot;&quot;&quot;
        resp = &quot;data: %s\n\n&quot; % data
        if event is not None and event != &quot;&quot;:
            resp = &quot;event: %s\n&quot; % event + resp
        if id is not None:
            resp = &quot;id: %d\n&quot; % id + resp
        return resp

    async def streaming(resp):
        for i in range(1, 10):
            now = datetime.datetime.now().isoformat()
            await resp.write(sse_data(data=json.dumps({&quot;now&quot;: now}), event=&quot;timenow&quot;, id=i))
            await asyncio.sleep(5)

    return response.stream(streaming, content_type=&quot;text/event-stream&quot;)
</code></pre>
<p>&#x5BA2;&#x6237;&#x7AEF; JS &#x4F7F;&#x7528;&#x539F;&#x751F;&#x7684; <code>EventSouce</code> &#xFF08;<a href="https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events">https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events</a>&#xFF09;&#x5BF9;&#x8C61;&#xFF1A;</p>
<pre><code class="language-javascript">var source = new EventSource(&quot;/sse&quot;)
source.onopen = e =&gt; {
    // Event type=open
    console.log(&quot;SSE open&quot;)
}
source.onerror = e =&gt; {
    // Event type=error
    console.log(&quot;SSE error&quot;)
}
source.onmessage = e =&gt; {
    // MessageEvent type=message
    console.log(&quot;SSE message: &quot; + e.data)
}
</code></pre>
<p>&#x4F7F;&#x7528; Chrome &#x5F00;&#x53D1;&#x8005;&#x5DE5;&#x5177;&#x89C2;&#x5BDF; SSE &#x8BF7;&#x6C42;&#xFF1A;</p>
<img src="https://cdn.nlark.com/yuque/0/2019/png/110142/1556295615852-e1da3f52-c1e8-4b2e-b992-f15ef4b6ae91.png#align=left&amp;display=inline&amp;height=473&amp;name=image.png&amp;originHeight=946&amp;originWidth=1060&amp;size=111514&amp;status=done&amp;width=530" referrerpolicy="no-referrer">
<p>&#x56E0;&#x4E3A;&#x5B83;&#x4ECE;&#x539F;&#x7406;&#x4E0A;&#x6BD4; Websocket &#x8981;&#x7B80;&#x5355;&#x4E00;&#x4E9B;&#xFF0C;&#x56E0;&#x6B64;&#x82E5;&#x662F;&#x53EA;&#x9700;&#x8981;&#x670D;&#x52A1;&#x7AEF;&#x63A8;&#x9001;&#x6570;&#x636E;&#x7684;&#x573A;&#x666F;&#xFF0C;&#x6BD4;&#x5982;&#x4E0A;&#x9762;&#x6240;&#x8BF4;&#x7684;&#x5B9E;&#x65F6;&#x83B7;&#x53D6;&#x4E00;&#x4E9B;&#x65E5;&#x5FD7;&#xFF0C;&#x4F7F;&#x7528; SSE &#x4E5F;&#x662F;&#x4E00;&#x79CD;&#x53EF;&#x9009;&#x7684;&#x65B9;&#x6848;&#x3002;</p>
<h2 id>&#x4E00;&#x4E2A;&#x5F88;&#x68D2;&#x7684;&#x65F6;&#x5E8F;&#x56FE;</h2>
<p>&#x6709;&#x4E00;&#x4E2A;&#x6BD4;&#x8F83;&#x76F4;&#x89C2;&#x6613;&#x61C2;&#x7684;&#x7F51;&#x7EDC;&#x8BF7;&#x6C42;&#x65F6;&#x5E8F;&#x56FE;&#x53BB;&#x5BF9;&#x6BD4;&#x4E86;&#x89E3;&#x5176;&#x4E2D;&#x51E0;&#x79CD;&#x65B9;&#x5F0F;&#x7684;&#x539F;&#x7406;&#xFF1A;</p>
<img src="https://cdn.nlark.com/yuque/0/2019/png/110142/1556296076171-ffc00850-9eee-498d-9760-1d9952f75b90.png#align=left&amp;display=inline&amp;height=385&amp;name=image.png&amp;originHeight=769&amp;originWidth=1059&amp;size=89897&amp;status=done&amp;width=529.5" referrerpolicy="no-referrer">
<h2 id>&#x53C2;&#x8003;</h2>
<ol>
<li><a href="https://codeburst.io/polling-vs-sse-vs-websocket-how-to-choose-the-right-one-1859e4e13bd9">https://codeburst.io/polling-vs-sse-vs-websocket-how-to-choose-the-right-one-1859e4e13bd9</a></li>
<li><a href="https://tools.ietf.org/html/rfc6455">https://tools.ietf.org/html/rfc6455</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events">https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events</a></li>
</ol>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[istio-pilot 进行配置推送源码分析（以EDS为例）]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>&#x5728;&#x516C;&#x53F8;&#x5B9E;&#x4E60;&#x63A5;&#x89E6;&#x5230; <strong>istio</strong> &#x8FD9;&#x4E2A;&#x5F3A;&#x5927;&#x7684;&#x5FAE;&#x670D;&#x52A1;&#x6846;&#x67B6;&#xFF0C;&#x4F5C;&#x4E3A;&#x4E00;&#x4E2A;&#x5FAE;&#x670D;&#x52A1;&#x6846;&#x67B6;&#xFF0C;&#x6838;&#x5FC3;&#x529F;&#x80FD;&#x4E4B;&#x4E00;&#x5C31;&#x662F;<strong>&#x670D;&#x52A1;&#x53D1;&#x73B0;</strong>&#xFF08;Service Discovery&#xFF09;&#xFF0C;&#x5728;istio&#x4E2D;</p>]]></description><link>https://ruofeng.me/2018/11/08/how-does-istio-pilot-push-eds-config/</link><guid isPermaLink="false">5d8e378da7d96200019ade23</guid><category><![CDATA[istio]]></category><dc:creator><![CDATA[Ruofeng Lei]]></dc:creator><pubDate>Thu, 08 Nov 2018 14:49:32 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>&#x5728;&#x516C;&#x53F8;&#x5B9E;&#x4E60;&#x63A5;&#x89E6;&#x5230; <strong>istio</strong> &#x8FD9;&#x4E2A;&#x5F3A;&#x5927;&#x7684;&#x5FAE;&#x670D;&#x52A1;&#x6846;&#x67B6;&#xFF0C;&#x4F5C;&#x4E3A;&#x4E00;&#x4E2A;&#x5FAE;&#x670D;&#x52A1;&#x6846;&#x67B6;&#xFF0C;&#x6838;&#x5FC3;&#x529F;&#x80FD;&#x4E4B;&#x4E00;&#x5C31;&#x662F;<strong>&#x670D;&#x52A1;&#x53D1;&#x73B0;</strong>&#xFF08;Service Discovery&#xFF09;&#xFF0C;&#x5728;istio&#x4E2D;&#x8D1F;&#x8D23;&#x670D;&#x52A1;&#x53D1;&#x73B0;&#x7684;&#x6838;&#x5FC3;&#x7EC4;&#x4EF6;&#x5C31;&#x662F; <strong>istio-pilot</strong> &#xFF0C;&#x5B83;&#x662F;&#x5982;&#x4F55;&#x7BA1;&#x7406;&#x96C6;&#x7FA4;&#x4E2D;&#x7684;&#x670D;&#x52A1;&#x5E76;&#x5C06;&#x5404;&#x4E2A;&#x670D;&#x52A1;&#x7684;&#x5177;&#x4F53;&#x4FE1;&#x606F;&#x4E0B;&#x53D1;&#x5230;&#x6240;&#x6709;&#x5176;&#x4ED6;&#x670D;&#x52A1;&#x7684;&#x5462;&#x4EE5;&#x6D41;&#x7545;&#x7BA1;&#x7406;&#x6574;&#x4E2A;&#x670D;&#x52A1;&#x7F51;&#x683C;&#x4E4B;&#x95F4;&#x7684;&#x8BF7;&#x6C42;&#x7684;&#x987A;&#x5229;&#x8FDB;&#x884C;&#x5462;&#x3002;&#x4E8E;&#x662F;&#x524D;&#x51E0;&#x5468;&#x5F88;&#x957F;&#x4E00;&#x6BB5;&#x65F6;&#x95F4;&#x6211;&#x90FD;&#x5728;&#x9605;&#x8BFB; isito-pilot &#x90E8;&#x5206;&#x7684;&#x6E90;&#x7801;&#xFF0C;&#x5C1D;&#x8BD5;&#x7406;&#x89E3;&#x5176;&#x914D;&#x7F6E;&#x66F4;&#x65B0;&#x63A8;&#x9001;&#x7684;&#x539F;&#x7406;&#xFF0C;&#x4E0B;&#x9762;&#x662F;&#x4E00;&#x4E9B;&#x7C97;&#x6D45;&#x7684;&#x89E3;&#x8BFB;&#x4E0E;&#x603B;&#x7ED3;&#x3002;</p>
<h2 id>&#x914D;&#x7F6E;&#x66F4;&#x65B0;&#x7684;&#x60C5;&#x666F;</h2>
<ul>
<li>pilot-discovery &#x76D1;&#x542C;&#x5230; k8s &#x5185; Pod &#x7684;&#x53D8;&#x5316;&#xFF0C;&#x5C06;&#x65B0;&#x7684; endpoint &#x4FE1;&#x606F;&#x63A8;&#x9001;&#x7ED9;&#x6240;&#x6709; envoy</li>
<li>envoy &#x53D1;&#x9001; DiscoveryRequest &#x8BF7;&#x6C42;&#x5230; pilot-dicovery&#xFF0C;&#x67E5;&#x8BE2;&#x914D;&#x7F6E;&#x4FE1;&#x606F;</li>
<li>&#x5373;&#x4F7F;&#x914D;&#x7F6E;&#x6CA1;&#x6709;&#x66F4;&#x65B0;&#xFF0C;pilot-discovery &#x4E5F;&#x4F1A;&#x5468;&#x671F;&#x6027;&#x63A8;&#x9001;&#x914D;&#x7F6E;&#x7ED9;&#x6240;&#x6709; envoy&#xFF08;&#x9ED8;&#x8BA4;&#x7981;&#x7528;&#xFF09;</li>
</ul>
<p>&#x5176;&#x4E2D;&#x4E3B;&#x8981;&#x7814;&#x7A76;&#x7B2C;&#x4E00;&#x79CD;&#x573A;&#x666F;&#xFF0C;&#x5373; pilot-discovery <strong>&#x4E3B;&#x52A8;&#x63A8;&#x9001;</strong>&#x914D;&#x7F6E;&#x7ED9;&#x6240;&#x6709; envoy&#xFF0C;&#x56E0;&#x4E3A;&#x8FD9;&#x4E2A;&#x573A;&#x666F;&#x662F;&#x670D;&#x52A1;&#x7684;&#x8FD0;&#x884C;&#x4E2D;&#x4F1A;&#x968F;&#x65F6;&#x53D1;&#x751F;&#x7684;&#xFF0C;&#x975E;&#x5E38;&#x666E;&#x904D;&#xFF0C;&#x800C;&#x4E14;&#x5B83;&#x5BF9;&#x4E0E;&#x670D;&#x52A1;&#x8FD0;&#x884C;&#x7684;&#x7A33;&#x5B9A;&#x6027;&#x662F;&#x606F;&#x606F;&#x76F8;&#x5173;&#x7684;&#xFF0C;&#x5C24;&#x5176;&#x662F;&#x5728;&#x6269;&#x5BB9;&#x7F29;&#x5BB9;&#x3001;&#x610F;&#x5916;&#x5B95;&#x673A;&#x3001;&#x6D41;&#x91CF;&#x914D;&#x7F6E;&#x53D8;&#x66F4;&#x7B49;&#x7B49;&#x65F6;&#x523B;&#xFF0C;&#x65F6;&#x9700;&#x8981;&#x4FDD;&#x8BC1;&#x6240;&#x6709;&#x7684; sidecar &#x80FD;&#x591F;&#x5728;&#x7B2C;&#x4E00;&#x65F6;&#x95F4;&#x5F97;&#x5230;&#x8FD9;&#x4E00;&#x53D8;&#x66F4;&#x4FE1;&#x606F;&#x3002;</p>
<p>&#x5728;&#x96C6;&#x7FA4;&#x4E2D;&#xFF0C;&#x6BCF;&#x4E2A; Pod &#x542F;&#x52A8;&#x65F6;&#x5176; sidecar &#x90FD;&#x4F1A;&#x4E0E; pilot-discovery &#x5EFA;&#x7ACB;&#x4E00;&#x4E2A;&#x53CC;&#x5411; gRPC &#x8FDE;&#x63A5;&#xFF0C;server &#x7AEF;&#x4F1A;&#xFF08;pilot-discovery&#xFF09;&#x5728;&#x4E00;&#x4E2A; select &#x4E2D;&#x63A5;&#x6536;&#x4E24;&#x79CD;&#x901A;&#x9053;&#x7684;&#x4FE1;&#x606F;&#xFF0C;&#x5206;&#x522B;&#x5BF9;&#x5E94; <strong>&#x54CD;&#x5E94;&#x67E5;&#x8BE2;&#x8BF7;&#x6C42;</strong> &#x4E0E; <strong>&#x4E3B;&#x52A8;&#x63A8;&#x9001;&#x914D;&#x7F6E;</strong>&#xFF0C;&#x6E90;&#x4EE3;&#x7801;&#x4F4D;&#x7F6E;&#x5982;&#x4E0B;&#xFF1A;</p>
<p>&#x9996;&#x5148;&#x662F;&#x521D;&#x59CB;&#x5316;&#x53D1;&#x73B0;&#x670D;&#x52A1;<code>initDiscoveryService</code></p>
<p><a href="https://github.com/istio/istio/blob/1.0.2/pilot/pkg/bootstrap/server.go#L844"><code>initDiscoveryService</code></a></p>
<pre><code class="language-go">func (s *Server) initDiscoveryService(args *PilotArgs) error {

	//&#x524D;&#x9762;&#x4F1A;&#x6709;&#x4E00;&#x4E9B;&#x83B7;&#x53D6;&#x53C2;&#x6570;&#x3001;&#x65B0;&#x5EFA;&#x65E7;&#x7248;&#x672C;v1&#x7684;DiscoveryServer&#xFF0C;&#x7528;&#x4E8E;&#x4E00;&#x4E9B;&#x65E7;&#x7248;&#x672C;&#x517C;&#x5BB9;&#x8FD8;&#x6709;debug&#x64CD;&#x4F5C;
	...

	//&#x542F;&#x52A8;envoy api v2&#x7248;&#x672C;&#x7684;DiscoveryServer
	s.EnvoyXdsServer = envoyv2.NewDiscoveryServer(environment, istio_networking.NewConfigGenerator(args.Plugins))
	envoy.V2ClearCache = s.EnvoyXdsServer.ClearCacheFunc()
	s.EnvoyXdsServer.Register(s.grpcServer)
	//Register&#x8FD9;&#x91CC;&#x4E3B;&#x8981;&#x662F;&#x6CE8;&#x518C;&#x4E86;&#x4E24;&#x79CD;gRPC stream
	//1. StreamAggregatedResources      &#x5B9E;&#x73B0;ADS&#x63A5;&#x53E3;&#xFF0C;&#x4E3B;&#x8981;&#x5173;&#x6CE8;&#x8FD9;&#x91CC;
	//2. IncrementalAggregatedResources &#x7528;&#x4E8E;&#x589E;&#x91CF;&#x66F4;&#x65B0;&#xFF0C;push&#x6548;&#x7387;&#x66F4;&#x9AD8;&#xFF0C;&#x5728;1.0.3&#x4E2D;&#x5B9E;&#x73B0;&#x4E86;EDS&#x7684;&#x589E;&#x91CF;&#x66F4;&#x65B0;

	...

	//&#x5728;&#x8FD9;&#x4E2A;init&#x4E2D;&#x6DFB;&#x52A0;StartFunc&#xFF0C;&#x542F;&#x52A8;&#x4E86;&#x5404;&#x79CD;HTTP&#x3001;gRPC Server
	s.addStartFunc(func(stop &lt;-chan struct{}) error {
		log.Infof(&quot;Discovery service started at http=%s grpc=%s&quot;, listener.Addr().String(), grpcListener.Addr().String())
		...
		go func() {
			if err = s.grpcServer.Serve(grpcListener); err != nil {
				log.Warna(err)
			}
		}()
		...

		return err
	})

	return nil
}
</code></pre>
<p>&#x7136;&#x540E;&#x5728;<code>StreamAggregatedResources</code>&#x4E2D;&#x4E3B;&#x8981;&#x5728;&#x4E00;&#x4E2A; select &#x4E2D;&#x63A5;&#x6536;&#x4E24;&#x4E2A;&#x901A;&#x9053;&#x7684;&#x6D88;&#x606F;&#x8FDB;&#x884C;&#x5904;&#x7406;</p>
<p><a href="https://github.com/istio/istio/blob/1.0.2/pilot/pkg/proxy/envoy/v2/ads.go#L336"><code>case discReq, ok = &lt;-reqChannel</code></a> &#x7528;&#x4E8E;&#x63A5;&#x6536; envoy &#x7684;&#x8BF7;&#x6C42;&#x88AB;&#x52A8;&#x63A8;&#x9001;</p>
<p><a href="https://github.com/istio/istio/blob/1.0.2/pilot/pkg/proxy/envoy/v2/ads.go#L472"><code>case pushEv, _ := &lt;-con.pushChannel</code></a> &#x7528;&#x4E8E;&#x63A5;&#x6536; watch &#x7684;&#x914D;&#x7F6E;&#x53D8;&#x5316;&#x7136;&#x540E;&#x4E3B;&#x52A8;&#x5411; envoy &#x63A8;&#x9001;&#x66F4;&#x65B0;</p>
<h2 id>&#x76D1;&#x542C;&#x5E76;&#x63A8;&#x9001;&#x8FC7;&#x7A0B;</h2>
<p>pilot-discovery &#x5728;&#x542F;&#x52A8;&#x65F6;&#x4F1A;&#x521D;&#x59CB;&#x5316;&#x4E00;&#x4E2A; ServiceController &#x5B83;&#x4F1A;&#x53BB;&#x4E0E; k8s &#x5BF9;&#x63A5;&#x540C;&#x6B65;&#x5176;&#x76F8;&#x5173;&#x7684;&#x670D;&#x52A1;&#x6CE8;&#x518C;&#x4FE1;&#x606F;&#xFF0C;&#x5728;<code>NewController</code>&#x65B9;&#x6CD5;&#x4E2D;&#x4F1A;&#x5BF9;&#x8FD9;&#x4E9B;&#x8D44;&#x6E90;&#xFF1A;</p>
<ul>
<li>Service</li>
<li>Endpoint</li>
<li>Node</li>
<li>Pod</li>
</ul>
<p>&#x8FDB;&#x884C;&#x4E00;&#x4E2A; watch/inform &#x7684;&#x64CD;&#x4F5C;&#xFF0C;&#x5728;&#x521D;&#x59CB;&#x5316;&#x65F6;&#x4F1A;&#x6267;&#x884C;<strong>List</strong>&#x4EE5;&#x83B7;&#x53D6;&#x6240;&#x6709;&#x9700;&#x8981;&#x7684;&#x670D;&#x52A1;&#x6CE8;&#x518C;&#x4FE1;&#x606F;&#x7136;&#x540E;&#x4FDD;&#x5B58;&#x5728;&#x81EA;&#x5DF1;&#x7684;&#x4E00;&#x4E2A; Cache &#x4E2D;&#xFF0C;&#x968F;&#x540E;&#x4F1A;&#x8FDB;&#x884C;<strong>Watch</strong>&#x6765;&#x76D1;&#x542C;&#x53D8;&#x66F4;&#x6765;&#x66F4;&#x65B0;&#x8FD9;&#x4E2A; Cache&#xFF0C;&#x8FD9;&#x4E2A; watch &#x64CD;&#x4F5C;&#x5B9E;&#x9645;&#x4E0A;&#x662F; k8s &#x96C6;&#x7FA4;&#x7684; apiserver &#x6240;&#x63D0;&#x4F9B;&#x7684;&#x4E00;&#x4E2A;&#x9AD8;&#x6548;&#x76D1;&#x542C;&#x53D8;&#x5316;&#x7684;&#x65B9;&#x5F0F;&#x3002;</p>
<p>&#x5728;<a href="https://github.com/istio/istio/blob/1.0.2/pilot/pkg/serviceregistry/kube/controller.go#L104"><code>NewController</code></a> &#x4E2D;&#xFF0C;&#x5373;&#x5728;<code>server.go</code>&#x91CC;&#x521B;&#x5EFA;<code>createK8sServiceController</code>&#x65F6;&#x4F1A;&#x5BF9;&#x8FD9;&#x4E9B;&#x8D44;&#x6E90;&#x521B;&#x5EFA;  &#x76F8;&#x5E94;&#x7684; watch/informer</p>
<pre><code class="language-go">out.services = out.createInformer(&amp;v1.Service{}, &quot;Service&quot;, options.ResyncPeriod,
	func(opts meta_v1.ListOptions) (runtime.Object, error) {
		return client.CoreV1().Services(options.WatchedNamespace).List(opts)
	},
	func(opts meta_v1.ListOptions) (watch.Interface, error) {
		return client.CoreV1().Services(options.WatchedNamespace).Watch(opts)
	})
// out.endpoints=...
// out.nodes=...
// out.pods=...
</code></pre>
<p>&#x5728;&#x5BF9;&#x6BCF;&#x4E2A;&#x7C7B;&#x578B;&#x8D44;&#x6E90;&#x7684;<code>createInformer</code>&#x65F6;&#xFF0C;&#x4F1A;&#x6DFB;&#x52A0; handler&#xFF1A;</p>
<p><a href="https://github.com/istio/istio/blob/1.0.2/pilot/pkg/serviceregistry/kube/controller.go#L165"><code>kube/controller.go#L165</code></a></p>
<pre><code class="language-go">informer.AddEventHandler(
    cache.ResourceEventHandlerFuncs{
        AddFunc: func(obj interface{}) {
            k8sEvents.With(prometheus.Labels{&quot;type&quot;: otype, &quot;event&quot;: &quot;add&quot;}).Add(1)
            c.queue.Push(Task{handler: handler.Apply, obj: obj, event: model.EventAdd})
        },
        UpdateFunc: func(old, cur interface{}) {
            if !reflect.DeepEqual(old, cur) {
                k8sEvents.With(prometheus.Labels{&quot;type&quot;: otype, &quot;event&quot;: &quot;update&quot;}).Add(1)
                c.queue.Push(Task{handler: handler.Apply, obj: cur, event: model.EventUpdate})
            } else {
                k8sEvents.With(prometheus.Labels{&quot;type&quot;: otype, &quot;event&quot;: &quot;updateSame&quot;}).Add(1)
            }
        },
        DeleteFunc: func(obj interface{}) {
            k8sEvents.With(prometheus.Labels{&quot;type&quot;: otype, &quot;event&quot;: &quot;add&quot;}).Add(1)
            c.queue.Push(Task{handler: handler.Apply, obj: obj, event: model.EventDelete})
        },
    })
</code></pre>
<p>&#x4E00;&#x5171;&#x6709;&#x4E09;&#x79CD;&#x7C7B;&#x578B;&#x7684;&#x4E8B;&#x4EF6;&#xFF1A;Add&#x3001;Update&#x3001;Delete&#x3002;&#x7136;&#x540E;&#x5C06;&#x4E8B;&#x4EF6;&#x7684;&#x8BE6;&#x7EC6;&#x5185;&#x5BB9;&#xFF08;&#x8981;&#x63A8;&#x9001;&#x7684;&#x5185;&#x5BB9;&#xFF09;&#xFF0C;&#x6DFB;&#x52A0;&#x5230; Controller &#x4E2D;&#x7684;&#x4E00;&#x4E2A; task queue &#x4E2D;&#x3002;</p>
<p>&#x8FD9;&#x4E2A; task queue &#x6267;&#x884C;&#x7684;&#x6E90;&#x7801;&#x5982;&#x4E0B;&#xFF1A;</p>
<p><a href="https://github.com/istio/istio/blob/1.0.2/pilot/pkg/serviceregistry/kube/queue.go#L74">kube/queue.go#74</a></p>
<pre><code class="language-go">func (q *queueImpl) Run(stop &lt;-chan struct{}) {
	// &#x5F00;&#x59CB;&#x5BF9;&#x4EFB;&#x52A1;&#x961F;&#x5217;&#x8FDB;&#x884C;&#x5904;&#x7406;&#x65F6;&#x5BF9;&#x961F;&#x5217;&#x52A0;&#x9501;&#xFF0C;&#x8FD9;&#x662F;&#x4E00;&#x6B21;&#x63A8;&#x9001;&#x4EFB;&#x52A1;
	go func() {
		&lt;-stop
		q.cond.L.Lock()
		q.closing = true
		q.cond.L.Unlock()
	}()

	for {
		q.cond.L.Lock()
		for !q.closing &amp;&amp; len(q.queue) == 0 {
			q.cond.Wait()
		}
		//&#x4E00;&#x6B21;&#x63A8;&#x9001;&#x4EFB;&#x52A1;&#x5168;&#x90E8;&#x5B8C;&#x6210;&#x5219;&#x9000;&#x51FA;&#x8FD0;&#x884C;
		if len(q.queue) == 0 {
			q.cond.L.Unlock()
			return
		}
		// &#x4ECE;&#x961F;&#x5217;&#x4E2D;&#x53D6;&#x51FA;&#x4E00;&#x4E2A;&#x4EFB;&#x52A1;
		var item Task
		item, q.queue = q.queue[0], q.queue[1:]
		q.cond.L.Unlock()
		// &#x6267;&#x884C;task&#xFF0C;&#x82E5;&#x6267;&#x884C;&#x5931;&#x8D25;&#x5219;&#x5EF6;&#x8FDF;&#x4E00;&#x5B9A;&#x65F6;&#x95F4;&#x5C06;&#x4EFB;&#x52A1;&#x91CD;&#x65B0;&#x52A0;&#x5165;&#x5230;&#x961F;&#x5217;
		if err := item.handler(item.obj, item.event); err != nil {
			log.Infof(&quot;Work item handle failed (%v), retry after delay %v&quot;, err, q.delay)
			time.AfterFunc(q.delay, func() {
				q.Push(item)
			})
		}

	}
}
</code></pre>
<p><code>item.hander</code>&#x5B9E;&#x9645;&#x6267;&#x884C;&#x7684;&#x662F; Task &#x4E2D;&#x7684;<code>handler.Apply</code></p>
<pre><code class="language-go">// &#x5176;&#x4E2D;&#x6709;&#x4E00;&#x7EC4;function&#x88AB;&#x4F9D;&#x6B21;&#x6267;&#x884C;
func (ch *ChainHandler) Apply(obj interface{}, event model.Event) error {
	for _, f := range ch.funcs {
		if err := f(obj, event); err != nil {
			return err
		}
	}
	return nil
}
</code></pre>
<p>&#x81F3;&#x4E8E;&#x8FD9;&#x4E9B; handler &#x5177;&#x4F53;&#x8981;&#x6267;&#x884C;  &#x7684;&#x662F;&#x4EC0;&#x4E48;&#xFF0C;&#x5B83;&#x4EEC;&#x662F;&#x4E0A;&#x9762;&#x5728;&#x521D;&#x59CB;&#x5316; Discovery Service &#x65F6;&#x6240;&#x5B9A;&#x4E49;&#x7684; handler&#xFF1A;<code>clearCache()</code></p>
<p><a href="https://github.com/istio/istio/blob/1.0.2/pilot/pkg/proxy/envoy/discovery.go#L324"><code>NewDiscoveryService</code></a></p>
<pre><code class="language-go">// Flush cached discovery responses whenever services, service
// instances, or routing configuration changes.
serviceHandler := func(*model.Service, model.Event) { out.clearCache() }
if err := ctl.AppendServiceHandler(serviceHandler); err != nil {
	return nil, err
}
instanceHandler := func(*model.ServiceInstance, model.Event) { out.clearCache() }
if err := ctl.AppendInstanceHandler(instanceHandler); err != nil {
	return nil, err
}
</code></pre>
<p><code>envoy/discovery.go</code>&#x4E2D;&#x7684; clearCache&#xFF0C;&#x8FD9;&#x4E2A;&#x65B9;&#x6CD5;&#x4E3B;&#x8981;&#x5B9E;&#x73B0;&#x4E86;&#x4E00;&#x4E2A;<code>debounce</code>&#x673A;&#x5236;&#xFF0C;&#x6709;&#x4E00;&#x4E2A;<code>DebounceAfter</code>&#x9ED8;&#x8BA4;&#x662F; 100ms&#xFF0C;&#x4E5F;&#x5C31;&#x662F;&#x6BCF;&#x6B21; push &#x90FD;&#x4F1A;&#x5148;&#x63A8;&#x8FDF;&#x8FD9;&#x4E2A;&#x65F6;&#x95F4;&#xFF0C;&#x5E76;&#x8BBE;&#x7F6E;&#x4E00;&#x4E2A;&#x5168;&#x5C40;&#x7684;&#x53D8;&#x91CF;<code>clearCacheTimerSet</code>&#x8BB0;&#x5F55;&#x6B64;&#x65F6;&#x662F;&#x5426;&#x6709;&#x4E00;&#x4E2A;&#x6B63;&#x5728;&#x8FDB;&#x884C; debounce push &#x7684;&#xFF0C;&#x82E5;&#x6709;&#x7684;&#x8BDD;&#x53EA;&#x76F4;&#x63A5;&#x653E;&#x5F03;&#x8FD9;&#x4E2A; push&#xFF0C;&#x5E76;&#x5C06;&#x5168;&#x5C40;&#x53D8;&#x91CF;<code>lastClearCacheEvent</code>&#x91CD;&#x65B0;&#x8BBE;&#x7F6E;&#x4E3A;&#x5F53;&#x524D;&#x65F6;&#x95F4;&#xFF0C;&#x5728;&#x90A3;&#x4E2A; debounce push &#x4EFB;&#x52A1;&#x4E2D;&#x4F1A;&#x8BA1;&#x7B97;&#x65B0;&#x7684;<code>since</code>&#x65F6;&#x95F4;&#xFF0C;&#x4E5F;&#x5C31;&#x662F;&#x8DDD;&#x79BB;&#x65B0;&#x7684; push &#x4EFB;&#x52A1;&#x5230;&#x6765;&#x7684;&#x65F6;&#x95F4;&#xFF0C;&#x77E5;&#x9053;&#x8FD9;&#x4E2A;&#x65F6;&#x95F4;&#x5927;&#x4E8E; 200ms &#x624D;&#x4F1A;&#x771F;&#x6B63;&#x6267;&#x884C; push&#xFF0C;&#x82E5;&#x77ED;&#x65F6;&#x95F4;&#x5185;&#x4E00;&#x76F4;&#x6709;&#x9891;&#x7E41;&#x7684;&#x914D;&#x7F6E;&#x66F4;&#x65B0;&#x800C;&#x5237;&#x65B0;&#x8FD9;&#x4E2A;<code>lastClearCacheEvent</code>&#x4F1A;&#x5BFC;&#x81F4; push &#x4EFB;&#x52A1;&#x6301;&#x7EED;&#x88AB;&#x63A8;&#x8FDF;&#x3002;&#x56E0;&#x4E3A; envoy &#x9700;&#x8981;&#x7684;&#x53EA;&#x662F;&#x6700;&#x65B0;&#x7684;&#x914D;&#x7F6E;&#x4FE1;&#x606F;&#xFF0C;&#x51CF;&#x5C11;&#x4E86;&#x914D;&#x7F6E;&#x9891;&#x7E41;&#x66F4;&#x65B0;&#x65F6;&#x800C;&#x591A;&#x6B21;&#x63A8;&#x9001;&#x5BFC;&#x81F4;&#x7684;&#x4E0D;&#x5FC5;&#x8981;&#x7684;&#x8D1F;&#x8F7D;&#x3002;</p>
<blockquote>
<p>&#x8FD9;&#x91CC;&#x6709;&#x4E00;&#x4E2A;&#x95EE;&#x9898;&#x5C31;&#x662F;&#xFF0C;&#x5982;&#x679C;&#x914D;&#x7F6E;&#x786E;&#x5B9E;&#x5728;&#x77ED;&#x65F6;&#x95F4;&#x5185;&#x9891;&#x7E41;&#x66F4;&#x65B0;&#x4E86;&#xFF0C;&#x90A3;&#x4E48;&#x7F13;&#x5B58;&#x548C;&#x63A8;&#x9001;&#x65F6;&#x95F4;&#x8FDF;&#x8FDF;&#x4E0D;&#x6267;&#x884C;&#xFF0C;&#x8FD9;&#x65F6;&#x6240;&#x6709;&#x7684; envoy &#x5C31;&#x65E0;&#x6CD5;&#x53CA;&#x65F6;&#x5F97;&#x5230;&#x6700;&#x65B0;&#x7684;&#x914D;&#x7F6E;&#x4FE1;&#x606F;&#xFF0C;&#x4E5F;&#x662F;&#x5F71;&#x54CD;&#x914D;&#x7F6E;&#x751F;&#x6548;&#x7684;&#x4E00;&#x4E2A;&#x6BD4;&#x8F83;&#x91CD;&#x8981;&#x7684;&#x539F;&#x56E0;&#x3002;</p>
</blockquote>
<pre><code class="language-go">// debouncePush is called on clear cache, to initiate a push.
func debouncePush(startDebounce time.Time) {
	clearCacheMutex.Lock()
	// &#x5DF2;&#x7ECF;&#x5728;&#x8FD9;&#x4E2A;debounce push&#x7684;&#x4EFB;&#x52A1;&#x4E2D;&#x53C8;&#x6709;&#x65B0;&#x7684;push&#x4EFB;&#x52A1;&#x5230;&#x6765;&#xFF0C;&#x8FD9;&#x4E2A;lastClearCacheEvent&#x65F6;&#x95F4;&#x88AB;&#x66F4;&#x65B0;
	// &#x5B9E;&#x73B0;&#x7684;&#x529F;&#x80FD;&#x5C31;&#x662F;debounce time&#x5185;&#x505A;&#x4E00;&#x4E2A;&#x7B80;&#x5355;&#x7684;&#x9650;&#x9891;&#xFF0C;&#x65F6;&#x95F4;&#x5185;&#x82E5;&#x6709;&#x65B0;&#x7684;push&#xFF0C;&#x5219;&#x4F1A;&#x6301;&#x7EED;debounce
	since := time.Since(lastClearCacheEvent)
	events := clearCacheEvents
	clearCacheMutex.Unlock()
	// &#x82E5;&#x81EA;&#x4ECE;&#x8FD9;&#x4E2A;debounce push&#x5F00;&#x59CB;&#x7684;&#x65F6;&#x95F4;&#x5DF2;&#x7ECF;&#x7ECF;&#x8FC7;&#x4E86;200ms&#x5C31;&#x5F00;&#x59CB;&#x6267;&#x884C;push
	if since &gt; 2*DebounceAfter ||
		time.Since(startDebounce) &gt; DebounceMax {

		log.Infof(&quot;Push debounce stable %d: %v since last change, %v since last push&quot;,
			events,
			since, time.Since(lastClearCache))
		clearCacheMutex.Lock()
		// &#x5C06;&#x8FD9;&#x4E2A;&#x8868;&#x793A;&#x662F;&#x5426;&#x6709;&#x6B63;&#x5728;&#x8FDB;&#x884C;push&#x7684;&#x5168;&#x5C40;&#x53D8;&#x91CF;&#x7F6E;&#x4E3A;false&#x4EE5;&#x5141;&#x8BB8;&#x4E0B;&#x4E00;&#x4E2A;&#x65B0;&#x7684;push&#x7684;&#x8FDB;&#x884C;
		clearCacheTimerSet = false
		lastClearCache = time.Now()
		clearCacheMutex.Unlock()
		V2ClearCache()
	// &#x5426;&#x5219;&#x63A8;&#x8FDF;100ms
	} else {
		log.Infof(&quot;Push debounce %d: %v since last change, %v since last push&quot;,
			events,
			since, time.Since(lastClearCache))
		time.AfterFunc(DebounceAfter, func() {
			debouncePush(startDebounce)
		})
	}
}
// clearCache will clear all envoy caches. Called by service, instance and config handlers.
// This will impact the performance, since envoy will need to recalculate.
func (ds *DiscoveryService) clearCache() {
	clearCacheMutex.Lock()
	defer clearCacheMutex.Unlock()

	clearCacheEvents++
	// &#x8FD9;&#x91CC;&#x7684;DebounceAfter&#x9ED8;&#x8BA4;&#x88AB;&#x8BBE;&#x7F6E;&#x4E3A;100ms
	if DebounceAfter &gt; 0 {
		// &#x8BB0;&#x5F55;&#x4E00;&#x4E0B;&#x65F6;&#x95F4;&#x3010;&#x6CE8;&#x610F;&#x8FD9;&#x662F;&#x4E00;&#x4E2A;&#x5168;&#x5C40;&#x7684;&#x53D8;&#x91CF;&#x3011;
		lastClearCacheEvent = time.Now()
		// clearCahceTimerSet &#x8868;&#x660E;&#x53C8;&#x6CA1;&#x6709;&#x4E00;&#x4E2A;&#x6B63;&#x5728;debounce&#x9012;&#x5F52;&#x4E2D;&#x7684;push&#x4EFB;&#x52A1;
		// &#x82E5;&#x4E3A;true&#x5219;&#x76F4;&#x63A5;&#x653E;&#x5F03;&#x8FD9;&#x4E2A;push
		if !clearCacheTimerSet {
			// &#x5F00;&#x59CB;&#x4E00;&#x4E2A;debounce push
			clearCacheTimerSet = true
			startDebounce := lastClearCacheEvent
			time.AfterFunc(DebounceAfter, func() {
				debouncePush(startDebounce)
			})
		}

		return
	}
	// &#x540E;&#x9762;&#x6E90;&#x7801;&#x4E2D;&#x6709;&#x4E00;&#x4E9B;&#x539F;&#x6765;&#x5B9E;&#x73B0;&#x7C7B;&#x4F3C;debounce&#x7684;&#x65B9;&#x5F0F;&#xFF0C;&#x5F53;debounceAfter&#x88AB;&#x8BBE;&#x7F6E;&#x4E3A;0&#x65F6;&#xFF0C;&#x6267;&#x884C;&#x5230;&#x540E;&#x9762;&#x7684;&#x4EE3;&#x7801;
}
</code></pre>
<p><code>envoy/v2/discovery.go</code>&#x4E2D;&#x7684;<code>ClearCacheFunc()</code>&#xFF0C;&#x5C31;&#x662F;&#x4E0A;&#x9762;&#x7684;<code>V2ClearCache()</code>&#xFF0C;&#x8FD9;&#x91CC;&#x4E3B;&#x8981;&#x8FDB;&#x884C;&#x4E00;&#x4E9B; pushContext &#x7684;&#x521D;&#x59CB;&#x5316;&#x7684;&#x64CD;&#x4F5C;&#xFF0C;&#x6700;&#x540E;&#x4F1A;&#x8D77;&#x4E00;&#x4E2A;&#x534F;&#x7A0B;&#x8C03;&#x7528;<code>adsPushAll</code>&#x53BB;&#x4EE5; ADS &#x534F;&#x8BAE;&#x6267;&#x884C;&#x63A8;&#x9001;</p>
<pre><code class="language-go">// ClearCacheFunc returns a function that invalidates v2 caches and triggers a push.
// This is used for transition, once the new config model is in place we&apos;ll have separate
// functions for each event and push only configs that need to be pushed.
// This is currently called from v1 and has attenuation/throttling.
func (s *DiscoveryServer) ClearCacheFunc() func() {
	return func() {
		...
		go s.AdsPushAll(versionLocal, push)
	}
}
</code></pre>
<p>&#x5BF9;&#x5F53;&#x524D;&#x6240;&#x6709;&#x4E0E; pilot-discovery &#x5EFA;&#x7ACB;&#x8FDE;&#x63A5;&#x7684; envoy &#x5BA2;&#x6237;&#x7AEF;&#x6267;&#x884C;&#x914D;&#x7F6E;&#x63A8;&#x9001;<code>ads.go</code></p>
<pre><code class="language-go">// AdsPushAll implements old style invalidation, generated when any rule or endpoint changes.
// Primary code path is from v1 discoveryService.clearCache(), which is added as a handler
// to the model ConfigStorageCache and Controller.
func (s *DiscoveryServer) AdsPushAll(version string, push *model.PushContext) {
	...
	// &#x83B7;&#x53D6;&#x6240;&#x6709;&#x5F85;&#x63A8;&#x9001;&#x7684;xds&#x8FDE;&#x63A5;&#xFF0C;&#x5BF9;&#x5E94;pilot-disovery&#x6765;&#x8BF4;&#x5C31;&#x662F;&#x6240;&#x6709;&#x4E0E;&#x4E4B;&#x5EFA;&#x7ACB;&#x8FDE;&#x63A5;&#x7684;Pod&#x7684;envoy
	adsClientsMutex.RLock()
	pending := []*XdsConnection{}
	for _, v := range adsClients {
		pending = append(pending, v)
	}
	adsClientsMutex.RUnlock()

	// &#x5728;for&#x4E2D;&#x6301;&#x7EED;&#x5BF9;xdsConnection&#x5217;&#x8868;&#x9010;&#x4E00;&#x8FDB;&#x884C;&#x63A8;&#x9001;
	for {
		//&#x7B49;&#x5F85;&#x63A8;&#x9001;&#x7684;&#x8FDE;&#x63A5;&#x6570;&#x4E3A;0&#xFF0C;&#x5373;&#x5DF2;&#x7ECF;&#x5168;&#x90E8;&#x63A8;&#x9001;&#x5B8C;&#x6BD5;
		if len(pending) == 0 {
			adsLog.Infof(&quot;PushAll done %s %v&quot;, version, time.Since(tstart))
			return
		}
		...
		// &#x53D6;&#x51FA;&#x4E00;&#x4E2A;pending&#x7684;&#x8FDE;&#x63A5;
		c := pending[0]
		pending = pending[1:]

		// Using non-blocking push has problems if 2 pushes happen too close to each other
		client := c
		// this should be in a thread group, to do multiple pushes in parallel.
		// &#x5B98;&#x65B9;&#x7684;todo&#x8868;&#x793A;&#x8FDB;&#x884C;&#x63A8;&#x9001;&#x7684;&#x64CD;&#x4F5C;&#x5E94;&#x8BE5;&#x5728;&#x4E00;&#x4E2A;&#x7EBF;&#x7A0B;&#x7EC4;&#x4E2D;&#x6765;&#x5E76;&#x884C;&#x6267;&#x884C;&#x591A;&#x4E2A;&#x63A8;&#x9001;&#x4EFB;&#x52A1;&#xFF0C;&#x8FD9;&#x91CC;&#x6709;&#x5F85;&#x6539;&#x8FDB;

		// &#x8BBE;&#x7F6E;&#x4E00;&#x4E2A;&#x5355;&#x6B21;&#x63A8;&#x9001;&#x8D85;&#x65F6;&#x65F6;&#x95F4;5s
		to := time.After(PushTimeout)
		select {
		// client.pushChannel&#x662F;&#x4E00;&#x4E2A;&#x7F13;&#x51B2;&#x4E3A;0&#x7684;&#x901A;&#x9053;&#xFF0C;&#x901A;&#x9053;&#x4E3A;&#x7A7A;&#x8868;&#x660E;&#x6CA1;&#x6709;&#x63A8;&#x9001;&#x4EFB;&#x52A1;&#xFF0C;&#x8FD9;&#x91CC;&#x5411;&#x5176;&#x53D1;&#x9001;&#x4E86;&#x4E00;&#x9879;XdsEvent&#x5176;&#x4E2D;&#x5305;&#x62EC;&#x4E86;&#x9700;&#x8981;&#x6267;&#x884C;&#x7684;&#x63A8;&#x9001;&#x4EFB;&#x52A1;
		// client&#x7AEF;&#x4F1A;&#x63A5;&#x6536;&#x8FD9;&#x4E2A;&#x901A;&#x9053;&#x7684;&#x4FE1;&#x53F7;&#x7136;&#x540E;&#x6267;&#x884C;&#x63A8;&#x9001;
		// &#x5728;asd.go&#x7684;StreamAggregatedResources&#x65B9;&#x6CD5;&#x4E2D;&#x4F1A;select&#x4E24;&#x79CD;&#x914D;&#x7F6E;&#x63A8;&#x9001;&#x60C5;&#x666F;&#x5982;&#x6700;&#x4E0A;&#x9762;&#x6240;&#x8BF4;&#xFF0C;&#x63A5;&#x6536;&#x5230;&#x4E86;pushChennel&#x7684;&#x4FE1;&#x606F;
		case client.pushChannel &lt;- &amp;XdsEvent{
			push:    pushContext,
			pending: &amp;pendingPush,
			version: version,
		}:
			client.LastPush = time.Now()
			client.LastPushFailure = timeZero
		case &lt;-client.doneChannel: // connection was closed
			adsLog.Infof(&quot;Client closed connection %v&quot;, client.ConID)
		case &lt;-to:
			pushTimeouts.Add(1)
			//default:
			// This may happen to some clients if the other side is in a bad state and can&apos;t receive.
			// The tests were catching this - one of the client was not reading.
			pending = append(pending, c)
			...
		}
	}
}
</code></pre>
<p>pushAll</p>
<pre><code class="language-go">// Compute and send the new configuration. This is blocking and may be slow
// for large configs.
func (s *DiscoveryServer) pushAll(con *XdsConnection, pushEv *XdsEvent) error {
	...
	//&#x5206;&#x522B;&#x5BF9;CDS&#xFF0C;RDS&#xFF0C;LDS&#xFF0C;EDS&#x8FDB;&#x884C;&#x5224;&#x65AD;&#x5E76;&#x6267;&#x884C;&#x4E0D;&#x540C;xDS&#x7684;&#x5B9E;&#x9645;&#x54CD;&#x5E94;&#x5C01;&#x88C5;
	if con.CDSWatch {
		err := s.pushCds(con, pushEv.push, pushEv.version)
		if err != nil {
			return err
		}
	}
	if len(con.Routes) &gt; 0 {
		err := s.pushRoute(con, pushEv.push)
		if err != nil {
			return err
		}
	}
	if len(con.Clusters) &gt; 0 {
		err := s.pushEds(pushEv.push, con)
		if err != nil {
			return err
		}
	}
	if con.LDSWatch {
		err := s.pushLds(con, pushEv.push, false, pushEv.version)
		if err != nil {
			return err
		}
	}
	return nil
}
</code></pre>
<p>&#x4F8B;&#x5982;&#x5BF9;&#x4E0E; eds &#x914D;&#x7F6E;&#x8FDB;&#x884C;&#x63A8;&#x9001;&#xFF1A;</p>
<pre><code class="language-go">func (s *DiscoveryServer) pushEds(push *model.PushContext, con *XdsConnection) error {
	...
	//&#x524D;&#x9762;&#x662F;&#x5BF9;&#x7ED3;&#x6784;&#x4F53;&#x7684;&#x4E00;&#x4E9B;&#x5C01;&#x88C5;&#x7EC4;&#x6210;EDS&#x7684;DiscoveryResponse
	response := s.endpoints(con.Clusters, resAny)
	//&#x7EC8;&#x4E8E;&#x53D1;&#x9001;&#x4E86;&#x3002;&#x3002;&#x3002;
	err := con.send(response)
	if err != nil {
		adsLog.Warnf(&quot;EDS: Send failure, closing grpc %v&quot;, err)
		pushes.With(prometheus.Labels{&quot;type&quot;: &quot;eds_senderr&quot;}).Add(1)
		return err
	}
	...
}
</code></pre>
<h2 id="endpointpushall">&#x4E00;&#x6B21; endpoint &#x6539;&#x53D8; pushAll &#x7684;&#x65F6;&#x95F4;</h2>
<p>&#x5728;&#x672C;&#x6B21;&#x6D4B;&#x8BD5;&#x7684;&#x96C6;&#x7FA4;&#x4E2D;&#xFF0C;&#x4E00;&#x5171;&#x6709;&#x4E09;&#x4E2A; pilot &#x5B9E;&#x4F8B;&#xFF0C;&#x5206;&#x522B;&#x8FDE;&#x63A5;&#x7740; 54&#x3001;4&#x3001;45 &#x4E2A; envoy clients</p>
<ul>
<li>54 istio-pilot-6c9f665466-5b49s &#xFF08;push &#x65F6;&#x95F4;&#x5927;&#x81F4;&#x5728; 600-700ms&#xFF09;</li>
<li>4 istio-pilot-6c9f665466-hgz7k &#xFF08;push &#x65F6;&#x95F4;&#x5927;&#x81F4;&#x5728; 180-200ms&#xFF09;</li>
<li>45 istio-pilot-6c9f665466-jxtpw &#xFF08;push &#x65F6;&#x95F4;&#x5927;&#x81F4;&#x5728; 500-600ms&#xFF09;</li>
</ul>
<p>&#x5927;&#x81F4;&#x8BA1;&#x7B97;&#x6BCF;&#x591A;&#x4E00;&#x4E2A; Pod&#xFF0C;push &#x7684;&#x65F6;&#x95F4;&#x5F00;&#x9500;&#x4F1A;&#x591A; 10ms &#x5DE6;&#x53F3;&#xFF0C;&#x56E0;&#x6B64; Pod &#x6570;&#x91CF;&#x8FC7;&#x591A;&#x5BFC;&#x81F4; push &#x901F;&#x5EA6;&#x4E0B;&#x964D;&#x53EF;&#x4EE5;&#x6DFB;&#x52A0; istio-pilot &#x7684;&#x526F;&#x672C;&#x4E2A;&#x6570;&#x89E3;&#x51B3;&#x4EE5;&#x5747;&#x8861;&#x6BCF;&#x4E2A; istio-pilot &#x8FDE;&#x63A5;&#x7684; envoy &#x6570;&#x76EE;</p>
<h2 id="push">Push &#x751F;&#x6548;&#x65F6;&#x95F4;&#x4F1A;&#x5BFC;&#x81F4;&#x7684;&#x95EE;&#x9898;</h2>
<p>&#x5728;&#x8FDB;&#x884C; scale down &#x64CD;&#x4F5C;&#x65F6;&#xFF0C;&#x7531;&#x4E8E; endpoint &#x914D;&#x7F6E;&#x6CA1;&#x6709;&#x53CA;&#x65F6;&#x7684;&#x63A8;&#x9001;&#x5230; envoy &#x4E2D;&#xFF0C;&#x56E0;&#x6B64;&#x7528;&#x6237;&#x5728;&#x8BBF;&#x95EE;&#x65F6;&#x4F1A;&#x5BFC;&#x81F4;&#x5C11;&#x91CF;&#x7684; 503 &#x9519;&#x8BEF;&#x3002;</p>
<p>&#x53EF;&#x4EE5;&#x4F7F;&#x7528;&#x8003;&#x8651; istio &#x7684; HTTPRetry &#x914D;&#x7F6E;&#xFF0C;&#x5176;&#x672C;&#x8D28;&#x662F;&#x4F20;&#x9001;&#x4E86;&#x4E00;&#x4E2A; HTTP &#x5934;&#x90E8;&#x7ED9; envoy &#x8FDB;&#x884C;&#x4E00;&#x4E2A;&#x914D;&#x7F6E;&#x4FE1;&#x606F;&#xFF0C;envoy &#x6536;&#x5230;&#x540E;&#x4F1A;&#x6839;&#x636E;&#x6307;&#x5B9A;&#x7684;&#x9519;&#x8BEF;&#x5982; 5XX &#x8FDB;&#x884C; retry &#x76F4;&#x5230;&#x6B63;&#x786E;&#x8FD4;&#x56DE;&#x3002;&#x4F46;&#x662F;&#x6839;&#x636E;&#x63A8;&#x9001;&#x65F6;&#x95F4;&#x5728; 500ms &#x4E0A;&#x4E0B;&#xFF0C;istio &#x6587;&#x6863;&#x4E2D;&#x6BCF;&#x6B21; retry &#x7684;&#x65F6;&#x95F4;&#x5927;&#x7EA6;&#x5728; 25ms+&#xFF0C;&#x6240;&#x4EE5;&#x96BE;&#x9053;&#x8981;&#x8FDB;&#x884C;&#x8FD9;&#x4E48;&#x591A;&#x6B21; retry &#x624D;&#x80FD;&#x6B63;&#x786E;&#x6536;&#x5230;&#x8BF7;&#x6C42;&#xFF1F;&#x66F4;&#x52A0;&#x9700;&#x8981;&#x6CE8;&#x610F;&#x7684;&#x662F;&#xFF0C;&#x5982;&#x679C;&#x5728;&#x751F;&#x4EA7;&#x73AF;&#x5883;&#x4E2D;&#x771F;&#x7684;&#x6709;&#x670D;&#x52A1; down &#x4E86;&#xFF0C;&#x90A3;&#x4E48;&#x6240;&#x6709;&#x7684;&#x9519;&#x8BEF;&#x8BF7;&#x6C42;&#x90FD;&#x4F1A;&#x6210;&#x500D;&#x7684;&#x589E;&#x52A0;&#xFF0C;&#x5BFC;&#x81F4;&#x6574;&#x4E2A;&#x96C6;&#x7FA4;&#x7684;&#x538B;&#x529B;&#x589E;&#x5927;&#xFF0C;&#x4E5F;&#x662F;&#x4E00;&#x4E2A;&#x9700;&#x8981;&#x8003;&#x8651;&#x7684;&#x95EE;&#x9898;&#x3002;</p>
<p>&#x76F8;&#x5173; issue &#x7684;&#x8BA8;&#x8BBA;<a href="https://github.com/istio/istio/issues/7665">503 errors when scaling down, or rolling out a new application version #7665</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Decorator in Python]]></title><description><![CDATA[<!--kg-card-begin: markdown--><blockquote>
<p>Don&apos;t Repeat Yourself</p>
</blockquote>
<hr>
<p>&#x5728; Python &#x4E2D;&#x4E00;&#x4E2A;&#x4E0E;&#x5176;&#x4ED6;&#x8BED;&#x8A00;&#x8F83;&#x4E3A;&#x7279;&#x6B8A;&#x7684;&#x8BED;&#x6CD5;&#x7CD6;&#x5C31;&#x662F; <strong>Decorator</strong> &#x4E86;&#xFF0C;&#x5C31;&#x5982;&#x540C;&#x5B83;&#x7684;&#x540D;&#x5B57;&#xFF0C;&#x4E00;&#x4E2A;&#x51FD;&#x6570;&#x7684; decorator &#x7684;&#x4F5C;&#x7528;&#x5C31;&#x662F;&#x5C06;&#x5176;&#x505A;</p>]]></description><link>https://ruofeng.me/2018/10/27/decorator-in-python/</link><guid isPermaLink="false">5d8e378da7d96200019ade22</guid><category><![CDATA[Python]]></category><dc:creator><![CDATA[Ruofeng Lei]]></dc:creator><pubDate>Sat, 27 Oct 2018 09:27:19 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><blockquote>
<p>Don&apos;t Repeat Yourself</p>
</blockquote>
<hr>
<p>&#x5728; Python &#x4E2D;&#x4E00;&#x4E2A;&#x4E0E;&#x5176;&#x4ED6;&#x8BED;&#x8A00;&#x8F83;&#x4E3A;&#x7279;&#x6B8A;&#x7684;&#x8BED;&#x6CD5;&#x7CD6;&#x5C31;&#x662F; <strong>Decorator</strong> &#x4E86;&#xFF0C;&#x5C31;&#x5982;&#x540C;&#x5B83;&#x7684;&#x540D;&#x5B57;&#xFF0C;&#x4E00;&#x4E2A;&#x51FD;&#x6570;&#x7684; decorator &#x7684;&#x4F5C;&#x7528;&#x5C31;&#x662F;&#x5C06;&#x5176;&#x505A;&#x4E00;&#x5C42;&#x5305;&#x88C5;&#xFF0C;&#x53EF;&#x4EE5;&#x5B9A;&#x4E49;&#x5728;&#x8FD9;&#x4E2A;&#x51FD;&#x6570;&#x6267;&#x884C;&#x4E4B;&#x524D;&#x505A;&#x4E00;&#x4E9B;&#x4EC0;&#x4E48;&#x5DE5;&#x4F5C;&#xFF0C;&#x5982;&#x68C0;&#x67E5;&#x4F20;&#x5165;&#x53C2;&#x6570;&#x7B49;&#xFF0C;&#x6267;&#x884C;&#x5B8C;&#x51FD;&#x6570;&#x4E4B;&#x540E;&#x505A;&#x4E00;&#x4E9B;&#x5B9A;&#x4E49;&#x7684;&#x64CD;&#x4F5C;&#x3002;&#x6BD4;&#x5982;&#x8BF4;&#x5BF9;&#x4E00;&#x4E2A;&#x51FD;&#x6570;&#x7684;&#x505A;&#x4E00;&#x4E9B;&#x989D;&#x5916;&#x7684;&#x64CD;&#x4F5C;&#xFF0C;&#x8BB0;&#x5F55;&#x65E5;&#x5FD7;&#xFF0C;&#x8BA1;&#x7B97;&#x51FD;&#x6570;&#x8FD0;&#x884C;&#x65F6;&#x95F4;&#xFF0C;&#x8FD9;&#x4E9B;&#x4E0E;&#x51FD;&#x6570;&#x7684;&#x6838;&#x5FC3;&#x8FD0;&#x884C;&#x903B;&#x8F91;&#x4E0D;&#x76F8;&#x5173;&#xFF0C;&#x800C;&#x4E14;&#x662F;&#x53EF;&#x4EE5;&#x80FD;&#x591F;&#x88AB;&#x591A;&#x4E2A;&#x51FD;&#x6570;&#x6240;&#x4F7F;&#x7528;&#x7684;&#x5C0F;<strong>&#x5305;&#x88C5;</strong>&#xFF0C;&#x56E0;&#x6B64;&#x53EF;&#x4EE5;&#x5355;&#x72EC;&#x5B9A;&#x4E49;&#x4E00;&#x4E2A;&#x8FD9;&#x4E48;&#x4E00;&#x4E2A;&#x88C5;&#x9970;&#x5668;&#x4EE5;&#x4F9B;&#x4E0D;&#x540C;&#x7684;&#x51FD;&#x6570;&#x590D;&#x7528;&#x3002;</p>
<p>&#x5728; web &#x5F00;&#x53D1;&#x4E2D;&#x66F4;&#x4E3A;&#x5E38;&#x89C1;&#x7684;&#x60C5;&#x666F;&#x5C31;&#x662F;&#x5728;&#x5904;&#x7406;&#x8BF7;&#x6C42;&#x5BF9;&#x4F20;&#x5165; request &#x6570;&#x636E;&#x8FDB;&#x884C;&#x6821;&#x9A8C;&#x3001;&#x7528;&#x6237;&#x8EAB;&#x4EFD;&#x7684;&#x6821;&#x9A8C;&#xFF0C;&#x5982;&#x679C;&#x4E0D;&#x7B26;&#x5408;&#x5219;&#x76F4;&#x63A5;&#x5728; decorator &#x4E2D; abort &#x8FD9;&#x4E2A;&#x8BF7;&#x6C42;&#x5373;&#x53EF;&#x3002;</p>
<p>decorator &#x7684;&#x4F7F;&#x7528;&#x5C31;&#x662F;&#x5728;&#x5B9A;&#x4E49;&#x51FD;&#x6570;&#x7684;&#x4E0A;&#x9762;&#x4E00;&#x884C;&#x52A0;&#x5165;<code>@&#x88C5;&#x9970;&#x5668;&#x540D;</code></p>
<pre><code class="language-python">@timethis
def countdown(n):
		pass
</code></pre>
<p>&#x8FD9;&#x4E2A;<code>@</code>&#x8BF4;&#x660E;&#x5176;&#x5B9E;&#x4EC5;&#x4EC5;&#x662F;&#x4E00;&#x4E2A;&#x8BED;&#x6CD5;&#x7CD6;&#xFF0C;&#x5B83;&#x7684;&#x6548;&#x679C;&#x548C;&#x4E0B;&#x9762;&#x7684;&#x5B9A;&#x4E49;&#x662F;&#x5B8C;&#x5168;&#x4E00;&#x6837;&#x7684;&#xFF1A;</p>
<pre><code class="language-python">def countdown(n):
		pass
countdown = timethis(countdown)
</code></pre>
<h2 id>&#x4E00;&#x4E2A;&#x7B80;&#x5355;&#x7684;&#x8BA1;&#x65F6;&#x88C5;&#x9970;&#x5668;</h2>
<p>&#x8BA1;&#x65F6;&#x5668;&#x53EF;&#x4EE5;&#x7B97;&#x662F;&#x6700;&#x7B80;&#x5355;&#x4E14;&#x7ECF;&#x5178;&#x7684;&#x88C5;&#x9970;&#x5668;&#x4F8B;&#x5B50;&#x4E86;&#xFF0C;&#x56E0;&#x4E3A;&#x5B83;&#x5728;&#x51FD;&#x6570;&#x7684;&#x6267;&#x884C;&#x524D;&#xFF0C;&#x6267;&#x884C;&#x540E;&#x5206;&#x522B;&#x6709;&#x83B7;&#x53D6;&#x65F6;&#x95F4;&#x3001;&#x8BA1;&#x7B97;&#x65F6;&#x95F4;&#x5DEE;&#x5E76;&#x8F93;&#x51FA;&#x7684;&#x64CD;&#x4F5C;&#xFF0C;&#x540C;&#x65F6;&#x5BF9;&#x51FD;&#x6570;&#x5185;&#x90E8;&#x903B;&#x8F91;&#x6CA1;&#x6709;&#x4FB5;&#x5165;&#x3002;</p>
<pre><code class="language-python">import time
from functools import wraps
def timethis(func):# &#x4F20;&#x5165;&#x7684;&#x662F;&#x8981;&#x88AB;&#x88C5;&#x9970;&#x7684;&#x539F;&#x51FD;&#x6570;
    &apos;&apos;&apos;
    Decorator that reports the execution time.
    &apos;&apos;&apos;
    @wraps(func)
    def wrapper(*args, **kwargs):# &#x8FD9;&#x6837;&#x5B9A;&#x4E49;wrapper&#x51FD;&#x6570;&#x7684;&#x53C2;&#x6570;&#x662F;&#x4E3A;&#x6765;&#x80FD;&#x591F;&#x6B63;&#x5E38;&#x63A5;&#x6536;&#x539F;&#x51FD;&#x6570;&#x7684;&#x53C2;&#x6570;
        start = time.time() # &#x8FD9;&#x4E2A;wrapper&#x5185;&#x5B9A;&#x4E49;&#x7684;&#x5728;&#x8FD9;&#x4E2A;&#x539F;&#x51FD;&#x6570;&#x6267;&#x884C;&#x524D;&#x6267;&#x884C;&#x7684;&#x4EE3;&#x7801;
        result = func(*args, **kwargs)# &#x6267;&#x884C;&#x539F;&#x51FD;&#x6570;&#xFF0C;&#x5E76;&#x4FDD;&#x5B58;&#x6267;&#x884C;&#x7ED3;&#x679C;
        end = time.time() # &#x8FD9;&#x4E2A;wrapper&#x5185;&#x5B9A;&#x4E49;&#x7684;&#x5728;&#x8FD9;&#x4E2A;&#x539F;&#x51FD;&#x6570;&#x6267;&#x884C;&#x540E;&#x6267;&#x884C;&#x7684;&#x4EE3;&#x7801;
        print(func.__name__, end - start)

        return result # &#x8FD4;&#x56DE;&#x503C;&#xFF0C;&#x5373;&#x539F;&#x51FD;&#x6570;&#x88AB;&#x5305;&#x88C5;&#x540E;&#x7684;&#x8FD4;&#x56DE;&#x503C;
    return wrapper
</code></pre>
<p>&#x4F7F;&#x7528;&#x65B9;&#x6CD5;&#xFF1A;</p>
<pre><code class="language-python">&gt;&gt;&gt; @timethis
... def countdown(n):
...     &apos;&apos;&apos;
...     Counts down
...     &apos;&apos;&apos;
...     whilen&gt;0:
...     n -= 1
...
&gt;&gt;&gt; countdown(100000)
countdown 0.008917808532714844
&gt;&gt;&gt; countdown(10000000)
countdown 0.87188299392912 &gt;&gt;&gt;
</code></pre>
<h2 id="functoolswraps">&#x4F7F;&#x7528;<code>functools</code>&#x5E93;&#x4E2D;&#x7684;<code>@wraps</code></h2>
<p>&#x9700;&#x8981;&#x6CE8;&#x610F;&#x7684;&#x662F;&#xFF0C;&#x5728;&#x5B9A;&#x4E49;&#x4EFB;&#x4F55;&#x88C5;&#x9970;&#x5668;&#x65F6;&#x90FD;&#x5E94;&#x8BE5;&#x4F7F;&#x7528; <code>functools</code> &#x5E93;&#x4E2D;&#x7684; <code>@wraps</code> &#x6765;&#x6CE8;&#x89E3; wrap &#x51FD;&#x6570;&#xFF0C;&#x4F7F;&#x7528; <code>@wraps</code> &#x7684;&#x91CD;&#x8981;&#x539F;&#x56E0;&#x4E4B;&#x4E00;&#x662F;&#x53EF;&#x4EE5;<strong>&#x4FDD;&#x7559;&#x539F;&#x51FD;&#x6570;&#x7684;&#x5143;&#x4FE1;&#x606F;</strong>&#xFF0C;&#x5982; <code>__name</code> &#x548C; <code>__doc__</code> &#x7B49;&#x3002;</p>
<p>&#x8FD8;&#x53EF;&#x4EE5;&#x4F7F;&#x7528; <code>__wrapped__</code> &#x6765;&#x76F4;&#x63A5;&#x8BBF;&#x95EE;&#x88AB;&#x5305;&#x88C5;&#x7684;&#x539F;&#x59CB;&#x51FD;&#x6570;&#xFF1A;</p>
<pre><code class="language-python">countdown.__wrapped__(1000000) # &#x53BB;&#x6389;&#x4E86;&#x4E00;&#x4E2A;&#x88C5;&#x9970;&#x5668;&#xFF0C;&#x4E0D;&#x4F1A;&#x8FDB;&#x884C;&#x8BA1;&#x65F6;&#x8F93;&#x51FA;
</code></pre>
<h2 id>&#x591A;&#x4E2A;&#x88C5;&#x9970;&#x5668;</h2>
<p>&#x6700;&#x4E0A;&#x9762;&#x5B9A;&#x4E49;&#x7684;&#x88C5;&#x9970;&#x5668;&#x6700;&#x5148;&#x6267;&#x884C;&#xFF0C;&#x7136;&#x540E;&#x4F9D;&#x6B21;&#x5411;&#x4E0B;</p>
<pre><code class="language-python"># d1 &#x5148;&#x4E0E; d2 &#x6267;&#x884C;
@decorator1
@decorator2
def add(x, y):
    return x + y
</code></pre>
<p>&#x540C;&#x6837;&#x5730;&#xFF0C;&#x82E5;&#x8981;&#x4F7F;&#x7528;<code>__wrapped__</code>&#xFF0C;&#x8981;&#x8FDE;&#x7EED;&#x4F7F;&#x7528;&#x4E24;&#x6B21;&#x624D;&#x80FD;&#x53BB;&#x9664;&#x521A;&#x521A;&#x5B9A;&#x4E49;&#x7684;&#x4E24;&#x4E2A;&#x88C5;&#x9970;&#x5668;&#x3002;</p>
<pre><code class="language-python"># &#x4E00;&#x4E2A; __wrapped__ &#x53EA;&#x53D6;&#x6D88;&#x4E86;d1&#xFF0C;&#x5373;&#x6700;&#x4E0A;&#x9762;&#x7684;decorator
add.__wrapped__(2, 3)
# &#x53D6;&#x6D88;&#x4E24;&#x4E2A;decorator
add.__wrapped__.__wrapped__(2, 3)
</code></pre>
<h2 id="decorator">&#x53EF;&#x4F20;&#x5165;&#x53C2;&#x6570;&#x7684; decorator</h2>
<p>&#x4F8B;&#x5982;&#x5728;&#x4F7F;&#x7528;&#x4E00;&#x4E2A;&#x8BB0;&#x5F55;&#x65E5;&#x5FD7;&#x7684; decorator &#x65F6;&#xFF0C;&#x9700;&#x8981;&#x6307;&#x5B9A; log &#x7684;&#x7EA7;&#x522B;</p>
<pre><code class="language-python">from functools import wraps
import logging

#  &#x5728;&#x8FD9;&#x91CC;&#x5B9A;&#x4E49;&#x8981;&#x4F20;&#x5165;decorator&#x7684;&#x53C2;&#x6570;&#xFF0C;&#x5BF9;decorator&#x518D;&#x8FDB;&#x884C;&#x4E00;&#x6B21;&#x5305;&#x88C5;
def logged(level, name=None, message=None):
    &quot;&quot;&quot;
    Add logging to a function.
    &quot;&quot;&quot;
    # &#x4F20;&#x5165;&#x539F;&#x51FD;&#x6570;&#x7684;decorator
    def decorator(func):
        # &#x9ED8;&#x8BA4;&#x503C;
        logname = name if name else func.__module__
        log = logging.getLogger(logname)
        logmsg = message if message else func.__name__

        @wraps(func)
        def wrapper(*args, **kwargs):
            log.log(level, logmsg)
            return func(*args, **kwargs)

        return wrapper

    return decorator


@logged(logging.DEBUG)
def add(x, y):
    return x + y


if __name__ == &quot;__main__&quot;:
    add(1, 2)
</code></pre>
<h2 id="flaskdecorator">&#x5728; flask &#x4E2D;&#x4F7F;&#x7528; decorator &#x524D;&#x7F6E;&#x68C0;&#x67E5;&#x7528;&#x6237;&#x662F;&#x5426;&#x8BA4;&#x8BC1;</h2>
<p>&#x5728;&#x4F7F;&#x7528; flask &#x5F00;&#x53D1; api &#x65F6;&#xFF0C;&#x6BD4;&#x8F83;&#x5E38;&#x89C1;&#x7684;&#x7528;&#x6237;&#x8BA4;&#x8BC1;&#x65B9;&#x6CD5;&#x4E4B;&#x4E00;&#x662F;&#x5728; HTTP Header &#x4E2D;&#x5E26;&#x5165;&#x4E00;&#x4E2A; Token&#xFF0C;&#x8FD9;&#x91CC;&#x6211;&#x4E3E;&#x4E86;&#x4E00;&#x4E2A;&#x7B80;&#x5355;&#x7684;&#x4F8B;&#x5B50;&#x6765;&#x7ED9; flask &#x5199;&#x4E00;&#x4E2A;&#x4EE5;&#x9A8C;&#x8BC1;&#x7528;&#x6237;&#x8BA4;&#x8BC1;&#x7684;&#x88C5;&#x9970;&#x5668;</p>
<pre><code class="language-python">from functools import wraps
from flask import request, make_response, jsonify


def must_auth(f):
    @wraps(f)
    def decorate(*args, **kwargs):
        hdrs = request.headers
        token = hdrs.get(&apos;Authorization&apos;)
        # &#x68C0;&#x67E5; request header &#x7684; Authorization &#x90E8;&#x5206;
        if token != &apos;Bearer 123456&apos;:
            # &#x6821;&#x9A8C;&#x5931;&#x8D25;&#x5219;&#x8FD4;&#x56DE;401&#x9519;&#x8BEF;
            return make_response(jsonify({&apos;errno&apos;: -1, &apos;msg&apos;: &apos;not auth&apos;}), 401)
        return f(*args, **kwargs)

    return decorate

# &#x5728;&#x8DEF;&#x7531;&#x65B9;&#x6CD5;&#x4E2D;&#x4F7F;&#x7528;must_auth&#x88C5;&#x9970;&#x5668;
@app.route(&apos;/api/auth&apos;)
@must_auth
def auth_route():
    return res_data({&apos;foo&apos;: &apos;bar&apos;})
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[简单接触 Python 中的模块 module 与包 package]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>&#x6700;&#x8FD1;&#x5728;&#x63A5;&#x89E6;&#x4E00;&#x4E2A;&#x91CD;&#x6784;&#x9879;&#x76EE;&#xFF0C;&#x4E3B;&#x8981;&#x662F;&#x8FDB;&#x884C;&#x4E00;&#x6B21;&#x8BED;&#x8A00;&#x7684;&#x5207;&#x6362;&#xFF0C;&#x4ECE; PHP &#x8FC1;&#x79FB;&#x5230; Python&#x3002;&#x5BF9;&#x4E8E; Python &#x8FD9;&#x95E8;&#x8BED;&#x8A00;&#x81EA;&#x5DF1;&#x6B64;&#x524D;&#x53EA;&#x662F;&#x975E;&#x5E38;&#x7B80;&#x5355;&#x5730;</p>]]></description><link>https://ruofeng.me/2018/10/21/get-started-with-module-and-package-of-python/</link><guid isPermaLink="false">5d8e378da7d96200019ade21</guid><category><![CDATA[Python]]></category><dc:creator><![CDATA[Ruofeng Lei]]></dc:creator><pubDate>Sun, 21 Oct 2018 13:32:50 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>&#x6700;&#x8FD1;&#x5728;&#x63A5;&#x89E6;&#x4E00;&#x4E2A;&#x91CD;&#x6784;&#x9879;&#x76EE;&#xFF0C;&#x4E3B;&#x8981;&#x662F;&#x8FDB;&#x884C;&#x4E00;&#x6B21;&#x8BED;&#x8A00;&#x7684;&#x5207;&#x6362;&#xFF0C;&#x4ECE; PHP &#x8FC1;&#x79FB;&#x5230; Python&#x3002;&#x5BF9;&#x4E8E; Python &#x8FD9;&#x95E8;&#x8BED;&#x8A00;&#x81EA;&#x5DF1;&#x6B64;&#x524D;&#x53EA;&#x662F;&#x975E;&#x5E38;&#x7B80;&#x5355;&#x5730;&#x63A5;&#x89E6;&#x8FC7;&#xFF0C;&#x4EC5;&#x9650;&#x4E8E;&#x5199;&#x4E86;&#x4E00;&#x4E9B;&#x5355;&#x6587;&#x4EF6;&#x7B97;&#x6CD5;&#x7EC3;&#x624B;&#x7B49;&#x7B49;&#xFF0C;&#x5E76;&#x6CA1;&#x6709;&#x5B9E;&#x9645;&#x4F7F;&#x7528;&#x5B83;&#x505A;&#x8FC7;&#x5DE5;&#x7A0B;&#x9879;&#x76EE;&#x3002;&#x8FD9;&#x6B21;&#x8981;&#x4ECE;&#x96F6;&#x5F00;&#x59CB;&#x5BF9;&#x4E00;&#x4E2A;&#x9879;&#x76EE;&#x8FDB;&#x884C;&#x91CD;&#x6784;&#xFF0C;&#x8FD9;&#x4E2A;&#x65F6;&#x5019;&#x7F16;&#x7801;&#x7684;&#x4EFB;&#x52A1;&#x5F80;&#x5F80;&#x662F;&#x6700;&#x4E0D;&#x91CD;&#x8981;&#x7684;&#xFF0C;&#x66F4;&#x591A;&#x7684;&#x662F;&#x5BF9;&#x4E0E;&#x5176;&#x6574;&#x4E2A;&#x9879;&#x76EE;&#x7ED3;&#x6784;&#x7684;&#x8BBE;&#x8BA1;&#x4E0E;&#x601D;&#x8003;&#x3002;&#x56E0;&#x6B64;&#xFF0C;&#x4E86;&#x89E3; Python &#x7684;&#x6A21;&#x5757;&#x4E0E;&#x5305;&#x7684;&#x673A;&#x5236;&#x6210;&#x4E86;&#x7B2C;&#x4E00;&#x4E2A;&#x8981;&#x4ED4;&#x7EC6;&#x4E86;&#x89E3;&#x7684;&#x4EFB;&#x52A1;&#x3002;</p>
<h2 id="module">Module</h2>
<p>&#x4E00;&#x4E2A;<strong>&#x6A21;&#x5757;</strong>&#x662F;&#x4E00;&#x4E2A;&#x5355;&#x72EC;&#x7684; Python &#x6587;&#x4EF6;&#xFF0C;&#x6A21;&#x5757;&#x540D;&#x5373;&#x4E3A;&#x6587;&#x4EF6;&#x540D;&#xFF0C;&#x5728;&#x8FD9;&#x4E2A;&#x6A21;&#x5757;&#x4E2D;&#x53EF;&#x4EE5;&#x4F7F;&#x7528;&#x5168;&#x5C40;&#x53D8;&#x91CF;<code>__name__</code>&#x6765;&#x8BBF;&#x95EE;&#x6A21;&#x5757;&#x540D;&#x3002;&#x4F8B;&#x5982;&#x73B0;&#x5728;&#x6709;&#x4E24;&#x4E2A;&#x6587;&#x4EF6;&#x4E00;&#x4E2A;&#x5165;&#x53E3;&#x6587;&#x4EF6;<code>app.py</code>&#x4E0E;&#x53E6;&#x5916;&#x7F16;&#x5199;&#x7684;&#x4E00;&#x4E2A;&#x7B80;&#x5355;&#x7684;&#x6A21;&#x5757;<code>firstmode.py</code></p>
<pre><code class="language-python"># firstmode.py
first_var = 100

def firstfunc1():
    print(&apos;hello from func1&apos;)
    print(&apos;I\&apos;m in &apos; + __name__)

def firstfunc2():
    print(&apos;hello from func2&apos;)

def _privatefunc3():
    print(&apos;i m a private func&apos;)

class FirstClass():
    pass
</code></pre>
<p>&#x5728;<code>app.py</code>&#x4E2D;&#x53EF;&#x4EE5;&#x8FD9;&#x6837;&#x5F15;&#x5165;&#x8FD9;&#x4E2A;&#x6A21;&#x5757;&#xFF0C;&#x8FD9;&#x6837;&#x6A21;&#x5757;&#x4E2D;&#x6240;&#x5B9A;&#x4E49;&#x7684;&#x53D8;&#x91CF;&#x3001;&#x51FD;&#x6570;&#x5219;&#x53EF;&#x4EE5;&#x5728;&#x5176;&#x4E2D;&#x4F7F;&#x7528;&#x6A21;&#x5757;&#x540D;&#x8C03;&#x7528;&#xFF0C; &#x5728; vscode &#x4E2D;&#x81EA;&#x52A8;&#x8865;&#x5168;&#x8FD8;&#x6709;<code>_privatefunc3</code>&#xFF0C;&#x4F46;&#x662F;&#x5B9E;&#x9645;&#x4E0A;&#x5728; Python &#x4E2D;&#x4EE5;&#x4E0B;&#x5212;&#x7EBF;&#x5F00;&#x5934;&#x7684;&#x51FD;&#x6570;&#x662F;&#x88AB;&#x7EA6;&#x5B9A;&#x4E3A;&#x79C1;&#x6709;&#x7684;&#xFF0C;&#x5E76;&#x4E0D;&#x5141;&#x8BB8;&#x4ECE;&#x6A21;&#x5757;&#x5916;&#x8C03;&#x7528;&#x3002;</p>
<p><img src="https://cdn.nlark.com/yuque/0/2018/png/110142/1540125502512-assets/web-upload/29b3add0-d581-4c30-bc16-77850be52e17.png" alt loading="lazy"></p>
<p>&#x6216;&#x8005;&#x53EA;&#x60F3;&#x5F15;&#x5165;&#x8FD9;&#x4E2A;&#x6A21;&#x5757;&#x4E2D;&#x7684;&#x67D0;&#x4E00;&#x4E2A;&#x51FD;&#x6570;&#xFF0C;&#x4E3A;&#x4E86;&#x51CF;&#x5C11;&#x5F15;&#x5165;&#x591A;&#x4F59;&#x90E8;&#x5206;&#x7684;&#x5F00;&#x59CB;&#xFF0C;&#x8FD8;&#x53EF;&#x4EE5;&#x4F7F;&#x7528;&#xFF1A;</p>
<pre><code class="language-python">from firstmod import firstfunc1

# &#x5C31;&#x53EF;&#x4EE5;&#x76F4;&#x63A5;&#x4F7F;&#x7528;firstfunc1&#x540D;&#x5B57;&#x4E86;&#x4E0D;&#x7528;&#x52A0;&#x4E0A;&#x6A21;&#x5757;&#x540D;&#x6765;&#x9650;&#x5B9A;
firstfunc1()
</code></pre>
<p>&#x8FD8;&#x6709;&#x66F4;&#x591A;&#x65B9;&#x5F0F;&#xFF1A;</p>
<pre><code class="language-python"># &#x9017;&#x53F7;&#x5206;&#x9694;&#x4EE5;&#x5F15;&#x5165;&#x4E00;&#x4E2A;&#x6A21;&#x5757;&#x4E2D;&#x7684;&#x591A;&#x4E2A;&#x5185;&#x5BB9;
from firstmod import firstfunc1, firstfunc2
# &#x5F15;&#x5165;&#x4E86;firstmod&#x4E2D;&#x7684;&#x6240;&#x6709;&#x5185;&#x5BB9;&#xFF0C;&#x4E14;&#x4F7F;&#x7528;&#x65F6;&#x4E0D;&#x9700;&#x8981;&#x5728;&#x524D;&#x9762;&#x52A0;&#x4E0A;&#x6A21;&#x5757;&#x540D;
from firstmod import *
# &#x4E3A;&#x5F15;&#x5165;&#x7684;&#x5185;&#x5BB9;&#x8BBE;&#x5B9A;&#x4E00;&#x4E2A;&#x522B;&#x540D;&#xFF0C;&#x5728;&#x4E0B;&#x9762;&#x76F4;&#x63A5;&#x4F7F;&#x7528;&#x81EA;&#x5B9A;&#x4E49;&#x7684;&#x522B;&#x540D;func1&#x5C31;&#x53EF;&#x4EE5;
from firstmode import firstfunc1 as func1
</code></pre>
<h2 id="package">Package</h2>
<p>Package(&#x5305;)&#xFF0C;&#x662F; Python &#x4E2D;&#x7528;&#x4E8E;&#x7EC4;&#x7EC7;&#x591A;&#x4E2A;&#x6A21;&#x5757;&#x7684;&#x65B9;&#x5F0F;&#xFF0C;&#x53EF;&#x4EE5;&#x4F7F;&#x7528;&#x5F62;&#x5982;<code>A.B</code>&#x7684;&#x65B9;&#x5F0F;&#x4F7F;&#x7528;&#xFF0C;&#x610F;&#x5473;&#x5B50;&#x6A21;&#x5757;<code>B</code>&#x4F4D;&#x4E8E;&#x540D;&#x4E3A;<code>A</code>&#x7684;&#x5305;&#x4E2D;&#x3002;&#x5B9A;&#x4E49;&#x4E00;&#x4E2A;&#x5305;&#x9700;&#x8981;&#x65B0;&#x5EFA;&#x4E00;&#x4E2A;&#x76EE;&#x5F55;&#x4E3A;&#x5305;&#x540D;&#xFF0C;&#x5728;&#x76EE;&#x5F55;&#x4E0B;&#x5FC5;&#x987B;&#x6709;&#x4E00;&#x4E2A;<code>__init__.py</code>&#x7684;&#x6587;&#x4EF6;&#xFF0C;&#x7528;&#x4E8E;&#x521D;&#x59CB;&#x5316;&#x4E00;&#x4E9B;&#x5F15;&#x5165;&#x5305;&#x7684;&#x5DE5;&#x4F5C;&#xFF0C;&#x4E00;&#x822C;&#x53EF;&#x4EE5;&#x7559;&#x7A7A;&#x3002;&#x4E0B;&#x9762;&#x6709;&#x4E00;&#x4E2A;&#x7B80;&#x5355;&#x7684;&#x76EE;&#x5F55;&#x7ED3;&#x6784;&#x3002;</p>
<pre><code>.
&#x251C;&#x2500;&#x2500; app.py
&#x251C;&#x2500;&#x2500; firstmod.py
&#x2514;&#x2500;&#x2500; mypackage
    &#x251C;&#x2500;&#x2500; __init__.py
    &#x251C;&#x2500;&#x2500; secondmod.py
    &#x2514;&#x2500;&#x2500; subpackage1
        &#x251C;&#x2500;&#x2500; __init__.py
        &#x2514;&#x2500;&#x2500; thirdmod.py
</code></pre>
<p>&#x5B9A;&#x4E49;&#x4E86;&#x591A;&#x4E2A;&#x5C42;&#x7EA7;&#x7684;&#x5305;&#x6765;&#x7BA1;&#x7406;&#x6A21;&#x5757;&#xFF0C;&#x4E3A;&#x4E86;&#x7B80;&#x5355;&#xFF0C;&#x5728; secondmode &#x4E2D;&#x53EA;&#x5B9A;&#x4E49;&#x4E86;&#x4E00;&#x4E2A;<code>second_var</code>&#x7684;&#x53D8;&#x91CF;&#xFF0C;<code>thirdmod.py</code>&#x4E2D;&#x53EA;&#x5B9A;&#x4E49;&#x4E86;<code>third_var</code>&#x53D8;&#x91CF;&#x3002;&#x90A3;&#x4E48;&#x5728;&#x5165;&#x53E3;&#x6587;&#x4EF6;<code>app.py</code>&#xFF0C;&#x5219;&#x53EF;&#x4EE5;&#x8FD9;&#x6837;&#x4F7F;&#x7528;&#xFF1A;</p>
<pre><code class="language-python"># &#x53EA;&#x5F15;&#x5165;&#x6700;&#x4E0A;&#x5C42;&#x7684;&#x5305;
import mypackage
# &#x53EF;&#x4EE5;&#x8C03;&#x7528;&#x8FD9;&#x4E2A;&#x5305;&#x4E0B;&#x7684;&#x6240;&#x6709;&#x5B50;&#x6A21;&#x5757;&#x7684;&#x5185;&#x5BB9;
print(mypackage.secondmod.second_var)
# &#x4F46;&#x662F;&#x8FD9;&#x6837;&#x8C03;&#x7528;&#x5305;&#x4E0B;&#x9762;&#x7684;&#x5B50;&#x5305;&#x4E0B;&#x7684;&#x6A21;&#x5757;&#x7684;&#x5185;&#x5BB9;&#x5C31;&#x4F1A;&#x51FA;&#x9519;
# AttributeError: module &apos;mypackage&apos; has no attribute &apos;subpackage1&apos;
print(mypackage.subpackage1.thirdmod.third_var)

# &#x4F7F;&#x7528;from
from mypackage import secondmod
print(secondmod.second_var)
</code></pre>
<p>&#x7B80;&#x800C;&#x8A00;&#x4E4B;&#xFF0C;&#x4F7F;&#x7528;<code>from a import b</code>&#xFF0C;&#x82E5;<code>a</code>&#x662F;&#x4E00;&#x4E2A;&#x6A21;&#x5757;&#x540D;&#xFF0C;&#x90A3;&#x4E48;&#x5C31;&#x5F15;&#x5165;&#x4E86;&#x6A21;&#x5757;<code>a</code>&#x4E0B;&#x7684;&#x4E00;&#x4E2A;&#x540D;&#x4E3A;<code>b</code>&#x7684;&#x51FD;&#x6570;&#x3001;&#x53D8;&#x91CF;&#x3001;&#x6216;&#x7C7B;&#xFF1B;&#x82E5;<code>a</code>&#x662F;&#x4E00;&#x4E2A;&#x5305;&#x540D;&#xFF0C;&#x90A3;&#x4E48;&#x5C31;&#x5F15;&#x5165;&#x4E86;&#x5305;<code>a</code>&#x4E0B;&#x7684;&#x4E00;&#x4E2A;&#x6A21;&#x5757;<code>b</code>&#x3002;</p>
<h2 id><code>*</code>&#x7684;&#x4F7F;&#x7528;</h2>
<p>&#x5F88;&#x591A;&#x65F6;&#x5019;&#x4E3A;&#x4E86;&#x65B9;&#x4FBF;&#x5728;&#x5F15;&#x5165;&#x5305;&#x65F6;&#x4F7F;&#x7528;<code>*</code>&#xFF0C;&#x4F46;&#x662F;&#x5B83;&#x5E76;&#x4E0D;&#x662F;&#x4E00;&#x4E2A;&#x597D;&#x65B9;&#x6CD5;&#xFF0C;&#x56E0;&#x4E3A;&#x8FD9;&#x6837;&#x4F7F;&#x7528;&#x4E0D;&#x53EF;&#x63A7;&#x4E14;&#x53EF;&#x8BFB;&#x6027;&#x5DEE;&#xFF0C;&#x82E5;&#x4E00;&#x5B9A;&#x8981;&#x4F7F;&#x7528;<code>*</code>&#xFF0C;&#x53EF;&#x4EE5;&#x5728;&#x6A21;&#x5757;&#x4E0B;&#x5B9A;&#x4E00;&#x4E2A; list<code>__all__</code>&#xFF0C;&#x5982;&#x5728;<code>firstmod.py</code>&#x4E2D;&#x5B9A;&#x4E49;&#x4E00;&#x4E2A;&#xFF1A;</p>
<pre><code class="language-python">__all__ = [&apos;firstfunc1&apos;, &apos;firstfunc2&apos;]
</code></pre>
<p>&#x90A3;&#x4E48;&#x5728;&#x4F7F;&#x7528;<code>from firstmod import *</code>&#x65F6;&#xFF0C;&#x5C31;&#x53EA;&#x6709;&#x5B9A;&#x4E49;&#x5728;<code>__all__</code>&#x4E2D;&#x7684;&#x4E24;&#x4E2A;&#x65B9;&#x6CD5;&#x88AB;&#x5F15;&#x5165;&#x4E86;&#x3002;</p>
<h2 id>&#x76F8;&#x5BF9;&#x5F15;&#x5165;</h2>
<p>&#x5C31;&#x5982;&#x5728;&#x8868;&#x793A;&#x76EE;&#x5F55;&#x65F6;&#x4F7F;&#x7528;<code>.</code>&#x8868;&#x793A;&#x5F53;&#x524D;&#x76EE;&#x5F55;&#xFF0C;<code>..</code>&#x8868;&#x793A;&#x4E0A;&#x4E00;&#x7EA7;&#x76EE;&#x5F55;&#x4E00;&#x6837;&#xFF0C;Python &#x5728; import &#x65F6;&#x4E5F;&#x53EF;&#x4EE5;&#x6709;&#x8FD9;&#x6837;&#x7684;&#x64CD;&#x4F5C;</p>
<pre><code class="language-python"># &#x5728;thirdmod.py&#x4E2D;
from .. import secondmod
print(secondmod.second_var)
</code></pre>
<h2 id="dir"><code>dir()</code></h2>
<p>&#x5185;&#x7F6E;&#x51FD;&#x6570;<code>dir()</code>&#x53EF;&#x4EE5;&#x67E5;&#x770B;&#x5728;&#x5F53;&#x524D;&#x6A21;&#x5757;&#x4E2D;&#x5B9A;&#x4E49;&#x4E86;&#x54EA;&#x4E9B;&#x540D;&#x5B57;&#xFF0C;&#x6216;&#x8005;&#x53EF;&#x4EE5;&#x4F7F;&#x7528;&#x53C2;&#x6570;&#x6307;&#x5B9A;&#x4E00;&#x4E2A;&#x6A21;&#x5757;</p>
<pre><code class="language-python">&gt;&gt;&gt; import flask
&gt;&gt;&gt; dir(flask)
[&apos;Blueprint&apos;, &apos;Config&apos;, &apos;Flask&apos;, &apos;Markup&apos;, &apos;Request&apos;, &apos;Response&apos;, &apos;Session&apos;, &apos;__builtins__&apos;, &apos;__cached__&apos;, &apos;__doc__&apos;, &apos;__file__&apos;, &apos;__loader__&apos;, &apos;__name__&apos;, &apos;__package__&apos;, &apos;__path__&apos;, &apos;__spec__&apos;, &apos;__version__&apos;, &apos;_app_ctx_stack&apos;, &apos;_compat&apos;, &apos;_request_ctx_stack&apos;, &apos;abort&apos;, &apos;after_this_request&apos;, &apos;app&apos;, &apos;appcontext_popped&apos;, &apos;appcontext_pushed&apos;, &apos;appcontext_tearing_down&apos;, &apos;before_render_template&apos;, &apos;blueprints&apos;, &apos;cli&apos;, &apos;config&apos;, &apos;copy_current_request_context&apos;, &apos;ctx&apos;, &apos;current_app&apos;, &apos;escape&apos;, &apos;flash&apos;, &apos;g&apos;, &apos;get_flashed_messages&apos;, &apos;get_template_attribute&apos;, &apos;globals&apos;, &apos;got_request_exception&apos;, &apos;has_app_context&apos;, &apos;has_request_context&apos;, &apos;helpers&apos;, &apos;json&apos;, &apos;json_available&apos;, &apos;jsonify&apos;, &apos;logging&apos;, &apos;make_response&apos;, &apos;message_flashed&apos;, &apos;redirect&apos;, &apos;render_template&apos;, &apos;render_template_string&apos;, &apos;request&apos;, &apos;request_finished&apos;, &apos;request_started&apos;, &apos;request_tearing_down&apos;, &apos;safe_join&apos;, &apos;send_file&apos;, &apos;send_from_directory&apos;, &apos;session&apos;, &apos;sessions&apos;, &apos;signals&apos;, &apos;signals_available&apos;, &apos;stream_with_context&apos;, &apos;template_rendered&apos;, &apos;templating&apos;, &apos;url_for&apos;, &apos;wrappers&apos;]
&gt;&gt;&gt;
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[在 k8s 中对指定 Pod 进行抓包]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>&#x8FD1;&#x65E5;&#x5728;&#x7814;&#x7A76;&#x5FAE;&#x670D;&#x52A1;&#x67B6;&#x6784;&#x4E2D;&#x7684; <a href="https://istio.io/docs/tasks/telemetry/distributed-tracing/">Distributed Tracing</a> &#x65F6;&#xFF0C;&#x9047;&#x5230;&#x4E86;&#x4E00;&#x4E9B;&#x95EE;&#x9898;&#xFF0C;&#x9700;&#x8981;&#x6DF1;&#x5165;&#x5230;&#x5E95;&#x5C42;&#x53BB;&#x8FDB;&#x884C;&#x7F51;&#x7EDC;&#x6293;&#x5305;&#x5206;&#x6790;&#x62A5;&#x6587;&#x3002;&#x4F46;&#x662F;&#x5E94;&#x7528;&#x65F6;&#x8FD0;&#x884C;</p>]]></description><link>https://ruofeng.me/2018/09/19/capture-packets-in-kubernetes/</link><guid isPermaLink="false">5d8e378da7d96200019ade20</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[Docker]]></category><category><![CDATA[计算机网络]]></category><dc:creator><![CDATA[Ruofeng Lei]]></dc:creator><pubDate>Wed, 19 Sep 2018 08:49:31 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>&#x8FD1;&#x65E5;&#x5728;&#x7814;&#x7A76;&#x5FAE;&#x670D;&#x52A1;&#x67B6;&#x6784;&#x4E2D;&#x7684; <a href="https://istio.io/docs/tasks/telemetry/distributed-tracing/">Distributed Tracing</a> &#x65F6;&#xFF0C;&#x9047;&#x5230;&#x4E86;&#x4E00;&#x4E9B;&#x95EE;&#x9898;&#xFF0C;&#x9700;&#x8981;&#x6DF1;&#x5165;&#x5230;&#x5E95;&#x5C42;&#x53BB;&#x8FDB;&#x884C;&#x7F51;&#x7EDC;&#x6293;&#x5305;&#x5206;&#x6790;&#x62A5;&#x6587;&#x3002;&#x4F46;&#x662F;&#x5E94;&#x7528;&#x65F6;&#x8FD0;&#x884C;&#x5728; k8s &#x96C6;&#x7FA4;&#x4E2D;&#x7684;&#xFF0C;&#x4E0E;&#x4F20;&#x7EDF;&#x7684;&#x5728;&#x4E00;&#x53F0;&#x673A;&#x5668;&#x4E0A;&#x8DD1;&#x4E00;&#x4E2A;&#x8FDB;&#x7A0B;&#x76F4;&#x63A5;&#x901A;&#x8FC7; tcpdump &#x6293;&#x5305;&#x65B9;&#x5F0F;&#x7565;&#x6709;&#x4E0D;&#x540C;&#x3002;&#x6700;&#x521D;&#x5BF9;&#x5BB9;&#x5668;&#x7684;&#x7406;&#x89E3;&#x4E0D;&#x6DF1;&#x523B;&#x8BA4;&#x4E3A;&#x4E00;&#x5B9A;&#x8981;&#x8FDB;&#x5165;&#x5230;&#x8FD9;&#x4E2A;&#x5BB9;&#x5668;&#x6293;&#x5305;&#xFF0C;&#x800C;&#x8FDB;&#x5165;&#x5BB9;&#x5668;&#x5185;&#x5E76;&#x6CA1;&#x6709; tcpdump &#x7B49;&#x57FA;&#x7840;&#x5DE5;&#x5177;&#xFF0C;&#x76F8;&#x5F53;&#x4E8E;&#x81EA;&#x5DF1;&#x8FD8;&#x662F;&#x628A;&#x5BB9;&#x5668;&#x5F53;&#x4F5C;&#x865A;&#x62DF;&#x673A;&#x5728;&#x770B;&#x5F85;&#x3002;&#x800C;&#x5B9E;&#x9645;&#x4E0A; <strong>&#x5B83;&#x4EEC;&#x53EA;&#x662F;&#x5728;&#x5BBF;&#x4E3B;&#x673A;&#x4E0A;&#x4E0D;&#x540C; namespace &#x8FD0;&#x884C;&#x7684;&#x8FDB;&#x7A0B;&#x800C;&#x5DF2;</strong> &#x3002;&#x56E0;&#x6B64;&#x8981;&#x5728;&#x4E0D;&#x540C;&#x7684;&#x5BB9;&#x5668;&#x6293;&#x5305;&#x53EF;&#x4EE5;&#x7B80;&#x5355;&#x5730;&#x4F7F;&#x7528;&#x547D;&#x4EE4;&#x5207;&#x6362; network namespace &#x5373;&#x53EF;&#xFF0C;&#x53EF;&#x4EE5;&#x4F7F;&#x7528;&#x5728;&#x5BBF;&#x4E3B;&#x673A;&#x4E0A;&#x7684; tcpdump &#x7B49;&#x5E94;&#x7528;&#x3002;</p>
<h2 id="pod">&#x67E5;&#x770B;&#x6307;&#x5B9A; pod &#x8FD0;&#x884C;&#x5728;&#x54EA;&#x4E2A;&#x5BBF;&#x4E3B;&#x673A;&#x4E0A;</h2>
<pre><code>kubctl describe pod &lt;pod&gt; -n mservice
</code></pre>
<h2 id="pid">&#x83B7;&#x5F97;&#x5BB9;&#x5668;&#x7684; pid</h2>
<pre><code>docker inspect -f {{.State.Pid}} &lt;container&gt;
</code></pre>
<h2 id="networknamespace">&#x8FDB;&#x5165;&#x8BE5;&#x5BB9;&#x5668;&#x7684; network namespace</h2>
<pre><code>nsenter --target &lt;PID&gt; -n
</code></pre>
<h2 id="tcpdumpeth0">&#x4F7F;&#x7528; <code>tcpdump</code> &#x6293;&#x5305;&#xFF0C;&#x6307;&#x5B9A; eth0 &#x7F51;&#x5361;</h2>
<pre><code>tcpdump -i eth0 tcp and port 80 -vvv
</code></pre>
<h2 id>&#x6216;&#x8005;&#x76F4;&#x63A5;&#x6293;&#x5305;&#x5E76;&#x5BFC;&#x51FA;&#x5230;&#x6587;&#x4EF6;</h2>
<pre><code>tcpdump -i eth0 -w ./out.cap
</code></pre>
<h2 id="scp">&#x4ECE;&#x8FDC;&#x7A0B; scp &#x5230;&#x672C;&#x5730;</h2>
<pre><code>scp ruofeng@ipaddr:/home/ruofeng/out.cap ./
</code></pre>
<p>&#x4E4B;&#x540E;&#x5728; Wireshark &#x4E2D;&#x53EF;&#x4EE5;&#x6253;&#x5F00;&#x6587;&#x4EF6;&#x975E;&#x5E38;&#x76F4;&#x89C2;&#x5F97;&#x67E5;&#x770B;&#x8FC7;&#x6EE4;&#x6293;&#x5230;&#x7684;&#x6570;&#x636E;&#x3002;</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[关于阿里秋招一道算法题的反思]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>&#x7531;&#x4E8E;&#x5F53;&#x65F6;&#x8BFB;&#x9898;&#x7406;&#x89E3;&#x9898;&#x610F;&#x7B2C;&#x4E00;&#x65F6;&#x95F4;&#x6CA1;&#x6709;&#x5F88;&#x597D;&#x7684;&#x5C06;&#x9898;&#x76EE;&#x62BD;&#x8C61;&#x6210;&#x826F;&#x597D;&#x7684;&#x6570;&#x636E;&#x7ED3;&#x6784;&#x6A21;&#x578B;&#xFF0C;&#x52A0;&#x4E0A;&#x53F3;&#x4E0A;&#x89D2;&#x7684;&#x65F6;&#x95F4;&#x5012;&#x8BA1;&#x65F6;&#x770B;&#x5F97;&#x5FC3;&#x614C;</p>]]></description><link>https://ruofeng.me/2018/07/21/thougths-about-an-algorithm-problem-of-alibaba/</link><guid isPermaLink="false">5d8e378da7d96200019ade1f</guid><category><![CDATA[算法]]></category><category><![CDATA[数据结构]]></category><dc:creator><![CDATA[Ruofeng Lei]]></dc:creator><pubDate>Sat, 21 Jul 2018 14:30:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>&#x7531;&#x4E8E;&#x5F53;&#x65F6;&#x8BFB;&#x9898;&#x7406;&#x89E3;&#x9898;&#x610F;&#x7B2C;&#x4E00;&#x65F6;&#x95F4;&#x6CA1;&#x6709;&#x5F88;&#x597D;&#x7684;&#x5C06;&#x9898;&#x76EE;&#x62BD;&#x8C61;&#x6210;&#x826F;&#x597D;&#x7684;&#x6570;&#x636E;&#x7ED3;&#x6784;&#x6A21;&#x578B;&#xFF0C;&#x52A0;&#x4E0A;&#x53F3;&#x4E0A;&#x89D2;&#x7684;&#x65F6;&#x95F4;&#x5012;&#x8BA1;&#x65F6;&#x770B;&#x5F97;&#x5FC3;&#x614C;&#xFF0C;&#x6574;&#x4E2A;&#x8FC7;&#x7A0B;&#x4E2D;&#x5FC3;&#x6001;&#x5F88;&#x4E0D;&#x597D;&#xFF0C;&#x5BFC;&#x81F4;&#x6CA1;&#x505A;&#x51FA;&#x6765;&#xFF0C;&#x6700;&#x540E;&#x4E5F;&#x5C06;&#x9898;&#x76EE;&#x590D;&#x5236;&#x4E86;&#x4E0B;&#x6765;&#x5F53;&#x5929;&#x665A;&#x4E0A;&#x8FDB;&#x884C;&#x4E86;&#x597D;&#x597D;&#x7684;&#x53CD;&#x601D;&#x3002;&#x4E3A;&#x4E86;&#x9632;&#x6B62;&#x88AB;&#x68C0;&#x7D22;&#xFF0C;&#x8FD9;&#x91CC;&#x5C31;&#x4E0D;&#x8D34;&#x5904;&#x8BE6;&#x7EC6;&#x7684;&#x5185;&#x5BB9;&#x4E86;&#xFF0C;&#x4EC5;&#x4EC5;&#x63CF;&#x8FF0;&#x4E00;&#x4E0B;&#x9898;&#x76EE;&#x672C;&#x610F;&#xFF1A;</p>
<p>&#x7ED9;&#x5B9A;&#x4E00;&#x4E2A; <strong>&#x6709;&#x5411;&#x65E0;&#x73AF;&#x56FE;</strong> &#xFF0C;&#x8FD9;&#x4E2A;&#x56FE;&#x7684;&#x6BCF;&#x4E2A;&#x8282;&#x70B9;&#x4E2D;&#x6709;&#x4E00;&#x4E2A;&#x6570;&#x503C;&#xFF0C;&#x9700;&#x8981;&#x6C42;&#x51FA;&#x7684;&#x662F;&#x4ECE;&#x5165;&#x5EA6;&#x4E3A; 0 &#x7684;&#x8282;&#x70B9;&#x5F00;&#x59CB;&#x904D;&#x5386;&#x6574;&#x5F20;&#x56FE;&#x7684;&#x6240;&#x6709;&#x8DEF;&#x5F84;&#x7684;&#x6761;&#x6570;&#xFF0C;&#x4EE5;&#x53CA;&#x6240;&#x7ECF;&#x8FC7;&#x8DEF;&#x5F84;&#x4E4B;&#x548C;&#x7684;&#x6700;&#x5927;&#x503C;&#x3002;</p>
<h2 id>&#x56FE;&#x8282;&#x70B9;&#x7684;&#x8868;&#x793A;</h2>
<p>&#x786E;&#x5B9E;&#x4E5F;&#x662F;&#x56E0;&#x4E3A;&#x6700;&#x8FD1;&#x63A5;&#x89E6;&#x5230;&#x7684;&#x56FE;&#x8BBA;&#x7684;&#x9898;&#x76EE;&#x592A;&#x5C11;&#x4E86;&#xFF0C;&#x62BD;&#x8C61;&#x80FD;&#x529B;&#x4E0D;&#x591F;&#xFF0C;&#x751A;&#x81F3;&#x60F3;&#x5230;&#x56FE;&#x90FD;&#x7B2C;&#x4E00;&#x65F6;&#x95F4;&#x6CA1;&#x60F3;&#x5230;&#x56FE;&#x8282;&#x70B9;&#x662F;&#x5982;&#x4F55;&#x8868;&#x793A;&#x7684;</p>
<pre><code class="language-cpp">class DirectedGraphNode {
  public:
    int tag;    //&#x4E3A;&#x4E86;&#x65B9;&#x4FBF;&#x8C03;&#x8BD5;&#xFF0C;&#x8FD9;&#x91CC;&#x6807;&#x8BC6;&#x4E00;&#x4E0B;&#x662F;&#x7B2C;&#x51E0;&#x4E2A;&#x8282;&#x70B9;
    int val;    //&#x8282;&#x70B9;&#x8BB0;&#x5F55;&#x7684;&#x503C;
    vector&lt;DirectedGraphNode *&gt; neighbors;                  //&#x7528;vector&#x8BB0;&#x5F55;&#x5176;&#x6307;&#x5411;&#x7684;&#x6240;&#x6709;&#x4E0B;&#x4E00;&#x4E2A;&#x8282;&#x70B9;
    DirectedGraphNode(int t, int x) : tag(t), val(x) {};   //&#x6784;&#x9020;&#x51FD;&#x6570;
};
</code></pre>
<h2 id>&#x8BA1;&#x7B97;&#x5E76;&#x4FDD;&#x5B58;&#x5165;&#x5EA6;</h2>
<p>&#x7531;&#x4E8E;&#x8FD9;&#x9053;&#x9898;&#x6D89;&#x53CA;&#x5230;&#x9012;&#x5F52;&#xFF0C;&#x5DF2;&#x7ECF;&#x8BB0;&#x5F55;&#x4E00;&#x4E9B;&#x5168;&#x5C40;&#x7684;&#x5173;&#x952E;&#x5C5E;&#x6027;&#xFF08;&#x8DEF;&#x5F84;&#x6761;&#x6570;&#x8FD8;&#x6709;&#x6700;&#x5927;&#x503C;&#xFF09;&#xFF0C;&#x56E0;&#x6B64;&#x5728;&#x4E00;&#x4E2A;&#x7C7B;&#x4E2D;&#x5B8C;&#x6210;&#x8FD9;&#x4E2A;&#x8BA1;&#x7B97;&#x51FD;&#x6570;&#x7684;&#x7F16;&#x5199;&#xFF0C;&#x9996;&#x5148;&#x8BB0;&#x5F55;&#x56DB;&#x4E2A;&#x5C5E;&#x6027;&#xFF1A;</p>
<ol>
<li>&#x56FE;</li>
<li>&#x5165;&#x5EA6;&#xFF08;&#x53EF;&#x4EE5;&#x5728;&#x6784;&#x9020;&#x51FD;&#x6570;&#x4E2D;&#x5B8C;&#x6210;&#x8BA1;&#x7B97;&#xFF09;</li>
<li>&#x6700;&#x5927;&#x8DEF;&#x5F84;&#x548C;</li>
<li>&#x8DEF;&#x5F84;&#x6570;&#x91CF;</li>
</ol>
<pre><code class="language-cpp">vector&lt;DirectedGraphNode *&gt; graph;
unordered_map&lt;DirectedGraphNode *, int&gt; degrees;
int maxSum;
int pathCount;
</code></pre>
<p>&#x5176;&#x4E2D;&#x5165;&#x5EA6;&#x7528;&#x4E00;&#x4E2A;&#x56FE;&#x8282;&#x70B9;&#x4E0E;&#x6574;&#x6570;&#x7684;&#x5BF9;&#x5E94; map &#x8BB0;&#x5F55;&#xFF0C;&#x6784;&#x9020;&#x65B9;&#x5F0F;&#x4E3A;&#x9996;&#x5148;&#x904D;&#x5386;&#x6574;&#x4E2A;&#x56FE;&#x7684;&#x6240;&#x6709;&#x8282;&#x70B9;&#xFF0C;&#x5728; map &#x4E2D;&#x82E5;&#x6CA1;&#x6709;&#x8FD9;&#x4E2A;&#x8282;&#x70B9;&#x7684; key &#x5219;&#x521D;&#x59CB;&#x5316;&#x4E3A; 0&#xFF0C;&#x82E5;&#x6709;&#x5219;&#x904D;&#x5386;&#x8FD9;&#x4E2A;&#x8282;&#x70B9;&#x662F;&#x6240;&#x6709; neighbor &#x5373;&#x6307;&#x5411;&#x7684;&#x6240;&#x6709;&#x4E0B;&#x4E00;&#x8282;&#x70B9;&#xFF0C;&#x5E76;&#x4E3A;&#x5176;&#x9012;&#x589E; 1<br>
&#xFF0C;&#x4EE3;&#x7801;&#x8868;&#x793A;&#x5982;&#x4E0B;&#xFF1A;</p>
<pre><code class="language-cpp">for (auto node: graph) {
    if (degrees.find(node) == degrees.end()) {
        degrees[node] = 0;
    }
    for (auto n:node-&gt;neighbors) {
        degrees[n]++;
    }
}
</code></pre>
<h2 id="0">&#x4ECE;&#x5165;&#x5EA6;&#x4E3A; 0 &#x7684;&#x8282;&#x70B9;&#x5F00;&#x59CB;&#x904D;&#x5386;</h2>
<p>&#x53EA;&#x6709;&#x5165;&#x5EA6;&#x4E3A; 0 &#x7684;&#x8282;&#x70B9;&#x80FD;&#x591F;&#x88AB;&#x5F53;&#x4F5C;&#x4E00;&#x6761;&#x8DEF;&#x5F84;&#x7684;&#x8D77;&#x59CB;&#x8282;&#x70B9;</p>
<pre><code class="language-cpp">void findFromStart() {
    for (auto node:graph) {
        if (degrees[node] == 0) {
            //&#x521D;&#x59CB;&#x5316;&#x4E00;&#x6761;&#x8DEF;&#x5F84;
            vector&lt;DirectedGraphNode *&gt; path;
            //&#x521D;&#x59CB;&#x5316;&#x8FD9;&#x6761;&#x8DEF;&#x5F84;&#x7684;&#x548C;
            int currentSum = 0;
            findPath(node, path, currentSum);
        }
    }
}
</code></pre>
<p>&#x9700;&#x8981;&#x5224;&#x65AD;&#x662F;&#x5426;&#x8D70;&#x5230;&#x5C3D;&#x5934;&#xFF0C;&#x82E5;&#x8D70;&#x5230;&#x5C3D;&#x5934;&#x5219;&#x9700;&#x8981;&#x51B3;&#x5B9A;&#x662F;&#x5426;&#x8BB0;&#x5F55;&#x8FD9;&#x6761;&#x8DEF;&#x5F84;&#x7684;&#x6700;&#x5927;&#x503C;&#x4EE5;&#x53CA;&#x8DEF;&#x5F84;&#x603B;&#x6761;&#x6570;&#x7D2F;&#x52A0;&#xFF0C;&#x82E5;&#x672A;&#x8D70;&#x5230;&#x5C3D;&#x5934;&#x5219;&#x9012;&#x5F52;&#x8C03;&#x7528;&#xFF1A;</p>
<pre><code class="language-cpp">void findPath(DirectedGraphNode *currentNode, vector&lt;DirectedGraphNode *&gt; currentPath, int currentSum) {
    //&#x8BBF;&#x95EE;&#x5230;&#x8FD9;&#x4E2A;&#x8282;&#x70B9;&#xFF0C;&#x5219;&#x5C06;&#x5F53;&#x524D;&#x8282;&#x70B9;&#x52A0;&#x5165;&#x5230;&#x8DEF;&#x5F84;&#x4E2D;&#xFF0C;&#x5F53;&#x524D;&#x8282;&#x70B9;&#x7684;&#x503C;&#x4E5F;&#x7D2F;&#x52A0;
    currentPath.push_back(currentNode);
    currentSum += currentNode-&gt;val;
    //&#x8D70;&#x5230;&#x8DEF;&#x5F84;&#x5C3D;&#x5934;&#xFF08;&#x51FA;&#x5EA6;&#x4E3A;0&#xFF09;
    if (currentNode-&gt;neighbors.size() == 0) {
        //&#x8DEF;&#x5F84;&#x6570;&#x76EE;+1
        pathCount++;
        //&#x8BA1;&#x7B97;&#x5E76;&#x51B3;&#x5B9A;&#x662F;&#x5426;&#x4FDD;&#x7559;&#x6700;&#x5927;&#x503C;
        if (currentSum &gt; maxSum)
            maxSum = currentSum;
        return;
    }
    //&#x7EE7;&#x7EED;&#x5411;&#x4E0B;&#x5BFB;&#x627E;&#xFF0C;&#x5E76;&#x9012;&#x5F52;&#x8C03;&#x7528;
    for (auto node:currentNode-&gt;neighbors) {
        findPath(node, currentPath, currentSum);
    }
}
</code></pre>
<h2 id>&#x603B;&#x7ED3;&#x5E76;&#x53CD;&#x601D;</h2>
<p>&#x9996;&#x5148;&#x662F;&#x7EC3;&#x4E60;&#x8FC7;&#x5C11;&#xFF0C;&#x8FD9;&#x9898;&#x5176;&#x5B9E;&#x662F;&#x975E;&#x5E38;&#x57FA;&#x7840;&#x7684;&#x56FE;&#x8BBA;&#x7B97;&#x6CD5;&#x9898;&#xFF0C;&#x4EC5;&#x4EC5;&#x662F;&#x4E00;&#x4E2A;&#x56FE;&#x7684;&#x904D;&#x5386;&#x800C;&#x5DF2;&#xFF0C;&#x53EA;&#x662F;&#x56E0;&#x4E3A;&#x81EA;&#x5DF1;&#x6700;&#x8FD1;&#x6240;&#x505A;&#x76F8;&#x5173;&#x7C7B;&#x578B;&#x9898;&#x76EE;&#x592A;&#x5C11;&#x4E86;&#x4E8E;&#x662F;&#x77ED;&#x65F6;&#x95F4;&#x5185;&#x6CA1;&#x80FD;&#x60F3;&#x5230;&#x6BD4;&#x8F83;&#x597D;&#x7684;&#x601D;&#x8DEF;&#x3002;&#x7B2C;&#x4E8C;&#x70B9;&#x5C31;&#x662F;&#x6700;&#x8FD1;&#x6240;&#x505A;&#x7684;&#x9898;&#x90FD;&#x662F;&#x7C7B;&#x4F3C; Leetcode &#x4E2D;&#x975E;&#x5E38;&#x76F4;&#x89C2;&#x7684;&#x7684;&#x7ED9;&#x51FA;&#x4E86;&#x6570;&#x636E;&#x7ED3;&#x6784;&#x4E0E;&#x7B97;&#x6CD5;&#x9700;&#x8981;&#x5B8C;&#x6210;&#x4EC0;&#x4E48;&#xFF0C;&#x800C;&#x8FD9;&#x9053;&#x9898;&#x5219;&#x6709;&#x4E00;&#x4E2A;&#x60C5;&#x666F;&#xFF0C;&#x5E76;&#x4E0D;&#x662F;&#x90A3;&#x4E48;&#x76F4;&#x63A5;&#xFF0C;&#x4E8E;&#x662F;&#x81EA;&#x5DF1;&#x7406;&#x89E3;&#x9898;&#x610F;&#x4E0E;&#x62BD;&#x8C61;&#x6570;&#x636E;&#x7ED3;&#x6784;&#x6709;&#x70B9;&#x5931;&#x8D25;&#x3002;</p>
<p>&#x79CB;&#x62DB;&#x7EE7;&#x7EED;&#x52A0;&#x6CB9;&#x628A;&#xFF0C;&#x4E0D;&#x8981;&#x8BA9;&#x6211;&#x5931;&#x671B;&#x3002;</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[堆栈中变量内存分配顺序的问题]]></title><description><![CDATA[<!--kg-card-begin: markdown--><blockquote>
<p>C &#x8BED;&#x8A00;&#x4E2D;&#x53D8;&#x91CF;&#x53EF;&#x80FD;&#x5E76;&#x4E0D;&#x662F;&#x6309;&#x7167;&#x4EE3;&#x7801;&#x4E2D;&#x58F0;&#x660E;&#x53D8;&#x91CF;&#x7684;&#x987A;&#x5E8F;&#x5206;&#x914D;&#x5728;&#x5185;&#x5B58;&#x4E2D;&#x7684;&#x3002;</p>
</blockquote>
<h2 id>&#x95EE;&#x9898;&#x7684;&#x53D1;&#x751F;</h2>
<p>&#x4ECA;&#x5929;&#x5728;&#x8BFB; <strong>C &#x9677;&#x9631;&#x4E0E;&#x7F3A;&#x9677;</strong> &#x4E00;&#x4E66;&#x65F6;&#x4E86;</p>]]></description><link>https://ruofeng.me/2018/07/18/order-of-local-variable-allocation-on-the-stack/</link><guid isPermaLink="false">5d8e378da7d96200019ade1e</guid><category><![CDATA[C/C++]]></category><dc:creator><![CDATA[Ruofeng Lei]]></dc:creator><pubDate>Wed, 18 Jul 2018 13:45:19 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><blockquote>
<p>C &#x8BED;&#x8A00;&#x4E2D;&#x53D8;&#x91CF;&#x53EF;&#x80FD;&#x5E76;&#x4E0D;&#x662F;&#x6309;&#x7167;&#x4EE3;&#x7801;&#x4E2D;&#x58F0;&#x660E;&#x53D8;&#x91CF;&#x7684;&#x987A;&#x5E8F;&#x5206;&#x914D;&#x5728;&#x5185;&#x5B58;&#x4E2D;&#x7684;&#x3002;</p>
</blockquote>
<h2 id>&#x95EE;&#x9898;&#x7684;&#x53D1;&#x751F;</h2>
<p>&#x4ECA;&#x5929;&#x5728;&#x8BFB; <strong>C &#x9677;&#x9631;&#x4E0E;&#x7F3A;&#x9677;</strong> &#x4E00;&#x4E66;&#x65F6;&#x4E86;&#x89E3;&#x5230;&#x6570;&#x7EC4;&#x8FB9;&#x754C;&#x8D4B;&#x503C;&#x6EA2;&#x51FA;&#x65F6;&#x4F1A;&#x8986;&#x76D6;&#x5176;&#x4ED6;&#x53D8;&#x91CF;&#x7684;&#x95EE;&#x9898;&#xFF0C;&#x4E66;&#x4E2D;&#x4F8B;&#x5B50;&#x662F;&#x8FD9;&#x6837;&#x7684;&#xFF0C;&#x5728;<code>a[10]</code>&#x7684;&#x5730;&#x65B9;&#xFF0C;&#x6570;&#x7EC4;<code>a</code>&#x5B9E;&#x9645;&#x4E0A;&#x4E00;&#x5171;&#x53EA;&#x6709; 10 &#x4E2A;&#x5143;&#x7D20;&#x800C;&#x7B2C;&#x5341;&#x4E00;&#x4E2A;&#x4F1A;&#x6EA2;&#x51FA;&#x5BFC;&#x81F4;&#x8986;&#x76D6; <code>i</code> &#x88AB;&#x8986;&#x76D6;&#x4E3A; 0 &#x7136;&#x540E;&#x8FDB;&#x5165;&#x6B7B;&#x5FAA;&#x73AF;&#xFF1A;</p>
<pre><code class="language-c">int i, a[10];
for (i = 1; i &lt;= 10; i++)
    a[i] = 0;
</code></pre>
<p>&#x7F16;&#x8BD1;&#x8FD0;&#x884C;&#x540E;&#x5E76;&#x6CA1;&#x6709;&#x53D1;&#x751F;&#x6B7B;&#x5FAA;&#x73AF;&#xFF0C;&#x4E8E;&#x662F;&#x4F7F;&#x7528; gdb &#x8C03;&#x8BD5;&#x770B;&#x4E86;&#x770B;&#x53D8;&#x91CF;&#x7684;&#x5730;&#x5740;&#xFF1A;</p>
<p><img src="https://ruofeng.me/content/images/2018/07/memory-allocation-order-on-stack-1.png" alt="memory-allocation-order-on-stack-1" loading="lazy"></p>
<p>&#x53D1;&#x73B0;&#x53D8;&#x91CF; i &#x7684;&#x5730;&#x5740;&#x5728;&#x6570;&#x7EC4; a &#x7684;&#x524D;&#x9762;&#xFF0C;&#x60F3;&#x7740;&#x53EF;&#x80FD;&#x662F;&#x7F16;&#x8BD1;&#x5668;&#x4E0D;&#x540C;&#x987A;&#x5E8F;&#x4E0D;&#x592A;&#x4E00;&#x6837;&#xFF1F;&#x4E8E;&#x662F;&#x6211;&#x4EA4;&#x6362;&#x4E86;&#x987A;&#x5E8F;&#xFF1A;</p>
<pre><code class="language-c">int a[10], i;
for (i = 1; i &lt;= 10; i++)
    a[i] = 0;
</code></pre>
<p>i &#x7684;&#x5730;&#x5740;&#x4F9D;&#x7136;&#x5728; a &#x524D;&#x9762;</p>
<p><img src="https://ruofeng.me/content/images/2018/07/memory-allocation-order-on-stack-2.png" alt="memory-allocation-order-on-stack-2" loading="lazy"></p>
<p>&#x8FD9;&#x5C31;&#x8BA9;&#x6211;&#x6BD4;&#x8F83;&#x7591;&#x60D1;&#x4E86;&#xFF0C;&#x6211;&#x5728;&#x4EE3;&#x7801;&#x4E2D;&#x58F0;&#x660E;&#x7684;&#x987A;&#x5E8F;&#x4E24;&#x6B21;&#x90FD;&#x4E0D;&#x4E00;&#x6837;&#xFF0C;&#x4E3A;&#x4F55;&#x7F16;&#x8BD1;&#x8FD0;&#x884C;&#x4E24;&#x6B21;&#x7ED3;&#x679C;&#x90FD;&#x662F; i &#x7684;&#x5730;&#x5740;&#x5728; a &#x7684;&#x524D;&#x9762;&#x5462;&#xFF1F;</p>
<h2 id>&#x518D;&#x6B21;&#x5C1D;&#x8BD5;</h2>
<p>&#x4E8E;&#x662F;&#x6211;&#x53C8;&#x5199;&#x4E0B;&#x8FD9;&#x6837;&#x7684;&#x4EE3;&#x7801;&#xFF0C;&#x591A;&#x5B9A;&#x4E49;&#x51E0;&#x4E2A;&#x53D8;&#x91CF;&#xFF0C;&#x7136;&#x540E;&#x6253;&#x5370;&#x5B83;&#x4EEC;&#x7684;&#x5730;&#x5740;&#x8BD5;&#x8BD5;&#xFF1A;</p>
<pre><code class="language-c">int main(){
    int m=0;
    int n=0;
    int a[4]={1,2,3,4};
    int i=0;
    int j=0;
    int b[4]={5,6,7,8};
    printf(&quot;m: %p\n&quot;,&amp;m);
    printf(&quot;n: %p\n&quot;,&amp;n);
    printf(&quot;a[0]: %p\n&quot;,&amp;(a[0]));
    printf(&quot;a[3]: %p\n&quot;,&amp;(a[3]));
    printf(&quot;i: %p\n&quot;,&amp;i);
    printf(&quot;j: %p\n&quot;,&amp;j);
    printf(&quot;b[0]: %p\n&quot;,&amp;(b[0]));
    printf(&quot;b[3]: %p\n&quot;,&amp;(b[3]));
    return 0;
</code></pre>
<p>&#x7ED3;&#x679C;&#x5982;&#x4E0B;&#xFF1A;</p>
<p><img src="https://ruofeng.me/content/images/2018/07/memory-allocation-order-on-stack-3.png" alt="memory-allocation-order-on-stack-3" loading="lazy"></p>
<p>&#x60CA;&#x5947;&#x7684;&#x53D1;&#x73B0;&#xFF0C;&#x5C3D;&#x7BA1;&#x6211;&#x5728;&#x4EE3;&#x7801;&#x4E2D;&#x5B9A;&#x4E49;&#x53D8;&#x91CF;&#x7684;&#x987A;&#x5E8F;&#x662F;<code>m-&gt;n-&gt;a[4]-&gt;i-&gt;j-&gt;[b]</code>&#xFF0C;&#x5B9E;&#x9645;&#x4E0A;&#x5B83;&#x4EEC;&#x5728;&#x5185;&#x5B58;&#x4E2D;&#x6309;&#x5730;&#x5740;&#x7531;&#x4F4E;&#x5230;&#x9AD8;&#x5206;&#x5E03;&#x7684;&#x987A;&#x5E8F;&#x662F;<code>m-&gt;n-&gt;i-&gt;j-&gt;a[4]-&gt;b[4]</code>&#x3002;&#x7ECF;&#x8FC7;&#x591A;&#x6B21;&#x5C1D;&#x8BD5;&#xFF0C;&#x53D1;&#x73B0;&#x8FD9;&#x6837;&#x4E0D;&#x7BA1;&#x6211;&#x5728;&#x4EE3;&#x7801;&#x4E2D;&#x53D8;&#x91CF;&#x58F0;&#x660E;&#x7684;&#x987A;&#x5E8F;&#x5982;&#x4F55;&#xFF0C;<strong>&#x6574;&#x578B;&#x6570;&#x7EC4;&#x7684;&#x5185;&#x5B58;&#x5730;&#x5740;&#x603B;&#x662F;&#x5728;&#x5355;&#x4E2A;&#x6574;&#x578B;&#x53D8;&#x91CF;&#x7684;&#x540E;&#x9762;</strong>&#x3002;</p>
<p>&#x4E5F;&#x8BB8;&#x662F;&#x5728;&#x7F16;&#x8BD1;&#x8FC7;&#x7A0B;&#x4E2D;&#x505A;&#x5566;&#x67D0;&#x4E9B;&#x4F18;&#x5316;&#xFF1F;&#x968F;&#x540E;&#x5C1D;&#x8BD5;&#x5728;&#x7F16;&#x8BD1;&#x65F6;&#x6DFB;&#x52A0;<code>-O0</code>&#x5173;&#x95ED;&#x4F18;&#x5316;&#x3001;&#x4EE5;&#x53CA;&#x8F93;&#x51FA;&#x9884;&#x5904;&#x7406;&#x7684;&#x4EE3;&#x7801;&#x7ED3;&#x679C;&#x90FD;&#x6CA1;&#x6709;&#x53D1;&#x73B0;&#x8FD9;&#x4E2A;&#x95EE;&#x9898;&#x7684;&#x6240;&#x5728;&#x3002;</p>
<h2 id="gcc">&#x95EE;&#x9898;&#x6240;&#x5728;&#xFF1A;GCC &#x7684;&#x6808;&#x6EA2;&#x51FA;&#x4FDD;&#x62A4;</h2>
<p>&#x5728; Google &#x641C;&#x7D22;&#x8BB8;&#x4E45;&#x53EA;&#x5F97;&#x5230;&#x4FE1;&#x606F;&#xFF1A;C &#x7684;&#x6807;&#x51C6;&#x4E2D;&#x5E76;&#x6CA1;&#x6709;&#x5BF9;&#x5C40;&#x90E8;&#x53D8;&#x91CF;&#x7684;&#x5185;&#x5B58;&#x5206;&#x914D;&#x987A;&#x5E8F;&#x6709;&#x4EFB;&#x4F55;&#x5B9A;&#x4E49;&#xFF0C;&#x56E0;&#x6B64;&#x4E0D;&#x540C;&#x7684;&#x7F16;&#x8BD1;&#x5668;&#x5B8C;&#x5168;&#x6709;&#x53EF;&#x4EE5;&#x6709;&#x81EA;&#x5DF1;&#x7684;&#x505A;&#x6CD5;&#x3002;</p>
<p>&#x968F;&#x540E; V &#x7AD9;&#x4E0A;&#x670B;&#x53CB;&#x6709;&#x63D0;&#x5230; <strong>&#x7F13;&#x51B2;&#x533A;&#x6EA2;&#x51FA;&#x653B;&#x51FB;</strong> &#x8FD9;&#x4E2A;&#x6982;&#x5FF5;&#xFF0C;&#x7A81;&#x7136;&#x5C31;&#x610F;&#x8BC6;&#x5230;&#x4E86; GCC &#x53EF;&#x80FD;&#x5C31;&#x662F;&#x4E3A;&#x4E86;&#x5B89;&#x5168;&#x8D77;&#x89C1;&#x4F5C;&#x51FA;&#x7684;&#x4E00;&#x4E9B;&#x8C03;&#x6574;&#x4F18;&#x5316;&#x4EE5;&#x907F;&#x514D;&#x6808;&#x6EA2;&#x51FA;&#x653B;&#x51FB;&#x3002;&#x5E26;&#x7740;&#x8FD9;&#x4E2A;&#x6982;&#x5FF5;&#x7EE7;&#x7EED;&#x5728; Google &#x4E0A;&#x68C0;&#x7D22;&#xFF0C;GCC &#x786E;&#x5B9E;&#x6709;&#x9ED8;&#x8BA4;&#x5F00;&#x542F;&#x5BF9;&#x6808;&#x6EA2;&#x51FA;&#x653B;&#x51FB;&#x7684;&#x4FDD;&#x62A4;&#xFF0C;&#x5E76;&#x5F97;&#x5230;&#x4E86; GCC &#x7684;&#x4E00;&#x4E2A;&#x7F16;&#x8BD1;&#x9009;&#x9879;&#x53EF;&#x4EE5;&#x5F3A;&#x5236;&#x5173;&#x95ED;&#x6808;&#x6EA2;&#x51FA;&#x4FDD;&#x62A4;&#xFF1A;<strong><code>-fno-stack-protector</code></strong>&#x3002;</p>
<p>&#x91CD;&#x65B0;&#x7F16;&#x8BD1;&#x8FD0;&#x884C;&#xFF1A;</p>
<p><img src="https://ruofeng.me/content/images/2018/07/memory-allocation-order-on-stack-4.png" alt="memory-allocation-order-on-stack-4" loading="lazy"></p>
<p>&#x6309;&#x7167;&#x53D8;&#x91CF;&#x5728;&#x4EE3;&#x7801;&#x4E2D;&#x5B9A;&#x4E49;&#x7684;&#x987A;&#x5E8F;&#xFF0C;&#x5176;&#x5728;&#x8FD0;&#x884C;&#x65F6;&#x5185;&#x5B58;&#x5206;&#x914D;&#x7684;&#x5730;&#x5740;&#x679C;&#x7136;&#x4E5F;&#x53D8;&#x6210;&#x4E86;&#x4ECE;&#x9AD8;&#x5730;&#x5740;&#x5230;&#x4F4E;&#x5730;&#x5740;&#x987A;&#x5E8F;&#x5206;&#x5E03;&#x4E86;&#xFF0C;&#x4E0D;&#x8FC7;&#x4ED4;&#x7EC6;&#x89C2;&#x5BDF;&#x8FD8;&#x662F;&#x53D1;&#x73B0;&#x6570;&#x7EC4;&#x6700;&#x540E;&#x4E00;&#x4E2A;&#x5143;&#x7D20;&#x4E0E;&#x4E0B;&#x4E00;&#x4E2A;&#x6574;&#x578B;&#x53D8;&#x91CF;&#x5730;&#x5740;&#x5E76;&#x4E0D;&#x662F;&#x8FDE;&#x7EED;&#x7684;&#xFF0C;&#x4E2D;&#x95F4;&#x8FD8;&#x95F4;&#x9694;&#x4E86;&#x51E0;&#x4E2A;&#x5B57;&#x8282;&#xFF0C;&#x4E5F;&#x8BB8;&#x662F;&#x50CF;&#x7ED3;&#x6784;&#x4F53;&#x4E2D;&#x5185;&#x5B58;&#x5BF9;&#x9F50;&#x5427;&#xFF0C;&#x4E0D;&#x8FC7;&#x6211;&#x4E5F;&#x4E0D;&#x6DF1;&#x7A76;&#x4E86;&#x3002;&#x81F3;&#x4E8E; GCC &#x662F;&#x5177;&#x4F53;&#x4F5C;&#x51FA;&#x600E;&#x6837;&#x7684;&#x4F18;&#x5316;&#x8C03;&#x6574;&#x987A;&#x5E8F;&#x6765;&#x4FDD;&#x62A4;&#x6808;&#x6EA2;&#x51FA;&#xFF0C;&#x5176;&#x6587;&#x6863;&#x4E0A;&#x5E94;&#x8BE5;&#x6709;&#x6240;&#x63CF;&#x8FF0;&#xFF0C;&#x6211;&#x4E5F;&#x4E0D;&#x53BB;&#x8BE6;&#x7EC6;&#x67E5;&#x8BE2;&#x4E86;&#xFF0C;&#x4E86;&#x89E3;&#x5230;&#x8FD9;&#x91CC;&#x5C31;&#x597D;&#x3002;</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[LRU Cache 算法实现]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><strong>Least recently used (LRU)</strong> &#x6700;&#x8FD1;&#x6700;&#x5C11;&#x4F7F;&#x7528;&#x7684;&#x7F13;&#x5B58;&#x66FF;&#x6362;&#x7B56;&#x7565;&#xFF0C;&#x4E00;&#x6B21; get &#x6216;&#x4E00;&#x6B21; put &#x90FD;&#x88AB;&#x79F0;&#x4E3A;&#x4F7F;&#x7528;&#x3002;&#x8FD9;&#x4E2A;&#x7B97;&#x6CD5;&#x7B56;&#x7565;&#x4E3B;&#x8981;&#x662F;&#x8BB0;&#x5F55;&#x5BB9;&#x91CF;&#x6709;&#x9650;&#x7684;&#x7F13;&#x5B58;</p>]]></description><link>https://ruofeng.me/2018/07/13/lru-cache/</link><guid isPermaLink="false">5d8e378da7d96200019ade1d</guid><category><![CDATA[算法]]></category><category><![CDATA[数据结构]]></category><category><![CDATA[C/C++]]></category><dc:creator><![CDATA[Ruofeng Lei]]></dc:creator><pubDate>Fri, 13 Jul 2018 03:18:58 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p><strong>Least recently used (LRU)</strong> &#x6700;&#x8FD1;&#x6700;&#x5C11;&#x4F7F;&#x7528;&#x7684;&#x7F13;&#x5B58;&#x66FF;&#x6362;&#x7B56;&#x7565;&#xFF0C;&#x4E00;&#x6B21; get &#x6216;&#x4E00;&#x6B21; put &#x90FD;&#x88AB;&#x79F0;&#x4E3A;&#x4F7F;&#x7528;&#x3002;&#x8FD9;&#x4E2A;&#x7B97;&#x6CD5;&#x7B56;&#x7565;&#x4E3B;&#x8981;&#x662F;&#x8BB0;&#x5F55;&#x5BB9;&#x91CF;&#x6709;&#x9650;&#x7684;&#x7F13;&#x5B58;&#x4E2D;&#x6BCF;&#x4E2A;&#x5143;&#x7D20;&#x662F;&#x90FD;&#x662F;<strong>&#x4F55;&#x65F6;</strong>&#x4F7F;&#x7528;&#x7684;&#x3002;</p>
<p>&#x4E3A;&#x4E86;&#x5B9E;&#x73B0;&#x8BB0;&#x5F55;&#x4F7F;&#x7528;&#x65F6;&#x5E8F;&#xFF0C;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x4F7F;&#x7528;&#x4E00;&#x4E2A;<code>list</code>&#x6765;&#x8BB0;&#x5F55; key-value pair&#xFF0C;&#x6BCF;&#x6B21;&#x4F7F;&#x7528;&#x65F6;&#x90FD;&#x5C06;&#x8FD9;&#x4E2A; pair &#x79FB;&#x52A8;&#x5230; list &#x7684;&#x9996;&#x90E8;&#xFF0C;&#x4E3A;&#x4E86;&#x4EC0;&#x4E48;&#x8981;&#x4F7F;&#x7528; list &#x800C;&#x4E0D;&#x662F; array &#x6216; vector &#x5462;&#xFF0C;&#x6B63;&#x662F;&#x56E0;&#x4E3A;&#x6211;&#x4EEC;&#x7684;&#x7F13;&#x5B58;&#x7684;&#x6BCF;&#x6B21;&#x64CD;&#x4F5C;&#x5747;&#x4F1A;&#x79FB;&#x52A8; list &#x4E2D;&#x7684;&#x5143;&#x7D20;&#x4F4D;&#x7F6E;&#xFF0C;&#x800C;&#x5143;&#x7D20;&#x4F4D;&#x7F6E;&#x79FB;&#x52A8;&#x9891;&#x7E41;&#x7684;&#x60C5;&#x51B5;&#x4E0B;&#x4F7F;&#x7528;<strong>&#x53CC;&#x5411;&#x94FE;&#x8868;</strong>&#x662F;&#x6700;&#x4F73;&#x7684;&#x9009;&#x62E9;&#xFF0C;&#x56E0;&#x4E3A;&#x8FD9;&#x4E2A;&#x6570;&#x636E;&#x7ED3;&#x6784;&#x79FB;&#x52A8;&#x5143;&#x7D20;&#x4F4D;&#x7F6E;&#x7684;&#x5F00;&#x9500;&#x662F;&#x6700;&#x5C0F;&#x7684;&#xFF0C;&#x4EC5;&#x4EC5;&#x662F;&#x6539;&#x53D8;&#x4E86;&#x6307;&#x9488;&#x800C;&#x5DF2;&#x3002;</p>
<p>&#x4F46;&#x662F;&#x4EC5;&#x4EC5;&#x4F7F;&#x7528;&#x4E00;&#x4E2A; list &#x8FD8;&#x662F;&#x505A;&#x4E0D;&#x5230;&#x9AD8;&#x6548;&#x7684;&#x67E5;&#x627E;&#xFF0C;&#x8981;&#x505A;&#x5230;&#x5E73;&#x5747;&#x65F6;&#x95F4;&#x590D;&#x6742;&#x5EA6;&#x4E3A; O(1)&#x7684;&#x67E5;&#x627E;&#xFF0C;&#x5C31;&#x9700;&#x8981;&#x4F7F;&#x7528; map&#xFF0C;&#x56E0;&#x6B64;&#x8FD8;&#x9700;&#x8981;<code>unordered_map</code>&#x7ED3;&#x6784;&#x6765;&#x5B8C;&#x6210;&#x67E5;&#x8BE2;&#x7684;&#x64CD;&#x4F5C;&#xFF0C;&#x800C;&#x9700;&#x8981;&#x6CE8;&#x610F;&#x7684;&#x662F;&#x5176;&#x50A8;&#x5B58;&#x7684;&#x4E0D;&#x662F; key-value &#x7684;&#x952E;&#x503C;&#x5BF9;&#x6570;&#x636E;&#xFF0C;&#x56E0;&#x4E3A;&#x9700;&#x8981;&#x7684;&#x6570;&#x636E;&#x5DF2;&#x7ECF;&#x5728;&#x4E0A;&#x9762;&#x7684; list &#x4E2D;&#x50A8;&#x5B58;&#x4E86;&#xFF0C;key &#x6240;&#x5BF9;&#x5E94;&#x50A8;&#x5B58;&#x7684;&#x6570;&#x636E;&#x662F;&#x4E0A;&#x9762; list &#x7ED3;&#x6784;&#x7684;&#x8FED;&#x4EE3;&#x5668;&#xFF0C;&#x56E0;&#x6B64;&#x5728;&#x67E5;&#x8BE2;&#x503C;&#x53EF;&#x4EE5;&#x5728;&#x5E73;&#x5747; O(1)&#x7684;&#x65F6;&#x95F4;&#x5185;&#x62FF;&#x5230;&#x4E00;&#x4E2A; list &#x7684;&#x8FED;&#x4EE3;&#x5668;&#xFF0C;&#x518D;&#x901A;&#x8FC7;&#x8FD9;&#x4E2A;&#x8FED;&#x4EE3;&#x5668;&#x4EE5; O(1)&#x7684;&#x65F6;&#x95F4;&#x5728; list &#x4E2D;&#x83B7;&#x53D6; value&#x3002;&#x540C;&#x65F6;&#x79FB;&#x52A8; list &#x7684;&#x4F4D;&#x7F6E;&#x7684;&#x5F00;&#x9500;&#x4F9D;&#x7136;&#x662F;&#x5E38;&#x6570;&#x65F6;&#x95F4;&#x590D;&#x6742;&#x5EA6;&#x3002;</p>
<p>&#x8FD9;&#x4E2A;&#x7ED3;&#x6784;&#x53EF;&#x4EE5;&#x5F62;&#x8C61;&#x5F97;&#x4EE5;&#x8FD9;&#x5F20;&#x56FE;&#x8868;&#x793A;&#xFF1A;</p>
<p><img src="https://ruofeng.me/content/images/2018/07/lru-cache.png" alt="lru-cache" loading="lazy"></p>
<h2 id>&#x57FA;&#x672C;&#x6570;&#x636E;&#x7ED3;&#x6784;&#x58F0;&#x660E;</h2>
<p>&#x6211;&#x4EEC;&#x9ED8;&#x8BA4;&#x4E3A; key-value &#x5747;&#x50A8;&#x5B58;&#x7684;&#x662F; string &#x7C7B;&#x578B;&#x7684;&#x6570;&#x636E;</p>
<pre><code class="language-cpp">// cache&#x7684;&#x6700;&#x5927;&#x5BB9;&#x91CF;
size_t capacity;
// list &#x4E2D;&#x50A8;&#x5B58;&#x7684;&#x7684;&#x662F;&#x9700;&#x8981;&#x4FDD;&#x5B58;&#x7684;&#x952E;&#x503C;&#x5BF9;
// &#x8BFB;&#x53D6;&#x65F6;&#x4F1A;&#x5C06;&#x76EE;&#x6807;&#x9879;&#x79FB;&#x52A8;&#x5230;&#x5934;&#x90E8;
// &#x5199;&#x5165;&#x662F;&#x76F4;&#x63A5;&#x63D2;&#x5165;&#x5230;&#x5934;&#x90E8;
list&lt;pair&lt;string, string&gt;&gt; dataList;
// map &#x4FDD;&#x5B58;&#x67E5;&#x627E;&#x8868;&#xFF0C;&#x4FDD;&#x5B58;&#x7684;&#x662F;key&#x4E0E;list&#x8FED;&#x4EE3;&#x5668;&#x7684;&#x5BF9;&#x5E94;
// &#x6BCF;&#x6B21;&#x67E5;&#x8BE2;&#x65F6;&#x6839;&#x636E;key&#x4ECE;map&#x62FF;&#x5230;&#x8FED;&#x4EE3;&#x5668;&#x53EF;&#x4EE5;&#x76F4;&#x63A5;&#x5728;list&#x4E2D;&#x5F97;&#x5230;&#x76F8;&#x5E94;value
unordered_map&lt;string, list&lt;pair&lt;string, string&gt;&gt;::iterator&gt; positionMap;
</code></pre>
<h2 id="put"><code>put</code> &#x64CD;&#x4F5C;</h2>
<p>&#x5411; LRU-Cache &#x4E2D;&#x63D2;&#x5165;&#x6570;&#x636E;&#x65F6;&#xFF0C;&#x53EF;&#x4EE5;&#x76F4;&#x63A5;&#x5C06; key-value &#x63D2;&#x5165;&#x5230; list &#x7684;&#x9996;&#x90E8;&#xFF0C;&#x7136;&#x540E;&#x5728; map &#x4E2D;&#x67E5;&#x627E;&#x7ED9;&#x5B9A;&#x7684; key &#x662F;&#x5426;&#x5DF2;&#x7ECF;&#x5B58;&#x5728;&#xFF0C;&#x82E5;&#x5DF2;&#x5B58;&#x5728;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x770B;&#x4F5C;&#x662F;&#x66FF;&#x6362; value &#x7684;&#x64CD;&#x4F5C;&#xFF0C;&#x53EF;&#x4EE5;&#x76F4;&#x63A5;&#x5220;&#x9664; map &#x4E0E; list &#x4E2D;&#x7684;&#x539F;&#x5185;&#x5BB9;&#x3002;&#x7136;&#x540E;&#x518D;&#x5C06;&#x65B0;&#x7684; key &#x4E0E;&#x6307;&#x5411; list &#x9879;&#x7684;&#x6307;&#x9488;&#x8BB0;&#x5F55;&#x5230; map &#x4E2D;</p>
<pre><code class="language-cpp">void put(string key, string value) {
    auto it = positionMap.find(key);
    //&#x5C06; pair &#x63D2;&#x5165;&#x5230;&#x5217;&#x8868;&#x5934;&#x90E8;
    dataList.push_front({key, value});
    if (it != positionMap.end()) {
        dataList.erase(it-&gt;second);
        positionMap.erase(it);
    }
    positionMap[key] = dataList.begin();
}
</code></pre>
<h2 id="get"><code>get</code> &#x64CD;&#x4F5C;</h2>
<p>&#x67E5;&#x627E;&#x6570;&#x636E;&#x65F6;&#xFF0C;&#x9996;&#x5148;&#x5728; map &#x4E2D;&#x67E5;&#x627E; key &#x5BF9;&#x5E94;&#x7684;&#x5185;&#x5BB9;&#x662F;&#x5426;&#x5B58;&#x5728;&#xFF0C;&#x82E5;&#x4E0D;&#x5B58;&#x5728;&#x5219;&#x8868;&#x660E; cache &#x4E2D;&#x6CA1;&#x6709;&#x8FD9;&#x4E00;&#x9879;&#x5185;&#x5BB9;&#xFF0C;&#x76F4;&#x63A5;&#x629B;&#x51FA;&#x9519;&#x8BEF;&#xFF0C;&#x82E5;&#x5B58;&#x5728;&#x5219;&#x5728; list &#x4E2D;&#x7684;&#x627E;&#x5230;&#x8FD9;&#x4E00;&#x9879;&#xFF0C;&#x5E76;&#x4F7F;&#x7528;<code>splice</code>&#x5C06;&#x8FD9;&#x4E00;&#x9879;&#x79FB;&#x52A8;&#x5230; list &#x7684;&#x9996;&#x90E8;&#xFF0C;&#x56E0;&#x4E3A;&#x6211;&#x4EEC;<strong>&#x6700;&#x8FD1;&#x4F7F;&#x7528;</strong>&#x5B83;&#x4E86;&#xFF0C;&#x7136;&#x540E;&#x8FD4;&#x56DE;&#x5176; value&#x3002;</p>
<pre><code class="language-cpp">string get(string key) {
    auto it = positionMap.find(key);
    //&#x82E5;map&#x4E2D;&#x672A;&#x627E;&#x5230;key&#xFF0C;&#x5219;&#x8FD4;&#x56DE;&#x9519;&#x8BEF;&#x4FE1;&#x606F;
    if (it == positionMap.end()) {
        return &quot;NotFound&quot;;
    }
    //&#x5728;list&#x4E2D;&#x627E;&#x5230;get&#x7684;pair&#x5E76;&#x5C06;&#x5B83;&#x79FB;&#x52A8;&#x5E76;&#x63D2;&#x5165;&#x5230;list&#x5934;&#x90E8;
    dataList.splice(dataList.begin(), dataList, it-&gt;second);
    return it-&gt;second-&gt;second;
}
</code></pre>
<h2 id="put"><code>put</code> &#x65F6;&#x8FBE;&#x5230;&#x5BB9;&#x91CF;&#x4E0A;&#x9650;</h2>
<p>&#x82E5;&#x5BB9;&#x91CF;&#x5DF2;&#x6EE1;&#xFF0C;&#x5219;&#x5C06; list &#x4E2D;&#x6700;&#x540E;&#x4E00;&#x4F4D;&#xFF08;&#x6700;&#x8FD1;&#x6700;&#x4E45;&#x672A;&#x4F7F;&#x7528;&#x7684;&#x4E00;&#x9879;&#xFF09;&#x4ECE; list &#x4E0E; map &#x4E2D;&#x79FB;&#x9664;</p>
<pre><code class="language-cpp">if (positionMap.size() &gt; capacity) {
    positionMap.erase(dataList.back().first);
    dataList.pop_back();
}
</code></pre>
<h2 id>&#x5B8C;&#x6574;&#x6E90;&#x4EE3;&#x7801;</h2>
<pre><code class="language-cpp">// LRU - Least Recently Used
#include &lt;iostream&gt;
#include &lt;list&gt;
#include &lt;string&gt;
#include &lt;unordered_map&gt;

using namespace std;

class LRUCache {
   public:
    LRUCache(int capacity) : capacity(capacity){};
    string get(string key) {
        auto it = positionMap.find(key);
        if (it == positionMap.end()) {
            return &quot;NotFound&quot;;
        }
        dataList.splice(dataList.begin(), dataList, it-&gt;second);
        return it-&gt;second-&gt;second;
    }
    void put(string key, string value) {
        auto it = positionMap.find(key);
        dataList.push_front({key, value});
        if (it != positionMap.end()) {
            dataList.erase(it-&gt;second);
            positionMap.erase(it);
        }
        positionMap[key] = dataList.begin();
        if (positionMap.size() &gt; capacity) {
            positionMap.erase(dataList.back().first);
            dataList.pop_back();
        }
    }

   private:
    size_t capacity;
    list&lt;pair&lt;string, string&gt;&gt; dataList;
    unordered_map&lt;string, list&lt;pair&lt;string, string&gt;&gt;::iterator&gt; positionMap;
};

int main() {
    LRUCache cache(10);
    cache.put(&quot;foo&quot;, &quot;bar&quot;);
    cache.put(&quot;name&quot;, &quot;ruofeng&quot;);
    cache.put(&quot;phone&quot;, &quot;iPhone 7&quot;);
    cache.put(&quot;PC&quot;, &quot;XPS 13&quot;);
    cache.put(&quot;CPU&quot;, &quot;i5 7200U&quot;);
    cout &lt;&lt; cache.get(&quot;name&quot;) &lt;&lt; endl;
    cout &lt;&lt; cache.get(&quot;PC&quot;) &lt;&lt; endl;
    return 0;
}
</code></pre>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[HashTable 的简单实现]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>&#x54C8;&#x5E0C;&#x8868; HashTable &#x662F;&#x4E00;&#x4E2A;&#x975E;&#x5E38;&#x5E38;&#x7528;&#x7684;&#x6570;&#x636E;&#x7ED3;&#x6784;&#xFF0C;&#x7528;&#x4E8E;&#x50A8;&#x5B58; k-v &#x952E;&#x503C;&#x5BF9;&#x7684;&#x6570;&#x636E;&#x3002;&#x800C;&#x4E14;&#x5176;&#x63D2;&#x5165;&#x3001;&#x67E5;&#x627E;&#x3001;&#x5220;&#x9664;&#x7684;&#x5E73;&#x5747;&#x65F6;&#x95F4;&#x590D;&#x6742;&#x5EA6;&#x5747;&#x4E3A;</p>]]></description><link>https://ruofeng.me/2018/07/12/implement-hashtable-in-c/</link><guid isPermaLink="false">5d8e378da7d96200019ade1c</guid><category><![CDATA[C/C++]]></category><category><![CDATA[数据结构]]></category><dc:creator><![CDATA[Ruofeng Lei]]></dc:creator><pubDate>Thu, 12 Jul 2018 09:03:47 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>&#x54C8;&#x5E0C;&#x8868; HashTable &#x662F;&#x4E00;&#x4E2A;&#x975E;&#x5E38;&#x5E38;&#x7528;&#x7684;&#x6570;&#x636E;&#x7ED3;&#x6784;&#xFF0C;&#x7528;&#x4E8E;&#x50A8;&#x5B58; k-v &#x952E;&#x503C;&#x5BF9;&#x7684;&#x6570;&#x636E;&#x3002;&#x800C;&#x4E14;&#x5176;&#x63D2;&#x5165;&#x3001;&#x67E5;&#x627E;&#x3001;&#x5220;&#x9664;&#x7684;&#x5E73;&#x5747;&#x65F6;&#x95F4;&#x590D;&#x6742;&#x5EA6;&#x5747;&#x4E3A;<code>O(1)</code>&#x3002;&#x4E3A;&#x4E86;&#x4E86;&#x89E3;&#x5230;&#x5176;&#x5185;&#x90E8;&#x5B9E;&#x73B0;&#xFF0C;&#x662F;&#x5982;&#x4F55;&#x5B9E;&#x73B0;&#x9AD8;&#x6548;&#x7684;&#x67E5;&#x8BE2;&#x65B9;&#x5F0F;&#xFF0C;&#x53C2;&#x8003;&#x4E86; <a href="https://github.com/jamesroutley/write-a-hash-table">https://github.com/jamesroutley/write-a-hash-table</a> &#x4F7F;&#x7528; C &#x8BED;&#x8A00;&#x5B9E;&#x73B0;&#x4E86;&#x4E00;&#x4E2A;&#x7B80;&#x6613;&#x7684; HashTable&#x3002;</p>
<h2 id>&#x57FA;&#x672C;&#x7ED3;&#x6784;</h2>
<p>HashTable &#x4E2D;&#x5143;&#x7D20;&#x7684;&#x6700;&#x57FA;&#x672C;&#x5355;&#x4F4D;&#x662F; k-v &#x952E;&#x503C;&#x5BF9;&#xFF0C;&#x6211;&#x4EEC;&#x5C06;&#x5176;&#x89C6;&#x4E3A;&#x5B57;&#x7B26;&#x4E32;&#xFF0C;&#x5219;&#x6709;&#x8FD9;&#x6837;&#x7684;&#x7ED3;&#x6784;&#xFF1A;</p>
<pre><code class="language-c">typedef struct {
    char* key;
    char* value;
} ht_item;
</code></pre>
<p>HashTable &#x7684;&#x57FA;&#x672C;&#x8868;&#x7ED3;&#x6784;&#x4E2D;&#x5305;&#x542B;&#x8868;&#x6700;&#x5927;&#x5BB9;&#x91CF;<code>size</code>&#x3001;&#x5F53;&#x524D;&#x8868;&#x4E2D;&#x5143;&#x7D20;&#x4E2A;&#x6570;<code>count</code>&#xFF0C;&#x4EE5;&#x53CA;&#x4E00;&#x4E2A;&#x50A8;&#x5B58;&#x5143;&#x7D20;&#x6307;&#x9488;&#x7684;&#x6570;&#x7EC4;<code>ht_item** items</code>&#xFF1A;</p>
<pre><code class="language-c">typedef struct {
    int size;
    int count;
    ht_item** items;
} ht_hash_table;
</code></pre>
<h2 id>&#x65B0;&#x5EFA;&#x4E0E;&#x5220;&#x9664;</h2>
<p>&#x5BF9;&#x4E8E;&#x6BCF;&#x4E2A;&#x8868;&#x5143;&#x7D20;&#xFF0C;&#x4E0E;&#x8868;&#x672C;&#x8EAB;&#xFF0C;&#x6211;&#x4EEC;&#x9700;&#x8981;&#x5206;&#x522B;&#x4E3A;&#x5176;&#x5B9A;&#x4E49;&#x521D;&#x59CB;&#x5316;&#x7684;&#x51FD;&#x6570;&#x4E0E;&#x5220;&#x9664;&#x7ED3;&#x6784;&#x7684;&#x51FD;&#x6570;&#xFF0C;&#x521D;&#x59CB;&#x5316;&#x5373;&#x5206;&#x914D;&#x5185;&#x5B58;&#xFF0C;&#x5220;&#x9664;&#x5373;&#x91CA;&#x653E;&#x5185;&#x5B58;&#x3002;&#x51FD;&#x6570;&#x8868;&#x793A;&#x4E3A;<code>static</code>&#x610F;&#x5473;&#x4EC5;&#x4F9B;&#x5185;&#x90E8;&#x8C03;&#x7528;&#xFF0C;&#x4E0D;&#x5141;&#x8BB8;&#x5916;&#x90E8;&#x8C03;&#x7528;&#xFF0C;&#x548C;&#x9762;&#x5411;&#x5BF9;&#x8C61;&#x4E2D;&#x7684;<code>private</code>&#x8BBF;&#x95EE;&#x63A7;&#x5236;&#x6807;&#x8BC6;&#x7C7B;&#x4F3C;&#x3002;</p>
<p><strong>&#x65B0;&#x5EFA;&#x5143;&#x7D20;</strong>&#xFF0C;&#x53C2;&#x6570;&#x4E3A; k-v &#x5B57;&#x7B26;&#x4E32;&#xFF0C;&#x4E3B;&#x8981;&#x4E3A;&#x5B57;&#x7B26;&#x4E32;&#x5206;&#x914D;&#x5185;&#x5B58;</p>
<pre><code class="language-c">static ht_item* ht_new_item(const char* k, const char* v) {
    ht_item* i = malloc(sizeof(ht_item));
    i-&gt;key = malloc(strlen(k) + 1);
    strcpy(i-&gt;key, k);
    i-&gt;value = malloc(strlen(v) + 1);
    strcpy(i-&gt;value, v);
    return i;
}
</code></pre>
<p><strong>&#x65B0;&#x5EFA;&#x8868;</strong>&#xFF0C;&#x521D;&#x59CB;&#x5316;&#x8868;&#x7A7A;&#x95F4;&#x5927;&#x5C0F;&#xFF0C;&#x8FD9;&#x91CC;&#x8BBE;&#x5B9A;&#x4E3A; 53&#xFF0C;&#x6570;&#x91CF;&#x521D;&#x59CB;&#x5316;&#x4E3A; 0&#xFF0C;&#x5E76;&#x6839;&#x636E; size &#x7ED9;&#x4FDD;&#x5B58;&#x5143;&#x7D20;&#x6570;&#x7EC4;&#x7684;<code>items</code>&#x6307;&#x9488;&#x5206;&#x914D;&#x4E00;&#x5B9A;&#x7684;&#x5185;&#x5B58;&#x5E76;&#x521D;&#x59CB;&#x5316;</p>
<pre><code class="language-c">ht_hash_table* ht_new() {
    ht_hash_table* ht = malloc(sizeof(ht_hash_table));
    ht-&gt;size = 53;
    ht-&gt;count = 0;
    ht-&gt;items = calloc((size_t)ht-&gt;size, sizeof(ht_item*));
    return ht;
}
</code></pre>
<p><strong>&#x5220;&#x9664;&#x5143;&#x7D20;</strong>&#xFF0C;&#x76F4;&#x63A5;&#x91CA;&#x653E;&#x5185;&#x5B58;</p>
<pre><code class="language-c">static void ht_del_item(ht_item* i) {
    free(i-&gt;key);
    free(i-&gt;value);
    free(i);
}
</code></pre>
<p><strong>&#x5220;&#x9664;&#x8868;</strong>&#xFF0C;&#x904D;&#x5386;&#x6574;&#x4E2A;&#x8868;&#x9010;&#x4E2A;&#x91CA;&#x653E;&#x5143;&#x7D20;&#x5185;&#x5B58;&#xFF0C;&#x7136;&#x540E;&#x91CA;&#x653E;&#x6570;&#x7EC4;&#x4EE5;&#x53CA;&#x672C;&#x8EAB;</p>
<pre><code class="language-c">void ht_del_hash_table(ht_hash_table* ht) {
    for (int i = 0; i &lt; ht-&gt;size; i++) {
        ht_item* item = ht-&gt;items[i];
        if (item != NULL) {
            ht_del_item(item);
        }
    }
    free(ht-&gt;items);
    free(ht);
}
</code></pre>
<h2 id>&#x54C8;&#x5E0C;&#x51FD;&#x6570;</h2>
<p><strong>&#x54C8;&#x5E0C;</strong>&#x8868;&#x6B63;&#x662F;&#x56E0;&#x4E3A;&#x5176;&#x7D22;&#x5F15;&#x7684;&#x6784;&#x5EFA;&#x8FC7;&#x7A0B;&#x4F7F;&#x7528;&#x4E86;&#x54C8;&#x5E0C;&#x51FD;&#x6570;&#x56E0;&#x6B64;&#x800C;&#x5F97;&#x540D;&#x3002;&#x7B80;&#x5355;&#x6765;&#x8BB2;&#xFF0C;&#x5728;&#x5411;&#x54C8;&#x5E0C;&#x8868;&#x4E2D;&#x63D2;&#x5165;&#x4E00;&#x4E2A; k-v &#x952E;&#x503C;&#x5BF9;&#x65F6;&#xFF0C;&#x9996;&#x5148;&#x9700;&#x8981;&#x5BF9;&#x5176; key &#x8FDB;&#x884C; hash&#xFF0C;&#x5F97;&#x5230;&#x4E00;&#x4E2A;&#x6570;&#xFF0C;&#x6700;&#x4E3A;&#x8868;&#x4E2D;&#x4FDD;&#x5B58;&#x6570;&#x7EC4;<code>ht-&gt;items</code>&#x7684;&#x7D22;&#x5F15;&#x5373;&#x6570;&#x7EC4;&#x4E0B;&#x6807;&#xFF0C;&#x7136;&#x540E;&#x518D;&#x5C06; value &#x8D4B;&#x503C;&#x7ED9;&#x6307;&#x5B9A;&#x7D22;&#x5F15;&#x6240;&#x6307;&#x5411;&#x5143;&#x7D20;&#x7684; value &#x4E2D;&#x3002;hash &#x51FD;&#x6570;&#x662F;&#x5355;&#x5411;&#x7684;&#xFF0C;&#x5BF9;&#x4E8E;&#x4E0D;&#x540C;&#x7684;&#x7ED9;&#x5B9A;&#x503C;&#x901A;&#x8FC7; hash &#x540E;&#x4F1A;&#x5F97;&#x5230;&#x4E0D;&#x540C;&#x7684;&#x786E;&#x5B9A;&#x7ED3;&#x679C;&#xFF0C;&#x4E14;&#x7406;&#x60F3;&#x7684; hash &#x51FD;&#x6570;&#xFF0C;&#x5BF9;&#x4E8E;&#x6240;&#x6709;&#x4E0D;&#x540C;&#x7684;&#x7ED9;&#x5B9A;&#x503C;&#x7ECF;&#x8FC7; hash &#x4E4B;&#x540E;&#x5747;&#x4F1A;&#x5F97;&#x5230;&#x4E0D;&#x540C;&#x7684;&#x7ED3;&#x679C;&#x3002;&#x56E0;&#x6B64;&#x5229;&#x7528;&#x8FD9;&#x4E00;&#x7279;&#x6027;&#x6211;&#x4EEC;&#x9700;&#x8981;&#x7684; hash &#x51FD;&#x6570;&#x5C06; key &#x8BA1;&#x7B97;&#x540E;&#x8FD4;&#x56DE;&#x5F97;&#x5230;&#x7684;&#x662F;&#x5927;&#x5C0F;&#x5728;&#x8868;&#x5BB9;&#x91CF;&#x4E4B;&#x5185;&#x7684;&#x4E00;&#x4E2A;&#x786E;&#x5B9A;&#x7ED3;&#x679C;&#x4F5C;&#x4E3A;&#x50A8;&#x5B58;&#x7684;&#x7D22;&#x5F15;&#xFF0C;&#x5728;&#x67E5;&#x8BE2;&#x65F6;&#x4E5F;&#x662F;&#x8BA1;&#x7B97; hash &#x7136;&#x540E;&#x5C06;&#x8BA1;&#x7B97;&#x7ED3;&#x679C;&#x4F5C;&#x4E3A;&#x7D22;&#x5F15;&#x76F4;&#x63A5;&#x5728;&#x6570;&#x7EC4;&#x4E2D;&#x53D6;&#x503C;&#x5373;&#x53EF;&#xFF0C;&#x8FD9;&#x5C31;&#x662F;&#x65F6;&#x95F4;&#x590D;&#x6742;&#x5EA6;<code>O(1)</code>&#x7684;&#x539F;&#x56E0;&#x3002;</p>
<p>&#x8FD9;&#x91CC;&#x5B9E;&#x73B0;&#x4E00;&#x4E2A;&#x5BF9;&#x5B57;&#x7B26;&#x4E32;&#x7684;&#x5EFA;&#x8BAE; hash &#x51FD;&#x6570;&#xFF0C;&#x8FD9;&#x4E2A; hash &#x51FD;&#x6570;&#x9700;&#x8981;&#x8FD9;&#x4E9B;&#x53C2;&#x6570;&#xFF0C;<code>s</code>&#x4E3A;&#x76EE;&#x6807;&#x5B57;&#x7B26;&#x4E32;&#xFF0C;<code>a</code>&#x4E3A;&#x4E00;&#x4E2A;&#x5927;&#x4E8E;&#x5B57;&#x6BCD;&#x8868;&#x7684;&#x7D20;&#x6570;&#xFF0C;&#x6211;&#x4EEC;&#x9700;&#x8981; hash &#x7684;&#x5B57;&#x7B26;&#x4E32;&#x662F; ASCII &#x5B57;&#x7B26;&#x4E32;&#xFF0C;&#x800C; ASCII &#x5927;&#x5C0F;&#x4E3A; 128&#xFF0C;&#x8FD9;&#x91CC;&#x53EF;&#x4EE5;&#x53D6;&#x4E00;&#x4E2A; 151&#xFF0C;<code>m</code>&#x4E3A;&#x5BB9;&#x91CF;&#xFF0C;&#x56E0;&#x4E3A;&#x7ED3;&#x679C;&#x662F;&#x6570;&#x7EC4;&#x7684;&#x4E0B;&#x6807;&#xFF0C;&#x8BA1;&#x7B97;&#x7ED3;&#x679C;&#x4E0D;&#x80FD;&#x591F;&#x5927;&#x4E8E;&#x5B83;&#xFF0C;&#x56E0;&#x6B64;&#x5728;&#x8FD0;&#x7B97;&#x4E2D;&#x4F1A;&#x4E0E;<code>m</code>&#x8FDB;&#x884C;&#x6C42;&#x4F59;&#x8FD0;&#x7B97;&#xFF1A;</p>
<pre><code class="language-c">static int ht_hash(const char* s, const int a, const int m) {
    long hash = 0;
    const int len_s = strlen(s);
    for (int i = 0; i &lt; len_s; i++) {
        hash += (long)pow(a, len_s - (i+1)) * s[i];
        hash = hash % m;
    }
    return (int)hash;
}
</code></pre>
<p>&#x8FD9;&#x4E2A;&#x51FD;&#x6570;&#x7ED9;&#x5B9A;&#x4E00;&#x4E2A;&#x5B57;&#x7B26;&#x4E32;&#xFF0C;&#x4F1A;&#x8FD4;&#x56DE;&#x4E00;&#x4E2A;&#x5728; 0-m &#x4E4B;&#x95F4;&#x7684;&#x6570;&#x7EC4;&#x4F5C;&#x4E3A;&#x7D22;&#x5F15;&#x3002;</p>
<h2 id>&#x54C8;&#x5E0C;&#x51B2;&#x7A81;</h2>
<p>&#x4F46;&#x662F;&#x5E76;&#x4E0D;&#x662F;&#x6240;&#x6709;&#x7684; hash &#x51FD;&#x6570;&#x90FD;&#x662F;&#x5B8C;&#x7F8E;&#x7684;&#xFF0C;&#x6709;&#x53EF;&#x80FD;&#x53D1;&#x751F;&#x51B2;&#x7A81;&#xFF0C;&#x5373;&#x7ED9;&#x5B9A;&#x4E0D;&#x540C;&#x7684;&#x8F93;&#x5165;&#xFF0C;&#x6709;&#x4E00;&#x5B9A;&#x53EF;&#x80FD;&#x8FD4;&#x56DE;&#x4E86;&#x76F8;&#x540C;&#x7684; hash &#x7ED3;&#x679C;&#x3002;&#x800C;&#x4E14;&#x5BF9;&#x4E8E;&#x4E00;&#x4E2A;&#x5BB9;&#x91CF;&#x8F83;&#x5C0F;&#xFF0C;&#x50A8;&#x5B58;&#x6570;&#x91CF;&#x8F83;&#x591A;&#x7684;&#x54C8;&#x5E0C;&#x8868;&#xFF0C;&#x6DFB;&#x52A0;&#x65B0;&#x5143;&#x7D20;&#x65F6;&#xFF0C;&#x53D1;&#x751F;&#x51B2;&#x7A81;&#x7684;&#x6982;&#x7387;&#x53D8;&#x5F97;&#x5F88;&#x5927;&#x3002;&#x56E0;&#x6B64;&#x6211;&#x4EEC;&#x9700;&#x8981;&#x89E3;&#x51B3;&#x5E76;&#x51CF;&#x5C11;&#x53D1;&#x751F;&#x51B2;&#x7A81;&#x7684;&#x60C5;&#x51B5;&#xFF1A;</p>
<ul>
<li>&#x4F7F;&#x7528; &#x5F00;&#x653E;&#x5730;&#x5740; + &#x53CC;&#x91CD; HASH &#x7684;&#x65B9;&#x6CD5;&#x89E3;&#x51B3;&#x51B2;&#x7A81;</li>
<li>&#x5728;&#x5BB9;&#x91CF;&#x8FBE;&#x5230;&#x4E00;&#x5B9A;&#x9608;&#x503C;&#x65F6;&#xFF0C;&#x9700;&#x8981; resize &#x6574;&#x5F20;&#x8868;</li>
</ul>
<p>&#x5176;&#x4E2D;&#x53CC;&#x91CD; HASH &#x5728;&#x4F7F;&#x7528;&#x65F6;&#x4F1A;&#x591A;&#x4E00;&#x4E2A;&#x53C2;&#x6570;<code>i</code>&#xFF0C;&#x5E76;&#x4E14;&#x4F1A;&#x4F7F;&#x7528;&#x5230;&#x4E24;&#x4E2A;&#x4E0D;&#x540C;&#x7684; hash &#x51FD;&#x6570;&#x5206;&#x522B;&#x4E3A;<code>hash_a</code>&#x4E0E;<code>hash_b</code>&#xFF0C;&#x6700;&#x57FA;&#x672C;&#x7684;&#x5F62;&#x5F0F;&#x5982;&#x4E0B;&#xFF1A;</p>
<pre><code class="language-c">index = hash_a(string) + i * hash_b(string) % num_buckets;
</code></pre>
<p>&#x9996;&#x6B21; hash &#x4E00;&#x4E2A; key &#x65F6;&#x8FD9;&#x4E2A;&#x53C2;&#x6570;&#x4E3A; 0&#xFF0C;&#x5F53;&#x6CA1;&#x6709;&#x51B2;&#x7A81;&#x65F6;&#xFF0C;&#x7ED3;&#x679C;&#x5C31;&#x662F;<code>hash_a</code>&#x7684;&#x7ED3;&#x679C;&#xFF1B;&#x5F53;&#x53D1;&#x751F;&#x51B2;&#x7A81;&#x65F6;&#xFF0C;&#x5C06; i &#x81EA;&#x589E;&#x5E76;&#x8BA1;&#x7B97;&#x4E24;&#x4E2A; hash&#xFF0C;&#x4F46;&#x662F;<code>hash_b</code>&#x7684;&#x7ED3;&#x679C;&#x6709;&#x4E00;&#x5B9A;&#x53EF;&#x80FD;&#x4E3A; 0&#xFF0C;&#x6B64;&#x65F6;&#x7684;&#x7ED3;&#x679C;&#x4ECD;&#x7136;&#x662F;&#x51B2;&#x7A81;&#x7684;&#xFF0C;&#x56E0;&#x6B64;&#x4F5C;&#x4E00;&#x70B9;&#x5904;&#x7406;&#x4EE5;&#x4FDD;&#x8BC1;&#x5176;&#x7ED3;&#x679C;&#x4E0D;&#x4F1A;&#x4E3A; 0&#xFF1A;</p>
<pre><code class="language-c">index = (hash_a(string) + i * (hash_b(string) + 1)) % num_buckets;
</code></pre>
<p>&#x5177;&#x4F53;&#x5B9E;&#x73B0;&#x5982;&#x4E0B;&#xFF0C;&#x5C06;&#x539F;&#x6765;&#x51FD;&#x6570;&#x7684;&#x7B2C;&#x4E8C;&#x4E2A;&#x53C2;&#x6570;&#x6539;&#x4E3A;&#x4E24;&#x4E2A;&#x4E0D;&#x540C;&#x7684;&#x7D20;&#x6570;<code>HT_PRIME_1</code>&#x3001;<code>HT_PRIME_2</code>&#x4F5C;&#x4E3A;&#x4E24;&#x4E2A; hash &#x51FD;&#x6570;</p>
<pre><code class="language-c">static int ht_get_hash(
    const char* s, const int num_buckets, const int attempt
) {
    const int hash_a = ht_hash(s, HT_PRIME_1, num_buckets);
    const int hash_b = ht_hash(s, HT_PRIME_2, num_buckets);
    return (hash_a + (attempt * (hash_b + 1))) % num_buckets;
}
</code></pre>
<h2 id>&#x57FA;&#x672C;&#x64CD;&#x4F5C;</h2>
<p>&#x63A5;&#x4E0B;&#x6765;&#x662F;&#x5B9E;&#x73B0;&#x4E00;&#x4E2A;&#x54C8;&#x5E0C;&#x8868;&#x7684;&#x57FA;&#x672C;&#x64CD;&#x4F5C;&#xFF1A;</p>
<ul>
<li>&#x63D2;&#x5165;</li>
<li>&#x67E5;&#x627E;</li>
<li>&#x5220;&#x9664;</li>
<li>&#x66F4;&#x65B0;</li>
</ul>
<h3 id>&#x63D2;&#x5165;&#xFF08;&#x4E0E;&#x66F4;&#x65B0;&#xFF09;</h3>
<p>&#x63D2;&#x5165;&#x64CD;&#x4F5C;&#x9996;&#x5148;&#x521D;&#x59CB;&#x5316;&#x5E76;&#x5BF9;&#x4E00;&#x4E2A;&#x57FA;&#x672C;&#x5143;&#x7D20;&#x8D4B;&#x503C;&#xFF0C;&#x7136;&#x540E;&#x8C03;&#x7528;&#x4E0A;&#x4E00;&#x6B65;&#x5B8C;&#x6210;&#x7684; hash &#x51FD;&#x6570;&#x5BF9; key &#x8FDB;&#x884C;&#x8BA1;&#x7B97;&#x5F97;&#x5230; <code>index</code>&#xFF0C;&#x7136;&#x540E;&#x62FF;&#x5230;&#x8FD9;&#x4E2A;<code>index</code>&#x5728;&#x8868;&#x4E2D;&#x8FDB;&#x884C;&#x8BBF;&#x95EE;&#xFF0C;&#x82E5;&#x8BBF;&#x95EE;&#x76EE;&#x6807;&#x4E3A;<code>NULL</code>&#xFF0C;&#x8868;&#x793A;&#x8FD9;&#x4E2A;&#x5730;&#x65B9;&#x662F;&#x7A7A;&#x95F2;&#x7684;&#x53EF;&#x4EE5;&#x76F4;&#x63A5;&#x63D2;&#x5165;&#xFF1B;&#x82E5;&#x4E0D;&#x4E3A;<code>NULL</code>&#x4EE3;&#x8868;&#x53D1;&#x751F;&#x4E86;&#x51B2;&#x7A81;&#xFF0C;&#x5C06; <code>i</code> &#x81EA;&#x589E;&#x5E76;&#x518D;&#x6B21; hash &#x5E76;&#x5728;&#x8868;&#x4E2D;&#x67E5;&#x627E;&#xFF0C;&#x77E5;&#x9053;&#x627E;&#x5230;&#x4E00;&#x4E2A;&#x7A7A;&#x5730;&#x5740;&#x53EF;&#x4EE5;&#x8FDB;&#x884C;&#x63D2;&#x5165;&#x3002;</p>
<p>&#x66F4;&#x65B0;&#x64CD;&#x4F5C;&#x53EF;&#x4EE5;&#x5728;&#x8FD9;&#x91CC;&#x5B9E;&#x73B0;&#xFF0C;&#x76F4;&#x63A5;&#x66FF;&#x6362;&#x539F;<code>value</code>&#x5373;&#x53EF;&#x3002;</p>
<pre><code class="language-c">void ht_insert(ht_hash_table* ht, const char* key, const char* value) {
    //&#x65B0;&#x5EFA;&#x5143;&#x7D20;&#x7ED3;&#x6784;
    ht_item* item = ht_new_item(key, value);
    //&#x8C03;&#x7528;double hash&#x8FD4;&#x56DE;&#x4F5C;&#x4E3A;hash&#x8868;&#x7684;&#x7D22;&#x5F15;
    int index = ht_get_hash(item-&gt;key, ht-&gt;size, 0);
    ht_item* cur_item = ht-&gt;items[index];
    int i = 1;
    // iterate through indexes until we find an empty bucket
    while (cur_item != NULL) {
        //&#x627E;&#x5230;&#x5339;&#x914D;&#x7684;key&#x5219;&#x8986;&#x76D6;value&#x4F5C;&#x4E3A;&#x66F4;&#x65B0;&#x64CD;&#x4F5C;
        if (strcmp(cur_item-&gt;key, key) == 0) {
            ht_del_item(cur_item);
            ht-&gt;items[index] = item;
            return;
        }
        index = ht_get_hash(item-&gt;key, ht-&gt;size, i);
        cur_item = ht-&gt;items[index];
        i++;
    }
    //&#x63D2;&#x5165;&#x5143;&#x7D20;&#x5185;&#x5BB9;
    ht-&gt;items[index] = item;
    ht-&gt;count++;
}
</code></pre>
<h3 id>&#x67E5;&#x627E;</h3>
<p>&#x67E5;&#x627E;&#x4E0E;&#x63D2;&#x5165;&#x7684;&#x7B97;&#x6CD5;&#x5927;&#x81F4;&#x76F8;&#x540C;&#xFF0C;&#x53EA;&#x662F;&#x5728;&#x5FAA;&#x73AF;&#x4E2D;&#x5224;&#x65AD;&#x7D22;&#x5F15;&#x5904;&#x7684; key &#x503C;&#x662F;&#x5426;&#x5339;&#x914D;&#xFF0C;&#x82E5;&#x627E;&#x5230;<code>NULL</code>&#x5219;&#x4EE3;&#x8868;&#x8868;&#x4E2D;&#x6CA1;&#x6709;&#x6B64;&#x9879;&#xFF0C;&#x76F4;&#x63A5;&#x8FD4;&#x56DE;&#x7A7A;&#x6307;&#x9488;&#x3002;</p>
<pre><code class="language-c">char* ht_search(ht_hash_table* ht, const char* key) {
    int index = ht_get_hash(key, ht-&gt;size, 0);
    ht_item* item = ht-&gt;items[index];
    int i = 1;
    //&#x4E0E;&#x63D2;&#x5165;&#x5143;&#x7D20;&#x7C7B;&#x4F3C;&#xFF0C;&#x4E0D;&#x8FC7;&#x5728;&#x5FAA;&#x73AF;&#x4E2D;&#x9700;&#x8981;&#x5224;&#x65AD;&#x7D22;&#x5F15;&#x5904;&#x7684;key&#x503C;&#x662F;&#x5426;&#x5339;&#x914D;
    //&#x82E5;&#x7D22;&#x5F15;&#x5904;&#x4E3A;NULL&#xFF0C;&#x5219;&#x8DF3;&#x51FA;&#x5FAA;&#x73AF;&#x76F4;&#x63A5;&#x8FD4;&#x56DE;NULL&#xFF0C;&#x8868;&#x793A;&#x672A;&#x627E;&#x5230;
    while (item != NULL) {
        if (strcmp(item-&gt;key, key) == 0) {
            return item-&gt;value;
        }
        index = ht_get_hash(key, ht-&gt;size, i);
        item = ht-&gt;items[index];
        i++;
    }
    return NULL;
}
</code></pre>
<h3 id>&#x5220;&#x9664;</h3>
<p>&#x5220;&#x9664;&#x64CD;&#x4F5C;&#x76F8;&#x5BF9;&#x4E8E;&#x63D2;&#x5165;&#x4E0E;&#x67E5;&#x627E;&#x590D;&#x6742;&#x4E00;&#x4E9B;&#xFF0C;&#x56E0;&#x4E3A;&#x5728;&#x627E;&#x5230;&#x5BF9;&#x5E94; key &#x7684;&#x5143;&#x7D20;&#x65F6;&#xFF0C;&#x4E0D;&#x80FD;&#x76F4;&#x63A5;&#x5C06;&#x8FD9;&#x4E2A;&#x5143;&#x7D20;&#x5220;&#x9664;&#xFF0C;&#x56E0;&#x4E3A;&#x8FD9;&#x4E2A;&#x5143;&#x7D20;&#x53EF;&#x80FD;&#x4F4D;&#x4E8E;&#x51B2;&#x7A81;&#x94FE;&#x7684;&#x4E00;&#x90E8;&#x5206;&#xFF0C;&#x82E5;&#x662F;&#x8FD9;&#x6837;&#xFF0C;&#x5C06;&#x5176;&#x91CA;&#x653E;&#x4E3A;<code>NULL</code>&#xFF0C;&#x5F53;&#x4E0B;&#x6B21;&#x67E5;&#x627E;&#x8FD9;&#x4E2A;&#x51B2;&#x7A81;&#x94FE;&#x5220;&#x9664;&#x6389;&#x7684;&#x5143;&#x7D20;&#x540E;&#x9762;&#x4E00;&#x4E2A;&#x5143;&#x7D20;&#x65F6;&#xFF0C;&#x627E;&#x5230;&#x524D;&#x9762;&#x88AB;&#x5220;&#x9664;&#x7684;&#x5143;&#x7D20;&#x53D1;&#x73B0;&#x4E3A;<code>NULL</code>&#x5C31;&#x4F1A;&#x76F4;&#x63A5;&#x8FD4;&#x56DE;&#x672A;&#x627E;&#x5230;&#x4E86;&#xFF0C;&#x800C;&#x4E0D;&#x4F1A;&#x7EE7;&#x7EED;&#x5728;&#x51B2;&#x7A81;&#x94FE;&#x4E2D;&#x8BA1;&#x7B97; hash &#x5E76;&#x7EE7;&#x7EED;&#x67E5;&#x627E;&#x3002;&#x56E0;&#x6B64;&#x9700;&#x8981;&#x4F7F;&#x7528;&#x6807;&#x8BC6;&#x5220;&#x9664; instead of &#x76F4;&#x63A5;&#x5220;&#x9664;&#x3002;&#x65B9;&#x5F0F;&#x53EF;&#x4EE5;&#x5C06;&#x8FD9;&#x4E2A;&#x8282;&#x70B9;&#x6307;&#x5411;&#x4E00;&#x4E2A;&#x5B9A;&#x4E49;&#x7684;&#x5168;&#x5C40;&#x7684;&#x4EE3;&#x8868;&#x4EE5;&#x5220;&#x9664;&#x7684;&#x8282;&#x70B9;&#x5373;&#x53EF;&#xFF1A;</p>
<pre><code class="language-c">//&#x5220;&#x9664;&#x6807;&#x8BB0;
static ht_item HT_DELETED_ITEM = {NULL, NULL};
//&#x5220;&#x9664;&#x64CD;&#x4F5C;
void ht_delete(ht_hash_table* ht, const char* key) {
    //&#x5148;&#x641C;&#x7D22;&#x5230;
    int index = ht_get_hash(key, ht-&gt;size, 0);
    ht_item* item = ht-&gt;items[index];
    int i = 1;
    while (item != NULL) {
        if (item != &amp;HT_DELETED_ITEM) {
            if (strcmp(item-&gt;key, key) == 0) {
                ht_del_item(item);
                //&#x7F6E;&#x5220;&#x9664;&#x6807;&#x5FD7;
                ht-&gt;items[index] = &amp;HT_DELETED_ITEM;
            }
        }
        index = ht_get_hash(key, ht-&gt;size, i);
        item = ht-&gt;items[index];
        i++;
    }
    ht-&gt;count--;
}
</code></pre>
<p>&#x6539;&#x8FDB;&#x5220;&#x9664;&#x65B9;&#x5F0F;&#x540E;&#xFF0C;&#x5728;&#x524D;&#x9762;&#x7684;&#x63D2;&#x5165;&#x4E0E;&#x67E5;&#x627E;&#x64CD;&#x4F5C;&#x4E2D;&#x5C31;&#x8981;&#x4F5C;&#x4E00;&#x5B9A;&#x7684;&#x6539;&#x8FDB;&#x3002;&#x8FD9;&#x91CC;&#x4E0D;&#x505A;&#x5177;&#x4F53;&#x63CF;&#x8FF0;&#x3002;</p>
<h2 id>&#x66F4;&#x65B0;&#x8868;&#x5927;&#x5C0F;</h2>
<p>&#x524D;&#x9762;&#x77E5;&#x9053;&#xFF0C;&#x5F53;&#x4E00;&#x4E2A;&#x8868;&#x5728;&#x5FEB;&#x8981;&#x6EE1;&#x65F6;&#xFF0C;hash &#x51B2;&#x7A81;&#x7684;&#x6982;&#x7387;&#x4F1A;&#x53D8;&#x5927;&#xFF0C;&#x56E0;&#x6B64;&#x5728;&#x8FD9;&#x4E2A;&#x65F6;&#x5019;&#x6211;&#x4EEC;&#x9700;&#x8981;&#x91CD;&#x65B0;&#x4FEE;&#x6539;&#x8868;&#x7684;&#x5BB9;&#x91CF;&#xFF0C;&#x4EE5;&#x5BB9;&#x7EB3;&#x66F4;&#x591A;&#x7684;&#x5143;&#x7D20;&#x4E0E;&#x51CF;&#x5C11;&#x51B2;&#x7A81;&#x6982;&#x7387;&#x3002;&#x53EF;&#x4EE5;&#x5728;&#x6BCF;&#x6B21;&#x63D2;&#x5165;&#x4E0E;&#x5220;&#x9664;&#x65F6;&#x8BA1;&#x7B97;&#x4E00;&#x4E2A;<code>load=count/size</code>&#x4F5C;&#x4E3A; resize &#x7684;&#x6807;&#x51C6;&#xFF0C;</p>
<ul>
<li>load &gt; 0.7 &#x5219;&#x5BB9;&#x91CF;&#x7FFB;&#x500D;</li>
<li>load &lt; 0.1 &#x5219;&#x5BB9;&#x91CF;&#x51CF;&#x534A;</li>
</ul>
<p>&#x66F4;&#x6539;&#x5BB9;&#x91CF;&#x5927;&#x5C0F;&#x7684;&#x64CD;&#x4F5C;&#x5373;&#x65B0;&#x5EFA;&#x4E00;&#x4E2A;&#x76EE;&#x6807;&#x5BB9;&#x91CF;&#x7684;&#x8868;&#x4F5C;&#x7136;&#x540E;&#x5C06;&#x539F;&#x8868;&#x5185;&#x5BB9;&#x590D;&#x5236;&#x8FC7;&#x53BB;&#xFF0C;&#x7136;&#x540E;&#x4EA4;&#x6362;&#x8868;&#x4E2D;&#x7684;&#x5C5E;&#x6027;&#xFF08;<code>size</code>&#x4E0E;<code>base_size</code>&#xFF09;&#x4E0E;&#x6240;&#x6709;&#x5185;&#x5BB9;&#xFF08;<code>items</code>&#xFF09;&#xFF0C;&#x7136;&#x540E;&#x5220;&#x9664;&#x65B0;&#x8868;&#xFF0C;&#x8FD9;&#x6837;&#x539F;&#x6765;&#x8868;&#x7684;&#x5BB9;&#x91CF;&#x88AB;&#x6539;&#x53D8;&#x4F46;&#x662F;&#x6307;&#x5411;&#x539F;&#x8868;&#x7684;&#x6307;&#x9488;&#x672A;&#x53D8;&#x3002;&#x7136;&#x800C;&#x8FD9;&#x4E2A;&#x64CD;&#x4F5C;&#x662F;&#x6BD4;&#x8F83;&#x8017;&#x65F6;&#x7684;&#xFF0C;&#x56E0;&#x6B64;&#x4E5F;&#x9700;&#x8981;&#x6839;&#x636E;&#x4F7F;&#x7528;&#x60C5;&#x666F;&#x8BBE;&#x5B9A;&#x5408;&#x7406;&#x7684;&#x9608;&#x503C;&#x3001;&#x589E;&#x5927;&#x51CF;&#x5C0F;&#x5BB9;&#x91CF;&#x7684;&#x6807;&#x51C6;&#x3001;&#x521D;&#x59CB;&#x5BB9;&#x91CF;&#xFF0C;&#x6765;&#x5C3D;&#x91CF;&#x907F;&#x514D;&#x5728;&#x4F7F;&#x7528;&#x65F6;&#x7684; resize &#x64CD;&#x4F5C;&#x3002;</p>
<p>&#x5728;&#x5B9E;&#x73B0; resize &#x64CD;&#x4F5C;&#x65F6;&#xFF0C;&#x5728;&#x8868;&#x7ED3;&#x6784;&#x4F53;&#x4E2D;&#x65B0;&#x589E;&#x52A0;&#x4E00;&#x4E2A;<code>base_size</code>&#x4F5C;&#x4E3A;&#x57FA;&#x7840;&#x5BB9;&#x91CF;&#xFF0C;<code>size</code>&#x4E3A;&#x5B9E;&#x9645;&#x5BB9;&#x91CF;&#xFF08;&#x5927;&#x4E8E;<code>base_size</code>&#x7684;&#x7B2C;&#x4E00;&#x4E2A;&#x7D20;&#x6570;&#xFF09;</p>
<pre><code class="language-c">//&#x91CD;&#x65B0;&#x5206;&#x914D;&#x5927;&#x5C0F;
static void ht_resize(ht_hash_table* ht, const int base_size) {
    //size&#x5C0F;&#x4E8E;&#x521D;&#x59CB;&#x5BB9;&#x91CF;&#x65F6;&#x4E0D;&#x518D;&#x51CF;&#x5C11;
    if (base_size &lt; HT_INITIAL_BASE_SIZE) {
        return;
    }
    //&#x65B0;&#x5EFA;&#x4E00;&#x5F20;&#x8868;&#xFF0C;&#x5E76;&#x590D;&#x5236;&#x539F;&#x8868;&#x7684;&#x6240;&#x6709;&#x6570;&#x636E;
    ht_hash_table* new_ht = ht_new_sized(base_size);
    for (int i = 0; i &lt; ht-&gt;size; i++) {
        ht_item* item = ht-&gt;items[i];
        if (item != NULL &amp;&amp; item != &amp;HT_DELETED_ITEM) {
            ht_insert(new_ht, item-&gt;key, item-&gt;value);
        }
    }

    //&#x4FEE;&#x6539;&#x539F;&#x8868;&#x7684;&#x5C5E;&#x6027;
    ht-&gt;base_size = new_ht-&gt;base_size;
    ht-&gt;count = new_ht-&gt;count;

    //&#x4E3A;&#x4E86;&#x5220;&#x9664;&#x65B0;&#x8868;&#xFF0C;&#x5C06;&#x539F;&#x8868;&#x7684;size&#x4E0E;base_size&#x5C5E;&#x6027;&#x8D4B;&#x503C;&#x7ED9;&#x65B0;&#x8868;
    const int tmp_size = ht-&gt;size;
    ht-&gt;size = new_ht-&gt;size;
    new_ht-&gt;size = tmp_size;

    //&#x5C06;&#x539F;&#x8868;&#x4E0E;&#x65B0;&#x8868;&#x7684;&#x5185;&#x5BB9;items&#x4EA4;&#x6362;
    ht_item** tmp_items = ht-&gt;items;
    ht-&gt;items = new_ht-&gt;items;
    new_ht-&gt;items = tmp_items;

    //&#x5220;&#x9664;&#x65B0;&#x8868;
    ht_del_hash_table(new_ht);
}

//&#x589E;&#x5927;&#x5BB9;&#x91CF;
static void ht_resize_up(ht_hash_table* ht) {
    const int new_size = ht-&gt;base_size * 2;
    ht_resize(ht, new_size);
}

//&#x7F29;&#x5C0F;&#x5BB9;&#x91CF;
static void ht_resize_down(ht_hash_table* ht) {
    const int new_size = ht-&gt;base_size / 2;
    ht_resize(ht, new_size);
}
</code></pre>
<p>&#x5728;&#x63D2;&#x5165;&#x5220;&#x9664;&#x5143;&#x7D20;&#x65F6;&#x4E4B;&#x524D;&#x9700;&#x8981;&#x8BA1;&#x7B97;<code>load</code>&#x5E76;&#x5224;&#x65AD;&#x662F;&#x5426;&#x9700;&#x8981; resize&#xFF1A;</p>
<pre><code class="language-c">void ht_insert(ht_hash_table* ht, const char* key, const char* value) {
    const int load = ht-&gt;count * 100 / ht-&gt;size;
    if (load &gt; 70) {
        ht_resize_up(ht);
    }
    // ...
}

void ht_delete(ht_hash_table* ht, const char* key) {
    const int load = ht-&gt;count * 100 / ht-&gt;size;
    if (load &lt; 10) {
        ht_resize_down(ht);
    }
    // ...
}
</code></pre>
<h2 id>&#x6D4B;&#x8BD5;</h2>
<p>&#x63A5;&#x4E0B;&#x6765;&#x5728; <code>main</code> &#x51FD;&#x6570;&#x4E2D;&#x8FDB;&#x884C;&#x6D4B;&#x8BD5;&#xFF1A;</p>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &quot;src/hash_table.h&quot;

int main(int argc, char const* argv[]) {
    // new hashtable
    ht_hash_table* ht = ht_new();

    // insert into hashtable
    ht_insert(ht, &quot;foo&quot;, &quot;bar&quot;);
    ht_insert(ht, &quot;name&quot;, &quot;ruofeng&quot;);
    ht_insert(ht, &quot;number&quot;, &quot;41524226&quot;);

    // search from hashtable
    printf(&quot;%s\n&quot;, ht_search(ht, &quot;foo&quot;));
    printf(&quot;%s\n&quot;, ht_search(ht, &quot;name&quot;));

    // update test
    ht_insert(ht, &quot;foo&quot;, &quot;barr&quot;);
    printf(&quot;%s\n&quot;, ht_search(ht, &quot;foo&quot;));

    // key not exsit test
    if (ht_search(ht, &quot;not&quot;) == NULL) printf(&quot;%s\n&quot;, &quot;key(not) doesn&apos;t exist&quot;);

    // delete key test
    ht_delete(ht, &quot;foo&quot;);
    if (ht_search(ht, &quot;foo&quot;) == NULL) printf(&quot;%s\n&quot;, &quot;key(foo) doesn&apos;t exist&quot;);

    // delete hash table
    ht_del_hash_table(ht);

    return 0;
}
</code></pre>
<p>&#x7F16;&#x8BD1;&#x5E76;&#x8FD0;&#x884C;&#xFF1A;</p>
<pre><code class="language-shell">gcc -g ./src/hash_table.c ./src/prime.c main.c -std=c11 -o ./build/main -lm
./build/main
</code></pre>
<p>&#x8FD0;&#x884C;&#x7ED3;&#x679C;</p>
<pre><code class="language-plaintext">$ ./build/main
bar
ruofeng
barr
key(not) doesn&apos;t exist
key(foo) doesn&apos;t exist
</code></pre>
<h2 id>&#x6E90;&#x4EE3;&#x7801;</h2>
<p>&#x6240;&#x6709;&#x53EF;&#x6267;&#x884C;&#x6E90;&#x4EE3;&#x7801;&#x53EF;&#x5728;&#x6211;&#x7684; GitHub &#x627E;&#x5230;&#xFF1A;</p>
<p><a href="https://github.com/abowloflrf/hash-table">https://github.com/abowloflrf/hash-table</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[记一次 Airbnb 面试]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>&#x5176;&#x5B9E;&#x8001;&#x65E9;&#x4EE5;&#x524D;&#x5C31;&#x5BF9; Airbnb &#x8FD9;&#x5BB6;&#x516C;&#x53F8;&#x5370;&#x8C61;&#x5341;&#x5206;&#x4E4B;&#x597D;&#xFF0C;&#x6280;&#x672F;&#x6C1B;&#x56F4;&#x5F00;&#x653E;&#x53CB;&#x597D;&#x6D3B;&#x8DC3;&#xFF0C;&#x867D;&#x7136;&#x4ECE;&#x6CA1;&#x4F53;&#x9A8C;&#x8FC7;&#x4F46;&#x662F;&#x603B;&#x4F53;&#x4E0A;&#x7ED9;&#x6211;&#x7684;&#x5370;&#x8C61;&#x5C31;&#x662F;</p>]]></description><link>https://ruofeng.me/2018/06/08/an-onsite-interview-of-airbnb/</link><guid isPermaLink="false">5d8e378da7d96200019ade1b</guid><category><![CDATA[随想]]></category><dc:creator><![CDATA[Ruofeng Lei]]></dc:creator><pubDate>Fri, 08 Jun 2018 15:55:16 GMT</pubDate><media:content url="https://ruofeng.me/content/images/2018/06/IMG_0299.JPG" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="https://ruofeng.me/content/images/2018/06/IMG_0299.JPG" alt="&#x8BB0;&#x4E00;&#x6B21; Airbnb &#x9762;&#x8BD5;"><p>&#x5176;&#x5B9E;&#x8001;&#x65E9;&#x4EE5;&#x524D;&#x5C31;&#x5BF9; Airbnb &#x8FD9;&#x5BB6;&#x516C;&#x53F8;&#x5370;&#x8C61;&#x5341;&#x5206;&#x4E4B;&#x597D;&#xFF0C;&#x6280;&#x672F;&#x6C1B;&#x56F4;&#x5F00;&#x653E;&#x53CB;&#x597D;&#x6D3B;&#x8DC3;&#xFF0C;&#x867D;&#x7136;&#x4ECE;&#x6CA1;&#x4F53;&#x9A8C;&#x8FC7;&#x4F46;&#x662F;&#x603B;&#x4F53;&#x4E0A;&#x7ED9;&#x6211;&#x7684;&#x5370;&#x8C61;&#x5C31;&#x662F;&#x4E00;&#x5BB6;&#x6709;&#x4EBA;&#x60C5;&#x5473;&#x53C8;&#x4E0D;&#x4E4F;&#x6280;&#x672F;&#x5B9E;&#x529B;&#x7684;&#x516C;&#x53F8;&#x3002;&#x5F88;&#x5DE7;&#xFF0C;&#x524D;&#x4E00;&#x9635;&#x6B63;&#x597D;&#x5728;V&#x7AD9;&#x4E0A;&#x53D1;&#x73B0;&#x4E86;&#x4ED6;&#x5BB6;&#x7684;&#x6821;&#x62DB;&#x8D34;&#xFF0C;&#x8FD9;&#x8C8C;&#x4F3C;&#x4E5F;&#x662F; Airbnb &#x5728;&#x56FD;&#x5185;&#x7684;&#x7B2C;&#x4E00;&#x6B21;&#x6821;&#x62DB;&#xFF0C;&#x975E;&#x5E38;&#x5E78;&#x8FD0;&#x7684;&#x6B63;&#x597D;&#x88AB;&#x5927;&#x4E09;&#x7684;&#x6211;&#x8D76;&#x4E0A;&#xFF0C;&#x4FBF;&#x6FC0;&#x52A8;&#x7684;&#x6574;&#x7406;&#x4E86;&#x7B80;&#x5386;&#x53D1;&#x4E86;&#x8FC7;&#x53BB;&#xFF0C;&#x4E5F;&#x5E78;&#x8FD0;&#x5730;&#x62FF;&#x5230;&#x4E86;&#x7B2C;&#x4E00;&#x9762;&#x7535;&#x9762;&#x7684;&#x7ECF;&#x5386;&#x3002;</p>
<p>&#x7136;&#x540E;&#x641C;&#x5BFB;&#x4E86;&#x4E00;&#x756A;&#x9762;&#x7ECF;&#xFF0C;&#x5F97;&#x5230;&#x7ED3;&#x679C;&#x662F;&#xFF1A;</p>
<p><strong>&#x9664;&#x4E86;&#x7B97;&#x6CD5;&#x9898;&#xFF0C;&#x8FD8;&#x662F;&#x7B97;&#x6CD5;&#x9898;</strong></p>
<p>&#x800C;&#x81EA;&#x5DF1;&#xFF0C;&#x65E2;&#x6CA1;&#x6709;&#x7B97;&#x6CD5;&#x7ADE;&#x8D5B;&#x7ECF;&#x5386;&#xFF0C;&#x81EA;&#x5DF1;&#x5E73;&#x65F6;&#x4E5F;&#x6CA1;&#x6709;&#x592A;&#x591A;&#x5237;&#x9898;&#x7684;&#x4E60;&#x60EF;&#xFF0C;&#x65E0;&#x7591;&#x8BA9;&#x6211;&#x538B;&#x529B;&#x589E;&#x52A0;&#x4E86;&#x8BB8;&#x591A;&#x3002;&#x4E3A;&#x4E86;&#x5BF9;&#x5F97;&#x8D77;&#x81EA;&#x5DF1;&#x4E89;&#x53D6;&#x5230;&#x7684;&#x8FD9;&#x6B21;&#x673A;&#x4F1A;&#xFF0C;&#x8FD9;&#x4E24;&#x5468;&#x624D;&#x6B63;&#x5F0F;&#x8D70;&#x5728;&#x4E86;&#x5237;&#x9898;&#x7684;&#x8DEF;&#x4E0A;&#x3002;&#x7B97;&#x6CD5;&#x7ECF;&#x9A8C;&#x8FD1;&#x4E4E;&#x4E3A;0&#x7684;&#x81EA;&#x5DF1;&#xFF0C;Leetcode&#x4E0A;&#x7B80;&#x5355;&#x9898;&#x53EF;&#x80FD;&#x6323;&#x624E;&#x4E00;&#x4F1A;&#x513F;&#x80FD;&#x72EC;&#x7ACB;&#x5199;&#x51FA;&#x6765;&#xFF0C;&#x4E2D;&#x7B49;&#x9898;&#x51E0;&#x4E4E;&#x90FD;&#x5F97;&#x641C;&#x89E3;&#x7B54;&#x81EA;&#x5DF1;&#x7406;&#x89E3;&#x8C03;&#x8BD5;&#x597D;&#x4E45;&#x624D;&#x80FD;&#x5B8C;&#x6210;&#xFF0C;&#x96BE;&#x9898;&#x53EF;&#x80FD;&#x9700;&#x8981;&#x4E00;&#x6574;&#x4E2A;&#x4E0B;&#x5348;&#x53BB;&#x7422;&#x78E8;&#x7406;&#x89E3;&#x751A;&#x81F3;&#x770B;&#x89E3;&#x7B54;&#x4E5F;&#x4E0D;&#x61C2;&#x4E3A;&#x4EC0;&#x4E48;&#x8981;&#x8FD9;&#x4E48;&#x5199;&#x3002;&#x5C31;&#x8FD9;&#x6837;&#x6BCF;&#x5929;&#x629B;&#x5F00;&#x4E86;&#x624B;&#x5934;&#x6240;&#x6709;&#x7684;&#x4E8B;&#xFF0C;&#x4E00;&#x5FC3;&#x4E00;&#x610F;&#x590D;&#x4E60;&#x7B97;&#x6CD5;&#xFF0C;&#x6BCF;&#x5929;&#x88AB;&#x6298;&#x78E8;&#x7684;&#x5FC3;&#x529B;&#x6194;&#x60B4;&#x3002;</p>
<p>&#x4E0D;&#x8FC7;&#x76F8;&#x5BF9;&#x5E78;&#x8FD0;&#x7684;&#x662F;&#xFF0C;&#x7B2C;&#x4E00;&#x8F6E;&#x7535;&#x9762;&#x7684;&#x9898;&#x5E76;&#x4E0D;&#x662F;&#x592A;&#x96BE;&#xFF0C;&#x5199;&#x4E86;&#x51FA;&#x6765;&#x6CA1;&#x6709;&#x51FA;&#x592A;&#x5927;&#x5DEE;&#x9519;&#xFF0C;&#x5C31;&#x8FD9;&#x6837;&#x81EA;&#x5DF1;&#x53C8;&#x9634;&#x5DEE;&#x9633;&#x9519;&#x7684;&#x62FF;&#x5230;&#x4E86; onsite &#x673A;&#x4F1A;&#x3002;&#x540E;&#x9762;&#x51E0;&#x5929;&#x66F4;&#x662F;&#x62FC;&#x547D;&#xFF0C;&#x8336;&#x996D;&#x4E0D;&#x601D;&#x5C31;&#x4E3A;&#x7422;&#x78E8;&#x8FD9;&#x90A3;&#x4E9B;&#x9898;&#x7684;&#x5957;&#x8DEF;&#x3002;</p>
<p><img src="https://ruofeng.me/content/images/2018/06/IMG_0299-1.JPG" alt="&#x8BB0;&#x4E00;&#x6B21; Airbnb &#x9762;&#x8BD5;" loading="lazy"></p>
<hr>
<p>&#x4ECA;&#x5929;&#x73B0;&#x573A;&#x9762;&#x5B8C;&#xFF0C;&#x53EA;&#x80FD;&#x4ECE;&#x5FC3;&#x5E95;&#x627F;&#x8BA4;&#x81EA;&#x5DF1;<strong>&#x8FD8;&#x662F;&#x592A;&#x5AE9;</strong>&#x4E86;&#x3002;&#x867D;&#x7136;&#x8BF4;&#x4E24;&#x4E2A;&#x9898;&#x81EA;&#x5DF1;&#x90FD;&#x6709;&#x4E86;&#x6E05;&#x6670;&#x7684;&#x601D;&#x8DEF;&#x4F46;&#x662F;Airbnb&#x7684;&#x8981;&#x6C42;&#x662F;&#x6BCF;&#x4E2A;&#x9898;<strong>45&#x5206;&#x949F;</strong>&#x5185;&#x4ECE;&#x7ED9;&#x9898;&#x5230;&#x601D;&#x8003;&#x4E0E;&#x9762;&#x8BD5;&#x5B98;&#x4EA4;&#x6D41;&#x5B9E;&#x73B0;&#x7B97;&#x6CD5;&#x8C03;&#x8BD5;&#x5B8C;&#x7F8E;&#x8DD1;&#x901A;&#x6240;&#x6709;case&#xFF0C;&#x663E;&#x7136;&#x65F6;&#x95F4;&#x5BF9;&#x81EA;&#x5DF1;&#x8FD8;&#x662F;&#x5B8C;&#x5168;&#x4E0D;&#x591F;&#x3002;&#x5C31;&#x662F;&#x56E0;&#x4E3A;&#x81EA;&#x5DF1;&#x5E73;&#x65F6;&#x7684;&#x5237;&#x9898;&#x592A;&#x5C11;&#xFF0C;&#x7528;&#x4EE3;&#x7801;&#x5B9E;&#x73B0;&#x81EA;&#x5DF1;&#x7684;&#x601D;&#x8DEF;&#x5E76;&#x6CA1;&#x6709;&#x5230;&#x719F;&#x7EC3;&#x7684;&#x7A0B;&#x5EA6;&#xFF0C;&#x6CA1;&#x628A; Leetcode &#x7FFB;&#x6765;&#x8986;&#x53BB;&#x7EC3;&#x4E2A;&#x51E0;&#x904D;&#x7684;&#x6C34;&#x5E73;&#x8981;&#x5728;45&#x5206;&#x949F;&#x5185;&#x5B8C;&#x6210;&#xFF0C;&#x8FD8;&#x771F;&#x7684;&#x662F;&#x53EF;&#x4EE5;&#x6B47;&#x7740;&#x4E86;&#x3002;</p>
<p>&#x4E0D;&#x8FC7;&#xFF0C;&#x53C2;&#x89C2;&#x4E86;&#x4E00;&#x8D9F;&#x516C;&#x53F8;&#x73AF;&#x5883;&#x4E5F;&#x4E0D;&#x4E8F;&#xFF0C;&#x8FDB;&#x53BB;&#x4E4B;&#x524D;&#x771F;&#x7684;&#x5F88;&#x96BE;&#x60F3;&#x8C61;&#x5728;&#x73AF;&#x7403;&#x91D1;&#x878D;&#x4E2D;&#x5FC3;&#x8FD9;&#x4E48;&#x4E25;&#x8083;&#x7684;&#x7ACB;&#x65B9;&#x4F53;&#x5EFA;&#x7B51;&#x7684;&#x67D0;&#x4E00;&#x5C42;&#x80FD;&#x6709;&#x4E00;&#x5BB6;&#x88C5;&#x4FEE;&#x5982;&#x6B64;&#x7CBE;&#x81F4;&#x7528;&#x5FC3;&#x7684;&#x516C;&#x53F8;&#xFF1A;&#x6574;&#x4F53;&#x4F9D;&#x7167;&#x5317;&#x4EAC;&#x4F20;&#x7EDF;&#x80E1;&#x540C;&#x5E03;&#x5C40;&#x88C5;&#x4FEE;&#xFF0C;&#x5176;&#x4E2D;&#x6BCF;&#x4E00;&#x95F4;&#x4F1A;&#x8BAE;&#x5BA4;&#x90FD;&#x662F;&#x6309;&#x7167;Airbnb&#x91CC;&#x67D0;&#x4E00;&#x4E2A;&#x72EC;&#x4E00;&#x65E0;&#x4E8C;&#x7684;&#x70ED;&#x95E8;&#x623F;&#x6E90;&#x4E13;&#x95E8;&#x88C5;&#x4FEE;&#x3002;&#x771F;&#x7684;&#x662F;&#x5F88;&#x7FA1;&#x6155;&#x80FD;&#x5728;&#x8FD9;&#x91CC;&#x5DE5;&#x4F5C;&#x7684;&#x5C0F;&#x4F19;&#x4F34;&#x3002;</p>
<p><img src="https://ruofeng.me/content/images/2018/06/IMG_0292.JPG" alt="&#x8BB0;&#x4E00;&#x6B21; Airbnb &#x9762;&#x8BD5;" loading="lazy"></p>
<hr>
<p>&#x8FD9;&#x4E00;&#x8D9F;&#x867D;&#x7136;&#x9762;&#x8BD5;&#x5F88;&#x7CDF;&#x7CD5;&#xFF0C;&#x4F46;&#x662F;&#x786E;&#x5B9E;&#x5F97;&#x627F;&#x8BA4;&#x6709;&#x540C;&#x9F84;&#x4EBA;&#x80FD;&#x591F;&#x6709;&#x80FD;&#x529B;&#x62FF;&#x5230;offer&#xFF0C;&#x5F97;&#x627F;&#x8BA4;&#x81EA;&#x5DF1;&#x548C;&#x4ED6;&#x4EEC;&#x7684;&#x5DEE;&#x8DDD;&#x975E;&#x5E38;&#x660E;&#x663E;&#x3002;&#x9A6C;&#x4E0A;&#x7684;&#x79CB;&#x62DB;&#xFF0C;&#x8FD9;&#x4E24;&#x5468;&#x7684;&#x6240;&#x6709;&#x7ECF;&#x5386;&#x4E5F;&#x8BA9;&#x76EE;&#x6807;&#x4E5F;&#x66F4;&#x52A0;&#x660E;&#x786E;&#xFF0C;&#x81EA;&#x5DF1;&#x8FD8;&#x662F;&#x4E0D;&#x80FD;&#x592A;&#x6025;&#xFF0C;<strong>&#x65E2;&#x7136;&#x81EA;&#x5DF1;&#x4E0D;&#x662F;&#x795E;&#x5C31;&#x53EA;&#x80FD;&#x8001;&#x8001;&#x5B9E;&#x5B9E;&#x5411;&#x4E0A;&#x722C;&#x5427;</strong>&#x3002;</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[站点的又一次搬家]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>&#x5176;&#x5B9E;&#x4ECE;&#x53BB;&#x5E74;&#x5E74;&#x5E95;&#x5F00;&#x59CB;&#x5C31;&#x53D1;&#x73B0;&#xFF0C;&#x7AD9;&#x70B9;&#x4E0A;&#x4E86; HTTPS &#x4E4B;&#x540E;&#x5C31;&#x4F1A;&#x95F4;&#x6B47;&#x6027;&#x5F97;&#x65E0;&#x6CD5;&#x8BBF;&#x95EE;&#xFF0C;&#x800C;&#x540C;&#x65F6; HTTP &#x8BBF;&#x95EE;&#x5374;&#x6B63;&#x5E38;&#xFF0C;&#x521D;&#x6B65;&#x89C9;&#x5F97;&#x662F;&#x4F4D;&#x670D;&#x52A1;&#x5668;</p>]]></description><link>https://ruofeng.me/2018/05/17/migration-of-blog-again/</link><guid isPermaLink="false">5d8e378da7d96200019ade1a</guid><category><![CDATA[随想]]></category><dc:creator><![CDATA[Ruofeng Lei]]></dc:creator><pubDate>Thu, 17 May 2018 18:29:36 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>&#x5176;&#x5B9E;&#x4ECE;&#x53BB;&#x5E74;&#x5E74;&#x5E95;&#x5F00;&#x59CB;&#x5C31;&#x53D1;&#x73B0;&#xFF0C;&#x7AD9;&#x70B9;&#x4E0A;&#x4E86; HTTPS &#x4E4B;&#x540E;&#x5C31;&#x4F1A;&#x95F4;&#x6B47;&#x6027;&#x5F97;&#x65E0;&#x6CD5;&#x8BBF;&#x95EE;&#xFF0C;&#x800C;&#x540C;&#x65F6; HTTP &#x8BBF;&#x95EE;&#x5374;&#x6B63;&#x5E38;&#xFF0C;&#x521D;&#x6B65;&#x89C9;&#x5F97;&#x662F;&#x4F4D;&#x670D;&#x52A1;&#x5668;&#x4E8E;&#x673A;&#x573A;&#x6A2A;&#x884C;&#x7684;&#x65E5;&#x672C;&#xFF0C;&#x4E22;&#x5305;&#x62E5;&#x585E;&#x6781;&#x9AD8;&#x5BFC;&#x81F4;&#x7684;&#x95EE;&#x9898;&#xFF0C;&#x4E8E;&#x662F;&#x5C31;&#x8FC1;&#x79FB;&#x8FC7;&#x4E00;&#x6B21;&#x670D;&#x52A1;&#x5668;&#xFF0C;&#x4ECE;&#x65E5;&#x672C;&#x5230;&#x4E86;&#x7F8E;&#x897F;&#xFF0C;&#x5EF6;&#x8FDF;&#x4E0A;&#x6765;&#x4E86;&#x4F46;&#x662F;&#x4E22;&#x5305;&#x4F4E;&#x70B9;&#x4E0D;&#x8FC7;&#x8BBF;&#x95EE;&#x6682;&#x65F6;&#x4E5F;&#x6B63;&#x5E38;&#x4E86;&#x3002;</p>
<p>&#x4E0D;&#x8FC7;&#x6700;&#x8FD1;&#x4E24;&#x4E2A;&#x6708;&#x53C8;&#x5F00;&#x59CB;&#x5982;&#x6B64;&#x62BD;&#x98CE;&#xFF0C;&#x800C;&#x4E14;V&#x7AD9;&#x4E0A;&#x4E5F;&#x9010;&#x6E10;&#x6709;&#x53D1;&#x5E16;&#xFF0C;&#x6709;&#x633A;&#x591A;&#x4EBA;&#x53D1;&#x73B0;&#x4E86;&#x8FD9;&#x4E2A;&#x60C5;&#x51B5;&#xFF0C;&#x5177;&#x4F53;&#x539F;&#x56E0;&#x5E76;&#x4E0D;&#x597D;&#x67E5;&#x660E;&#xFF0C;&#x4F46;&#x662F;&#x786E;&#x5B9E;&#x662F;&#x56FD;&#x5916;&#x4E00;&#x4E9B;&#x670D;&#x52A1;&#x5546;&#x6216; IP &#x4F1A;&#x88AB;&#x91CD;&#x70B9;&#x7167;&#x987E;&#xFF0C;&#x5728; TLS &#x63E1;&#x624B;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x53EA;&#x6709;&#x4E00;&#x4E2A; Client Hello&#xFF0C;Server Hello &#x4E0D;&#x77E5;&#x9053;&#x6B7B;&#x5728;&#x4E86;&#x56DE;&#x56FD;&#x7684;&#x54EA;&#x4E00;&#x6761;&#x8DEF;&#x7531;&#x4E0A;&#xFF0C;&#x5BFC;&#x81F4; TLS &#x63E1;&#x624B;&#x5931;&#x8D25;&#xFF0C;Chrome &#x6C38;&#x8FDC;&#x5361;&#x5728; Establishing Secure Connection &#x4E0A;&#x3002;&#x4F5C;&#x4E3A;&#x4E2A;&#x4EBA;&#x6280;&#x672F;&#x535A;&#x5BA2;&#xFF0C;&#x8981;&#x56DE;&#x5230; HTTP &#x786E;&#x5B9E;&#x4F1A;&#x80FD;&#x7A33;&#x5B9A;&#x8BBF;&#x95EE;&#xFF0C;&#x53EF;&#x662F;&#x4F3C;&#x4E4E;&#x663E;&#x5F97;&#x53C8;&#x4E0D;&#x592A;&#x5408;&#x9002;&#xFF0C;Not Secure &#x6302;&#x5728;&#x5730;&#x5740;&#x680F;&#x8FC7;&#x4E8E;&#x4E11;&#x964B;&#x3002;&#x60F3;&#x7740;&#xFF0C;&#x518D;&#x8FC1;&#x4E00;&#x6B21;&#x7AD9;&#x5427;&#xFF0C;&#x770B;&#x770B;&#x4F1A;&#x4E0D;&#x4F1A;&#x597D;&#x4E9B;&#x5427;&#xFF0C;&#x4E5F;&#x8BB8;&#x5462;&#x3002;</p>
<p>&#x8FD8;&#x597D; Ghost &#x7684;&#x8FC1;&#x79FB;&#x8FC7;&#x7A0B;&#x5F88;&#x987A;&#x5229;&#xFF0C;&#x9700;&#x8981;&#x5907;&#x4EFD;&#x7684;&#x6570;&#x636E;&#x5C31;&#x4E24;&#x6837;&#xFF1A;</p>
<ol>
<li>&#x6587;&#x672C;&#x6570;&#x636E;&#xFF08;&#x76F4;&#x63A5;&#x5728; Ghost &#x540E;&#x53F0; export &#x6253;&#x5305;&#x6210; json &#x5C31;&#x53EF;&#x4EE5;&#x4E86;&#xFF0C;&#x4E0D;&#x9700;&#x8981;&#x53BB;&#x6570;&#x636E;&#x5E93;&#x5907;&#x4EFD;&#xFF09;</li>
<li>&#x56FE;&#x7247;&#xFF08;content/images &#x6253;&#x4E2A;&#x5305;&#xFF09;</li>
</ol>
<h2 id>&#x5177;&#x4F53;&#x8FC7;&#x7A0B;</h2>
<ol>
<li>&#x5BFC;&#x51FA; json</li>
<li>&#x6253;&#x5305;&#x56FE;&#x7247;</li>
<li>&#x4FEE;&#x6539;&#x57DF;&#x540D; DNS &#x6307;&#x5411;&#x65B0;&#x670D;&#x52A1;&#x5668;</li>
<li>&#x65B0;&#x670D;&#x52A1;&#x5668;&#x5B89;&#x88C5; Node&#xFF0C;ghost-cli &#x540E;&#x65B0;&#x5EFA;&#x4E00;&#x4E2A;&#x7AD9;</li>
<li>&#x8FDB;&#x5165;&#x65B0;&#x7AD9;&#x76EE;&#x5F55;&#x89E3;&#x538B;&#x56FE;&#x7247;</li>
<li>&#x8FDB;&#x5165;&#x65B0;&#x7AD9;&#x540E;&#x53F0;&#xFF0C;&#x5BFC;&#x5165; json</li>
<li>&#x4F7F;&#x7528;<code>acme.sh</code>&#x7B7E;&#x65B0;&#x8BC1;&#x4E66;&#xFF08;&#x987A;&#x4FBF;&#x8BD5;&#x8BD5;&#x91CE;&#x5361;&#xFF09;</li>
<li>&#x914D;&#x7F6E; Nginx &#x8BC1;&#x4E66;</li>
<li><code>ghost config</code>&#x5C06;&#x57DF;&#x540D;&#x4FEE;&#x6539;&#x4E3A;<code>https</code></li>
<li>&#x5B8C;&#x6210;</li>
</ol>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[将 Memcached 作为数据库缓存]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>&#x9AD8;&#x6027;&#x80FD;&#x7F13;&#x5B58;&#x6570;&#x636E;&#x5E93;&#x4E00;&#x822C;&#x6211;&#x4EEC;&#x4F7F;&#x7528;&#x7684;&#x6709;&#x4E24;&#x79CD;&#xFF0C;&#x4E00;&#x4E2A;&#x662F; Redis&#xFF0C;&#x4E00;&#x4E2A;&#x5C31;&#x662F; Memcached&#xFF0C;&#x5176;&#x4E2D; Redis &#x652F;&#x6301; 5 &#x79CD;&#x4E0D;&#x540C;&#x7684;&#x6570;&#x636E;&#x7C7B;&#x578B;&#x64CD;&#x4F5C;&#xFF0C;&#x9664;&#x4E86;&#x7F13;</p>]]></description><link>https://ruofeng.me/2018/05/16/basic-usage-of-memcached/</link><guid isPermaLink="false">5d8e378da7d96200019ade19</guid><category><![CDATA[Memcached]]></category><category><![CDATA[MySQL]]></category><category><![CDATA[PHP]]></category><dc:creator><![CDATA[Ruofeng Lei]]></dc:creator><pubDate>Wed, 16 May 2018 08:45:49 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>&#x9AD8;&#x6027;&#x80FD;&#x7F13;&#x5B58;&#x6570;&#x636E;&#x5E93;&#x4E00;&#x822C;&#x6211;&#x4EEC;&#x4F7F;&#x7528;&#x7684;&#x6709;&#x4E24;&#x79CD;&#xFF0C;&#x4E00;&#x4E2A;&#x662F; Redis&#xFF0C;&#x4E00;&#x4E2A;&#x5C31;&#x662F; Memcached&#xFF0C;&#x5176;&#x4E2D; Redis &#x652F;&#x6301; 5 &#x79CD;&#x4E0D;&#x540C;&#x7684;&#x6570;&#x636E;&#x7C7B;&#x578B;&#x64CD;&#x4F5C;&#xFF0C;&#x9664;&#x4E86;&#x7F13;&#x5B58;&#x5916;&#x8FD8;&#x652F;&#x6301;&#x6570;&#x636E;&#x6301;&#x4E45;&#x5316;&#xFF0C;&#x751A;&#x81F3;&#x53EF;&#x4EE5;&#x5F53;&#x4F5C;&#x4E00;&#x4E2A;&#x9AD8;&#x6027;&#x80FD; K-V &#x6570;&#x636E;&#x5E93;&#x6765;&#x4F7F;&#x7528;&#xFF1B;Memcached &#x5219;&#x662F;&#x4E00;&#x4E2A;&#x66F4;&#x52A0;&#x7EAF;&#x7CB9;&#x7684;&#x7F13;&#x5B58;&#xFF0C;&#x53EA;&#x6709; K-V &#x50A8;&#x5B58;&#x7ED3;&#x6784;&#xFF0C;&#x4E0D;&#x652F;&#x6301;&#x6301;&#x4E45;&#x5316;&#xFF0C;&#x4F7F;&#x7528;&#x8D77;&#x6765;&#x4E5F;&#x975E;&#x5E38;&#x7B80;&#x5355;&#x3002;</p>
<p>&#x5728; Memcached <a href="http://memcached.org/about">&#x5B98;&#x7F51;</a> &#x4E2D;&#x662F;&#x8FD9;&#x6837;&#x63CF;&#x8FF0;&#x5B83;&#x7684;&#xFF1A;</p>
<blockquote>
<p>memcached is a high-performance, distributed memory object caching system, generic in nature, but originally intended for use in speeding up dynamic web applications by alleviating database load.</p>
</blockquote>
<h2 id="php">PHP &#x4E2D;&#x7684;&#x4F7F;&#x7528;</h2>
<p>&#x5728; PHP &#x4E2D;&#x4F7F;&#x7528; Memcached &#x6709;&#x4E24;&#x79CD;&#x65B9;&#x5F0F;&#xFF1A;</p>
<ul>
<li><a href="https://secure.php.net/manual/zh/class.memcached.php">memcached</a> &#x4F7F;&#x7528; libmemcached &#x5B9E;&#x73B0;&#xFF0C;&#x652F;&#x6301;&#x64CD;&#x4F5C;&#x591A;&#x6027;&#x80FD;&#x9AD8;</li>
<li><a href="https://secure.php.net/manual/zh/book.memcache.php">memcache</a> &#x4F7F;&#x7528;&#x7EAF; PHP &#x5B9E;&#x73B0;&#xFF0C;&#x6700;&#x521D;&#x7684; PHP &#x64CD;&#x4F5C; memcached &#x6269;&#x5C55;</li>
</ul>
<p>&#x8FD9;&#x91CC;&#x76F4;&#x63A5;&#x4F7F;&#x7528; C &#x8BED;&#x8A00;&#x5B9E;&#x73B0;&#x7684; PHP &#x6269;&#x5C55; php-memcached&#xFF0C;&#x4E3A;&#x4E86;&#x65B9;&#x4FBF;&#x76F4;&#x63A5;&#x53EA;&#x7528;&#x5305;&#x7BA1;&#x7406;&#x5DE5;&#x5177;&#x5B89;&#x88C5;&#xFF1A;</p>
<pre><code class="language-shell">sudo apt install memcached
sudo apt install php-memcached
</code></pre>
<h2 id>&#x4F7F;&#x7528;&#x4E3E;&#x4F8B;</h2>
<p>&#x5728;&#x4E86;&#x89E3;&#x5230; Memcached &#x7684;&#x57FA;&#x672C;&#x4F7F;&#x7528;&#x64CD;&#x4F5C;&#x4E4B;&#x540E;&#xFF0C;&#x6211;&#x5728;&#x4E4B;&#x524D;&#x5199;&#x8FC7;&#x7684;&#x4E00;&#x4E2A;<a href="https://github.com/abowloflrf/url-shortener">&#x77ED;&#x94FE;&#x5B9E;&#x73B0;</a>&#x4E2D;&#x52A0;&#x5165;&#x7684;&#x4E00;&#x5C42;&#x7F13;&#x5B58;&#x7684;&#x64CD;&#x4F5C;&#xFF0C;&#x5728;&#x77ED;&#x94FE;&#x6570;&#x636E;&#x91CF;&#x5DE8;&#x5927;&#x65F6;&#x6BCF;&#x6B21;&#x4ECE;&#x4E00;&#x4E2A;&#x5DE8;&#x5927;&#x7684;&#x8868;&#x4E2D;&#x67E5;&#x8BE2;&#x4E00;&#x6761;&#x77ED;&#x94FE;&#x660E;&#x663E;&#x4F1A;&#x975E;&#x5E38;&#x8017;&#x65F6;&#xFF0C;&#x800C;&#x5728;&#x8FD9;&#x79CD;&#x5178;&#x578B;&#x7684; &#x8BFB;&gt;&gt;&#x5199; &#x7684;&#x64CD;&#x4F5C;&#x4E2D;&#xFF0C;&#x4F7F;&#x7528;&#x7F13;&#x5B58;&#x662F;&#x4E00;&#x4E2A;&#x5F88;&#x4E0D;&#x9519;&#x7684;&#x9009;&#x62E9;&#x3002;</p>
<h3 id>&#x5178;&#x578B;&#x7684;&#x7F13;&#x5B58;&#x4F7F;&#x7528;&#x6D41;&#x7A0B;&#x56FE;</h3>
<p><img src="https://dev.mysql.com/doc/refman/5.6/en/images/memcached-flow.png" alt="flowchart" loading="lazy"></p>
<h3 id="slimframework">&#x5728; Slim Framework &#x4E2D;&#x52A0;&#x5165;&#x4F9D;&#x8D56;</h3>
<p>&#x5728;<code>dependencies.php</code>&#x4E2D;&#x52A0;&#x5165;&#xFF1A;</p>
<pre><code class="language-php">//Memcached
$container[&apos;memcached&apos;] = function ($container) {
    $mc = new Memcached();
    $mc-&gt;addServer(&quot;127.0.0.1&quot;, 11211);
    return $mc;
};
</code></pre>
<h3 id>&#x52A0;&#x5165;&#x7F13;&#x5B58;&#x4F7F;&#x7528;&#x903B;&#x8F91;</h3>
<p>&#x6700;&#x521D;&#x5B9E;&#x73B0;&#x7684;&#x77ED;&#x94FE;&#x63A5;&#x8DF3;&#x8F6C;&#x4E2D;&#xFF0C;&#x662F;&#x5F88;&#x76F4;&#x63A5;&#x7684;&#x8BFB;&#x53D6;&#x5230;&#x8DEF;&#x7531;&#x4E2D;&#x7684;&#x53C2;&#x6570;&#x7136;&#x540E;&#x5C06;&#x8FD9;&#x4E2A;&#x53C2;&#x6570;&#x5728; MySQL &#x4E2D;&#x67E5;&#x8BE2;&#x5BF9;&#x5E94;&#x7684;&#x5B8C;&#x6574;&#x94FE;&#x63A5;&#x8FD4;&#x56DE;&#x7136;&#x540E;&#x8DF3;&#x8F6C;&#xFF0C;&#x73B0;&#x5728;&#x52A0;&#x5165;&#x7F13;&#x5B58;&#x673A;&#x5236;&#x540E;&#xFF0C;&#x9996;&#x5148;&#x662F;&#x5728; Memcached &#x4E2D;&#x67E5;&#x8BE2;&#x77ED;&#x94FE;&#x63A5;&#x5BF9;&#x5E94;&#x7684;&#x7F13;&#x5B58;&#x662F;&#x5426;&#x5B58;&#x5728;&#xFF0C;&#x82E5;&#x5B58;&#x5728;&#x5219;&#x76F4;&#x63A5;&#x8BFB;&#x53D6;&#x6570;&#x636E;&#x5E76;&#x8FD4;&#x56DE;&#x8DF3;&#x8F6C;&#x5373;&#x53EF;&#xFF0C;&#x82E5;&#x4E0D;&#x5B58;&#x5728;&#x5219;&#x5728; MySQL &#x4E2D;&#x67E5;&#x8BE2;&#xFF0C;&#x5F97;&#x5230;&#x5B8C;&#x6574;&#x94FE;&#x63A5;&#x540E;&#xFF0C;&#x5C06;&#x8FD9;&#x6761;&#x8BB0;&#x5F55;&#x79CD;&#x5728; Memcached &#x4E2D;&#xFF0C;&#x518D;&#x8FD4;&#x56DE;&#x54CD;&#x5E94;&#x3002;</p>
<pre><code class="language-php">    //&#x4F7F;&#x7528;Mamcached&#x4F5C;&#x4E3A;&#x7F13;&#x5B58;
    public function redirect(Request $request, Response $response, array $args)
    {
        //&#x77ED;&#x57DF;&#x540D;&#x683C;&#x5F0F;&#x4E0D;&#x5339;&#x914D;&#xFF0C;&#x8FD4;&#x56DE;404
        if (!preg_match(&apos;/^[a-zA-Z0-9]{6}$/&apos;, $args[&apos;url&apos;])) {
            return $response-&gt;withStatus(404)
                -&gt;withHeader(&apos;Content-Type&apos;, &apos;text/html&apos;)
                -&gt;write(&apos;404 Page not found&apos;);
        }
        //&#x4ECE;&#x7F13;&#x5B58;&#x4E2D;&#x67E5;&#x627E;
        $inCache = $this-&gt;mc-&gt;get(&apos;url_&apos; . $args[&apos;url&apos;]);
        if ($inCache) {
            return $response-&gt;withRedirect($inCache, 301);
        } else {
            //&#x4ECE;&#x6570;&#x636E;&#x5E93;&#x4E2D;&#x67E5;&#x8BE2;&#x5B8C;&#x6574;&#x57DF;&#x540D;&#x5E76;&#x8DF3;&#x8F6C;
            $result = $this-&gt;url-&gt;where(&apos;url_short&apos;, $args[&apos;url&apos;])-&gt;first();
            if ($result) {
                //&#x79CD;&#x7F13;&#x5B58;
                $this-&gt;mc-&gt;set(&apos;url_&apos; . $args[&apos;url&apos;], $result-&gt;url_full);
                //&#x8DF3;&#x8F6C;&#x5230;&#x76EE;&#x6807;&#x94FE;&#x63A5;
                return $response-&gt;withRedirect($result-&gt;url_full, 301);
            }
            //&#x672A;&#x67E5;&#x8BE2;&#x5230;&#x57DF;&#x540D;&#x5219;&#x8DF3;&#x8F6C;&#x5230;&#x9996;&#x9875;
            else {
                return $response-&gt;withRedirect(&apos;/&apos;, 301);
            }
        }
    }
</code></pre>
<h2 id>&#x5BF9;&#x6BD4;&#x538B;&#x6D4B;</h2>
<p>&#x6211;&#x540C;&#x65F6;&#x4FDD;&#x7559;&#x4E86;&#x4E00;&#x4E2A;&#x4E0D;&#x8BFB;&#x53D6;&#x7F13;&#x5B58;&#x7684;&#x8DEF;&#x7531;<code>/s/URL_S</code>&#xFF0C;&#x6765;&#x4E0E;&#x52A0;&#x5165;&#x7F13;&#x5B58;&#x540E;&#x8FDB;&#x884C;&#x5BF9;&#x6BD4;&#x6D4B;&#x8BD5;:</p>
<ul>
<li>ab -n1000 <a href="http://127.0.0.1:8080/mN8r9q">http://127.0.0.1:8080/mN8r9q</a></li>
</ul>
<pre><code class="language-plain">Concurrency Level:      1
Time taken for tests:   2.388 seconds
Complete requests:      1000
Failed requests:        0
Non-2xx responses:      1000
Total transferred:      349000 bytes
HTML transferred:       0 bytes
Requests per second:    418.83 [#/sec] (mean)
Time per request:       2.388 [ms] (mean)
Time per request:       2.388 [ms] (mean, across all concurrent requests)
Transfer rate:          142.75 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:     2    2   1.2      2      30
Waiting:        0    2   1.2      2      30
Total:          2    2   1.2      2      30

Percentage of the requests served within a certain time (ms)
  50%      2
  66%      3
  75%      3
  80%      3
  90%      3
  95%      3
  98%      4
  99%      4
 100%     30 (longest request)
</code></pre>
<ul>
<li>ab -n1000 <a href="http://127.0.0.1:8080/s/mN8r9q">http://127.0.0.1:8080/s/mN8r9q</a></li>
</ul>
<pre><code class="language-plain">Concurrency Level:      1
Time taken for tests:   3.537 seconds
Complete requests:      1000
Failed requests:        0
Non-2xx responses:      1000
Total transferred:      349000 bytes
HTML transferred:       0 bytes
Requests per second:    282.73 [#/sec] (mean)
Time per request:       3.537 [ms] (mean)
Time per request:       3.537 [ms] (mean, across all concurrent requests)
Transfer rate:          96.36 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:     2    3  17.9      3     567
Waiting:        2    3  17.7      3     564
Total:          2    4  17.9      3     567

Percentage of the requests served within a certain time (ms)
  50%      3
  66%      3
  75%      3
  80%      3
  90%      3
  95%      4
  98%      4
  99%      5
 100%    567 (longest request)
</code></pre>
<p>&#x6BCF;&#x79D2;&#x8BF7;&#x6C42;&#x5206;&#x522B;&#x4E3A;<strong>418</strong>&#x4E0E;<strong>282</strong>&#xFF0C;&#x4E0D;&#x8FC7;&#x7531;&#x4E8E; MySQL &#x672C;&#x8EAB;&#x5C31;&#x5E94;&#x8BE5;&#x6709;&#x67E5;&#x8BE2;&#x7F13;&#x5B58;&#x7684;&#x673A;&#x5236;&#xFF0C;&#x5DEE;&#x8DDD;&#x53EF;&#x80FD;&#x4E0D;&#x662F;&#x592A;&#x660E;&#x663E;&#xFF0C;&#x4E0D;&#x8FC7;&#x663E;&#x7136;&#x6027;&#x80FD;&#x5DEE;&#x8DDD;&#x8FD8;&#x662F;&#x5728;&#x8FD9;&#x91CC;&#x4F53;&#x73B0;&#x51FA;&#x6765;&#x4E86;&#x3002;</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[MySQL 中的索引结构]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>&#x5728;&#x8C08;&#x8BBA;&#x6570;&#x636E;&#x5E93;&#x4E2D;&#x7684;&#x7D22;&#x5F15;&#x65F6;&#xFF0C;&#x4E00;&#x822C;&#x6240;&#x6307;&#x7684;&#x662F;<strong>B-Tree</strong>&#x7D22;&#x5F15;</p>
<h2 id="btree">B-Tree</h2>
<p><img src="https://upload.wikimedia.org/wikipedia/commons/6/65/B-tree.svg" alt loading="lazy"></p>
<ul>
<li>&#x6B63;&#x6574;&#x6570; d &#x5B9A;&#x4E49;&#x4E3A; B-Tree &#x7684;<strong>&#x5EA6; Degree</strong></li>
<li>&#x4E5F;&#x6709;&#x4E00;&#x4E2A;&#x5B9A;&#x4E49; B-Tree &#x7684;&#x5C5E;&#x6027;&#x79F0;&#x4E3A;<strong>&#x9636; Order</strong>&#xFF0C;&#x5176;&#x503C;</li></ul>]]></description><link>https://ruofeng.me/2018/05/16/index-in-mysql/</link><guid isPermaLink="false">5d8e378da7d96200019ade18</guid><category><![CDATA[MySQL]]></category><category><![CDATA[数据结构]]></category><dc:creator><![CDATA[Ruofeng Lei]]></dc:creator><pubDate>Wed, 16 May 2018 08:10:37 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>&#x5728;&#x8C08;&#x8BBA;&#x6570;&#x636E;&#x5E93;&#x4E2D;&#x7684;&#x7D22;&#x5F15;&#x65F6;&#xFF0C;&#x4E00;&#x822C;&#x6240;&#x6307;&#x7684;&#x662F;<strong>B-Tree</strong>&#x7D22;&#x5F15;</p>
<h2 id="btree">B-Tree</h2>
<p><img src="https://upload.wikimedia.org/wikipedia/commons/6/65/B-tree.svg" alt loading="lazy"></p>
<ul>
<li>&#x6B63;&#x6574;&#x6570; d &#x5B9A;&#x4E49;&#x4E3A; B-Tree &#x7684;<strong>&#x5EA6; Degree</strong></li>
<li>&#x4E5F;&#x6709;&#x4E00;&#x4E2A;&#x5B9A;&#x4E49; B-Tree &#x7684;&#x5C5E;&#x6027;&#x79F0;&#x4E3A;<strong>&#x9636; Order</strong>&#xFF0C;&#x5176;&#x503C;&#x4E3A; 2d</li>
<li>&#x6BCF;&#x4E2A;&#x975E;&#x53F6;&#x5B50;&#x8282;&#x70B9;&#x6709; n-1 &#x4E2A; key &#x4E0E; n &#x4E2A;&#x6307;&#x9488;&#xFF0C;key &#x4E0E;&#x6307;&#x9488;&#x76F8;&#x4E92;&#x95F4;&#x9694;&#xFF0C;key &#x7684;&#x4E24;&#x7AEF;&#x662F;&#x6307;&#x9488;&#xFF0C;d&#x2264;n&#x2264;2d</li>
<li>&#x6BCF;&#x4E2A;&#x53F6;&#x5B50;&#x8282;&#x70B9;&#x81F3;&#x5C11;&#x5305;&#x542B;&#x4E00;&#x4E2A; key &#x548C;&#x4E24;&#x4E2A;&#x6307;&#x9488;&#xFF0C;&#x6700;&#x591A;&#x5305;&#x542B; 2d-1 &#x4E2A; key &#x4E0E; 2d &#x4E2A;&#x6307;&#x9488;&#xFF0C;&#x53F6;&#x5B50;&#x8282;&#x70B9;&#x7684;&#x6307;&#x9488;&#x5747;&#x4E3A; null</li>
<li>&#x6BCF;&#x4E2A;&#x8282;&#x70B9;&#x4E2D; key &#x4ECE;&#x5DE6;&#x81F3;&#x53F3;&#x975E;&#x9012;&#x51CF;&#x6392;&#x5E8F;</li>
<li>&#x6240;&#x6709;&#x53F6;&#x5B50;&#x8282;&#x70B9;&#x7684;&#x6DF1;&#x5EA6;&#x76F8;&#x540C;&#xFF0C;&#x7B49;&#x4E8E;&#x6811;&#x9AD8; h</li>
</ul>
<h3 id="btree">B-Tree &#x7684;&#x68C0;&#x7D22;</h3>
<p><strong>&#x67E5;&#x627E;</strong>&#xFF1A;&#x9996;&#x5148;&#x5728;&#x6839;&#x8282;&#x70B9;<strong>&#x4E8C;&#x5206;&#x67E5;&#x627E;</strong>&#xFF0C;&#x627E;&#x5230;&#x5219;&#x8FD4;&#x56DE;&#x54CD;&#x5E94;&#x8282;&#x70B9;&#x7684;&#x6570;&#x636E;&#xFF0C;&#x672A;&#x627E;&#x5230;&#x5219;&#x5728;<strong>&#x76F8;&#x5E94;&#x533A;&#x95F4;</strong>&#x6307;&#x9488;&#x6307;&#x5411;&#x7684;&#x5B50;&#x8282;&#x70B9;&#x4E2D;<strong>&#x9012;&#x5F52;</strong>&#x4E8C;&#x5206;&#x67E5;&#x627E;&#xFF0C;&#x76F4;&#x5230;&#x67E5;&#x627E;&#x5230;&#x6307;&#x5B9A;&#x7684; key &#x8868;&#x660E;&#x67E5;&#x627E;&#x6210;&#x529F;&#xFF0C;&#x6216;&#x8005;&#x5230; null &#x8868;&#x793A;&#x67E5;&#x627E;&#x5931;&#x8D25;&#x3002;</p>
<p><strong>&#x63D2;&#x5165;</strong>&#xFF1A;&#x6211;&#x4EEC;&#x77E5;&#x9053;&#x5728;&#x4E00;&#x4E2A;&#x5EA6;&#x4E3A; d &#x7684; B-Tree &#x91CC;&#xFF0C;&#x6BCF;&#x4E2A;&#x8282;&#x70B9;&#x6700;&#x591A; 2d &#x4E2A;&#x5B50;&#x8282;&#x70B9;&#xFF0C;&#x540C;&#x65F6;&#x9664;&#x4E86;&#x6839;&#x8282;&#x70B9;&#x548C;&#x53F6;&#x5B50;&#x8282;&#x70B9;&#x6BCF;&#x4E2A;&#x8282;&#x70B9;&#x81F3;&#x5C11;&#x6709; d &#x4E2A;&#x5B50;&#x8282;&#x70B9;&#xFF08;d&#x2264;n&#x2264;2d&#xFF09;&#xFF0C;&#x82E5;&#x6839;&#x8282;&#x70B9;&#x4E0D;&#x662F;&#x53F6;&#x5B50;&#x8282;&#x70B9;&#x5219;&#x81F3;&#x5C11;&#x5E94;&#x8BE5;&#x6709; 2 &#x4E2A;&#x5B50;&#x8282;&#x70B9;&#x3002;&#x8981;&#x5411; B-Tree &#x4E2D;&#x63D2;&#x5165;&#x4E00;&#x4E2A;&#x5143;&#x7D20;&#x65F6;&#xFF0C;&#x9996;&#x5148;&#x4ECE;&#x6839;&#x8282;&#x70B9;&#x67E5;&#x627E;&#x5230;&#x8FD9;&#x4E2A;&#x5143;&#x7D20;&#x5E94;&#x8BE5;&#x4F4D;&#x4E8E;&#x7684;&#x4F4D;&#x7F6E;&#xFF0C;&#x82E5;&#x8FD9;&#x4E2A;&#x8282;&#x70B9;&#x7684;&#x5B50;&#x8282;&#x70B9;&#x6570;&#x5C0F;&#x4E8E;&#x6700;&#x5927;&#x5BB9;&#x91CF;&#xFF0C;&#x5219;&#x53EF;&#x4EE5;&#x76F4;&#x63A5;&#x5C06;&#x8FD9;&#x4E2A;&#x5143;&#x7D20;&#x63D2;&#x5165;&#x5230;&#x5E94;&#x8BE5;&#x7684;&#x4F4D;&#x7F6E;&#xFF1B;&#x82E5;&#x8FD9;&#x4E2A;&#x8282;&#x70B9;&#x7684;&#x5B50;&#x8282;&#x70B9;&#x6570;&#x5DF2;&#x7ECF;&#x5230;&#x4E86;&#x6700;&#x5927;&#x5BB9;&#x91CF;&#xFF0C;&#x5219;&#x5E94;&#x5F53;&#x5C06;&#x5176;&#x63D2;&#x5165;&#x540E;&#x4ECE;&#x4E2D;&#x95F4;&#x4E00;&#x4E2A;&#x5143;&#x7D20;&#x5206;&#x88C2;&#xFF0C;&#x4E2D;&#x95F4;&#x7684;&#x5143;&#x7D20;&#x79FB;&#x52A8;&#x5230;&#x7236;&#x8282;&#x70B9;&#xFF0C;&#x5DE6;&#x8FB9;&#x7684;&#x5143;&#x7D20;&#x7EC4;&#x5408;&#x4F5C;&#x4E3A;&#x5176;&#x5DE6;&#x5B50;&#x8282;&#x70B9;&#xFF0C;&#x53F3;&#x8FB9;&#x7684;&#x5143;&#x7D20;&#x7EC4;&#x5408;&#x4F5C;&#x4E3A;&#x5176;&#x53F3;&#x5B50;&#x8282;&#x70B9;&#x3002;&#x540C;&#x6837;&#x5730;&#xFF0C;&#x82E5;&#x7236;&#x8282;&#x70B9;&#x4E5F;&#x6EE1;&#xFF0C;&#x5219;&#x6309;&#x7167;&#x540C;&#x6837;&#x7684;&#x5206;&#x88C2;&#x65B9;&#x5F0F;&#x7EE7;&#x7EED;&#x5411;&#x4E0A;&#x5206;&#x88C2;&#x3002;&#x82E5;&#x5230;&#x4E86;&#x6839;&#x8282;&#x70B9;&#x53D1;&#x73B0;&#x6839;&#x8282;&#x70B9;&#x4E5F;&#x6EE1;&#x4E86;&#xFF0C;&#x5219;&#x5C06;&#x6839;&#x8282;&#x70B9;&#x4E5F;&#x5206;&#x88C2;&#xFF0C;&#x4E2D;&#x95F4;&#x5143;&#x7D20;&#x4F5C;&#x4E3A;&#x9876;&#x90E8;&#x4E00;&#x4E2A;&#x65B0;&#x7684;&#x6839;&#x8282;&#x70B9;&#x3002;</p>
<p><strong>&#x5220;&#x9664;</strong>&#xFF1A;&#x5728; B-Tree &#x4E2D;&#x5220;&#x9664;&#x4E00;&#x4E2A;&#x5143;&#x7D20;&#x65F6;&#xFF0C;&#x9996;&#x5148;&#x540C;&#x6837;&#x5730;&#x5728;&#x6811;&#x4E2D;&#x67E5;&#x627E;&#x5230;&#x76EE;&#x6807;&#x5143;&#x7D20;&#xFF0C;&#x7136;&#x540E;&#x5C06;&#x5176;&#x5220;&#x9664;&#xFF0C;&#x4F46;&#x662F;&#x7531;&#x4E8E; B-Tree &#x7684;&#x9650;&#x5236;&#xFF1A;&#x9664;&#x4E86;&#x6839;&#x8282;&#x70B9;&#x4E0E;&#x53F6;&#x5B50;&#x8282;&#x70B9;&#x6BCF;&#x4E2A;&#x8282;&#x70B9;&#x81F3;&#x5C11;&#x6709; d &#x4E2A;&#x5B50;&#x8282;&#x70B9;&#xFF0C;&#x6839;&#x8282;&#x70B9;&#x81F3;&#x5C11;&#x6709; 2 &#x4E2A;&#x5B50;&#x8282;&#x70B9;&#x3002;&#x6240;&#x4EE5;&#x5220;&#x9664;&#x540E;&#x82E5;&#x4E0D;&#x6EE1;&#x8DB3;&#x8FD9;&#x4E2A;&#x6761;&#x4EF6;&#x5373; key &#x8FC7;&#x5C11;&#xFF0C;&#x5219;&#x5E94;&#x9996;&#x5148;&#x4ECE;&#x5B50;&#x8282;&#x70B9;&#x53D6;&#x4E00;&#x4E2A;&#x5143;&#x7D20;&#xFF0C;&#x82E5;&#x5B50;&#x8282;&#x70B9;&#x65E0;&#x6CD5;&#x53D6;&#xFF0C;&#x5219;&#x5411;&#x7236;&#x8282;&#x70B9;&#x53D6;&#xFF0C;&#x7136;&#x540E;&#x518D;&#x5C06;&#x5B50;&#x8282;&#x70B9;&#x4E2D;&#x7684;&#x4E2D;&#x95F4;&#x503C;&#x66FF;&#x6362;&#x5230;&#x539F;&#x6765;&#x7236;&#x8282;&#x70B9;&#x5143;&#x7D20;&#x7684;&#x4F4D;&#x7F6E;&#x3002;</p>
<h3 id="btree">B+Tree</h3>
<p>&#x4E0E; B-Tree &#x76F8;&#x6BD4;&#xFF0C;B+Tree &#x7D22;&#x5F15;&#x6709;&#x4EE5;&#x4E0B;&#x7279;&#x70B9;</p>
<ul>
<li>&#x975E;&#x53F6;&#x5B50;&#x8282;&#x70B9;&#x53EA;&#x4FDD;&#x5B58; key &#x800C;&#x4E0D;&#x4FDD;&#x5B58; data</li>
<li>&#x53F6;&#x5B50;&#x8282;&#x70B9;&#x53EA;&#x4FDD;&#x5B58; data</li>
<li>B+Tree &#x7684;&#x975E;&#x53F6;&#x5B50;&#x8282;&#x70B9;&#x53EA;&#x8FDB;&#x884C;&#x7D22;&#x5F15;&#x4E0D;&#x4F1A;&#x4FDD;&#x5B58;&#x5B9E;&#x9645;&#x8BB0;&#x5F55;&#x7684;&#x6307;&#x9488;&#xFF0C;&#x6240;&#x6709;&#x6570;&#x636E;&#x5FC5;&#x987B;&#x8981;&#x8BBF;&#x95EE;&#x5230;&#x53F6;&#x5B50;&#x8282;&#x70B9;&#x624D;&#x80FD;&#x5F97;&#x5230;</li>
<li>B+Tree &#x7684;&#x6839;&#x8282;&#x70B9;&#x7684; Key &#x6570;&#x4E0E;&#x5B50;&#x8282;&#x70B9;&#x6570;&#x76F8;&#x7B49;</li>
<li>&#x4E00;&#x822C;&#x4F1A;&#x5C06; B+Tree &#x8FDB;&#x884C;&#x4F18;&#x5316;&#xFF1A;&#x5728;&#x53F6;&#x5B50;&#x8282;&#x70B9;&#x65B0;&#x589E;&#x4E86;&#x4E00;&#x4E2A;&#x987A;&#x5E8F;&#x8BBF;&#x95EE;&#x7684;&#x6307;&#x9488;&#xFF0C;&#x65B9;&#x4FBF;&#x5BF9;&#x6240;&#x6709;&#x7684;&#x53F6;&#x5B50;&#x8282;&#x70B9;&#x8FDB;&#x884C;&#x904D;&#x5386;&#xFF0C;&#x63D0;&#x9AD8;&#x533A;&#x95F4;&#x8BBF;&#x95EE;&#x7684;&#x6027;&#x80FD;</li>
</ul>
<p><img src="https://raw.githubusercontent.com/CyC2018/Interview-Notebook/master/pics/1ee5f0a5-b8df-43b9-95ab-c516c54ec797.jpg" alt loading="lazy"></p>
<h2 id="btreemysql">B-Tree &#x5728; MySQL &#x7684;&#x7D22;&#x5F15;&#x4E2D;&#x7684;&#x5B9E;&#x73B0;</h2>
<p>&#x6709;&#x8FD9;&#x6837;&#x4E00;&#x4E2A;&#x6570;&#x636E;&#x8868;&#xFF1A;</p>
<pre><code class="language-sql">CRETE TABLE People(
    last_name varchar(50) not null,
    first_name varchar(50) not null,
    dob date not null,
    gender enum(&apos;m&apos;,&apos;f&apos;) not null,
    key(last_name, first_name, dob)
);
</code></pre>
<p>&#x5BF9;&#x4E8E;&#x8FD9;&#x4E2A;&#x8868;&#x4E2D;&#x7684;&#x6BCF;&#x4E00;&#x884C;&#x6570;&#x636E;&#xFF0C;&#x7D22;&#x5F15;&#x4E2D;&#x5305;&#x542B;&#x4E86; <code>last_name</code> , <code>first_name</code> , <code>dob</code> &#x5217;&#x7684;&#x503C;</p>
<p><img src="https://www.notion.so/file/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fca3bdae5-aac8-4c6d-a5af-0ab8fbf63fd0%2FUntitled" alt loading="lazy"></p>
<p>&#x5982;&#x56FE;&#x6240;&#x793A;&#xFF0C;&#x7D22;&#x5F15;&#x5BF9;&#x591A;&#x4E2A;&#x503C;&#x6392;&#x5E8F;&#x7684;&#x4F9D;&#x636E;&#x662F; create &#x8BED;&#x53E5;&#x4E2D;&#x5B9A;&#x4E49;&#x7D22;&#x5F15;&#x65F6;&#x7684;&#x987A;&#x5E8F;&#xFF0C;&#x5982;&#x8FD9;&#x4E2A;&#x8868;&#x4E2D;&#x4E24;&#x4E2A;&#x4EBA;&#x7684;&#x59D3;&#x540D;&#x5747;&#x4E00;&#x6837;&#xFF0C;&#x5219;&#x6309;&#x7167;&#x5176;&#x751F;&#x65E5;&#x6765;&#x6392;&#x5E8F;&#x3002;</p>
<h3 id="btree">&#x53EF;&#x4EE5;&#x4F7F;&#x7528; B-Tree &#x7D22;&#x5F15;&#x7684;&#x67E5;&#x8BE2;&#x7C7B;&#x578B;</h3>
<ul>
<li>&#x5168;&#x503C;&#x5339;&#x914D;</li>
<li>&#x5339;&#x914D;&#x6700;&#x5DE6;&#x524D;&#x7F00;</li>
<li>&#x5339;&#x914D;&#x5217;&#x524D;&#x7F00;</li>
<li>&#x5339;&#x914D;&#x8303;&#x56F4;&#x503C;</li>
<li>&#x7CBE;&#x786E;&#x5339;&#x914D;&#x67D0;&#x4E00;&#x5217;&#x5E76;&#x8303;&#x56F4;&#x5339;&#x914D;&#x53E6;&#x4E00;&#x5217;</li>
<li>&#x53EA;&#x8BBF;&#x95EE;&#x7D22;&#x5F15;&#x7684;&#x67E5;&#x8BE2;</li>
</ul>
<h3 id="btree">&#x4F7F;&#x7528; B-Tree &#x7D22;&#x5F15;&#x7684;&#x4E00;&#x4E9B;&#x9650;&#x5236;</h3>
<ul>
<li>&#x5982;&#x679C;&#x4E0D;&#x662F;&#x6309;&#x7167;&#x7D22;&#x5F15;&#x7684;&#x6700;&#x5DE6;&#x5217;&#x5F00;&#x59CB;&#x67E5;&#x627E;&#x5219;&#x65E0;&#x6CD5;&#x4F7F;&#x7528;&#x7D22;&#x5F15;&#xFF0C;&#x4F8B;&#x5982;&#x4E0A;&#x9762;&#x4F8B;&#x5B50;&#x4E2D;&#x65E0;&#x6CD5;&#x67E5;&#x627E;&#x540D;&#x4E3A; Bill &#x7684;&#x4EBA;&#xFF0C;&#x4E5F;&#x65E0;&#x6CD5;&#x67E5;&#x627E;&#x7279;&#x5B9A;&#x751F;&#x65E5;&#x7684;&#x4EBA;</li>
<li>&#x4E0D;&#x80FD;&#x8DF3;&#x8FC7;&#x7D22;&#x5F15;&#x4E2D;&#x7684;&#x5217;&#xFF0C;&#x4E0A;&#x4F8B;&#x4E2D;&#x7D22;&#x5F15;&#x65E0;&#x6CD5;&#x7528;&#x4E8E;&#x67E5;&#x627E;&#x67D0;&#x786E;&#x5B9A;&#x59D3;&#x6C0F;&#xFF0C;&#x540C;&#x65F6;&#x53C8;&#x662F;&#x67D0;&#x65E5;&#x751F;&#x65E5;&#x7684;&#x4EBA;&#xFF0C;&#x56E0;&#x4E3A;&#x5176;&#x8DF3;&#x8FC7;&#x4E86;&#x4E2D;&#x95F4;&#x4E00;&#x5217;</li>
<li>&#x5982;&#x679C;&#x67E5;&#x8BE2;&#x4E2D;&#x6709;&#x67D0;&#x4E2A;&#x5217;&#x7684;&#x8303;&#x56F4;&#x67E5;&#x8BE2;&#xFF0C;&#x5219;&#x5176;&#x53F3;&#x8FB9;&#x7684;&#x5217;&#x90FD;&#x65E0;&#x6CD5;&#x4F7F;&#x7528;&#x7D22;&#x5F15;&#x4F18;&#x5316;&#x67E5;&#x627E;</li>
</ul>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>