2010-01-03 10 views
6

tôi đang xóa một con đường duy nhất từ ​​bộ nhớ cache Django như thế này:hủy bỏ hiệu lực một đường đi từ bộ nhớ cache Django đệ quy

from models     import Graph 
from django.http    import HttpRequest 
from django.utils.cache  import get_cache_key 
from django.db.models.signals import post_save 
from django.core.cache  import cache 

def expire_page(path): 
    request  = HttpRequest() 
    request.path = path 
    key   = get_cache_key(request) 
    if cache.has_key(key): 
     cache.delete(key) 

def invalidate_cache(sender, instance, **kwargs): 
    expire_page(instance.get_absolute_url()) 

post_save.connect(invalidate_cache, sender = Graph) 

này hoạt động - nhưng có một cách để xóa đệ quy? con đường của tôi trông như thế này:

/graph/123 
/graph/123/2009-08-01/2009-10-21 

Bất cứ khi nào đồ thị với id "123" được lưu, bộ nhớ cache cho cả hai con đường cần phải được chấm dứt hiệu lực. Điều này có thể được thực hiện?

+0

Tôi không chắc chắn Nếu tôi hiểu câu hỏi của bạn đúng, Bạn có nghĩa là bạn muốn xóa tất cả bộ nhớ cache mong đợi một với id "123"? – Prashanth

+0

Tôi muốn xóa bộ nhớ cache cho bất kỳ đường dẫn nào bắt đầu bằng '/ graph/123 /'. – knipknap

+0

Tôi không hiểu tại sao bạn lại lo lắng về một con đường? – Prashanth

Trả lời

10

Bạn có thể muốn xem xét việc sử dụng một chiến lược bộ nhớ đệm thế hệ, có vẻ như nó sẽ phù hợp với những gì bạn đang cố gắng hoàn thành. Trong mã mà bạn đã cung cấp, bạn sẽ lưu trữ một số "thế hệ" cho mỗi url tuyệt đối. Vì vậy, ví dụ bạn sẽ khởi tạo "/ graph/123" để có một thế hệ của một, sau đó khóa bộ nhớ cache của nó sẽ trở thành một cái gì đó như "/ GENERATION/1/graph/123". Khi bạn muốn hết hạn bộ nhớ cache cho url tuyệt đối đó, bạn tăng giá trị thế hệ của nó (đến hai trong trường hợp này). Bằng cách đó, lần tới khi có ai đó tìm kiếm "/ graph/123", khóa bộ nhớ cache sẽ trở thành "/ GENERATION/2/graph/123". Điều này cũng giải quyết vấn đề hết hạn tất cả các trang con vì chúng nên đề cập đến cùng một khóa bộ nhớ cache dưới dạng "/ graph/123".

Hơi khó hiểu lúc đầu nhưng đây thực sự là một chiến lược bộ nhớ đệm thực sự thanh lịch, nếu được thực hiện đúng nghĩa là bạn không bao giờ phải xóa mọi thứ khỏi bộ nhớ cache. Để biết thêm thông tin ở đây là a presentation on generational caching, nó cho Rails nhưng khái niệm là như nhau, bất kể ngôn ngữ.

+0

Vì vậy, bạn đang nói rằng khóa bộ nhớ cache của '/ graph/123' sẽ luôn tồn tại và chứa nội dung'/gen/1/graph/123' hoặc '/ gen/2/graph/123', v.v ... do đó, ứng dụng truy vấn đầu tiên '/ graph/123' để lấy khóa của khóa thế hệ mới nhất và sau đó truy vấn lại bộ nhớ cache bằng'/gen/x/graph/123' để nhận nội dung được lưu trong bộ nhớ cache gần đây nhất? Đó là một phần khó khăn, bởi vì, nếu đây không phải là trường hợp, làm thế nào để ứng dụng truy vấn bộ đệm ẩn nếu khóa bộ nhớ cache luôn thay đổi với một thế hệ mới. – raffian

-1

Thanh toán shutils.rmtree() hoặc os.removedirs(). Tôi nghĩ rằng đầu tiên có lẽ là những gì bạn muốn.

Cập nhật dựa trên một số nhận xét: Trên thực tế, cơ chế bộ nhớ đệm Django tổng quát hơn và mịn hơn chỉ sử dụng path cho khóa (mặc dù bạn có thể sử dụng ở cấp đó). Chúng tôi có một số trang có 7 hoặc 8 thành phần phụ được lưu trong bộ nhớ cache riêng biệt hết hạn dựa trên một loạt các tiêu chí. Tên bộ nhớ cache thành phần của chúng tôi phản ánh các đối tượng chính (hoặc các lớp đối tượng) và được sử dụng để xác định những gì cần phải được vô hiệu hóa trên các bản cập nhật nhất định.

Tất cả các trang của chúng tôi đều có khóa bộ nhớ cache tổng thể dựa trên trạng thái thành viên/không phải thành viên, nhưng đó chỉ là khoảng 95% của trang. 5% còn lại có thể thay đổi trên cơ sở từng thành viên và do đó không được lưu vào bộ nhớ cache.

Cách bạn lặp qua bộ nhớ cache để tìm các mục không hợp lệ là một chức năng của cách nó được lưu trữ thực sự. Nếu đó là các tập tin bạn có thể sử dụng chỉ đơn giản là globs và/hoặc thư mục đệ quy xóa, nếu đó là một số cơ chế khác thì bạn sẽ phải sử dụng cái gì khác.

Câu trả lời của tôi và một số nhận xét của người khác, là cố gắng nói rằng cách bạn hoàn thành việc vô hiệu hóa bộ nhớ cache được liên kết chặt chẽ với cách bạn đang sử dụng/lưu trữ bộ nhớ cache.

Cập nhật thứ hai: @andybak: Vì vậy, tôi đoán nhận xét của bạn có nghĩa là tất cả các trang web Django thương mại của tôi sẽ phát nổ trong ngọn lửa? Cảm ơn những người đứng đầu về điều đó. Tôi nhận thấy bạn không cố gắng trả lời cho vấn đề.

Vấn đề của Knipknap là anh ta có một nhóm các mục trong bộ nhớ cache xuất hiện để liên quan và phân cấp vì tên của chúng, nhưng logic thế hệ khóa của cơ chế bộ nhớ cache xóa tên đó bằng cách tạo băm MD5 đường dẫn + vary_on. Vì không có dấu vết của đường dẫn/tham số ban đầu, bạn sẽ phải đoán toàn bộ tất cả các kết hợp đường dẫn/thông số có thể có, hy vọng bạn có thể tìm thấy nhóm phù hợp. Tôi có sở thích khác thú vị hơn.

Nếu bạn muốn để có thể tìm thấy nhóm các mặt hàng lưu trữ dựa trên một số sự kết hợp của đường dẫn và/hoặc các giá trị tham số bạn phím phải hoặc sử dụng bộ nhớ cache có thể được mô hình phù hợp trực tiếp hoặc một số hệ thống mà vẫn giữ được thông tin này để sử dụng vào thời gian tìm kiếm.

Vì chúng tôi có nhu cầu không liên quan đến vấn đề của OP, chúng tôi đã kiểm soát bộ đệm mẫu của bộ nhớ mẫu - và tạo ra khóa đặc biệt - cách đây hơn 2 năm. Nó cho phép chúng ta sử dụng regexps theo một số cách để vô hiệu hóa các nhóm các mục có liên quan trong bộ nhớ đệm.Chúng tôi cũng đã thêm thời gian chờ mặc định và các tên biến khác nhau (được giải quyết tại thời gian chạy) được định cấu hình trong settings.py, đã thay đổi thứ tự thời gian chờ tên là & vì không cần phải ghi đè thời gian chờ mặc định để đặt tên cho đoạn. resolvable (nghĩa là nó có thể là một biến) để làm việc tốt hơn với lược đồ kế thừa mẫu đa cấp và một vài thứ khác.

Lý do duy nhất cho câu trả lời ban đầu của tôi, điều này thực sự sai đối với Django hiện tại, là vì tôi đã sử dụng các khóa bộ đệm của saner quá lâu nên tôi đã quên mất cơ chế đơn giản mà chúng tôi đã bỏ đi.

+0

Không * khá * ý tôi là gì. Cảm ơn mặc dù. – knipknap

+0

Vâng, sau đó bạn cần phải cụ thể hơn. Bộ nhớ cache của bạn ở đâu? Các tập tin? memcached? Cơ sở dữ liệu? Nếu họ đang ở trong các tập tin, sau đó câu trả lời của tôi là đi đúng hướng. Nếu chúng ở một nơi khác thì bạn cần một số cơ chế để phù hợp với tất cả các mục được lưu trong bộ nhớ cache chứa đối tượng đã sửa đổi của bạn. Chúng tôi đã giải quyết vấn đề này (và một số vấn đề mất hiệu lực bộ nhớ cache khác) bằng cách triển khai cơ chế bộ nhớ đệm của chính chúng ta. Nó không phải là khó để làm. –

+0

Xin lỗi để downvote nhưng câu hỏi ban đầu là hoàn toàn rõ ràng cho bất cứ ai sử dụng Django! –

1

Tùy chọn khác là sử dụng bộ nhớ cache hỗ trợ khóa gắn thẻ và loại bỏ khóa bằng thẻ. API bộ nhớ cache tích hợp của Django không có hỗ trợ cho phương pháp này. Nhưng ít nhất một bộ đệm phụ trợ (không phải là một phần của Django thích hợp) có hỗ trợ.

DiskCache * là một đĩa được cấp phép Apache2 và thư viện bộ nhớ cache được hỗ trợ tệp, được viết bằng tinh khiết-Python và tương thích với Django. Để sử dụng DiskCache trong dự án của bạn, chỉ cần cài đặt nó và cấu hình thiết lập CACHES của bạn.

cài đặt rất dễ dàng với pip:

$ pip install diskcache 

Sau đó cấu hình CACHES thiết lập của bạn:

CACHES = { 
    'default': { 
     'BACKEND': 'diskcache.DjangoCache', 
     'LOCATION': '/tmp/path/to/directory/', 
    } 
} 

Cache set phương pháp được mở rộng bởi một cuộc tranh cãi tag từ khóa tùy chọn như vậy:

from django.core.cache import cache 

cache.set('/graph/123', value, tag='/graph/123') 
cache.set('/graph/123/2009-08-01/2009-10-21', other_value, tag='/graph/123') 

diskcache.DjangoCache sử dụng một số diskcache.FanoutCache nội bộ. FanoutCache tương ứng có thể truy cập thông qua thuộc tính _cache và hiển thị phương thức evict. Để đuổi tất cả các phím được gắn thẻ với /graph/123 đơn giản:

cache._cache.evict('/graph/123') 

Mặc dù nó có thể cảm thấy khó khăn khi phải truy cập vào một thuộc tính gạch-tiền tố, dự án DiskCache là ổn định và khó có thể thực hiện thay đổi đáng kể đối với việc thực hiện DjangoCache.

Trang Django cache benchmarks có cuộc thảo luận về các phụ trợ bộ nhớ cache thay thế.

  • Tuyên bố từ chối trách nhiệm: Tôi là tác giả ban đầu của dự án DiskCache.