Menggunakan Memcached: apakah itu praktik yang baik untuk memperbarui cache ketika memperbarui database?

13

Pertanyaan ini tentang praktik terbaik dalam arsitektur.

Arsitektur Kami Saat Ini

Saya memiliki kelas PHP yang mengakses MySQL untuk info pengguna. Sebut saja User. Userdiakses berkali-kali, jadi kami telah menerapkan lapisan cache untuk mengurangi beban.

Lapisan pertama adalah apa yang kita sebut cache "per permintaan". Setelah data diambil dari MySQL, kami menyimpan data di properti pribadi PT User. Permintaan data berikutnya akan mengembalikan properti alih-alih meminta kembali data dari MySQL.

Karena permintaan web hidup dan mati berdasarkan permintaan, cache ini hanya mencegah aplikasi mengakses MySQL lebih dari sekali dalam satu permintaan.

Lapisan kedua kami adalah Memcached. Ketika properti pribadi kosong, kami pertama-tama memeriksa Memcached untuk datanya. Jika Memcached kosong, kami meminta data MySQL, memperbarui Memcached, dan memperbarui properti pribadi User.

Pertanyaan

Aplikasi kita adalah sebuah permainan, dan kadang-kadang sangat penting bahwa beberapa data harus diperbarui. Dalam rentang waktu sekitar lima menit, permintaan baca untuk data pengguna dapat terjadi 10 atau 11 kali; maka pembaruan dapat terjadi. Permintaan baca selanjutnya harus mutakhir atau mekanisme permainan gagal.

Jadi, apa yang kami lakukan adalah mengimplementasikan sepotong kode yang dieksekusi ketika pembaruan basis data terjadi. Kode ini menetapkan kunci dalam Memcached dengan data yang diperbarui, sehingga semua permintaan berikutnya untuk Memcached terbaru.

Apakah ini optimal? Apakah ada masalah kinerja atau "gotcha" lain yang harus kita ketahui ketika mencoba mempertahankan semacam "cache hidup" seperti ini?

Stephen
sumber
Apa hubungannya ini dengan menghapus dan menambahkan kembali data?
Mike Nakis
Memperjelas judul pertanyaan.
Stephen
Mengapa tidak hanya kedaluwarsa data yang di-cache? Memperbarui itu berarti Anda harus memastikan pembaruan tetap terjaga (sehingga jika data baru perlu diperbarui dengan cara ini, Anda harus terus mengubah pembaruan). Kedaluwarsa cache berarti semuanya ditarik baru dari basis data --- dan setiap pembaruan baru tidak memerlukan perubahan baru pada kode pembaruan. Kelemahannya adalah bahwa beban basis data mungkin lebih tinggi.
Peter K.
@ Peter Ya, kami juga memikirkan hal itu. Jika tidak ada masalah lain dengan pendekatan kami saat ini, kami akan mematuhinya. Kalau tidak, kita bisa pergi dengan apa yang telah Anda jelaskan.
Stephen
1
@Stephen Pendekatan yang Anda gambarkan disebut "Write Through Cache", dan merupakan pendekatan yang cukup umum.
Sripathi Krishnan

Jawaban:

10

Rekomendasi saya adalah untuk melihat profil penggunaan Anda dan persyaratan Anda untuk cache.

Saya tidak melihat alasan mengapa Anda meninggalkan data basi di memcached. Saya pikir Anda telah memilih pendekatan yang tepat yaitu: memperbarui DB.

Bagaimanapun, Anda akan membutuhkan pembungkus pada pembaruan DB Anda (yang telah Anda lakukan). Kode Anda untuk memperbarui Pengguna dalam DB dan dalam-RAM juga harus melakukan push to memcached, ATAU kadaluwarsa dalam memcached.

Misalnya - Jika pengguna Anda biasanya melakukan pembaruan satu kali per sesi sebagai bagian dari logout, tidak ada banyak gunanya memperbarui data dalam cache (mis. Total skor tinggi) - Anda harus segera habis masa berlakunya.

Namun JIKA mereka akan memperbarui data (misalnya keadaan permainan saat ini) dan kemudian 0,2 detik kemudian Anda akan memiliki halaman PHP langsung hit yang akan meminta data, Anda ingin segar dalam cache.

jasonk
sumber
3

Saya tidak akan membahasnya seperti yang Anda uraikan. Yang perlu Anda lakukan adalah memutuskan apakah Anda benar-benar MEMBUTUHKAN data yang benar-benar terkini. Kemudian, jika Anda benar-benar membutuhkannya, putuskan bagian mana dari data yang perlu diperbarui setiap saat dan pisahkan dari hal-hal yang dapat di-cache dalam arsitektur Anda.

Misalnya, Anda mungkin ingin memperbarui alamat email pengguna Anda segera setelah mereka mengubahnya, sehingga Anda tidak mengirim email ke alamat yang salah, tetapi tidak mungkin tanggal lahir atau nama pengguna pengguna harus sepenuhnya lengkap. terkini untuk memberikan pengalaman pengguna yang layak. (NB Saya tidak menggunakan contoh arsitektur game karena saya tidak tahu jenis permainan apa yang ditujukan, dan saya pikir yang satu ini cukup mudah dimengerti).

Dengan cara ini Anda memiliki dua set data yang jelas: data cacheable jangka pendek dan jangka panjang. Anda mungkin bisa lolos dengan durasi cache satu menit atau lebih pada data jangka pendek, hanya untuk meringankan beban pada DB, tetapi data jangka panjang dapat dibiarkan dalam cache pada durasi geser selama itu bekas.

Maka Anda harus berurusan dengan pembaruan. Saya pertama kali akan melihat menggunakan pemicu DB untuk hanya menghapus item dari cache setelah mereka kedaluwarsa. Itu akan memaksa lapisan bisnis Anda untuk memicu penyegaran cache pada saat berikutnya permintaan data, membebaskan beberapa ruang dalam cache jika data tidak digunakan (misalnya jika pengguna mengubah alamat email mereka kemudian segera logout) . Jika ini akan menyebabkan masalah kinerja di UI (yaitu, terlalu banyak keterlambatan saat menunggu penyegaran cache) maka Anda dapat melihat cukup memicu panggilan cache setelah item dihapus dari cache. Saya juga ingin mengoptimalkan waktu membaca DB untuk sekumpulan kecil data ini, untuk memastikan bahwa kelambatan yang diinduksi dalam menyegarkan cache minimal (ini harus lebih mudah karena Anda hanya perlu memuat data yang benar-benar Anda butuhkan).

Apa yang tidak akan saya lakukan, dalam keadaan apa pun, adalah menambahkan metode tambahan untuk mengisi cache, karena Anda harus mempertahankan panggilan (dan kait API, dll.) Di dua tempat.

Sedangkan untuk gotcha, hal utama yang perlu Anda perhatikan jika Anda menulis langsung ke cache adalah sinkronisasi. Jika banyak utas mencoba membaca saat Anda melakukan pembaruan diam, Anda mungkin memiliki beberapa masalah data yang tidak valid serius, yang akan mengalahkan titik mencoba menjaga data tetap di tempat pertama.

Ed James
sumber