Memcached
 sql >> Teknologi Basis Data >  >> NoSQL >> Memcached

Python + Memcached:Caching Efisien dalam Aplikasi Terdistribusi

Saat menulis aplikasi Python, caching itu penting. Menggunakan cache untuk menghindari penghitungan ulang data atau mengakses database yang lambat dapat memberi Anda peningkatan performa yang luar biasa.

Python menawarkan kemungkinan bawaan untuk caching, dari kamus sederhana hingga struktur data yang lebih lengkap seperti functools.lru_cache . Yang terakhir dapat men-cache item apa pun menggunakan algoritme Least-Recently Used untuk membatasi ukuran cache.

Namun, struktur data tersebut menurut definisi lokal ke proses Python Anda. Saat beberapa salinan aplikasi Anda berjalan di platform besar, menggunakan struktur data dalam memori melarang berbagi konten yang di-cache. Ini bisa menjadi masalah untuk aplikasi skala besar dan terdistribusi.

Oleh karena itu, ketika suatu sistem didistribusikan di seluruh jaringan, itu juga membutuhkan cache yang didistribusikan di seluruh jaringan. Saat ini, ada banyak server jaringan yang menawarkan kemampuan caching—kita telah membahas bagaimana menggunakan Redis untuk caching dengan Django.

Seperti yang akan Anda lihat dalam tutorial ini, memcached adalah opsi bagus lainnya untuk caching terdistribusi. Setelah pengenalan singkat tentang penggunaan memcache dasar, Anda akan mempelajari pola lanjutan seperti "cache dan set" dan menggunakan cache fallback untuk menghindari masalah performa cold cache.


Menginstal memcached

Memcache tersedia untuk banyak platform:

  • Jika Anda menjalankan Linux , Anda dapat menginstalnya menggunakan apt-get install memcached atau yum install memcached . Ini akan menginstal memcached dari paket yang dibuat sebelumnya tetapi Anda juga dapat membuat memcached dari sumber, seperti yang dijelaskan di sini.
  • Untuk macOS , menggunakan Homebrew adalah opsi paling sederhana. Jalankan saja brew install memcached setelah Anda menginstal pengelola paket Homebrew.
  • Di Windows , Anda harus mengompilasi memcached sendiri atau menemukan binari yang telah dikompilasi sebelumnya.

Setelah diinstal, memcache dapat dengan mudah diluncurkan dengan memanggil memcached perintah:

$ memcached

Sebelum Anda dapat berinteraksi dengan memcached dari Python-land, Anda harus menginstal klien memcached Perpustakaan. Anda akan melihat cara melakukannya di bagian berikutnya, bersama dengan beberapa operasi akses cache dasar.



Menyimpan dan Mengambil Nilai Cache Menggunakan Python

Jika Anda tidak pernah menggunakan memcached , cukup mudah dipahami. Ini pada dasarnya menyediakan kamus jaringan yang tersedia raksasa. Kamus ini memiliki beberapa properti yang berbeda dari kamus Python klasik, terutama:

  • Kunci dan nilai harus berupa byte
  • Kunci dan nilai dihapus secara otomatis setelah waktu kedaluwarsa

Oleh karena itu, dua operasi dasar untuk berinteraksi dengan memcached adalah set dan gets . Seperti yang mungkin sudah Anda duga, masing-masing digunakan untuk menetapkan nilai ke kunci atau untuk mendapatkan nilai dari kunci.

Pustaka Python pilihan saya untuk berinteraksi dengan memcached adalah pymemcache —Saya sarankan menggunakannya. Anda cukup menginstalnya menggunakan pip:

$ pip install pymemcache

Kode berikut menunjukkan bagaimana Anda dapat terhubung ke memcached dan gunakan sebagai cache yang didistribusikan ke jaringan di aplikasi Python Anda:

>>> from pymemcache.client import base

# Don't forget to run `memcached' before running this next line:
>>> client = base.Client(('localhost', 11211))

# Once the client is instantiated, you can access the cache:
>>> client.set('some_key', 'some value')

# Retrieve previously set data again:
>>> client.get('some_key')
'some value'

memcache protokol jaringan sangat sederhana dan implementasinya sangat cepat, yang membuatnya berguna untuk menyimpan data yang seharusnya lambat diambil dari sumber data kanonik atau untuk menghitung lagi:

Meskipun cukup sederhana, contoh ini memungkinkan penyimpanan tupel kunci/nilai di seluruh jaringan dan mengaksesnya melalui banyak salinan aplikasi Anda yang terdistribusi dan berjalan. Ini sederhana, namun kuat. Dan ini adalah langkah awal yang bagus untuk mengoptimalkan aplikasi Anda.



Data Tembolok Secara Otomatis Kedaluwarsa

Saat menyimpan data ke dalam memcached , Anda dapat menyetel waktu kedaluwarsa—jumlah detik maksimum untuk memcache untuk menjaga kunci dan nilai tetap ada. Setelah penundaan itu, memcache secara otomatis menghapus kunci dari cache-nya.

Apa yang harus Anda atur waktu cache ini? Tidak ada angka ajaib untuk penundaan ini, dan itu sepenuhnya akan tergantung pada jenis data dan aplikasi yang Anda gunakan. Bisa beberapa detik, atau mungkin beberapa jam.

Pembatalan cache , yang menentukan kapan harus menghapus cache karena tidak sinkron dengan data saat ini, juga merupakan sesuatu yang harus ditangani oleh aplikasi Anda. Apalagi jika menyajikan data yang terlalu tua atau atau basi harus dihindari.

Di sini sekali lagi, tidak ada resep ajaib; itu tergantung pada jenis aplikasi yang Anda buat. Namun, ada beberapa kasus luar yang harus ditangani—yang belum kita bahas dalam contoh di atas.

Server caching tidak dapat tumbuh tanpa batas—memori adalah sumber daya yang terbatas. Oleh karena itu, kunci akan dihapus oleh server caching segera setelah membutuhkan lebih banyak ruang untuk menyimpan hal-hal lain.

Beberapa kunci mungkin juga kedaluwarsa karena telah mencapai waktu kedaluwarsa (kadang-kadang juga disebut "time-to-live" atau TTL.) Dalam kasus tersebut, data hilang, dan sumber data kanonik harus ditanyakan lagi.

Ini terdengar lebih rumit daripada yang sebenarnya. Anda biasanya dapat bekerja dengan pola berikut saat bekerja dengan memcached dengan Python:

from pymemcache.client import base


def do_some_query():
    # Replace with actual querying code to a database,
    # a remote REST API, etc.
    return 42


# Don't forget to run `memcached' before running this code
client = base.Client(('localhost', 11211))
result = client.get('some_key')

if result is None:
    # The cache is empty, need to get the value
    # from the canonical source:
    result = do_some_query()

    # Cache the result for next time:
    client.set('some_key', result)

# Whether we needed to update the cache or not,
# at this point you can work with the data
# stored in the `result` variable:
print(result)

Catatan: Menangani kunci yang hilang adalah wajib karena operasi flush-out normal. Juga wajib untuk menangani skenario cold cache, yaitu ketika memcache baru saja dimulai. Dalam hal ini, cache akan sepenuhnya kosong dan cache perlu diisi ulang sepenuhnya, satu permintaan pada satu waktu.

Ini berarti Anda harus melihat data yang di-cache sebagai sementara. Dan Anda tidak boleh mengharapkan cache berisi nilai yang sebelumnya Anda tulis.



Memanaskan Cache Dingin

Beberapa skenario cache dingin tidak dapat dicegah, misalnya memcache menabrak. Tetapi beberapa dapat, misalnya bermigrasi ke memcache baru server.

Ketika dimungkinkan untuk memprediksi bahwa skenario cache dingin akan terjadi, lebih baik untuk menghindarinya. Cache yang perlu diisi ulang berarti bahwa tiba-tiba, penyimpanan kanonik dari data yang di-cache akan diserang secara besar-besaran oleh semua pengguna cache yang kekurangan data cache (juga dikenal sebagai masalah thundering herd.)

pymemcache menyediakan kelas bernama FallbackClient yang membantu dalam menerapkan skenario ini seperti yang ditunjukkan di sini:

from pymemcache.client import base
from pymemcache import fallback


def do_some_query():
    # Replace with actual querying code to a database,
    # a remote REST API, etc.
    return 42


# Set `ignore_exc=True` so it is possible to shut down
# the old cache before removing its usage from 
# the program, if ever necessary.
old_cache = base.Client(('localhost', 11211), ignore_exc=True)
new_cache = base.Client(('localhost', 11212))

client = fallback.FallbackClient((new_cache, old_cache))

result = client.get('some_key')

if result is None:
    # The cache is empty, need to get the value 
    # from the canonical source:
    result = do_some_query()

    # Cache the result for next time:
    client.set('some_key', result)

print(result)

FallbackClient menanyakan cache lama yang diteruskan ke konstruktornya, dengan menghormati pesanan. Dalam hal ini, server cache yang baru akan selalu ditanyakan terlebih dahulu, dan jika cache hilang, yang lama akan ditanyakan—menghindari kemungkinan perjalanan kembali ke sumber data utama.

Jika ada kunci yang disetel, itu hanya akan disetel ke cache baru. Setelah beberapa waktu, cache lama dapat dinonaktifkan dan FallbackClient dapat diganti diarahkan dengan new_cache klien.



Periksa Dan Setel

Saat berkomunikasi dengan cache jarak jauh, masalah konkurensi yang biasa muncul kembali:mungkin ada beberapa klien yang mencoba mengakses kunci yang sama secara bersamaan. memcache menyediakan periksa dan setel operasi, disingkat menjadi CAS , yang membantu memecahkan masalah ini.

Contoh paling sederhana adalah aplikasi yang ingin menghitung jumlah pengguna yang dimilikinya. Setiap kali pengunjung terhubung, penghitung bertambah 1. Menggunakan memcached , implementasi sederhananya adalah:

def on_visit(client):
    result = client.get('visitors')
    if result is None:
        result = 1
    else:
        result += 1
    client.set('visitors', result)

Namun, apa yang terjadi jika dua contoh aplikasi mencoba memperbarui penghitung ini secara bersamaan?

Panggilan pertama client.get('visitors') akan mengembalikan jumlah pengunjung yang sama untuk keduanya, misalkan 42. Kemudian keduanya akan menambah 1, menghitung 43, dan menetapkan jumlah pengunjung menjadi 43. Angka itu salah, dan hasilnya harus 44, yaitu 42 + 1 + 1.

Untuk mengatasi masalah konkurensi ini, operasi CAS memcache berguna. Cuplikan berikut mengimplementasikan solusi yang benar:

def on_visit(client):
    while True:
        result, cas = client.gets('visitors')
        if result is None:
            result = 1
        else:
            result += 1
        if client.cas('visitors', result, cas):
            break

gets metode mengembalikan nilai, seperti gets metode, tetapi juga mengembalikan nilai CAS .

Apa yang ada dalam nilai ini tidak relevan, tetapi digunakan untuk metode berikutnya cas panggilan. Metode ini setara dengan set operasi, kecuali gagal jika nilainya telah berubah sejak gets operasi. Dalam kasus sukses, loop rusak. Jika tidak, operasi akan dimulai ulang dari awal.

Dalam skenario di mana dua instance aplikasi mencoba memperbarui penghitung secara bersamaan, hanya satu yang berhasil memindahkan penghitung dari 42 ke 43. Instance kedua mendapatkan False nilai yang dikembalikan oleh client.cas panggilan, dan harus mencoba ulang loop. Ini akan mengambil 43 sebagai nilai kali ini, akan menambahnya menjadi 44, dan cas panggilan akan berhasil, sehingga memecahkan masalah kita.

Menambah penghitung menarik sebagai contoh untuk menjelaskan cara kerja CAS karena sederhana. Namun, memcache juga menyediakan incr dan decr metode untuk menambah atau mengurangi bilangan bulat dalam satu permintaan, daripada melakukan beberapa gets /cas panggilan. Dalam aplikasi dunia nyata gets dan cas digunakan untuk tipe data atau operasi yang lebih kompleks

Sebagian besar server caching jarak jauh dan penyimpanan data menyediakan mekanisme seperti itu untuk mencegah masalah konkurensi. Sangat penting untuk menyadari kasus-kasus tersebut untuk memanfaatkan fitur-fiturnya dengan benar.



Di Luar Caching

Teknik sederhana yang diilustrasikan dalam artikel ini menunjukkan betapa mudahnya memanfaatkan memcached untuk mempercepat kinerja aplikasi Python Anda.

Hanya dengan menggunakan dua operasi "set" dan "get" dasar, Anda sering kali dapat mempercepat pengambilan data atau menghindari penghitungan ulang hasil berulang kali. Dengan memcached Anda dapat berbagi cache di sejumlah besar node terdistribusi.

Pola lain yang lebih canggih yang Anda lihat dalam tutorial ini, seperti Check And Set (CAS) operasi memungkinkan Anda untuk memperbarui data yang disimpan dalam cache secara bersamaan di beberapa utas atau proses Python sambil menghindari kerusakan data.

Jika Anda tertarik untuk mempelajari lebih lanjut tentang teknik lanjutan untuk menulis aplikasi Python yang lebih cepat dan skalabel, lihat Scaling Python. Ini mencakup banyak topik lanjutan seperti distribusi jaringan, sistem antrian, hashing terdistribusi, dan pembuatan profil kode.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Instal Memcached di Ubuntu 16.04

  2. Cara memeriksa koneksi antara mysql dan memcached di php

  3. Cara Menggunakan Memcached Dengan Yii2 Framework

  4. Menginstal Memcached Pada CentOS 8

  5. Menginstal Memcached Pada Debian 9