其他疑難排解步 - Amazon ElastiCache (雷迪OSS斯)

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

其他疑難排解步

疑難排解持續連線問題時,必須驗證下列項目 ElastiCache:

安全群組

安全群組是保護 ElastiCache 用戶端 (EC2 執行個體、 AWS Lambda 函數、Amazon ECS 容器等) 和 ElastiCache 快取的虛擬防火牆。安全群組具有狀態,這表示允許傳入或傳出流量之後,該流量的回應將在該特定安全群組的內容中自動授權。

具狀態功能需要安全群組追蹤所有授權的連線,而且追蹤的連線數有限額。如果達到限額,新的連線將會失敗。請參閱故障排除部分,以獲取有關如何識別用戶端或 ElastiCache 端限制是否已達到的幫助。

您可以同時將單一安全群組指派給用戶端和 ElastiCache 叢集,也可以指派給每個群組的個別安全群組。

對於這兩種情況,您都必須允許來自來源的 ElastiCache 連接埠上的 TCP 輸出流量,以及相同連接埠上的輸入流量允許到 ElastiCache。記憶體快取的預設連接埠為 11211,而 Redis 的 OSS 則為 6379。根據預設,安全群組允許所有對外流量。在此情況下,只需要目標安全群組中的傳入規則。

如需詳細資訊,請參閱在 Amazon VPC 中存取 ElastiCache 叢集的存取模式

網路 ACL

網路存取控制清單 (ACL) 是無狀態規則。必須允許雙向 (傳入和傳出) 的流量才能成功。網路 ACL 會指派給子網路,而非特定資源。您可以將相同的 ACL 指派給 ElastiCache 和用戶端資源,特別是當它們位於相同的子網路時。

根據預設,網路 ACL 允許所有流量。不過,您可以自訂為拒絕或允許流量。此外,ACL 規則的評估會依序進行,這表示符合流量的數字最小規則將會予以允許或拒絕。允許 Redis OSS 流量的最低設定為:

用戶端網路 ACL:

  • 傳入規則:

  • Rule number (規則編號):最好低於任何拒絕規則;

  • Type (類型):Custom TCP Rule (自訂 TCP 規則);

  • Protocol (通訊協定):TCP

  • Port Range (連接埠範圍):1024-65535

  • 來源:0.0.0.0/0(或為叢集子網路建立個別規則) ElastiCache

  • Allow/Deny (允許/拒絕):Allow (允許)

  • 傳出規則:

  • Rule number (規則編號):最好低於任何拒絕規則;

  • Type (類型):Custom TCP Rule (自訂 TCP 規則);

  • Protocol (通訊協定):TCP

  • Port Range (連接埠範圍):6379

  • 資料來源:0.0.0.0/0 (或叢集子網路。 ElastiCache 請記住,在容錯移轉或擴展叢集的情況下,使用特定 IP 可能會產生問題)

  • Allow/Deny (允許/拒絕):Allow (允許)

ElastiCache 網路 ACL:

  • 傳入規則:

  • Rule number (規則編號):最好低於任何拒絕規則;

  • Type (類型):Custom TCP Rule (自訂 TCP 規則);

  • Protocol (通訊協定):TCP

  • Port Range (連接埠範圍):6379

  • 來源:0.0.0.0/0(或為叢集子網路建立個別規則) ElastiCache

  • Allow/Deny (允許/拒絕):Allow (允許)

  • 傳出規則:

  • Rule number (規則編號):最好低於任何拒絕規則;

  • Type (類型):Custom TCP Rule (自訂 TCP 規則);

  • Protocol (通訊協定):TCP

  • Port Range (連接埠範圍):1024-65535

  • 資料來源:0.0.0.0/0 (或叢集子網路。 ElastiCache 請記住,在容錯移轉或擴展叢集的情況下,使用特定 IP 可能會產生問題)

  • Allow/Deny (允許/拒絕):Allow (允許)

如需詳細資訊,請參閱網路 ACL

路由表

類似於網路 ACL,每個子網路也可以有不同的路由表。如果用戶端和 ElastiCache 叢集位於不同的子網路中,請確定其路由表允許它們互相連接。

較複雜的環境 (涉及多個 VPC、動態路由或網路防火牆) 可能會變得難以疑難排解。請參閱 網路連線能力驗證,確認您的網路設定是否適當。

DNS 解析

ElastiCache 根據 DNS 名稱提供服務端點。可用的端點為 ConfigurationPrimaryReaderNode 端點。如需詳細資訊,請參閱 尋找連線端點

在修改容錯移轉或叢集的情況下,與端點名稱相關聯的地址可能會變更且會自動更新。

自訂 DNS 設定 (即不使用 VPC DNS 服務) 可能不知道 ElastiCache提供的 DNS 名稱。確保您的系統可以使用系統工具dig(如下所示)或成功解析 ElastiCache 端點nslookup

$ dig +short example.xxxxxx.ng.0001.use1.cache.amazonaws.com example-001.xxxxxx.0001.use1.cache.amazonaws.com. 1.2.3.4

您也可以透過 VPC DNS 服務強制執行名稱解析:

$ dig +short example.xxxxxx.ng.0001.use1.cache.amazonaws.com @169.254.169.253 example-001.tihewd.0001.use1.cache.amazonaws.com. 1.2.3.4

透過伺服器端診斷識別問題

CloudWatch 來自 ElastiCache 引擎的指標和執行階段資訊是識別潛在連線問題來源的常見來源或資訊。優質的分析資料通常從下列項目開始:

  • CPU 使用率:Redis 的 OSS 是一個多執行緒應用程式。但是每個命令的執行發生在單個 (主) 執行序中。基於這個原因,請 ElastiCache 提供指標CPUUtilizationEngineCPUUtilization. EngineCPUUtilization提供 Redis OSS 處理序專用的 CPU 使用率,以及所有 vCPUs CPUUtilization 的使用率。具有多個 vCPU 的節點的 CPUUtilizationEngineCPUUtilization 值一般會不同,後者通常較高。出現高 EngineCPUUtilization,可能是由於需要大量 CPU 時間才能完成的請求或複雜作業數量增加所造成。您可以透過以下項目來識別兩者:

    • 請求數增加:檢查其他符合 EngineCPUUtilization 模式的指標是否增加。有用的指標包括:

      • CacheHitsCacheMisses:成功請求或沒有在快取中找到有效項目的請求之數目。如果未命中與命中的比率很高,表示應用程式正在對無效果的請求浪費時間和資源。

      • SetTypeCmdsGetTypeCmds:這些指標與 EngineCPUUtilization 相關,有助於了解寫入請求 (由 SetTypeCmds 測量) 或讀取請求 (由 GetTypeCmds 測量) 的負載是否明顯高。如果負載主要是讀取作業,使用多個僅供讀取複本可以在多個節點之間平衡請求,並撥出主節點用於寫入作業。在停用叢集模式的叢集中,可以使用讀取器端點在應用程式中建立額外的連線組態來完成僅供讀取複本的使用。 ElastiCache 如需詳細資訊,請參閱 尋找連線端點。讀取作業必須提交至這個額外的連線。寫入作業將透過一般主要端點完成。在啟用叢集模式的情況下,建議您使用原生支援僅供讀取複本的程式庫。使用正確的旗標,程式庫將能夠自動探索叢集拓撲、複本節點、透過 READON LY Redis OSS 命令啟用讀取作業,以及將讀取要求提交給複本。

    • 連線數增加:

      • CurrConnectionsNewConnectionsCurrConnection 是收集資料點時的已建立連線數,而 NewConnections 會顯示這段期間內建立的連線數。

        建立和處理連線意味著可觀的 CPU 額外負荷。此外,成立新連線所需的 TCP 三向交握會對整體回應時間產生負面影響。

        NewConnections每分鐘數千個 ElastiCache 節點表示連接僅由幾個命令創建和使用,這是不是最佳的。保持連線的成立狀態,並重複使用這些連線來進行新作業是最佳實務。當用戶端應用程式支援並妥善實作連線集區或持續連線時,此情況有可能實現。使用連線集區時,currConnections 數不會有很大的變化,而 NewConnections 應盡可能壓低。Redis 的 OSS 提供了最佳的性能與少量的 CURR連接。讓 CurrConnection 數量維持在大約數十或數百個,可最大限度壓低資源的使用量,以支援個別連線,例如供連線使用的用戶端緩衝區和 CPU 週期。

    • 網路輸送量:

      • 判斷頻寬: ElastiCache 節點的網路頻寬與節點大小成比例。由於應用程式具有不同的特性,結果可能會根據工作負載而有所不同。舉例來說,小型請求率高的應用程式,對 CPU 使用率造成的影響往往高於網路輸送量,而索引鍵較大則會造成網路使用率較高。因此,建議您使用實際工作負載來測試節點,以便更深入了解限制。

        模擬來自應用程式的負載會提供更準確的結果。但是,基準化分析工具可讓您更妥善了解限制。

      • 針對請求主要都是讀取的情況,使用複本進行讀取作業將能減輕主節點上的負載。如果使用案例主要是寫入,則使用許多複本將會提高網路使用量。針對寫入主節點的每個位元組,系統會將 N 個位元組傳送到複本 (N 即複本的數量)。寫入密集型工作負載的最佳做法是在啟用叢集模式的情況下使用 ElastiCache (Redis OSS),因此可以在多個碎片之間平衡寫入,或擴展為具有更多網路功能的節點類型。

      • CloudWatchmetrics NetworkBytesIn並分別NetworkBytesOut提供進入或離開節點的資料量。 ReplicationBytes是專用於資料複製的流量。

      如需詳細資訊,請參閱 網路相關限制

    • 複雜的命令:Redis OSS 命令在單個線程上提供,這意味著請求按順序提供。單一緩慢命令可能會影響其他請求和連線,最終導致逾時。使用作用於多個值、索引鍵或資料類型的命令時必須小心。根據參數的數量或其輸入或輸出值的大小,可能會封鎖或終止連線。

      一個惡名昭彰的例子是 KEYS 命令。它會掃描整個 Keyspace,搜尋指定的模式,並在其執行過程中阻止其他命令的執行。Redis 的 OSS 使用「大 O」表示法來描述其命令的複雜性。

      索引鍵命令帶有 O(N) 時間複雜度,N 是資料庫中索引鍵的數量。因此,索引鍵數越多,命令執行速度就會越慢。KEYS 可能會以不同的方式造成問題:如果沒有使用搜尋模式,該命令將會傳回所有可用的索引鍵名稱。在具有數千個或數百萬個項目的資料庫中,系統會建立巨大的輸出並淹沒網路緩衝區。

      如果使用搜尋模式,則只會將符合該模式的索引鍵傳回用戶端。但是,引擎仍然會掃描整個 Keyspace 搜尋它,且完成命令的時間相同。

      KEYS 的替代方案是 SCAN 命令。它會反覆運算 Keyspace,限制在特定數量的項目中執行反覆運算,避免延長引擎上區塊的執行時間。

      掃描具有 COUNT 參數,用來設定反覆運算區塊的大小。預設值為 10 (每個反覆運算 10 個項目)。

      根據資料庫中項目數的不同,COUNT 值小的區塊需執行更多的反覆運算才能完成完整掃描,而較大的值每次反覆運算時會讓引擎維持忙碌狀態更久。小計數值會使 SCAN 執行速度較慢,而較大的值可能會對 KEYS 造成上述相同問題。

      範例是以計數值 10 執行 SCAN 命令,將需要在具有 1 百萬個索引鍵的資料庫上進行 100,000 次重複作業。如果平均網路封包來回時間為 0.5 毫秒,則傳輸請求會花費大約 50,000 毫秒 (50 秒)。

      另一方面,如果計數值為 100,0000,則需要執行單次反覆運算,且傳輸只會花 0.5 毫秒。不過,引擎會完全封鎖其他作業,直到該命令完成掃描所有的 Keyspace。

      除了 KEYS 以外,如果未正確使用,其他幾個命令可能有害。若要查看所有命令及其各自時間複雜度的清單,請前往 https://redis.io/commands

      潛在問題範例:

      • Lua 腳本:Redis 的 OSS 提供了一個嵌入式 Lua 解釋器,允許在服務器端執行腳本。Redis OSS 上的 Lua 指令碼會在引擎層級執行,並且根據定義是原子的,這表示在執行指令碼時不允許執行其他命令或指令碼。Lua 指令碼提供直接在 Redis OSS 引擎上執行多個命令、決策演算法、資料剖析和其他指令的可能性。雖然這類指令碼的不可部分完成特性和卸載應用程式的機會很誘人,但將指令碼用於小型作業時必須小心。開啟時 ElastiCache,Lua 指令碼的執行時間限制為 5 秒。未寫入 Keyspace 的指令碼將在 5 秒過後自動終止。為了避免資料損毀和不一致,如果指令碼執行沒有在 5 秒內完成,且執行期間有任何寫入,節點便會容錯移轉。交易是保證 Redis OSS 中多個相關金鑰修改一致性的替代方案。交易允許執行一個命令區塊,觀察現有的索引鍵修改項目。如果觀察的任何索引鍵在交易完成之前有所變更,系統會捨棄所有修改。

      • 大量刪除項目:DEL 命令接受多個參數,這些參數是要刪除的索引鍵名稱。刪除作業會同步進行,如果參數清單很大,或是包含大型清單、集合、排序集合或雜湊 (包含多個子項目的資料結構),則需花費大量的 CPU 時間。換句話說,如果單一索引鍵有許多元素,即使只是刪除單一索引鍵,也可能需要花相當長的時間。的替代方法DELUNLINK,這是自 Redis OSS 4 以來可用的異步命令。 UNLINK必須DEL盡可能優先。從 ElastiCache (Redis OSS) 6x 開始,該lazyfree-lazy-user-del參數會使DEL命令的行為與啟用時的行為相同UNLINK。如需詳細資訊,請參閱 Redis OSS 6.0 參數變更。

      • 對多個索引鍵上產生作用的命令:先前提到的 DEL 是接受多個參數的命令,且其執行時間將直接與此成正比。但是,Redis 的 OSS 提供了許多類似工作的命令。範例為 MSETMGET 允許一次插入或檢索多個字串索引鍵。使用它們可能有助於減少許多個別 SETGET 命令的固有網路延遲。不過,廣泛的參數清單會影響 CPU 使用率。

        雖然單獨 CPU 使用率並不是連線問題的原因,但花太多時間對多個索引鍵處理單一或幾個命令,可能會造成其他請求失敗,並增加整體 CPU 使用率。

        索引鍵的數量和大小會影響命令的複雜性,進而影響完成時間。

        可以作用於多個索引鍵的其他命令範例有:HMGETHMSETMSETNXPFCOUNTPFMERGESDIFFSDIFFSTORESINTERSINTERSTORESUNIONSUNIONSTORETOUCHZDIFFZDIFFSTOREZINTERZINTERSTORE

      • 根據多種資料類型作用的命令:Redis OSS 也提供針對一個或多個索引鍵作用的命令,而不論其資料類型為何。 ElastiCache (Redis OSS) 提供了用於監視此類命令的指KeyBasedCmds標。此指標會加總在所選期間內執行下列命令的次數:

        • O(N) 複雜性:

          • KEYS

        • O(1)

          • EXISTS

          • OBJECT

          • PTTL

          • RANDOMKEY

          • TTL

          • TYPE

          • EXPIRE

          • EXPIREAT

          • MOVE

          • PERSIST

          • PEXPIRE

          • PEXPIREAT

          • UNLINK (O(N) 用於回收記憶體。但是,記憶體回收任務發生在單獨一個執行序中,且不會阻止引擎

        • 根據資料類型而不同的複雜性時間:

          • DEL

          • DUMP

          • RENAME 視為具有 O(1) 複雜性的命令,但在 DEL 內部執行。執行時間會依重新命名索引鍵的大小而變動。

          • RENAMENX

          • RESTORE

          • SORT

        • 大雜湊:雜湊是一種資料類型,允許單個索引鍵具有多個鍵值子項目。每個雜湊都可以存放 4.294.967.295 個項目,且大雜湊上的作業可能會變得非常昂貴。與 KEYS 類似,雜湊具有帶有 O(N) 時間複雜度的 HKEYS 命令,N 是雜湊中的項目數。HSCAN 必須優先於 HKEYS 以避免長時間執行命令。HDELHGETALLHMGETHMSETHVALS 命令應在大雜湊上謹慎使用。

      • 其他大數據結構:除了雜湊之外,其他資料結構可能是 CPU 密集型。集合、清單、排序集合和 Hyperloglog 也可能需要花大量時間來操作,取決於其大小和使用的命令。如需這些命令的詳細資訊,請參閱 https://redis.io/commands

網路連線能力驗證

檢閱與 DNS 解析、安全群組、網路 ACL 和路由表相關的網路組態之後,可以使用 VPC Reachability Analyzer 和系統工具來驗證連線。

Reachability Analyzer 會測試網路連線能力,並確認是否滿足所有的需求和許可。對於以下測試,您將需要 VPC 中其中一個可用 ElastiCache 節點的 ENI ID(彈性網路介面識別)。若要取得此資料,請執行下列操作:

  1. 前往 https://console.aws.amazon.com/ec2/v2/home?#NIC:

  2. 依 ElastiCache 叢集名稱或先前從 DNS 驗證取得的 IP 位址篩選介面清單。

  3. 寫下或以其他方式儲存 ENI ID。如果顯示多個介面,請檢閱說明以確認它們屬於正確的 ElastiCache 叢集,然後選擇其中一個介面。

  4. 繼續下一個步驟。

  5. https://console.aws.amazon.com/vpc/home? # 建立分析路徑,ReachabilityAnalyzer然後選擇下列選項:

    • 來源類型 :如果您的用 ElastiCache 戶端在 Amazon EC2 執行個體上執行,請選擇執行個體,如果它使用其他服務 (例如具有 awsvpc 網路的 AWS Fargate Amazon ECS 等),以及相應的資源 ID (EC2 執行個體或 ENI ID); AWS Lambda

    • Destination Type (目的地類型):選擇 Network Interface (網路介面),然後從清單中選取 ElastiCache ENI

    • 目標連接埠:為 ElastiCache (Redis OSS) 指定 6379,或為 (記憶體快取) 指定 11211。 ElastiCache 這些是使用預設組態定義的連接埠,此範例假設未加以變更。

    • Protocol (通訊協定):TCP

建立分析路徑,並等待一段時間產生結果。如果狀態為無法連線,請開啟分析詳細資料並檢閱分析總管,取得遭封鎖請求的詳細資訊。

如果通過可連線性測試,請繼續執行作業系統層級的驗證。

若要驗證 ElastiCache 服務連接埠上的 TCP 連線:在 Amazon Linux 上,Nping可在套件中使用nmap,可以測試連接 ElastiCache 埠上的 TCP 連線,以及提供建立連線的網路往返時間。使用此選項可驗證 ElastiCache 叢集的網路連線能力和目前的延遲,如下所示:

$ sudo nping --tcp -p 6379 example.xxxxxx.ng.0001.use1.cache.amazonaws.com Starting Nping 0.6.40 ( http://nmap.org/nping ) at 2020-12-30 16:48 UTC SENT (0.0495s) TCP ... (Output suppressed ) Max rtt: 0.937ms | Min rtt: 0.318ms | Avg rtt: 0.449ms Raw packets sent: 5 (200B) | Rcvd: 5 (220B) | Lost: 0 (0.00%) Nping done: 1 IP address pinged in 4.08 seconds

根據預設,nping 每傳送 5 次探查會延遲 1 秒。您可以使用「-c」選項來增加探查數,並使用「--delay」來變更傳送新測試的時間。

如果測試出現 nping 失敗,且通過了 VPC Reachability Analyzer 測試,請您的系統管理員檢閱可能的主機式防火牆規則、非對稱式路由規則,或是作業系統層級任何其他可能的限制。

在 ElastiCache 主控台上,檢查 ElastiCache 叢集詳細資料中是否已啟用傳輸中加密。如果已啟用傳輸中加密,請確認是否可以使用下列命令建立 TLS 工作階段:

openssl s_client -connect example.xxxxxx.use1.cache.amazonaws.com:6379

如果連線和 TLS 交涉成功,預期會有密集的傳出。檢查最後一行中可用的傳回碼,該值必須是 0 (ok)。如果 openssl 傳回不同的內容,請前往以下頁面查看錯誤原因:https://www.openssl.org/docs/man1.0.2/man1/verify.html#DIAGNOSTICS

如果所有基礎結構和作業系統測試都通過,但您的應用程式仍無法連線 ElastiCache,請檢查應用程式組態是否符合 ElastiCache 設定。常見的錯誤包括:

  • 您的應用程序不支持 ElastiCache 集群模式,並啟用 ElastiCache 了集群模式;

  • 您的應用程式不支援 TLS/SSL,且 ElastiCache 已啟用傳輸中加密功能;

  • 應用程式支援 TLS/SSL,但沒有正確的組態標記或信任的憑證授權機構;

網路相關限制

  • 連線數上限:同時連線數具有硬性限制。每個 ElastiCache 節點允許在所有用戶端之間同時連線達 65,000 個。您可以透過上的CurrConnections測量結果監視此限制 CloudWatch。不過,用戶端也有自己的傳出連線限制。在 Linux 上,請使用下列命令檢查允許的暫時性連接埠範圍:

    # sysctl net.ipv4.ip_local_port_range net.ipv4.ip_local_port_range = 32768 60999

    在前面的範例中,將允許 28231 從相同來源連線到相同目的地 IP (ElastiCache 節點) 和連接埠。下列指令顯示特定 ElastiCache 節點存在多少連線 (IP 1.2.3.4):

    ss --numeric --tcp state connected "dst 1.2.3.4 and dport == 6379" | grep -vE '^State' | wc -l

    如果數字太高,您的系統可能會因為嘗試處理連線請求而過載。建議考慮實作適用技術,例如連線集區或持續連線,以便更妥善處理連線。盡可能設定連線集區,將連線數上限限制為幾百個。此外,用於處理逾時或其他連線例外狀況的退避邏輯是明智的做法,可避免發生問題的情況下連線流失。

  • 網路流量限制:檢查 Redis OSS 的下列CloudWatch 指標,以識別節點上可能達到的網路限制: ElastiCache

    • NetworkBandwidthInAllowanceExceeded/NetworkBandwidthOutAllowanceExceeded:因為輸送量超過彙總頻寬限制而形成的網路封包。

      請務必注意,寫入主節點的每個位元組都會複寫到 N 個複本 (N 是複本數)。具有小型節點類型、多個複本以及密集寫入型請求的叢集,可能無法處理複寫待處理項目。對於這種情況,最佳實務是擴充規模 (更改節點類型)、水平擴展 (在啟用叢集模式的叢集中增加碎片),減少複本數或最大限度減少寫入次數。

    • NetworkConntrackAllowanceExceeded:因為超過指派給節點的連線數 (在所有安全群組之間追蹤) 上限而形成的封包。這段期間內,新的連線可能會失敗。

    • NetworkPackets PerSecondAllowanceExceeded:超過每秒的封包數上限。以高極小型請求率為基礎的工作負載,可能會在達到頻寬上限之前達到此限制。

    上述指標是確認節點達到網路限制的理想方式。但是,限制也可以藉由網路指標維持平穩來識別。

    如果觀察到很長時間都維持平穩,接著可能會出現複寫延遲、用於快取的位元組增加、可釋出的記憶體減少,高交換和 CPU 使用率。Amazon EC2 執行個體也有網路限制,可透過 ENA 驅動程式指標追蹤。搭配增強型網路支援和 ENA 驅動程式 2.2.10 或更新版本的 Linux 執行個體,可以使用下列命令檢閱限制計數器:

    # ethtool -S eth0 | grep "allowance_exceeded"

CPU 使用率

CPU 使用率測量結果是調查的起點,下列項目有助於縮小可能發生的問題範 ElastiCache 圍:

  • Redis 的 OSS SlowLogs: ElastiCache 預設組態會保留最後 128 個命令,這些命令需要超過 10 毫秒才能完成。慢速命令的歷史記錄會在引擎執行時間內保留,且會在故障或重新啟動的情況下遺失。如果清單達到 128 個項目,將會刪除舊活動,為新的活動騰出空間。慢速事件清單的大小和視為緩慢的執行時間,可以透過自訂參數群組中的 slowlog-max-lenslowlog-log-slower-than 參數加以修改。慢速日誌清單可以透過在引擎上執行 SLOWLOG GET 128 來擷取,其中 128 是最後回報的 128 個慢速命令。每個項目都有下列欄位:

    1) 1) (integer) 1 -----------> Sequential ID 2) (integer) 1609010767 --> Timestamp (Unix epoch time)of the Event 3) (integer) 4823378 -----> Time in microseconds to complete the command. 4) 1) "keys" -------------> Command 2) "*" ----------------> Arguments 5) "1.2.3.4:57004"-> Source

    上述事件發生在 12 月 26 日 19:26:07 (UTC),花了 4.8 秒 (4.823 毫秒) 完成,其原因是從用戶端 1.2.3.4 請求的 KEYS 命令。

    在 Linux 上,時間戳記可以使用命令日期轉換:

    $ date --date='@1609010767' Sat Dec 26 19:26:07 UTC 2020

    使用 Python:

    >>> from datetime import datetime >>> datetime.fromtimestamp(1609010767) datetime.datetime(2020, 12, 26, 19, 26, 7)

    或在窗戶上使用 PowerShell:

    PS D:\Users\user> [datetimeoffset]::FromUnixTimeSeconds('1609010767') DateTime : 12/26/2020 7:26:07 PM UtcDateTime : 12/26/2020 7:26:07 PM LocalDateTime : 12/26/2020 2:26:07 PM Date : 12/26/2020 12:00:00 AM Day : 26 DayOfWeek : Saturday DayOfYear : 361 Hour : 19 Millisecond : 0 Minute : 26 Month : 12 Offset : 00:00:00Ticks : 637446075670000000 UtcTicks : 637446075670000000 TimeOfDay : 19:26:07 Year : 2020

    在短時間內 (一分鐘以內) 出現許多緩慢命令是值得關注的原因。檢閱命令的性質及如何最佳化 (請參閱前面的範例)。如果經常回報具有 O(1) 時間複雜性的命令,請檢查之前提到出現高 CPU 使用率的其他因素。

  • 延遲指標: ElastiCache (Redis OSS) 提供 CloudWatch 指標來監控不同類別命令的平均延遲。資料點的計算方式是將類別中命令的執行總次數除以期間的總執行時間。請務必了解,延遲指標結果是多個命令的彙總結果。單一命令可能會導致非預期的結果 (例如逾時),而不會對指標造成重大影響。針對這種情況,慢速事件會是更準確的資訊來源。下列清單包含可用的延遲指標,以及影響這些指標的各別命令。

    • EvalBasedCmdsLatency: 與 Lua 腳本命令相關,eval,evalsha;

    • GeoSpatialBasedCmdsLatency: geodist, geohash, geopos, georadius, georadiusbymember, geoadd;

    • GetTypeCmdsLatency:讀取命令,無論資料類型為何;

    • HashBasedCmdsLatency: hexists, hget, hgetall, hkeys, hlen, hmget, hvals, hstrlen, hdel, hincrby, hincrbyfloat, hmset, hset, hsetnx;

    • HyperLogLogBasedCmdsLatency: pfselftest, pfcount, pfdebug, pfadd, pfmerge;

    • KeyBasedCmdsLatency:可以對不同數據類型採取行動的命令:dumpexistskeysobject,pttl,randomkey,ttl,type,,del,expire,expireat,move,,persist,pexpire,pexpireat,,rename,renamenx,restoreK,,sort,unlink;

    • ListBasedCmdsLatency: 林德斯, LLEN, 左範圍, BLPOP, brpop 的, brpop, brpoplpush, 林塞特, lpop, lpush, Lpushx, LREM, LSET 的, ltrim, rpop, rpoplpush, rpush, rpushx;

    • PubSubBasedCmdsLatency:訂閱,發布,發布,訂閱,訂閱,取消訂閱;

    • SetBasedCmdsLatency: scard, sdiff, sinter, sismember, smembers, srandmember, sunion, sadd, sdiffstore, sinterstore, smove, spop, srem, sunionstore;

    • SetTypeCmdsLatency:編寫命令,無論數據類型如何;

    • SortedSetBasedCmdsLatency: zcard, zcount, zrange, zrangebyscore, zrank, zrevrange, zrevrangebyscore, zrevrank, zscore, zrangebylex, zrevrangebylex, zlexcount, zadd. zincrby, zinterstore, zrem, zremrangebyrank, zremrangebyscore, zunionstore, zremrangebylex, zpopmax, zpopmin, bzpopmin, bzpopmax;

    • StringBasedCmdsLatency: bitcount, get, getbit, getrange, mget, strlen, substr, bitpos, append, bitop, bitfield, decr, decrby, getset, incr, incrby, incrbyfloat, mset, msetnx, psetex, set, setbit, setex, setnx, setrange;

    • StreamBasedCmdsLatency: xrange, xrevrange, xlen, xread, xpending, xinfo, xadd, xgroup, readgroup, xack, xclaim, xdel, xtrim, xsetid;

  • Redis 的 OSS 運行時命令:

    • info command stats:提供自 Redis OSS 引擎啟動後執行的命令清單、累計執行次數、總執行時間,以及每個命令的平均執行時間;

    • client list:提供目前連線的用戶端和相關資訊的清單,如緩衝區使用率、上次執行的命令等;

  • Backup 和複寫: ElastiCache (Redis OSS) 早於 2.8.22 的版本使用分叉處理程序來建立備份,並處理與複本的完整同步。這種方法可能會在寫入密集型使用案例中產生顯著的記憶體額外負荷。

    從 ElastiCache Redis OSS 2.8.22 開始, AWS 引入了無叉式備份和複製方法。新方法可能會延遲寫入以防止失敗。這兩種方法都會造成某些時段的 CPU 使用率較高,導致更長的回應時間,進而引發用戶端在執行期間逾時。請一律檢查是否在備份期間內發生用戶端故障或 SaveInProgress 指標為 1 的情況。建議您將備份時段排定為使用率低的時段,盡量減少用戶端發生問題或備份失敗的可能性。

從伺服器端終止連線

預設 ElastiCache (Redis OSS) 設定會保持無限期建立用戶端連線。不過在某些情況下可能需終止連線。例如:

  • 用戶端應用程式中的錯誤可能會造成連線遭遺忘,並以閒置狀態保持成立。這就是所謂的「連線流失」,結果會發現 CurrConnections 指標中已成立的連線數穩定增加。此行為可能會導致用戶端或 ElastiCache 端的飽和度。當無法從用戶端立即修正時,有些管理員會在其 ElastiCache 參數群組中設定「逾時」值。逾時是讓閒置連線持續存在的時間 (以秒為單位)。如果用戶端在此期間未提交任何要求,則 Redis OSS 引擎會在連線達到逾時值後立即終止連線。較小的逾時值可能會導致不必要的連線中斷,屆時用戶端需要妥善處理並重新連線,進而導致延遲。

  • 用於存放索引鍵的記憶體與用戶端緩衝區共用。具有大型請求或回應的慢速用戶端,可能需要大量的記憶體來處理其緩衝區。預設 ElastiCache (Redis OSS) 設定不會限制一般用戶端輸出緩衝區的大小。如果達到 maxmemory 上限,引擎將會嘗試移出項目以滿足緩衝區使用量。在極低記憶體情況下, ElastiCache (Redis OSS) 可能會選擇中斷耗用大型用戶端輸出緩衝區的用戶端連線,以釋放記憶體並保留叢集的健全狀況。

    可以使用自訂組態來限制用戶端緩衝區的大小,且用戶端達到限制時將會中斷連線。不過用戶端應該能處理未預期的中斷連線。處理一般用戶端的緩衝區大小的參數如下:

    • client-query-buffer-limit:單個輸入請求的最大大小;

    • client-output-buffer-limit-normal-soft-limit:用戶端連線的軟限制。如果超過軟限制的時間超過定義的時間(以秒為單位)normal-soft-seconds 或達到硬限制,則連接將終止; client-output-buffer-limit

    • client-output-buffer-limit-normal-soft-seconds:允許的時間超過 client-output-buffer-limit-的連接normal-soft-limit;

    • client-output-buffer-limit-normal-hard-limit:達到此限制的連線會立即終止。

    除了一般用戶端緩衝區,下列選項也可控制複本節點和 Pub/Sub (發佈/訂閱) 用戶端的緩衝區:

    • client-output-buffer-limit-replica-hard-limit;

    • client-output-buffer-limit-replica-soft-seconds;

    • client-output-buffer-limit-replica-hard-limit;

    • client-output-buffer-limit-pubsub-soft-limit;

    • client-output-buffer-limit-pubsub-soft-seconds;

    • client-output-buffer-limit-pubsub-hard-limit;

Amazon EC2 執行個體的用戶端疑難排解

客戶端的負載和響應也會影響到的請求 ElastiCache。疑難排解間歇性連線或逾時問題時,需要仔細檢閱 EC2 執行個體和作業系統限制。幾項需觀察的要點:

  • CPU:

    • EC2 執行個體 CPU 使用率:確定 CPU 尚未飽和或接近 100%。歷史分析可以通過以下方式完成 CloudWatch,但請記住,數據點粒度為 1 分鐘(啟用詳細監控)或 5 分鐘;

    • 如果使用高載 EC2 執行個體,請確定其 CPU 餘額尚未耗盡。此資訊可用於CPUCreditBalance CloudWatch 測量結果。

    • 短時間的高 CPU 使用率可能會導致逾時,而不會反映 100% 的使用率。 CloudWatch這種情況需使用作業系統工具 (如 toppsmpstat) 進行即時監控。

  • 網路

    • 根據執行個體容量檢查網路輸送量是否低於可接受的值。如需詳細資訊,請參閱 Amazon EC2 執行個體類型

    • 在具有 ena 增強型網路驅動程式的執行個體上,查看 ENA 統計數字以取得逾時或超出的限制。下列統計數字有助於確認網路限制飽和情況:

      • bw_in_allowance_exceeded/bw_out_allowance_exceeded:因過量的傳入或傳出輸送量而造成的封包數;

      • conntrack_allowance_exceeded:由於安全群組連線追蹤限制而捨棄的封包數。當此限制飽和時,新的連線將會失敗;

      • linklocal_allowance_exceeded:由於透過 VPC DNS 對執行個體中繼資料 NTP 發出過多請求而捨棄的封包數。所有服務的限制都是每秒 1024 個封包;

      • pps_allowance_exceeded:由於每秒封包比率過高而捨棄的封包數。當網路流量包含每秒數千或數百萬個極小的請求時,便可能達到 PPS 限制。 ElastiCache 可以優化流量,通過管道或一次執行多個操作的命令來更好地利用網絡數據包,MGET而不是GET

解析完成單個請求所花費的時間

  • 在網絡上:TcpdumpWireshark(命令行上的 tshark)是方便的工具,以了解請求花了多少時間旅行網絡,擊中 ElastiCache 引擎並獲得回報。下列範例說明如何使用下列命令建立單一請求:

    $ echo ping | nc example.xxxxxx.ng.0001.use1.cache.amazonaws.com 6379 +PONG

    tcpdump 與上面的命令同時執行並傳回了:

    $ sudo tcpdump -i any -nn port 6379 -tt tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes 1609428918.917869 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [S], seq 177032944, win 26883, options [mss 8961,sackOK,TS val 27819440 ecr 0,nop,wscale 7], length 0 1609428918.918071 IP 172.31.11.247.6379 > 172.31.11.142.40966: Flags [S.], seq 53962565, ack 177032945, win 28960, options [mss 1460,sackOK,TS val 3788576332 ecr 27819440,nop,wscale 7], length 0 1609428918.918091 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [.], ack 1, win 211, options [nop,nop,TS val 27819440 ecr 3788576332], length 0 1609428918.918122 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [P.], seq 1:6, ack 1, win 211, options [nop,nop,TS val 27819440 ecr 3788576332], length 5: RESP "ping" 1609428918.918132 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [F.], seq 6, ack 1, win 211, options [nop,nop,TS val 27819440 ecr 3788576332], length 0 1609428918.918240 IP 172.31.11.247.6379 > 172.31.11.142.40966: Flags [.], ack 6, win 227, options [nop,nop,TS val 3788576332 ecr 27819440], length 0 1609428918.918295 IP 172.31.11.247.6379 > 172.31.11.142.40966: Flags [P.], seq 1:8, ack 7, win 227, options [nop,nop,TS val 3788576332 ecr 27819440], length 7: RESP "PONG" 1609428918.918300 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [.], ack 8, win 211, options [nop,nop,TS val 27819441 ecr 3788576332], length 0 1609428918.918302 IP 172.31.11.247.6379 > 172.31.11.142.40966: Flags [F.], seq 8, ack 7, win 227, options [nop,nop,TS val 3788576332 ecr 27819440], length 0 1609428918.918307 IP 172.31.11.142.40966 > 172.31.11.247.6379: Flags [.], ack 9, win 211, options [nop,nop,TS val 27819441 ecr 3788576332], length 0 ^C 10 packets captured 10 packets received by filter 0 packets dropped by kernel

    從上方的輸出中,我們可以確認 TCP 三向交握花了 222 微秒 (918091 - 917869) 完成,並且花 173 微秒 (918295 - 918122) 提交並傳回 Ping 命令。

    從請求到關閉連線花了 438 微秒 (918307 - 917869)。這些結果可以確認網路和引擎的回應時間良好,而且可以專注於其他元件進行調查。

  • 在作業系統上:Strace 有助於識別作業系統層級的時間落差。實際應用程式的分析會更廣泛,建議使用專門的應用程式剖析工具或除錯工具。下列範例只會顯示基礎作業系統元件是否正常運作,若不正常則可能需要進一步調查。使用相同的 Redis OSS PING 命令,strace我們得到:

    $ echo ping | strace -f -tttt -r -e trace=execve,socket,open,recvfrom,sendto nc example.xxxxxx.ng.0001.use1.cache.amazonaws.com (http://example.xxxxxx.ng.0001.use1.cache.amazonaws.com/) 6379 1609430221.697712 (+ 0.000000) execve("/usr/bin/nc", ["nc", "example.xxxxxx.ng.0001.use"..., "6379"], 0x7fffede7cc38 /* 22 vars */) = 0 1609430221.708955 (+ 0.011231) socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3 1609430221.709084 (+ 0.000124) socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3 1609430221.709258 (+ 0.000173) open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3 1609430221.709637 (+ 0.000378) open("/etc/host.conf", O_RDONLY|O_CLOEXEC) = 3 1609430221.709923 (+ 0.000286) open("/etc/resolv.conf", O_RDONLY|O_CLOEXEC) = 3 1609430221.711365 (+ 0.001443) open("/etc/hosts", O_RDONLY|O_CLOEXEC) = 3 1609430221.713293 (+ 0.001928) socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 3 1609430221.717419 (+ 0.004126) recvfrom(3, "\362|\201\200\0\1\0\2\0\0\0\0\rnotls20201224\6tihew"..., 2048, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("172.31.0.2")}, [28->16]) = 155 1609430221.717890 (+ 0.000469) recvfrom(3, "\204\207\201\200\0\1\0\1\0\0\0\0\rnotls20201224\6tihew"..., 65536, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("172.31.0.2")}, [28->16]) = 139 1609430221.745659 (+ 0.027772) socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 3 1609430221.747548 (+ 0.001887) recvfrom(0, 0x7ffcf2f2ca50, 8192, 0, 0x7ffcf2f2c9d0, [128]) = -1 ENOTSOCK (Socket operation on non-socket) 1609430221.747858 (+ 0.000308) sendto(3, "ping\n", 5, 0, NULL, 0) = 5 1609430221.748048 (+ 0.000188) recvfrom(0, 0x7ffcf2f2ca50, 8192, 0, 0x7ffcf2f2c9d0, [128]) = -1 ENOTSOCK (Socket operation on non-socket) 1609430221.748330 (+ 0.000282) recvfrom(3, "+PONG\r\n", 8192, 0, 0x7ffcf2f2c9d0, [128->0]) = 7 +PONG 1609430221.748543 (+ 0.000213) recvfrom(3, "", 8192, 0, 0x7ffcf2f2c9d0, [128->0]) = 0 1609430221.752110 (+ 0.003569) +++ exited with 0 +++

    在上面的例子中,該命令花費超過 54 毫秒才完成 (752110 - 697712 = 54398 微秒)。

    將 nc 執行個體化並執行名稱解析花了約 20 毫秒的大量時間 (從 697712 到 717890),在這之後,花了 2 毫秒來建立 TCP 通訊端 (745659 到 747858),再花 0.4 毫秒 (747858 到 748330) 提交和接收請求的回應。