

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

# 使用僅供讀取複本的最佳實務
<a name="ReadReplicas"></a>

許多應用程式，例如工作階段存放區、排行榜和建議引擎，都需要高可用性，並處理比寫入操作更多的讀取操作。這些應用程式通常可以容忍略微過時的資料 （最終一致性），這表示如果不同的使用者暫時看到略有不同的相同資料版本，則可以接受。例如：
+ 快取的查詢結果通常可以容忍稍微過時的資料，尤其是在事實來源為外部的快取旁模式。
+ 在遊戲排行榜中，更新分數的幾秒鐘延遲通常不會顯著影響使用者體驗。
+ 對於工作階段存放區，在複本之間傳播工作階段資料時有些輕微的延遲很少影響應用程式功能。
+ 建議引擎通常會使用歷史資料分析，因此即時一致性較不重要。

最終一致性表示複寫程序完成後，所有複本節點最終都會傳回相同的資料，通常在幾毫秒內。對於這類使用案例，實作僅供讀取複本是一種有效的策略，可降低從 ElastiCache 執行個體讀取時的延遲。

在 Amazon ElastiCache 中使用僅供讀取複本可透過下列方式提供顯著的效能優勢：

**增強的讀取可擴展性**
+ 將讀取操作分散到多個複本節點
+ 從主節點卸載讀取流量
+ 提供地理位置更接近複本的請求，以減少讀取延遲

**最佳化的主要節點效能**
+ 專用主節點資源來寫入操作
+ 減少主節點上的連線額外負荷
+ 改善寫入效能，並在尖峰流量期間維持更好的回應時間

## 在 ElastiCache Serverless 中使用從複本讀取
<a name="ReadReplicas.serverless"></a>

ElastiCache 無伺服器提供兩個不同的端點，以滿足不同的一致性要求。兩個端點使用相同的 DNS 名稱，但使用不同的連接埠。若要使用read-from-replica連接埠，您必須[設定 VPC 的安全群組和網路存取控制清單，以授權從用戶端應用程式存取這兩個連接埠](set-up.md#elasticache-install-grant-access-VPN)。

**主要端點 （連接埠 6379)**
+ 用於需要立即一致性的操作
+ 保證讀取up-to-date資料
+ 最適合關鍵交易和寫入操作
+ 寫入操作的必要項目
+ 範例：`test-12345.serverless.use1.cache.amazonaws.com:6379`

**延遲最佳化端點 （連接埠 6380)**
+ 針對可容忍最終一致性的讀取操作進行最佳化
+ 如果可能，ElastiCache Serverless 會自動將讀取請求路由到用戶端本機可用區域中的複本節點。此最佳化可避免從不同可用區域中的節點擷取資料時產生的額外網路延遲，藉此降低延遲。
+ 如果本機節點無法使用，ElastiCache Serverless 會自動選取其他區域中的可用節點
+ 範例：`test-12345.serverless.use1.cache.amazonaws.com:6380`
+ 如果您提供複本組態的讀取，Glide 和 Lettuce 等用戶端會自動偵測並路由讀取至延遲最佳化端點。如果您的用戶端不支援路由組態 （例如 valkey-java 和較舊的 jedis 版本），您必須定義正確的連接埠和用戶端組態以從複本讀取。

## 在 ElastiCache Serverless - Valkey 和 Glide 中連線至僅供讀取複本
<a name="ReadReplicas.connecting-primary"></a>

下列程式碼片段顯示如何在 Valkey glide 程式庫中設定 ElastiCache Serverless 複本的讀取。您不需要指定從複本讀取的連接埠，但您需要設定路由組態 `ReadFrom.PREFER_REPLICA`。

```
package glide.examples;

import glide.api.GlideClusterClient;
import glide.api.logging.Logger;
import glide.api.models.configuration.GlideClusterClientConfiguration;
import glide.api.models.configuration.NodeAddress;
import glide.api.models.exceptions.ClosingException;
import glide.api.models.exceptions.ConnectionException;
import glide.api.models.exceptions.TimeoutException;
import glide.api.models.configuration.ReadFrom;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class ClusterExample {

    public static void main(String[] args) {
        // Set logger configuration
        Logger.setLoggerConfig(Logger.Level.INFO);

        GlideClusterClient client = null;

        try {
            System.out.println("Connecting to Valkey Glide...");

            // Configure the Glide Client
            GlideClusterClientConfiguration config = GlideClusterClientConfiguration.builder()
                .address(NodeAddress.builder()
                    .host("your-endpoint")
                    .port(6379)
                    .build())
                .useTLS(true)
                .readFrom(ReadFrom.PREFER_REPLICA)
                .build();

            // Create the GlideClusterClient
            client = GlideClusterClient.createClient(config).get();
            System.out.println("Connected successfully.");

            // Perform SET operation
            CompletableFuture<String> setResponse = client.set("key", "value");
            System.out.println("Set key 'key' to 'value': " + setResponse.get());

            // Perform GET operation
            CompletableFuture<String> getResponse = client.get("key");
            System.out.println("Get response for 'key': " + getResponse.get());

            // Perform PING operation
            CompletableFuture<String> pingResponse = client.ping();
            System.out.println("PING response: " + pingResponse.get());

        } catch (ClosingException | ConnectionException | TimeoutException | ExecutionException e) {
            System.err.println("An exception occurred: ");
            e.printStackTrace();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            // Close the client connection
            if (client != null) {
                try {
                    client.close();
                    System.out.println("Client connection closed.");
                } catch (ClosingException | ExecutionException e) {
                    System.err.println("Error closing client: " + e.getMessage());
                }
            }
        }
    }
}
```