2015-05-07 20 views
6

Tôi có kiểu TicketType có khoảng 500 trường hợp.Vô hiệu hóa một số khóa bộ nhớ cache được nhóm lại

Nó chỉ thay đổi vài lần mỗi tuần.

Nhưng nếu thay đổi, tôi cần phải làm mất hiệu lực tất cả giá trị được lưu trong bộ nhớ cache sử dụng TicketTypes cũ.

Rất tiếc, một số khóa bộ nhớ cache không được sửa. Chúng chứa dữ liệu được tính toán.

tôi thấy các giải pháp này:

Sử dụng đối số version và cập nhật giá trị phiên bản trên một bài tiết kiệm xử lý tín hiệu của TicketType.

Sử dụng tiền tố chung cho tất cả các khóa bộ nhớ cache dựa trên Loại vé. Sau đó, vô hiệu hóa tất cả các khóa bộ nhớ cache trong trình xử lý tín hiệu lưu bài đăng.

Tôi đoán có một cách thứ ba, và tốt hơn ...

Ví dụ:

TicketType là một cái cây. Mức độ hiển thị của TicketTypes bị ràng buộc với quyền. Hai người dùng có thể thấy cây theo một cách khác, nếu họ có các quyền khác nhau. Chúng tôi lưu trữ nó, theo các điều khoản. Quyền của người dùng được đăng và được băm. Chìa khóa bộ nhớ cache được tạo ra bằng cách tạo ra một chuỗi chứa băm và một phần cố định:

hash_key='ticket-type-tree--%s' % hashed_permissions 

Nếu những thay đổi cây TicketType, chúng ta cần phải chắc chắn, không có dữ liệu cũ được nạp từ bộ nhớ cache. Hoạt động vô hiệu hóa là không cần thiết, miễn là không có dữ liệu cũ được sử dụng.

+0

Bạn có thể giải thích một chút về mô hình của mình và những gì được lưu trong bộ nhớ cache - cũng như cách bạn xác định các khóa bộ nhớ cache? – Marcanpilami

+0

@Marcanpilami Tôi đã cập nhật câu hỏi. – guettli

+1

Bạn vui lòng cho biết mô hình TicketType của mình và những gì bạn đã đưa vào bộ nhớ cache của mình một cách rõ ràng? – Charlesthk

Trả lời

1

Bạn có thể sử dụng thời gian sửa đổi vé như một phần của khóa bộ nhớ cache.

hash_key = 'ticket-type-tree--%s-%s' % (hashed_permissions, tree.lastmodified) 

Bạn có thể thêm DateTimeField với auto_now=True. Nếu nhận được thời gian sửa đổi từ db quá đắt, bạn cũng có thể lưu bộ nhớ cache đó.

Thông thường, việc cập nhật bộ nhớ cache trong bộ xử lý tín hiệu post_save vẫn ổn. Trừ khi bạn muốn có dữ liệu nhất quán mọi lúc và muốn trả thêm chi phí cho các giao dịch.

+0

Vì cây thay đổi không thường xuyên. Tôi muốn * một * dấu thời gian. Nếu tôi thêm một 'DateTimeField', mỗi hàng sẽ có một giá trị. Việc sửa đổi lần cuối sẽ dễ dàng ('max()') của cột này. Tôi đoán tôi sử dụng một phiên bản như thế này, nhưng thay vì 'last_modified' tôi sẽ có một' phiên bản' được lưu trữ trong bộ nhớ cache (không có thời gian chờ) và sử dụng 'incr()'. – guettli

+0

có, bạn có thể sử dụng bất kỳ trường nào mà bạn biết sẽ thay đổi mỗi lần có sửa đổi. – dnozay

0

Vâng, về cơ bản, vấn đề của bạn chỉ đơn giản là biểu hiện khóa bộ nhớ cache. Khi bạn phải làm một cái gì đó phức tạp như băm một bộ để lấy chìa khóa, nó phải là một gợi ý có cái gì đó còn thiếu.

Trong trường hợp này, tôi tin rằng những gì còn thiếu chỉ đơn giản là một đối tượng "cho phép đặt". Bạn có thể gọi nó là một nhóm, một vai trò (như trong RBAC) ... Đó là lý do tại sao tôi hỏi bạn nếu các bộ lặp lại - thực sự, khóa băm của bạn chỉ đơn giản là cách tạo lại ID của đối tượng đã đặt không tồn tại.

Vì vậy, một giải pháp sẽ là:

  • để tạo ra một mô hình vai trò, với một rel M2M cho người dùng và một rel M2M đến quyền (mà như tôi hiểu được liên kết đến TicketTypes của bạn)
  • sử dụng một xử lý sự kiện để bắt lưu vào TicketType.
    • lấy tất cả các vai trò ảnh hưởng (thông qua điều khoản)
    • tạo ra các phím (giống như vé-type-TREEID-Id vai trò) và vô hiệu hóa chúng
  • nhận xét

Hai thức:

  • Đôi khi cache.clear() là giải pháp - đặc biệt nếu bạn không sử dụng bộ nhớ cache cho bất kỳ điều gì khác
  • Bạn nói câu lệnh SQL của bạn ery đếm là rất lớn khi điều hướng cây.Nếu bạn chưa thử như vậy, bạn có thể chỉ đơn giản là wan để tối ưu hóa rằng với prefetch và select_related (xem doc).
+0

Tôi nghĩ rằng sửa đổi lược đồ cơ sở dữ liệu để giải quyết vấn đề này là không có giải pháp tốt. Nó sẽ là thừa, một cái gì đó tôi tránh trong lược đồ cơ sở dữ liệu. 'cache.clear()' không phải là một giải pháp. Bộ nhớ cache cũng được sử dụng cho rất nhiều thứ khác nhau. Số truy vấn SQL không lớn. Đếm trong SQL (postgres) là chậm. Đó là lý do tại sao select_related() hoặc prefetch_related() sẽ không giúp ích gì. – guettli

0

Trong bài TicketType tiết kiệm xử lý tín hiệu:
a) tạo ra chìa khóa phụ thuộc vào quyền của tất cả người sử dụng và vô hiệu hóa các phím
b) tạo ra chìa khóa cho mỗi hoán vị (cho phép) (nếu bạn có thể tính toán cho họ) và làm mất hiệu lực các phím
c) sử dụng một bản ghi nhớ thứ hai chỉ để lưu trữ bộ nhớ cache này và xóa nó (dễ nhất)

PS: Mẹo chuyên nghiệp là làm mới bộ đệm thay vì chỉ làm mất hiệu lực chúng. Tuy nhiên, một ngoại lệ vô tình trong tín hiệu django có thể gây rắc rối, vì vậy hãy mệt mỏi

1

Sử dụng redis để cache mô hình của bạn

Con đường tôi sẽ bộ nhớ cache trường hợp của tôi sẽ được như sau:

1-Hãy chắc chắn rằng bạn đang nhận được một mục vào thời điểm đó. Ví dụ: Model.objects.get (foo = 'bar') và bạn đang sử dụng thuộc tính foo mỗi lần lấy mô hình từ cơ sở dữ liệu. Điều đó sẽ được sử dụng để đảm bảo dữ liệu bị vô hiệu hóa sau này.

Phương pháp ghi đè 2 lần lưu() và đảm bảo lưu dữ liệu vào bộ nhớ cache bằng cách sử dụng thuộc tính foo.

ví dụ:

class Model(model.Model): 
    foo = models.CharField() 
    bar = models.CharField() 

    def save(self, *args, **kwargs): 
     redis.set(foo, serialize_model()) 
     super(Model, self).save(*args, **kwargs) 

    def serialize_model(): 
     return serilized_object 

3-Override get phương pháp để có được những đối tượng serialized trước khi nhấn cơ sở dữ liệu.

Ví dụ:

class Model(model.Model): 
    ... 
    def get(self, *args, **kwargs): 
     if redis.get(self.foo): 
      return redis.get(self.foo) 
     else: 
      return super(Model).get(*args, **kwargs) 

4-Override phương pháp xóa của bạn để loại bỏ bộ nhớ cache trong trường hợp nếu trường hợp đã bị xoá hoặc xóa

Ví dụ

class Model(model.Model): 
    ... 
    def delete(self,*args, **kwargs): 
     redis.delete(self.foo) 
     super(Model, self).delete(*args, **kwargs) 

Thay thế lớp mẫu với mô hình của bạn , trong trường hợp này, đây sẽ là Loại vé

Một điều, tôi giả sử bạn sẽ không chạm vào cơ sở dữ liệu bên ngoài ứng dụng Django của bạn. Nếu bạn đang sử dụng sql thô ở bất kỳ nơi nào khác, điều này sẽ không hoạt động.

Tìm các chức năng redis trên trang web của chúng, chúng có chức năng xóa, đặt và nhận. Nếu bạn đang sử dụng cách bộ nhớ đệm khác. Tìm cách đặt, nhận và xóa.

+0

Điều này lưu trữ quá nhiều. Trong trường hợp của tôi, tôi muốn cache cấu trúc cây, không phải tất cả các đối tượng riêng lẻ. Câu trả lời không phù hợp với trường hợp sử dụng của tôi. Lấy làm tiếc. – guettli

Các vấn đề liên quan