

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Konfigurasi klien selada (Valkey dan Redis OSS)
<a name="BestPractices.Clients-lettuce"></a>

Bagian ini menjelaskan opsi konfigurasi Java dan Lettuce yang direkomendasikan, dan bagaimana penerapannya pada ElastiCache cluster.

Rekomendasi di bagian ini diuji dengan Lettuce versi 6.2.2.

**Topics**
+ [Contoh: Konfigurasi selada untuk mode cluster, TLS diaktifkan](BestPractices.Clients-lettuce-cme.md)
+ [Contoh: Konfigurasi selada untuk mode cluster dinonaktifkan, TLS diaktifkan](BestPractices.Clients-lettuce-cmd.md)

**TTL cache DNS Java**

Mesin virtual Java (JVM) menyimpan cache pencarian nama DNS. Ketika JVM meresolusi nama host ke alamat IP, JVM menyimpan cache alamat IP untuk jangka waktu tertentu, yang disebut *time-to-live* (TTL).

Pilihan nilai TTL merupakan kompromi antara latensi dan responsivitas terhadap perubahan. Dengan TTL yang lebih pendek, peresolusi DNS menemukan pembaruan dalam DNS klaster dengan lebih cepat. Hal ini dapat membuat aplikasi Anda lebih cepat dalam merespons penggantian atau alur kerja lain yang dialami klaster Anda. Namun, jika TTL terlalu rendah, hal ini meningkatkan volume kueri, yang dapat meningkatkan latensi aplikasi Anda. Meskipun tidak ada nilai TTL yang benar, sebaiknya pertimbangkan lama waktu yang sesuai bagi Anda untuk menunggu perubahan berlaku saat menetapkan nilai TTL Anda.

Karena ElastiCache node menggunakan entri nama DNS yang mungkin berubah, kami sarankan Anda mengonfigurasi JVM Anda dengan TTL rendah 5 hingga 10 detik. Hal ini dapat memastikan bahwa ketika alamat IP simpul berubah, aplikasi Anda dapat menerima dan menggunakan alamat IP baru sumber daya dengan mengueri ulang DNS.

Pada beberapa konfigurasi Java, TTL default JVM diatur untuk tidak pernah menyegarkan entri DNS hingga JVM dimulai ulang.

Untuk detail tentang cara mengatur TTL JVM Anda, lihat [How to set the JVM TTL](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/java-dg-jvm-ttl.html#how-to-set-the-jvm-ttl).

**Versi Lettuce**

Sebaiknya gunakan Lettuce versi 6.2.2 atau versi yang lebih baru.

**Titik akhir**

Saat Anda menggunakan klaster dengan mode klaster diaktifkan, atur `redisUri` ke titik akhir konfigurasi klaster. Pencarian DNS untuk URI ini menampilkan daftar semua simpul yang tersedia di klaster, dan diresolusi secara acak ke salah satu simpul selama inisialisasi klaster. Untuk detail selengkapnya tentang cara kerja penyegaran topologi, lihat *dinamis RefreshSources* nanti dalam topik ini.

**SocketOption**

Aktifkan [KeepAlive](https://lettuce.io/core/release/api/io/lettuce/core/SocketOptions.KeepAliveOptions.html). Mengaktifkan opsi ini akan mengurangi kebutuhan untuk menangani koneksi yang gagal selama runtime perintah.

Pastikan Anda menetapkan [Waktu habis koneksi](https://lettuce.io/core/release/api/io/lettuce/core/SocketOptions.Builder.html#connectTimeout-java.time.Duration-) berdasarkan persyaratan aplikasi dan beban kerja Anda. Untuk informasi selengkapnya, lihat bagian Waktu habis dalam topik ini.

**ClusterClientOption: Mode Cluster Opsi klien yang diaktifkan**

Aktifkan [AutoReconnect](https://lettuce.io/core/release/api/io/lettuce/core/cluster/ClusterClientOptions.Builder.html#autoReconnect-boolean-)saat koneksi terputus.

Atur [CommandTimeout](https://lettuce.io/core/release/api/io/lettuPrce/core/RedisURI.html#getTimeout--). Untuk detail selengkapnya, lihat bagian Waktu habis dalam topik ini.

Atur [nodeFilter](https://lettuce.io/core/release/api/io/lettuce/core/cluster/ClusterClientOptions.Builder.html#nodeFilter-java.util.function.Predicate-) untuk memfilter simpul yang gagal dari topologi. Lettuce menyimpan semua node yang ditemukan di output 'cluster nodes' (termasuk node dengan PFAIL/FAIL status) di 'partisi' klien (juga dikenal sebagai pecahan). Selama proses pembuatan topologi klaster, Lettuce mencoba terhubung ke semua simpul partisi. Perilaku Lettuce yang menambahkan simpul yang gagal ini dapat menyebabkan kesalahan koneksi (atau peringatan) ketika simpul diganti karena alasan apa pun. 

Misalnya, setelah failover selesai dan klaster memulai proses pemulihan, sementara clusterTopology sedang diperbarui, peta simpul bus klaster memiliki periode waktu singkat ketika simpul yang nonaktif dicantumkan sebagai simpul FAIL, sebelum sepenuhnya dihapus dari topologi. Selama periode ini, klien Selada menganggapnya sebagai simpul yang sehat dan terus terhubung dengannya. Hal ini menyebabkan kegagalan setelah percobaan kembali habis. 

Contoh:

```
final ClusterClientOptions clusterClientOptions = 
    ClusterClientOptions.builder()
    ... // other options
    .nodeFilter(it -> 
        ! (it.is(RedisClusterNode.NodeFlag.FAIL) 
        || it.is(RedisClusterNode.NodeFlag.EVENTUAL_FAIL) 
        || it.is(RedisClusterNode.NodeFlag.HANDSHAKE)
        || it.is(RedisClusterNode.NodeFlag.NOADDR)))
    .validateClusterNodeMembership(false)
    .build();
redisClusterClient.setOptions(clusterClientOptions);
```

**catatan**  
Pemfilteran node paling baik digunakan dengan DynamicRefreshSources set ke true. Sebaliknya, jika tampilan topologi diambil dari satu simpul seed yang bermasalah, yang melihat simpul primer dari serpihan tertentu sebagai simpul yang mengalami kegagalan, pemfilteran tersebut akan memfilter simpul primer ini, sehingga akan mengakibatkan slot tidak tercakup. Memiliki beberapa node benih (kapan DynamicRefreshSources benar) mengurangi kemungkinan masalah ini, karena setidaknya beberapa node benih harus memiliki tampilan topologi yang diperbarui setelah failover dengan primer yang baru dipromosikan.

**ClusterTopologyRefreshOptions: Opsi untuk mengontrol penyegaran topologi cluster dari klien Cluster Mode Enabled**

**catatan**  
Klaster dengan mode klaster dinonaktifkan tidak mendukung perintah penemuan klaster dan tidak kompatibel dengan semua fungsionalitas penemuan topologi dinamis klien.  
Mode cluster dinonaktifkan dengan ElastiCache tidak kompatibel dengan Lettuce. `MasterSlaveTopologyRefresh` Sebagai gantinya, untuk mode klaster dinonaktifkan, Anda dapat mengonfigurasi `StaticMasterReplicaTopologyProvider` dan menyediakan titik akhir baca dan tulis klaster.  
Untuk informasi selengkapnya tentang menghubungkan ke klaster dengan mode klaster dinonaktifkan, lihat [Menemukan Titik Akhir Cluster Valkey atau Redis OSS (Mode Cluster Dinonaktifkan) (Konsol)](Endpoints.md#Endpoints.Find.Redis).  
Jika Anda ingin menggunakan fungsionalitas penemuan topologi dinamis Lettuce, Anda dapat membuat klaster dengan mode klaster diaktifkan dengan konfigurasi serpihan yang sama dengan klaster yang ada. Namun, untuk klaster dengan mode klaster diaktifkan, sebaiknya konfigurasi setidaknya 3 serpihan dengan minimal 1 replika untuk mendukung failover cepat.

[Aktifkan aktifkan PeriodicRefresh](https://lettuce.io/core/release/api/io/lettuce/core/cluster/ClusterTopologyRefreshOptions.Builder.html#enablePeriodicRefresh-java.time.Duration-). Opsi ini memungkinkan pembaruan topologi klaster berkala sehingga klien memperbarui topologi klaster dalam interval refreshPeriod (default: 60 detik). Ketika opsi ini dinonaktifkan, klien memperbarui topologi klaster hanya ketika kesalahan terjadi ketika klien tersebut mencoba menjalankan perintah terhadap klaster. 

Dengan mengaktifkan opsi ini, Anda dapat mengurangi latensi yang terkait dengan penyegaran topologi klaster dengan menambahkan pekerjaan ini ke tugas latar belakang. Saat penyegaran topologi dilakukan dalam pekerjaan latar belakang, prosesnya bisa agak lambat untuk klaster yang memiliki banyak simpul. Hal ini karena semua simpul sedang dikueri untuk mendapatkan tampilan klaster yang paling terbaru. Jika Anda menjalankan klaster dalam jumlah besar, Anda sebaiknya menambah periodenya.

[Aktifkan aktifkan AllAdaptiveRefreshTriggers](https://lettuce.io/core/release/api/io/lettuce/core/cluster/ClusterTopologyRefreshOptions.Builder.html#enableAllAdaptiveRefreshTriggers--). Hal ini memungkinkan penyegaran topologi adaptif yang menggunakan semua [pemicu](https://lettuce.io/core/6.1.6.RELEASE/api/io/lettuce/core/cluster/ClusterTopologyRefreshOptions.RefreshTrigger.html): MOVED\_REDIRECT, ASK\_REDIRECT, PERSISTENT\_RECONNECTS, UNCOVERED\_SLOT, UNKNOWN\_NODE. Pemicu penyegaran adaptif memulai pembaruan tampilan topologi berdasarkan peristiwa yang terjadi selama operasi klaster Valkey atau Redis OSS. Mengaktifkan opsi ini akan membuat penyegaran topologi langsung dilakukan ketika salah satu pemicu sebelumnya terjadi. Penyegaran yang dipicu secara adaptif dibatasi lajunya menggunakan waktu habis karena peristiwa dapat terjadi dalam skala besar (waktu habis default di antara pembaruan: 30).

Aktifkan [tutup StaleConnections](https://lettuce.io/core/release/api/io/lettuce/core/cluster/ClusterTopologyRefreshOptions.Builder.html#closeStaleConnections-boolean-). Hal ini memungkinkan penutupan koneksi yang sudah tidak berlaku saat menyegarkan topologi klaster. Itu hanya berlaku jika [ClusterTopologyRefreshOptions.isPeriodicRefreshEnabled()](https://lettuce.io/core/release/api/io/lettuce/core/cluster/ClusterTopologyRefreshOptions.html#isPeriodicRefreshEnabled--) benar. Ketika diaktifkan, klien dapat menutup koneksi yang tidak berlaku dan membuat yang baru di latar belakang. Hal ini mengurangi kebutuhan untuk menangani koneksi yang gagal selama runtime perintah.

Aktifkan [dinamis RefreshSources](https://lettuce.io/core/release/api/io/lettuce/core/cluster/ClusterTopologyRefreshOptions.Builder.html#dynamicRefreshSources-boolean-). Kami merekomendasikan untuk mengaktifkan dynamic RefreshSources untuk cluster kecil, dan menonaktifkannya untuk cluster besar. dynamic RefreshSources memungkinkan penemuan node cluster dari node seed yang disediakan (misalnya, titik akhir konfigurasi cluster). Ia menggunakan semua simpul yang ditemukan sebagai sumber untuk menyegarkan topologi klaster. 

Menggunakan dynamic refresh akan mengueri semua simpul yang ditemukan untuk topologi klaster dan mencoba memilih tampilan klaster yang paling akurat. Jika diatur ke false, hanya simpul seed awal yang digunakan sebagai sumber untuk penemuan topologi, dan jumlah klien diperoleh hanya untuk simpul seed awal. Saat dinonaktifkan, jika titik akhir konfigurasi klaster diresolusi ke simpul yang gagal, percobaan untuk menyegarkan tampilan klaster akan gagal dan menyebabkan pengecualian. Skenario ini dapat terjadi karena dibutuhkan beberapa waktu hingga entri simpul yang gagal dihapus dari titik akhir konfigurasi klaster. Oleh karena itu, titik akhir konfigurasi masih dapat diresolusi secara acak ke simpul yang gagal untuk waktu yang singkat. 

Namun, ketika diaktifkan, kita menggunakan semua simpul klaster yang diterima dari tampilan klaster untuk mengueri tampilannya saat ini. Karena kita memfilter simpul yang gagal dari tampilan tersebut, penyegaran topologi akan berhasil. Namun, ketika dinamis RefreshSources benar, Lettuce menanyakan semua node untuk mendapatkan tampilan cluster, dan kemudian membandingkan hasilnya. Jadi, klaster dengan banyak simpul bisa menghabiskan banyak daya komputasi. Sebaiknya nonaktifkan fitur ini untuk klaster dengan banyak simpul. 

```
final ClusterTopologyRefreshOptions topologyOptions = 
    ClusterTopologyRefreshOptions.builder()
    .enableAllAdaptiveRefreshTriggers()
    .enablePeriodicRefresh()
    .dynamicRefreshSources(true)
    .build();
```

**ClientResources**

Konfigurasikan [DnsResolver](https://lettuce.io/core/release/api/io/lettuce/core/resource/DefaultClientResources.Builder.html#dnsResolver-io.lettuce.core.resource.DnsResolver-)dengan [DirContextDnsResolver](https://lettuce.io/core/release/api/io/lettuce/core/resource/DirContextDnsResolver.html). DNS resolver didasarkan pada com.sun.jndi.dns Java. DnsContextFactory.

Konfigurasikan [reconnectDelay](https://lettuce.io/core/release/api/io/lettuce/core/resource/DefaultClientResources.Builder.html#reconnectDelay-io.lettuce.core.resource.Delay-) dengan backoff eksponensial dan jitter penuh. Lettuce memiliki mekanisme percobaan ulang bawaan berdasarkan strategi backoff eksponensial. Untuk detailnya, lihat [Exponential Backoff dan Jitter](https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter) di Blog Arsitektur. AWS Untuk informasi lebih lanjut tentang pentingnya memiliki strategi backoff coba lagi, lihat bagian logika backoff dari [posting blog Praktik Terbaik di Blog](https://aws.amazon.com/blogs/database/best-practices-redis-clients-and-amazon-elasticache-for-redis/) Database. AWS 

```
ClientResources clientResources = DefaultClientResources.builder()
   .addressResolverGroup(new DirContextDnsResolver())
    .reconnectDelay(
        Delay.fullJitter(
            Duration.ofMillis(100),     // minimum 100 millisecond delay
            Duration.ofSeconds(10),      // maximum 10 second delay
            100, TimeUnit.MILLISECONDS)) // 100 millisecond base
    .build();
```

**Batas Waktu**

Gunakan nilai waktu habis koneksi yang lebih rendah daripada waktu habis perintah Anda. Lettuce menggunakan pembuatan lazy connection. Jadi, jika waktu habis koneksi lebih tinggi dari waktu habis perintah, Anda dapat mengalami periode kegagalan persisten setelah penyegaran topologi jika Lettuce mencoba terhubung ke simpul yang tidak berkondisi baik dan waktu habis perintah selalu terlampaui. 

Gunakan waktu habis perintah dinamis untuk perintah yang berbeda-beda. Sebaiknya tetapkan waktu habis perintah berdasarkan durasi perintah yang diharapkan. Misalnya, gunakan waktu habis yang lebih lama untuk perintah yang mengulangi beberapa kunci, seperti skrip FLUSHDB, FLUSHALL, KEYS, SMEMBERS, atau Lua. Gunakan waktu habis yang lebih pendek untuk perintah kunci tunggal, seperti SET, GET, dan HSET.

**catatan**  
Batas waktu yang dikonfigurasi dalam contoh berikut adalah untuk pengujian yang menjalankan SET/GET perintah dengan kunci dan nilai hingga 20 byte. Waktu pemrosesan bisa lebih lama jika perintahnya kompleks atau kunci dan nilainya lebih besar. Anda harus mengatur waktu habis berdasarkan kasus penggunaan aplikasi Anda. 

```
private static final Duration META_COMMAND_TIMEOUT = Duration.ofMillis(1000);
private static final Duration DEFAULT_COMMAND_TIMEOUT = Duration.ofMillis(250);
// Socket connect timeout should be lower than command timeout for Lettuce
private static final Duration CONNECT_TIMEOUT = Duration.ofMillis(100);
    
SocketOptions socketOptions = SocketOptions.builder()
    .connectTimeout(CONNECT_TIMEOUT)
    .build();
 

class DynamicClusterTimeout extends TimeoutSource {
     private static final Set<ProtocolKeyword> META_COMMAND_TYPES = ImmutableSet.<ProtocolKeyword>builder()
          .add(CommandType.FLUSHDB)
          .add(CommandType.FLUSHALL)
          .add(CommandType.CLUSTER)
          .add(CommandType.INFO)
          .add(CommandType.KEYS)
          .build();

    private final Duration defaultCommandTimeout;
    private final Duration metaCommandTimeout;

    DynamicClusterTimeout(Duration defaultTimeout, Duration metaTimeout)
    {
        defaultCommandTimeout = defaultTimeout;
        metaCommandTimeout = metaTimeout;
    }

    @Override
    public long getTimeout(RedisCommand<?, ?, ?> command) {
        if (META_COMMAND_TYPES.contains(command.getType())) {
            return metaCommandTimeout.toMillis();
        }
        return defaultCommandTimeout.toMillis();
    }
}

// Use a dynamic timeout for commands, to avoid timeouts during
// cluster management and slow operations.
TimeoutOptions timeoutOptions = TimeoutOptions.builder()
.timeoutSource(
    new DynamicClusterTimeout(DEFAULT_COMMAND_TIMEOUT, META_COMMAND_TIMEOUT))
.build();
```