Praktik terbaik untuk Memorystore for Redis

Halaman ini memberikan panduan tentang cara menggunakan Memorystore for Redis secara optimal. Halaman ini juga menunjukkan potensi masalah yang harus dihindari.

Untuk mengetahui daftar skenario pemecahan masalah, lihat Pemecahan masalah.

Praktik terbaik ketersediaan tinggi dan ketahanan data

Sebaiknya gunakan Paket Standar sebagai mekanisme utama untuk ketersediaan tinggi (HA). Paket Standar menyediakan instance dengan tingkat ketersediaan tinggi dengan beberapa replika, dan memungkinkan pemulihan cepat menggunakan failover otomatis jika instance utama gagal. Selain itu, mengaktifkan snapshot RDB pada instance Paket Standar memberikan perlindungan tambahan dari kegagalan node.

Dalam beberapa skenario, Anda mungkin juga ingin memastikan bahwa Anda dapat memulihkan data dari cadangan snapshot. Dalam skenario ini, pencadangan dan kemampuan untuk memulihkan data dari snapshot RDB dapat memberikan perlindungan tambahan dari kehilangan data.

Jika Anda mengaktifkan snapshot RDB dan perlu memulihkan data, Memorystore for Redis dapat melakukannya dari snapshot terbaru. Snapshot ini hanya untuk pemulihan sistem internal dan Anda tidak dapat mengaksesnya.

Batasan ketahanan dan praktik terbaik

Meskipun Paket Standar menyediakan HA melalui replikasi dan failover otomatis, HA tidak menjamin ketahanan data sepenuhnya. Memorystore for Redis tidak dapat memberikan ketahanan data penuh meskipun HA diaktifkan selama peristiwa bencana tertentu, seperti kegagalan regional sementara.

Untuk membantu melindungi data Anda dan memberikan tingkat persistensi dasar, snapshot RDB diaktifkan secara default saat Anda membuat instance Memorystore for Redis menggunakan konsol Google Cloud .

Untuk workload produksi, pertimbangkan praktik terbaik berikut untuk lebih meningkatkan ketahanan data Anda:

  • Disaster recovery: Memorystore for Redis tidak mendukung replikasi lintas region. Jika strategi disaster recovery Anda memerlukan replikasi lintas region untuk ketahanan regional yang sebenarnya, sebaiknya gunakan instance Memorystore for Valkey. Untuk mengetahui informasi selengkapnya tentang cara mengonfigurasi dan mengelola instance sekunder di seluruh region, lihat Bekerja dengan replikasi lintas region dalam dokumentasi Memorystore for Valkey.
  • Ketahanan maksimum: jika aplikasi Anda memerlukan tingkat ketahanan data setinggi mungkin, sebaiknya gunakan instance Memorystore for Valkey yang dikonfigurasi dengan replikasi lintas region, pencadangan harian otomatis, dan persistensi Append-Only File (AOF). Kombinasi ini memberikan perlindungan paling tangguh terhadap kehilangan data. Untuk mengetahui informasi selengkapnya, lihat Ringkasan persistensi dalam dokumentasi Memorystore for Valkey.

Praktik terbaik perencanaan kapasitas

Untuk memastikan bahwa Anda dapat berhasil menyediakan resource dan membangun arsitektur yang tangguh, sebaiknya ikuti praktik terbaik perencanaan kapasitas berikut:

  • Deploy di beberapa lokasi: jika Anda tidak dapat membuat instance di zona pilihan Anda karena batasan resource sementara, coba buat instance di zona lain dalam region yang sama atau di region lain.
  • Gunakan akses lintas region: konfigurasikan klien Anda untuk mengakses instance yang berada di region berbeda. Jika Anda perlu menyediakan instance yang berada di region berbeda karena batasan resource lokal, klien Anda dapat terhubung ke instance tersebut.
  • Pilih tingkat kapasitas yang berbeda: jika Anda mengalami batasan resource karena ukuran instance, pilih tingkat kapasitas yang berbeda atau ubah ukuran instance. Untuk mengetahui informasi selengkapnya, lihat Performa paket kapasitas.

Ekspor RDB

Saat mengekspor cadangan RDB, gunakan panduan berikut:

Operasi yang memerlukan banyak resource

Untuk instance Redis Paket Standar, operasi berikut menggunakan memori tambahan selama durasi operasi:

Upgrade versi, penskalaan, dan failover manual menggunakan memori tambahan (untuk instance Paket Standar) karena replikasi. Operasi ini mengikuti proses replikasi yang dijelaskan dalam Perilaku upgrade instance Paket Standar.

Operasi impor dan ekspor memerlukan memori tambahan karena proses Redis yang di-fork dan pengelolaan data copy-on-write yang terkait dengan operasi ini.

Untuk mengurangi kelemahan operasi yang menggunakan banyak resource, Anda harus:

Operasi dan skenario yang memerlukan percobaan ulang koneksi

Operasi dan skenario berikut memutuskan koneksi jaringan antara jaringan Anda dan instance Redis:

Operasi ini mengubah instance Anda, sehingga memerlukan pemutusan koneksi sementara. Anda harus memiliki logika percobaan ulang dengan backoff eksponensial sebelum menjalankan operasi ini agar aplikasi Anda otomatis terhubung kembali dan terus berfungsi secara normal.

Pemeliharaan rutin

Instance Memorystore for Redis menjalani pemeliharaan secara berkala. Untuk mengetahui detail selengkapnya, lihat kebijakan pemeliharaan Memorystore for Redis.

Terapkan praktik terbaik berikut agar Anda siap menghadapi pemeliharaan rutin:

Manajemen memori

Manajemen memori dapat menjadi tantangan karena fragmentasi memori yang umum terjadi pada Redis open source. Sebaiknya turunkan konfigurasi maxmemory untuk instance Anda agar memiliki overhead jika terjadi tekanan memori yang tinggi.

Cara terbaik untuk memantau tekanan memori pada instance Memorystore Anda adalah dengan menggunakan metrik System Memory Usage Ratio. Untuk panduan lebih mendetail tentang cara mengelola memori untuk Memorystore for Redis, lihat Praktik terbaik manajemen memori.

Mengelola koneksi yang tidak ada aktivitas

Seiring waktu, Anda mungkin melihat jumlah koneksi ke instance Memorystore meningkat jika koneksi tidak dihentikan dengan benar. Hal ini dapat berdampak negatif pada performa, terutama jika Anda menggunakan enkripsi dalam pengiriman, yang memberlakukan batas koneksi maksimum berdasarkan paket kapasitas Anda. Untuk mengurangi hal ini, sebaiknya gunakan parameter konfigurasi Redis timeout yang memungkinkan Anda menetapkan jumlah detik sebelum koneksi klien yang tidak aktif dihentikan secara otomatis.

Nama resource Transparansi Akses

Data sensitif tidak boleh disimpan dalam nama resource Memorystore for Redis. Nama resource yang dimaksud adalah nama instance Memorystore for Redis, dan metadata instance, seperti tag. Data yang disimpan dalam nama resource tidak dijamin akan dilindungi oleh Google Cloud Transparansi Akses, dan dapat bertentangan dengan persyaratan kepatuhan Transparansi Akses organisasi Anda.

Konektor Akses VPC Serverless diperlukan untuk beberapa lingkungan serverless

Beberapa lingkungan serverless memerlukan Konektor Akses VPC Serverless untuk terhubung ke Memorystore for Redis. Siapkan konektor Akses VPC Serverless untuk project Anda jika Anda ingin terhubung menggunakan salah satu lingkungan ini.

Jaringan

Sebaiknya gunakan mode koneksi akses layanan pribadi. Memorystore for Redis menggunakan dua mode koneksi: akses layanan pribadi dan peering langsung. Mode koneksi akses layanan pribadi membuat pengelolaan rentang IP menjadi lebih sederhana dan memungkinkan Anda menggunakan VPC Bersama jika diinginkan.

Setelah Anda membuat instance, mode koneksi tidak dapat diubah.

Untuk mengetahui detail selengkapnya, lihat Networking.

Pemantauan dan pemberitahuan

Sebaiknya gunakan pemantauan dan pemberitahuan karena keduanya memberikan sinyal penting tentang penggunaan memori instance Redis Anda. Metrik ini juga memberi Anda insight tentang seberapa efisien instance Redis Anda merespons permintaan cache yang masuk.

Anda harus menyiapkan pemberitahuan default berikut:

Praktik terbaik penggunaan CPU

Penggunaan perintah redis yang mahal secara tidak tepat akan menyebabkan latensi tinggi, tidak responsif, atau masalah konektivitas. Instance Paket Standar menyediakan HA selama disaster recovery dan mengandalkan replikasi asinkron antara node utama dan replika. Jika salah satu node memiliki pemrosesan perintah yang mahal dan memblokir thread utama Redis, replikasi dapat terpengaruh. Jika masalah berlanjut dan terjadi pemadaman layanan lokasi, data terbaru yang ditulis di lokasi pemadaman layanan mungkin tidak tersedia di lokasi lain.

Sebaiknya gunakan Cloud Monitoring untuk menyetel pemberitahuan untuk metrik Detik CPU Thread Utama (redis.googleapis.com/stats/cpu_utilization_main_thread) guna memastikan utilisasi CPU tidak melebihi 0,8 detik untuk node utama atau 0,5 detik untuk setiap node replika, saat replika ditetapkan sebagai replika baca.

Jika instance Redis Anda melebihi nilai yang direkomendasikan, sebaiknya skalakan instance ke tingkat kapasitas yang lebih tinggi atau ikuti petunjuk pemecahan masalah untuk menghindari operasi intensif CPU.

Jika instance Anda mengalami penggunaan CPU yang tinggi atau resource instance habis (misalnya, karena terlalu banyak koneksi), instance mungkin akan mengalami gangguan dan metrik eksternal mungkin akan hilang.

Perintah yang memerlukan banyak resource

Sebaiknya hindari penggunaan perintah Redis yang menggunakan banyak resource. Penggunaan perintah ini dapat menyebabkan masalah performa berikut:

  • Latensi tinggi dan waktu tunggu klien
  • Tekanan memori yang disebabkan oleh perintah yang meningkatkan penggunaan memori
  • Kehilangan data selama replikasi dan sinkronisasi node karena thread utama Redis diblokir
  • Health check, kemampuan observasi, dan replikasi yang kekurangan resource

Tabel berikut mencantumkan contoh perintah Redis yang menggunakan banyak resource dan memberikan alternatif yang hemat resource.

Kategori Perintah yang menggunakan banyak resource Alternatif yang hemat resource
Jalankan untuk seluruh keyspace KEYS SCAN
Menjalankan untuk keyset dengan panjang variabel LRANGE Batasi ukuran rentang yang Anda gunakan untuk kueri.
ZRANGE Batasi ukuran rentang yang Anda gunakan untuk kueri.
HGETALL HSCAN
SMEMBERS SSCAN
Memblokir eksekusi skrip EVAL Pastikan skrip Anda tidak berjalan tanpa batas waktu.
EVALSHA Pastikan skrip Anda tidak berjalan tanpa batas waktu.
Menghapus file dan link DEL UNLINK
Publikasikan dan berlangganan PUBLISH SPUBLISH
SUBSCRIBE SSUBSCRIBE

Praktik terbaik klien Redis

Bagian ini memberikan panduan tentang cara menggunakan klien Redis secara optimal.

Mendeteksi dan menangani koneksi yang tidak responsif

Sebaiknya konfigurasikan aplikasi klien Anda untuk mendeteksi koneksi yang tidak responsif ke Memorystore for Redis. Saat koneksi yang tidak responsif terdeteksi, klien harus meresetnya. Untuk membangun aplikasi yang tangguh, sebaiknya gunakan konfigurasi klien berikut:

  • Konfigurasikan parameter keep-alive TCP: tetapkan parameter TCP keepalive time, TCP keepalive interval, dan TCP keepalive probes agar klien mendeteksi dan menghapus koneksi yang tidak responsif secara proaktif, bahkan saat koneksi tidak ada aktivitas. Misalnya, jika Anda menetapkan parameter TCP keepalive time ke 30 detik, TCP keepalive interval ke 10 detik, dan TCP keepalive probes ke 3, maka klien akan mereset koneksi tidak ada aktivitas yang tidak responsif dalam waktu satu menit.
  • Konfigurasi waktu tunggu pengguna TCP: tetapkan waktu tunggu ini di klien Anda untuk mereset koneksi yang memiliki permintaan yang belum terselesaikan dan berhenti merespons. Misalnya, jika Anda menetapkan waktu tunggu ke 15 detik, klien akan mereset koneksi yang tidak responsif yang memiliki permintaan yang belum terselesaikan setelah 15 detik.

Praktik terbaik khusus klien

Jika Anda melakukan penyebaran skala aplikasi, Anda mungkin mengalami error READONLY pada perintah tulis. Memorystore for Redis menggunakan deployment non-Sentinel dengan endpoint statis, dan klien tidak menerima informasi peran dinamis di awal. Jika Anda menggunakan satu koneksi klien untuk endpoint utama dan replika, klien Anda mungkin secara tidak sengaja mengirim perintah tulis ke replika hanya baca. Replika menampilkan error READONLY karena tidak dapat memproses perintah tulis.

Untuk mencegah kesalahan pemilihan rute penulisan, jangan gunakan satu koneksi untuk pembacaan dan penulisan. Sebagai gantinya, pisahkan operasi Anda dengan membuat instance klien terpisah berikut:

  • Klien utama: hanya terhubung ke endpoint utama
  • Klien replika: hanya terhubung ke endpoint replika

Tab berikut menunjukkan cara mengonfigurasi template terpisah di Go, Java, Node.js, dan Python.

Go

package main

import (
  "context"
  "fmt"

  "github.com/redis/go-redis/v9"
)

func main() {
ctx := context.Background()

  // Initialize the primary client connecting only to the primary endpoint
  primaryClient := redis.NewClient(&redis.Options{
      Addr:     "PRIMARY_HOST:6379",
      Password: "YOUR_PASSWORD",
      DB:       0,
  })
  defer primaryClient.Close()

  // Initialize the replica client connecting only to the replica endpoint
  replicaClient := redis.NewClient(&redis.Options{
      Addr:     "REPLICA_HOST:6379",
      Password: "YOUR_PASSWORD",
      DB:       0,
  })
  defer replicaClient.Close()

  // Use the primary client for all mutating commands
  err := primaryClient.Set(ctx, "example_key", "example_value", 0).Err()
  if err != nil {
      fmt.Printf("Failed to write to primary: %v\n", err)
  }

  // Use the replica client for all read-only commands
  val, err := replicaClient.Get(ctx, "example_key").Result()
  if err != nil {
      fmt.Printf("Failed to read from replica: %v\n", err)
  } else {
      fmt.Printf("Successfully read value: %s\n", val)
  }
}

Java

@Bean
public RedisConnectionFactory primaryConnectionFactory() {
  RedisStandaloneConfiguration config = new RedisStandaloneConfiguration("PRIMARY_HOST", 6379);
  config.setPassword(RedisPassword.of("YOUR_PASSWORD"));
  return new LettuceConnectionFactory(config);
}

@Bean
public RedisConnectionFactory replicaConnectionFactory() {
  RedisStaticMasterReplicaConfiguration config =
      new RedisStaticMasterReplicaConfiguration("PRIMARY_HOST", 6379);
  config.addNode("REPLICA_HOST", 6379);
  config.setPassword(RedisPassword.of("YOUR_PASSWORD"));

  LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
      .readFrom(ReadFrom.REPLICA_PREFERRED)
      .build();

  return new LettuceConnectionFactory(config, clientConfig);
}

@Bean
public RedisTemplate<String, Object> primaryRedisTemplate(
  @Qualifier("primaryConnectionFactory") RedisConnectionFactory factory) {

  RedisTemplate<String, Object> template = new RedisTemplate<>();
  template.setConnectionFactory(factory);
  return template;
}

@Bean
public RedisTemplate<String, Object> replicaRedisTemplate(
  @Qualifier("replicaConnectionFactory") RedisConnectionFactory factory) {

  RedisTemplate<String, Object> template = new RedisTemplate<>();
  template.setConnectionFactory(factory);
  return template;
}

Node.js

import { createClient } from 'redis';

async function main() {
// Initialize the primary client connecting only to the primary endpoint
const primaryClient = createClient({
  url: 'redis://PRIMARY_HOST:6379',
  password: 'YOUR_PASSWORD'
});

// Initialize the replica client connecting only to the replica endpoint
const replicaClient = createClient({
  url: 'redis://REPLICA_HOST:6379',
  password: 'YOUR_PASSWORD'
});

primaryClient.on('error', (err) => console.error('Primary Client Error', err));
replicaClient.on('error', (err) => console.error('Replica Client Error', err));

await primaryClient.connect();
await replicaClient.connect();

// Use the primary client for all mutating commands
try {
  await primaryClient.set('example_key', 'example_value');
  console.log('Successfully wrote to primary');
} catch (err) {
  console.error('Failed to write to primary:', err);
}

// Use the replica client for all read-only commands
try {
  const val = await replicaClient.get('example_key');
  console.log(`Successfully read value: ${val}`);
} catch (err) {
  console.error('Failed to read from replica:', err);
}

await primaryClient.disconnect();
await replicaClient.disconnect();
}

main();

Python

import redis

def main():
  # Initialize the primary client connecting only to the primary endpoint
  primary_client = redis.Redis(
      host='PRIMARY_HOST',
      port=6379,
      password='YOUR_PASSWORD',
      decode_responses=True
  )

  # Initialize the replica client connecting only to the replica endpoint
  replica_client = redis.Redis(
      host='REPLICA_HOST',
      port=6379,
      password='YOUR_PASSWORD',
      decode_responses=True
  )

  # Use the primary client for all mutating commands
  try:
      primary_client.set('example_key', 'example_value')
      print('Successfully wrote to primary')
  except redis.RedisError as e:
      print(f'Failed to write to primary: {e}')

  # Use the replica client for all read-only commands
  try:
      val = replica_client.get('example_key')
      print(f'Successfully read value: {val}')
  except redis.RedisError as e:
      print(f'Failed to read from replica: {e}')

if __name__ == '__main__':
  main()