1 poin oleh GN⁺ 4 jam lalu | 1 komentar | Bagikan ke WhatsApp
  • Cache hadir untuk mengurangi beban database, tetapi alat yang mudah digunakan seperti Redis seiring waktu mudah menjadi sesuatu yang diandalkan seperti penyimpanan persisten
  • Masalahnya bukan pada fitur persistensi Redis, melainkan pada alur operasional ketika komponen yang awalnya diperkenalkan sebagai cache volatil menjadi terikat dengan status inti aplikasi
  • Sejak definisi resminya, memcached adalah sistem caching objek memori terdistribusi dan tidak mengandaikan penyimpanan ke disk, sehingga lebih mudah diperlakukan sebagai beban kerja cache tanpa status
  • Beberapa instance memcached dibagi bukan oleh server melainkan oleh klien menggunakan daftar URL dan hash kunci, dan node yang gagal akan dikeluarkan dari hasher lalu dicoba sambungkan kembali nanti
  • Daripada langsung menambahkan cache karena “database lambat”, sebaiknya periksa dulu kueri lambat dan indeks yang hilang

Saat Redis berubah dari cache menjadi penyimpanan

  • Saat mengelola infrastruktur, permintaan “kita butuh cache” sering muncul, dan Redis yang familier serta kaya fitur mudah menjadi pilihan pertama yang terlintas
  • Situs Redis menonjolkan Redis Iris, mesin konteks real-time untuk aplikasi AI, tetapi arah ini bisa dipahami mengingat Redis adalah perusahaan yang harus menghasilkan pendapatan
  • Setelah Redis di-deploy dan string koneksinya dibagikan, pada awalnya ia bekerja seperti cache yang andal

Masalah yang muncul beberapa bulan kemudian

  • Seiring waktu, karena cache.set("key", "value") jauh lebih sederhana daripada INSERT INTO table VALUES ('key', 'value'), orang mulai memperlakukan Redis seperti ini
    • Sebagai komponen yang selalu ada, tempat menyimpan data. Sebuah database de facto
    • Orang mulai memandang REmote DIctionary Server sebagai penyimpanan permanen, bukan cache volatil
  • Anda dan rekan-rekan tim operasi Anda mungkin tidak menyadari hal ini, dan karena mengira cache akan diasumsikan volatil, sistem alerting pun tidak mendeteksinya
    • Masalah baru terlihat ketika sesuatu dilakukan pada Redis, seperti upgrade, pemindahan node, atau insiden semacam tray HDD server RAID0 terlepas
  • Masalah intinya bukan bahwa Redis tidak memiliki fitur persistensi, tetapi ketidaksesuaian asumsi bahwa Redis yang diperkenalkan sebagai cache tidak diperlakukan orang seperti cache
  • Saat ketergantungan ini ditemukan terlambat, Redis sudah terlalu dalam terjalin dengan aplikasi sehingga sulit dihapus, dan pada akhirnya harus dirawat dan dimonitor seperti “hewan peliharaan”

Mengapa memcached lebih langsung untuk peran cache

  • memcached adalah “gratis, open-source, berkinerja tinggi, sistem caching objek memori terdistribusi” dan merupakan cache umum untuk mempercepat aplikasi web dinamis dengan mengurangi beban database
  • Dalam framework yang mendukung caching yang dapat dipasang seperti Django, backend cache bisa diganti
  • Meski fiturnya lebih sedikit daripada Redis, ada alasan untuk memilih memcached karena karakteristik operasionalnya lebih sederhana
    • Penanganan downtime mudah: pustaka klien sering mengabaikan pengecualian koneksi, dan get sederhana masih bisa mengembalikan nilai default atau None meski server mati
    • memcached tidak memiliki fitur clustering bawaan, justru membuat clustering lebih praktis
      • Jika beberapa URL diatur pada pustaka klien, instance target dipilih berdasarkan hash kunci
      • Saat panggilan klien mendeteksi instance mati, ia akan menghapus node dari hasher lalu otomatis mencoba menyambung kembali setelah beberapa waktu
    • Beban persistensi berkurang secara struktural: memcached tidak menyimpan ke disk sehingga cocok dijadwalkan di mana saja sebagai beban kerja tanpa status
  • Pola operasional serupa memang bisa dibuat dengan Redis, tetapi arsitektur memcached lebih dekat ke arah ini sehingga lebih intuitif diperlakukan sebagai cache
  • memcached adalah aplikasi yang relatif sederhana, dan fakta bahwa menjalankan puluhan instance dengan ukuran cache sekitar 64MB hampir tidak menimbulkan overhead menjadi alasan memilihnya
  • Banyak masalah “database lambat” sebenarnya berawal dari kueri lambat atau indeks yang hilang, jadi selain menambahkan cache, optimasi kueri juga perlu diperiksa
  • Jika penasaran dengan keputusan desain memcached, ada banyak tulisan menarik di blog memcached, salah satunya artikel bulan Mei “How Long Does That Response Take… For Real?”

1 komentar

 
GN⁺ 4 jam lalu
Komentar Hacker News
  • Redis adalah teknologi yang hebat, tetapi menurut saya ia kesulitan karena berusaha menjalankan dua peran berbeda sekaligus dengan baik: struktur data persisten dan cache volatil
    Bahkan di Redis sendiri, keduanya tidak terlalu menyatu dengan baik, sehingga persistensi pada dasarnya dinyalakan atau dimatikan secara global
    Untuk cache murni, saya akan memakai memcached atau yang setara, dan hanya memakai Redis dengan persistensi aktif saat membutuhkan struktur data seperti papan skor
    Di $WORK, kami tidak mengadopsi keduanya, dan untuk lapisan cache pekerjaan lambat kami menaruh data baik di filesystem maupun di tabel DB yang dipakai seperti penyimpanan key-value
    DB membantu mengoordinasikan thundering herd, pembacaan dari server yang sama hanya menyentuh filesystem, dan pembacaan dari server lain melihat DB sekali lalu menyimpannya di filesystem
    Lapisan filesystem itu bisa saja diganti dengan memcached, tetapi sejauh ini cara sekarang bekerja dengan sangat baik

    • Setelah pernah menangani Memcachedb (memcache + bdb untuk persistensi) pada akhir 2000-an, saya sampai pada kesimpulan yang hampir sama
      Redis jelas punya lebih banyak fitur, dan antirez juga sosok yang menarik sekaligus sangat rendah hati, jadi saya paham mengapa Redis menjadi lebih populer
      Meski begitu, bagi saya memcached selalu menjadi puncak dari prinsip pilih teknologi yang membosankan
      Sebagai platform engineer, saya bisa mendukung keduanya, tetapi kalau developer mulai memakai fitur Redis yang lebih canggih seperti persistensi, replikasi, dan clustering, saya akan mencoba memastikan mereka benar-benar memahami sisi negatif dari keputusan itu
    • Hanya dengan memakai tabel DB seperti penyimpanan key-value dan menambahkan filesystem, sebenarnya ada sangat banyak hal yang bisa dilakukan sebelum membayar biaya menyiapkan penyimpanan cache khusus
      Setiap kali mengusulkan solusi seperti ini, saya sudah tak terhitung kali berdebat dengan orang-orang yang kurang berpengalaman dan merasa cache harus selalu berada di penyimpanan khusus dalam praktik engineering
  • Memakai memcache sama sekali tidak otomatis menghindarkan masalah-masalah ini
    Pada pertengahan 2000-an saya pernah menangani sistem skala besar yang memakai memcache, dan para developer jatuh ke jebakan yang persis sama seperti contoh Redis di artikel
    Mereka mencoba mengakali hukum sistem terdistribusi dengan memcache, lalu karena cache addiction, ukuran cluster server ditentukan dengan asumsi memcache selalu aktif, sehingga saat terjadi gangguan semuanya meledak seperti DDoS
    Ada juga write amplification ketika satu host menghapus key dengan TPS tinggi lalu semua host lain memukul service dependensi untuk mengisi ulang key itu, hot key menciptakan hot host, dan memcached dijalankan bersama service daemon hingga memicu lonjakan CPU misterius
    Panggilan memcache juga pernah masuk ke black hole karena sifat lengket entri DNS lama
    Semua itu sebenarnya bisa dihindari kalau memcache dipakai dengan lebih baik, tetapi godaan untuk menyalahgunakannya terlalu besar

  • Masalah Redis/Valkey yang disebut penulis sepertinya hampir semuanya pernah saya lihat di production
    Pernah ada insiden ketika Valkey tidak punya kebijakan memori sehingga memakan semua memori dan menyebabkan error penulisan append-only file, dan ada juga kasus penulisan AOF gagal karena disk benar-benar penuh
    Pernah juga Redis hidup, berjalan, dan sepenuhnya diasumsikan berisi semua data pengguna, tetapi karena tidak ada mekanisme untuk kembali ke jalur lambat, hasilnya muncul error 500
    Ada juga kasus penggunaan sorted set dan struktur data lain secara kreatif sambil bergantung pada asumsi bahwa kumpulan itu tidak akan pernah dieviction
    Meski sudah melihat semua itu di lapangan, saya tetap merasa sulit merekomendasikan memcache lebih dulu daripada Redis
    Mendesain aplikasi agar punya tata letak cache yang ramah memcache bisa cukup rumit, dan jika tim yang cukup besar memakai memcache, sangat besar kemungkinan mereka pada akhirnya menemukan jalan yang membuat mereka membutuhkan Redis
    Maka Anda akhirnya harus memelihara 2 teknologi cache

    • Kalau seseorang memutuskan memakai Redis untuk hal selain cache, pada dasarnya mereka sudah punya 2 teknologi cache
      Instance Redis yang dikonfigurasi untuk cache tidak bisa dipakai untuk tujuan lain, instance cache harus punya eviction, dan instance non-cache tidak boleh punya eviction
      Pada akhirnya Anda memerlukan Redis kedua dengan konfigurasi berbeda
      Sejujurnya, mendesain aplikasi dengan tata letak cache yang ramah memcache sama saja dengan mendesainnya agar ramah Redis
      Pola cache aplikasi seperti ini identik: ambil, kalau tidak ada maka hitung lalu set
    • Kalau belum ada, saya akan membuat abstraction interface sehingga saat meminta key, kita juga memberikan fungsi async atau lambda untuk mengambil nilai dari sumber asal ketika terjadi cache miss
      var value = cache.lookup( keyname, () => db.query(...), TimeSpan.FromMinutes(5) // or CacheOptions );
      Dengan begitu, saat cache miss kita bisa langsung menuju jalur fallback atau melakukan insert
    • Tidak perlu memelihara 2 teknologi cache selalu merupakan argumen yang menang
  • Fitur lain pada memcache yang jarang dibahas adalah bahwa semua operasinya secara desain bersifat O(1)
    Ini adalah pilihan desain yang sengaja diambil para pembuatnya, jadi meski ada keterbatasan, ia menjamin tidak ada operasi sederhana yang tiba-tiba berhenti secara acak
    Sebaliknya, Redis memakai desain inti single-threaded sehingga bisa menjalankan operasi dengan kompleksitas arbitrer, dan dari sudut pandang developer itu mungkin terasa pintar untuk digunakan, tetapi sampai operasi itu selesai semua yang lain harus menunggu

  • Dalam proyek open source atau program yang dipelihara jangka panjang, hal seperti ini sering terjadi
    Saat codebase membesar, pada akhirnya mulai mendukung hal-hal yang awalnya tidak direncanakan
    Ketika fitur bertambah banyak, pengguna juga bertambah; sebagian orang hanya memakai fitur lama, sebagian lain menerima fitur baru, dan pada akhirnya nilai tertentu menjadi default de facto sehingga tidak lagi tampak sebagai sesuatu yang opsional
    Jika memakai Redis sebagai contoh, ketika AOF dimatikan ia bekerja sebagai cache in-memory yang volatil, tetapi kebanyakan orang bahkan tidak memikirkannya seperti itu
    Karena itu muncul logika bahwa lebih sedikit fitur dan lebih sederhana itu lebih baik, dan dalam konteks ini Memcached adalah contoh dari pendekatan straitjacket seperti itu
    Itu sangat masuk akal untuk tim besar, tetapi proyek open source membutuhkan pembaruan rutin agar terus mendapatkan pendanaan atau kontribusi, jadi ada ketegangan yang melekat
    Terkadang ini berujung pada fork atau proyek turunan yang terspesialisasi untuk satu ceruk tertentu
    Secara pribadi, menurut saya tidak ada jawaban yang benar dan semuanya bergantung pada konteks
    Karena komunikasi itu sendiri juga tidak gratis

    • Fakta bahwa komunikasi tidak gratis adalah masalah yang saya miliki terhadap microservices
      Para developer tampaknya sama sekali tidak menyadari hal ini
    • Contoh paling jelas adalah orang-orang mengira Redis hanya bekerja sebagai cache yang kehilangan data saat crash atau shutdown
      Saya rasa itu karena mereka mengganti Memcached dengan Redis dan mengharapkan hal yang sama
    • Pada skala besar, AOF justru menyebabkan gangguan, jadi akhirnya dimatikan
      Meski begitu, itu tetap cache yang hebat
  • Selama beberapa tahun terakhir saya cukup banyak mengerjakan Flask, dan meski bukan full-time, saya memakainya sebagai bagian dari tech stack bisnis e-commerce kecil
    Di stack Python untuk MongoEngine, SQLAlchemy, Celery, dan Google/eBay/Shopify, saya pernah menemui berbagai ranjau darat dan keanehan, tetapi tidak pernah dengan Redis
    Mungkin karena saya tidak memberi hak admin kepada siapa pun yang menganggap Redis sebagai penyimpanan persisten, tetapi sejujurnya saya ingin menggambarkan Redis sebagai teknologi yang sangat tangguh dan dirancang dengan baik
    API-nya sangat sederhana, dan setiap kali perlu melakukan sesuatu yang agak aneh, ada cara yang masuk akal dan dipikirkan dengan matang untuk melakukannya

    • Saya sedang memulai proyek dengan Flask, SQLAlchemy, dan Celery sekarang, jadi saya ingin mendengar lebih banyak tentang mengapa harus menghindari Celery dan apa penggantinya
    • Di dunia saya, sistem cache seperti memcached dan Redis hanyalah cache untuk menyimpan dan mengambil
      Mungkin saya bisa memakai sistem invalidasi seperti tagging
      Saya sungguh penasaran apa saja hal aneh yang bisa dilakukan dengan sistem cache, dan selain sekadar meng-cache data, apa yang sebenarnya orang lakukan dengan cache
  • Saya suka memcached, tetapi jika Redis dikonfigurasi sebagai cache volatil lalu orang-orang memperlakukannya seperti penyimpanan data persisten, itu bukan salah Redis
    Perbandingannya juga terasa sangat aneh karena memcached juga tidak persisten

    • Di banyak perusahaan, mungkin sebagian besar, Redis dipahami dan dioperasikan bukan sebagai cache yang boleh hilang kapan saja, melainkan sebagai database produksi yang benar-benar durable
      Jika tidak diberi tahu sebaliknya, tidak aneh juga bila developer baru berasumsi seperti itu
  • Memcached adalah penyelamat caching pada masa perilisannya
    Menarik juga bahwa ia dibuat oleh Brad Fitzpatrick untuk LiveJournal pada 2003
    Setiap posting di feed pengguna bisa memiliki pembatasan akses yang berbeda, dan berkat itu posting maupun seluruh halaman bisa di-cache
    Saya memakainya selama bertahun-tahun bersama Ruby on Rails, halaman jadi lebih cepat, dan semuanya berjalan dengan baik
    Kekurangannya, sekaligus keunggulannya dari sisi kecepatan, adalah bahwa cache disimpan di memori, bukan di disk
    Jika data yang perlu di-cache sangat besar dan situsnya berskala besar, biaya hosting bisa menjadi mahal
    Dalam kasus seperti itu, Solid Cache adalah penyelamat bagi saya
    Pada proyek yang sedang saya kerjakan sekarang, cache-nya lebih dari 100GB, disimpan di disk PostgreSQL, dicari dengan cepat menggunakan indeks, dan Rails otomatis menangani kedaluwarsa lalu menghapus baris terkait
    Jika skala cache lebih kecil dan Anda sudah memakai Redis, saya mungkin akan langsung memakai Redis
    Tetapi jika kecepatan adalah prioritas nomor satu, saya akan membandingkan Memcached dan Redis dengan benchmark

  • Fakta bahwa memcached bersifat sementara, dan apakah orang akan memakainya seolah-olah persisten, adalah dua hal yang terpisah
    Jika cache hit rate tampak seperti 99,9% dan datanya selalu ada, cepat atau lambat seseorang akan menulis kode yang bergantung pada perilaku itu
    Saya pikir mungkin di mode development pustaka klien bisa membantu dengan mengembalikan null sekitar 10% dari waktu

  • memcached luar biasa lebih cepat daripada Redis untuk pekerjaan cache key-value yang sederhana
    Ia punya thread dan sangat dioptimalkan untuk melakukan satu hal dengan sangat baik
    Sementara Redis terasa lebih mirip heap Python bersama yang arbitrer dengan semua struktur data dan sifat single-threaded-nya
    Di Notion, Redis dipakai untuk berbagai hal, tetapi caching yang sebenarnya diserahkan ke memcached

    • Bisa dipastikan bahwa untuk key-value perbedaannya tidak sampai sejauh itu
      Rata-ratanya sekitar 300 mikrodetik vs 350 mikrodetik per read
      Fakta bahwa ia single-threaded juga tidak terlalu penting, karena bottleneck-nya bukan CPU melainkan I/O reaktif
    • Thread tidak gratis
      Mereka memungkinkan penggunaan lebih banyak core CPU, tetapi jika bebannya tidak terlalu tinggi, memcached single-threaded justru memakai CPU lebih sedikit daripada yang multi-threaded