Baru-baru ini saya membaca sebuah artikel di blog 37Signals dan saya bertanya-tanya bagaimana mereka bisa mendapatkan kunci cache.
Semuanya baik dan bagus memiliki kunci cache yang menyertakan stempel waktu objek (ini berarti bahwa ketika Anda memperbarui objek, cache akan tidak valid); tetapi bagaimana Anda kemudian menggunakan kunci cache dalam templat tanpa menyebabkan hit DB untuk objek yang Anda coba ambil dari cache.
Khususnya, bagaimana hal ini memengaruhi hubungan One to Many di mana Anda memberikan Komentar Posting, misalnya.
Contoh dalam Django:
{% for comment in post.comments.all %}
{% cache comment.pk comment.modified %}
<p>{{ post.body }}</p>
{% endcache %}
{% endfor %}
Apakah caching di Rails berbeda dengan hanya permintaan untuk memcached misalnya (saya tahu mereka mengonversi kunci cache Anda ke sesuatu yang berbeda). Apakah mereka juga menyimpan kunci cache?
post.body
dimaksudkancomment.body
?Jawaban:
Untuk melakukan caching dump langsung dari satu objek yang sudah dimuat, ya, Anda tidak mendapatkan apa-apa atau hampir tidak ada. Bukan itu yang dijelaskan oleh contoh-contoh itu - mereka menggambarkan hierarki, di mana setiap perubahan ke sesuatu yang lebih rendah juga harus memicu pembaruan untuk segala sesuatu yang lebih tinggi dalam hierarki.
Contoh pertama, dari blog 37signals, digunakan
Project -> Todolist -> Todo
sebagai hierarki. Contoh populasi mungkin terlihat seperti ini:Jadi, katakanlah
Bang3
sudah diperbarui. Semua orang tuanya juga mendapatkan pembaruan:Maka ketika tiba saatnya untuk merender, memuat
Project
dari basis data pada dasarnya tidak terhindarkan. Anda perlu titik untuk memulai. Namun, karenalast_modified
ini merupakan indikator semua anak-anaknya , itulah yang Anda gunakan sebagai kunci cache sebelum mencoba memuat anak-anak.Sementara posting blog menggunakan templat terpisah, saya akan menyatukannya menjadi satu. Semoga melihat interaksi yang lengkap di satu tempat akan membuatnya sedikit lebih jelas.
Jadi, template Django mungkin terlihat seperti ini:
Katakanlah kita lulus dalam Proyek yang
cache_key
masih ada di cache. Karena kami menyebarkan perubahan ke semua objek terkait ke induk, fakta bahwa kunci tertentu masih ada berarti seluruh konten yang diberikan dapat ditarik dari cache.Jika Proyek tertentu itu baru saja diperbarui - misalnya, seperti di
Foo
atas - maka ia harus membuat anak-anaknya, dan hanya kemudian akan menjalankan permintaan untuk semua Todolists untuk Proyek itu. Demikian juga untuk Todolist tertentu - jika cache_key daftar itu ada, maka todos di dalamnya belum berubah, dan semuanya dapat ditarik dari cache.Perhatikan juga bagaimana saya tidak menggunakan
todo.cache_key
dalam template ini. Itu tidak layak, karena seperti yang Anda katakan dalam pertanyaan,body
telah ditarik dari basis data. Namun, hit basis data bukan satu-satunya alasan Anda menyimpan sesuatu. Sebagai contoh, mengambil teks markup mentah (seperti apa yang kita ketik ke dalam kotak pertanyaan / jawaban di StackExchange) dan mengonversinya menjadi HTML mungkin memerlukan waktu yang cukup agar hasil cache lebih efisien.Jika demikian, loop dalam template mungkin terlihat lebih seperti ini:
Jadi, untuk menyatukan semuanya, mari kembali ke data asli saya di bagian atas jawaban ini. Jika kita mengasumsikan:
Bang3
baru saja diperbaruiexpensive_markup_parser
)Maka ini adalah bagaimana semuanya akan dimuat:
Foo
diambil dari databaseFoo.cache_key
(2014-05-16) tidak ada di cacheFoo.todolists.all()
dipertanyakan:Bar1
danBar2
diambil dari basis dataBar1.cache_key
(2014-05-10) sudah ada di cache ; ambil dan keluarkanBar2.cache_key
(2014-05-16) tidak ada di cacheBar2.todos.all()
dipertanyakan:Bang3
danBang4
diambil dari basis dataBang3.cache_key
(2014-05-16) tidak ada di cache{{ Bang3.body|expensive_markup_parser }}
diberikanBang4.cache_key
(2014-04-01) sudah ada di cache ; ambil dan keluarkanPenghematan dari cache dalam contoh kecil ini adalah:
Bar1.todos.all()
expensive_markup_parser
dihindari 3 kali:Bang1
,Bang2
, danBang4
Dan tentu saja, lain kali dilihat,
Foo.cache_key
akan ditemukan, jadi satu-satunya biaya untuk rendering adalah mengambilFoo
sendiri dari database dan meminta cache.sumber
Contoh Anda bagus jika perlu pengambilan data atau pemrosesan untuk setiap komentar. Jika Anda hanya mengambil tubuh dan menampilkannya - cache tidak akan berguna. Tetapi Anda dapat men-cache semua pohon komentar (termasuk {% untuk%}). Dalam hal ini Anda perlu membatalkannya dengan setiap komentar yang ditambahkan, sehingga Anda dapat memasukkan stempel waktu komentar terakhir atau komentar menghitung di suatu tempat ke dalam Posting dan membangun kunci cache komentar dengannya. Jika Anda lebih suka data yang lebih normal, dan menggunakan komentar hanya pada satu halaman, Anda bisa menghapus kunci cache pada penyimpanan komentar.
Bagi saya, menyimpan jumlah komentar dalam Posting terlihat cukup baik (jika Anda tidak mengizinkan untuk menghapus dan mengedit komentar) - Anda memiliki nilai untuk ditampilkan di mana saja dengan Post dan kunci untuk caching.
sumber