Pujian untuk memcached
(jchri.st)- 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 daripadaINSERT 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
getsederhana masih bisa mengembalikan nilai default atauNonemeski 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
- Penanganan downtime mudah: pustaka klien sering mengabaikan pengecualian koneksi, dan
- 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
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
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
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
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
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
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
Para developer tampaknya sama sekali tidak menyadari hal ini
Saya rasa itu karena mereka mengganti Memcached dengan Redis dan mengharapkan hal yang sama
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
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
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
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
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