Memcached
 sql >> Cơ Sở Dữ Liệu >  >> NoSQL >> Memcached

Python + Memcached:Bộ nhớ đệm hiệu quả trong các ứng dụng phân tán

Khi viết các ứng dụng Python, bộ nhớ đệm là rất quan trọng. Sử dụng bộ nhớ đệm để tránh tính toán lại dữ liệu hoặc truy cập vào cơ sở dữ liệu chậm có thể cung cấp cho bạn hiệu suất cao.

Python cung cấp các khả năng tích hợp cho bộ nhớ đệm, từ một từ điển đơn giản đến một cấu trúc dữ liệu hoàn chỉnh hơn, chẳng hạn như functools.lru_cache . Sau này có thể lưu vào bộ nhớ cache bất kỳ mục nào bằng thuật toán Ít được sử dụng gần đây để giới hạn kích thước bộ nhớ cache.

Tuy nhiên, các cấu trúc dữ liệu đó là cục bộ cho quy trình Python của bạn. Khi một số bản sao của ứng dụng của bạn chạy trên một nền tảng lớn, việc sử dụng cấu trúc dữ liệu trong bộ nhớ không cho phép chia sẻ nội dung đã lưu trong bộ nhớ cache. Đây có thể là một vấn đề đối với các ứng dụng phân tán và quy mô lớn.

Do đó, khi một hệ thống được phân phối trên một mạng, nó cũng cần một bộ đệm ẩn được phân phối trên một mạng. Ngày nay, có rất nhiều máy chủ mạng cung cấp khả năng lưu vào bộ nhớ đệm — chúng tôi đã trình bày cách sử dụng Redis để lưu vào bộ nhớ đệm với Django.

Như bạn sẽ thấy trong hướng dẫn này, memcached là một lựa chọn tuyệt vời khác cho bộ nhớ đệm phân tán. Sau phần giới thiệu nhanh về cách sử dụng bộ nhớ đệm cơ bản, bạn sẽ tìm hiểu về các mẫu nâng cao, chẳng hạn như “bộ đệm và đặt” và sử dụng bộ đệm dự phòng để tránh các vấn đề về hiệu suất bộ đệm lạnh.


Cài đặt memcached

Bản ghi nhớ có sẵn cho nhiều nền tảng:

  • Nếu bạn chạy Linux , bạn có thể cài đặt nó bằng cách sử dụng apt-get install memcached hoặc yum install memcached . Điều này sẽ cài đặt memcached từ một gói được tạo sẵn nhưng bạn có thể xây dựng memcached từ nguồn, như được giải thích ở đây.
  • Đối với macOS , sử dụng Homebrew là lựa chọn đơn giản nhất. Chỉ cần chạy brew install memcached sau khi bạn đã cài đặt trình quản lý gói Homebrew.
  • Trên Windows , bạn sẽ phải tự biên dịch bản ghi nhớ hoặc tìm các tệp nhị phân được biên dịch trước.

Sau khi cài đặt, memcached chỉ có thể được khởi chạy bằng cách gọi memcached lệnh:

$ memcached

Trước khi có thể tương tác với memcached từ Python-land, bạn cần cài đặt một ứng dụng khách memcached thư viện. Bạn sẽ thấy cách thực hiện việc này trong phần tiếp theo, cùng với một số thao tác truy cập bộ nhớ cache cơ bản.



Lưu trữ và truy xuất các giá trị được lưu trong bộ nhớ đệm bằng Python

Nếu bạn chưa bao giờ sử dụng memcached , nó khá dễ hiểu. Về cơ bản, nó cung cấp một từ điển có sẵn trên mạng khổng lồ. Từ điển này có một số thuộc tính khác với một nhị phân Python cổ điển, chủ yếu là:

  • Các khóa và giá trị phải là byte
  • Các khóa và giá trị sẽ tự động bị xóa sau một thời gian hết hạn

Do đó, hai thao tác cơ bản để tương tác với memcached được setget . Như bạn có thể đoán, chúng được sử dụng để gán giá trị cho một khóa hoặc để nhận giá trị từ một khóa, tương ứng.

Thư viện Python ưa thích của tôi để tương tác với memcached pymemcache —Tôi khuyên bạn nên sử dụng nó. Bạn chỉ cần cài đặt nó bằng pip:

$ pip install pymemcache

Đoạn mã sau cho biết cách bạn có thể kết nối với memcached và sử dụng nó như một bộ đệm ẩn được phân phối trên mạng trong các ứng dụng Python của bạn:

>>> 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'

memcached giao thức mạng thực sự đơn giản, việc triển khai nó cực kỳ nhanh chóng, điều này làm cho việc lưu trữ dữ liệu sẽ rất chậm để truy xuất từ ​​nguồn dữ liệu chuẩn hoặc để tính toán lại:

Mặc dù đủ đơn giản, nhưng ví dụ này cho phép lưu trữ các bộ giá trị / khóa trên toàn mạng và truy cập chúng thông qua nhiều bản sao ứng dụng của bạn đang chạy, được phân phối. Điều này là đơn giản, nhưng mạnh mẽ. Và đó là bước đầu tiên tuyệt vời để tối ưu hóa ứng dụng của bạn.



Tự động hết hạn dữ liệu được lưu trong bộ nhớ đệm

Khi lưu trữ dữ liệu vào memcached , bạn có thể đặt thời gian hết hạn — số giây tối đa cho memcached để giữ chìa khóa và giá trị xung quanh. Sau thời gian trì hoãn đó, memcached tự động xóa khóa khỏi bộ nhớ cache của nó.

Bạn nên đặt thời gian bộ nhớ cache này thành gì? Không có con số kỳ diệu nào cho sự chậm trễ này, và nó sẽ hoàn toàn phụ thuộc vào loại dữ liệu và ứng dụng mà bạn đang làm việc. Có thể là vài giây hoặc có thể là vài giờ.

Vô hiệu bộ nhớ cache , xác định thời điểm xóa bộ nhớ cache vì nó không đồng bộ với dữ liệu hiện tại, cũng là thứ mà ứng dụng của bạn sẽ phải xử lý. Đặc biệt nếu trình bày dữ liệu quá cũ hoặc là điều cần tránh.

Ở đây một lần nữa, không có công thức kỳ diệu nào; nó phụ thuộc vào loại ứng dụng bạn đang xây dựng. Tuy nhiên, có một số trường hợp ngoại lệ cần được xử lý — mà chúng tôi chưa đề cập đến trong ví dụ trên.

Một máy chủ bộ nhớ đệm không thể phát triển vô hạn — bộ nhớ là một tài nguyên hữu hạn. Do đó, các khóa sẽ bị xóa bởi máy chủ bộ nhớ đệm ngay khi nó cần thêm dung lượng để lưu trữ những thứ khác.

Một số khóa cũng có thể hết hạn vì chúng đã đến thời gian hết hạn (đôi khi còn được gọi là “thời gian tồn tại” hoặc TTL.) Trong những trường hợp đó, dữ liệu bị mất và nguồn dữ liệu chuẩn phải được truy vấn lại.

Điều này nghe có vẻ phức tạp hơn thực tế. Nói chung, bạn có thể làm việc với mẫu sau khi làm việc với memcached trong 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)

Lưu ý: Xử lý các khóa bị thiếu là bắt buộc vì các hoạt động xả thông thường. Nó cũng bắt buộc phải xử lý kịch bản bộ đệm lạnh, tức là khi memcached mới được bắt đầu. Trong trường hợp đó, bộ nhớ đệm sẽ hoàn toàn trống và bộ đệm cần được tạo lại hoàn toàn, mỗi lần một yêu cầu.

Điều này có nghĩa là bạn nên xem mọi dữ liệu đã lưu trong bộ nhớ cache là tạm thời. Và bạn đừng bao giờ mong đợi bộ nhớ đệm chứa một giá trị mà bạn đã ghi trước đó vào nó.



Làm nóng bộ nhớ cache nguội

Không thể ngăn chặn một số trường hợp bộ đệm lạnh, ví dụ: memcached tai nạn. Nhưng một số có thể, ví dụ:di chuyển sang memcached mới máy chủ.

Khi có thể dự đoán rằng một kịch bản cache lạnh sẽ xảy ra, tốt hơn là nên tránh nó. Bộ nhớ đệm cần được lấp đầy lại có nghĩa là đột nhiên, bộ lưu trữ thông thường của dữ liệu đã lưu trong bộ đệm sẽ bị tấn công ồ ạt bởi tất cả những người dùng bộ đệm thiếu dữ liệu bộ đệm (còn được gọi là sự cố đàn sấm sét).

pymemcache cung cấp một lớp có tên FallbackClient giúp thực hiện kịch bản này như được trình bày ở đây:

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 truy vấn bộ đệm cũ được chuyển đến phương thức khởi tạo của nó, tôn trọng thứ tự. Trong trường hợp này, máy chủ bộ nhớ cache mới sẽ luôn được truy vấn trước và trong trường hợp bộ nhớ cache bị bỏ sót, máy chủ cũ sẽ được truy vấn — tránh việc quay trở lại nguồn dữ liệu chính có thể xảy ra.

Nếu bất kỳ khóa nào được đặt, nó sẽ chỉ được đặt thành bộ đệm mới. Sau một thời gian, bộ đệm cũ có thể ngừng hoạt động và FallbackClient có thể được thay thế bằng new_cache khách hàng.



Kiểm tra và Đặt

Khi giao tiếp với bộ đệm từ xa, vấn đề đồng thời thông thường sẽ trở lại:có thể có một số máy khách đang cố gắng truy cập cùng một khóa cùng một lúc. memcached cung cấp một kiểm tra và thiết lập hoạt động, được rút ngắn thành CAS , giúp giải quyết vấn đề này.

Ví dụ đơn giản nhất là một ứng dụng muốn đếm số lượng người dùng mà nó có. Mỗi khi khách truy cập kết nối, bộ đếm sẽ tăng lên 1. Sử dụng memcached , một cách triển khai đơn giản sẽ là:

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

Tuy nhiên, điều gì sẽ xảy ra nếu hai phiên bản của ứng dụng cố gắng cập nhật bộ đếm này cùng một lúc?

Cuộc gọi đầu tiên client.get('visitors') sẽ trả về cùng một số lượng khách truy cập cho cả hai người, giả sử là 42. Sau đó, cả hai sẽ cộng 1, tính 43 và đặt số lượng khách truy cập là 43. Con số đó là sai và kết quả phải là 44, tức là 42 + 1 + 1.

Để giải quyết vấn đề đồng thời này, hoạt động CAS của memcached là tiện dụng. Đoạn mã sau thực hiện một giải pháp đúng:

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 phương thức trả về giá trị, giống như get nhưng nó cũng trả về một giá trị CAS .

Những gì trong giá trị này không liên quan, nhưng nó được sử dụng cho phương pháp tiếp theo cas gọi điện. Phương thức này tương đương với set hoạt động, ngoại trừ nó không thành công nếu giá trị đã thay đổi kể từ khi get hoạt động. Trong trường hợp thành công, vòng lặp bị hỏng. Nếu không, hoạt động sẽ được khởi động lại từ đầu.

Trong trường hợp hai phiên bản của ứng dụng cố gắng cập nhật bộ đếm cùng một lúc, chỉ một phiên bản thành công để di chuyển bộ đếm từ 42 sang 43. Phiên bản thứ hai nhận được False giá trị được trả về bởi client.cas gọi, và phải thử lại vòng lặp. Nó sẽ lấy 43 làm giá trị lần này, sẽ tăng lên 44 và cas của nó cuộc gọi sẽ thành công, do đó giải quyết được vấn đề của chúng tôi.

Việc tăng bộ đếm là một ví dụ thú vị để giải thích cách hoạt động của CAS vì nó đơn giản. Tuy nhiên, memcached cũng cung cấp incrdecr các phương pháp để tăng hoặc giảm một số nguyên trong một yêu cầu duy nhất, thay vì thực hiện nhiều get / cas cuộc gọi. Trong các ứng dụng thực tế, getscas được sử dụng cho kiểu dữ liệu hoặc hoạt động phức tạp hơn

Hầu hết các máy chủ lưu trữ dữ liệu và bộ nhớ đệm từ xa đều cung cấp một cơ chế như vậy để ngăn chặn các vấn đề đồng thời. Điều quan trọng là phải nhận thức được những trường hợp đó để sử dụng hợp lý các tính năng của chúng.



Ngoài bộ nhớ đệm

Các kỹ thuật đơn giản được minh họa trong bài viết này đã cho bạn thấy cách dễ dàng sử dụng memcached để tăng tốc hiệu suất của ứng dụng Python của bạn.

Chỉ cần sử dụng hai thao tác cơ bản “set” và “get”, bạn thường có thể tăng tốc độ truy xuất dữ liệu hoặc tránh tính toán lại kết quả nhiều lần. Với memcached, bạn có thể chia sẻ bộ nhớ cache trên một số lượng lớn các nút được phân phối.

Các mẫu nâng cao khác mà bạn đã thấy trong hướng dẫn này, chẳng hạn như Kiểm tra và đặt (CAS) hoạt động cho phép bạn cập nhật đồng thời dữ liệu được lưu trữ trong bộ nhớ cache trên nhiều luồng hoặc quy trình Python trong khi tránh bị hỏng dữ liệu.

Nếu bạn muốn tìm hiểu thêm về các kỹ thuật nâng cao để viết các ứng dụng Python nhanh hơn và có thể mở rộng hơn, hãy xem Scaling Python. Nó bao gồm nhiều chủ đề nâng cao như phân phối mạng, hệ thống xếp hàng, băm phân tán và lập hồ sơ mã.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Cài đặt Memcached trên Ubuntu 16.04 / 18.04 với Nginx và PHP-7.3

  2. Cài đặt Memcached trên Debian 9

  3. Python + Memcached:Bộ nhớ đệm hiệu quả trong các ứng dụng phân tán

  4. Cách sử dụng Memcached với Yii2 Framework

  5. Cách kiểm tra kết nối giữa mysql và memcached trong php