Distributed Cache

Problem statement

1 hệ thống cơ bản bao gồm các components sau:

Ở điều kiện ít người sử dụng, hệ thống này có thể thực hiện tốt mọi nhiệm vụ. Nhưng nếu lượng tải từ ng sử dụng tăng cao, các vấn đề chịu tải sẽ xuất hiện.

Để giải quyết các vấn đề về chịu tải, cache là một trong các phương án ta có thể nghĩ đến đầu tiên. Ý tưởng là tạo 1 component chịu trách nhiệm lưu trữ dữ liệu tạm thời, và hệ thống sẽ thực hiện logic sau:

Overview

1 distributed cache là hệ thống caching gồm nhiều server cache liên kết với nhau để lưu trữ các dữ liệu được truy cập thường xuyên.

Trong 1 môi trường mà chỉ 1 cache server là ko đủ để gánh lượng tải của requests, thì ta sẽ cần mở rộng lên hệ thống cache phân tán.

Nhìn chung, distributed caches cho ta các lợi ích như sau:

Caching at different layers of a system

System LayerTechnology in UseUsage
WebHTTP cache headers, web accelerators, key-value store, CDNs, and so onAccelerate retrieval of static web content, and manage sessions
ApplicationLocal cache and key-value data storeAccelerate application-level computations and data retrieval
DatabaseDatabase cache, buffers, and key-value data storeReduce data retrieval latency and I/O load from database

Background of distributed cache

Writing policies

Thông thường, cache lưu trữ 1 bản copy của dữ liệu (hoặc 1 phần dữ liệu). Khi ta muốn lưu 1 số dữ liệu nào đó vào cache, ta thường đưa ra các câu hỏi sau:

Câu trả lời là: phụ thuộc vào requirements của ứng dụng.

Ta sẽ tập trung vào các writing policies như sau:

Eviction policies

1 trong các lý do caches hoạt động nhanh là kích thước dữ liệu nhỏ. Điều này có nghĩa là capacity storage cho cache được giới hạn trong 1 lượng nhỏ.

Vì thế, ta cần có cơ chế xóa đi các dữ liệu mà ít được đọc thường xuyên đi, tránh chiếm dung lương dư thừa.

Các chiến lược phổ biến nhất bao gồm:

Cache invalidation

Trong trường hợp dữ liệu lưu trong cache bị outdated, ta cần có cơ chế để trigger việc xóa các dữ liệu này đi, và thay thế dữ liệu mới nhất vào.

How do we identify stale entries?

Ta có thể xác định dữ liệu outdated thông qua các metadata được gắn kèm với entry của dữ liệu đó.

Thông thường ta sẽ check time-to-live (TTL) nhằm xác định thời điểm mà dữ liệu sẽ cần fetch mới lại:

Storage mechanism

Khi ta sử dụng nhiều máy chủ cache, ta sẽ cần cân nhắc tới các câu hỏi sau:

Hash function

Ta có thể sẽ cần sử dụng hashing trong 2 viễn cảnh:

Trong trường hợp đầu tiên, ta nên ưu tiên sử dụng consistent hashing vì nó đã hoạt động rất tốt trong hệ thống phân tán.

Trong trường hợp còn lại, ta có thể sử dụng hàm hash thông thường để định vị cache entries.

Linked list

Ta sẽ sử dụng cấu trúc dữ liệu double linked list để lưu trữ dữ liệu cache.

Lý do là vì đây là cấu trúc đơn giản và phổ biến. Hơn nữa, nó cho ta khả năng thêm và xóa entry ở thời gian O(1).

Ta có thể sử dụng kỹ thuật bloom filters để xác định sự tồn tại của cache entry trong cache server. Nhưng kỹ thuật này dựa trên xác suất để nhận biết, nên nó sẽ có hiệu quả hơn nhiều nếu được sử dụng trong hệ thống caching lớn hoặc hệ thống databases.

Sharding in cache clusters

Để tránh SPOF và tải cao, ta có sharding, chia cache data ra nhiều cache servers khác nhau.

Dedicated cache servers

Trong kỹ thuật này, ta tách cache servers ra khỏi application & web servers.

Điều này cho ta các lợi ích như sau:

Data temperature

Để diễn tả độ truy cập thường xuyên của dữ liệu, ta phân chia theo 3 mức sau:

  • Hot: Highly accessed data

  • Warm: Less frequently accessed data

  • Cold: Rarely accessed data

Co-located cache

Cách này sẽ cho cache và service vào chung 1 host.

Thường ta sẽ cân nhắc cách này khi cần giảm capacity expenditures và operational expenditures với phần cứng.

High-level design

Requirements

Functional

Non-functional

API design

Insertion

insert(key, value)

Retrieval

retrieve(key)

Considerations

Storage hardware

Nếu dữ liệu của ta lớn, ta có lẽ sẽ cần sharding, dẫn tới việc cần dùng shard servers cho cache partitions.

Ta có thể xây dựng hệ thống cache lớn dựa trên commodity servers. Nhìn chung, số lượng shard servers sẽ phụ thuộc vào kích cỡ của cache và độ truy cập thường xuyên.

Hơn nữa, ta có thể cân nhắc lưu trữ dữ liệu trong storage phụ nhằm đảm bảo độ thống nhất phòng trường hợp cần restart, và dựng lại cache tốn nhiều thời gian.

Data structures

Một phần thiết yếu trong thiết kế là tốc độ truy cập dữ liệu. Ta ưu tiên sử dụng cấu trúc dữ liệu có thời gian lưu trữ và truy vấn mức constant time, như bảng băm.

Ngoài ra, ta cần một cấu trúc dữ liệu tối ưu việc loại bỏ dữ liệu trong cache, và double linked list có thể đáp ứng yêu cầu này.

Bên cạnh đó, ta vẫn cần hiểu các loại cấu trúc dữ liệu khác mà cache có thể lưu trữ.

Cache client

Ta cần xác định xem nên đặt cache client ở đâu.

Nếu chỉ sử dụng nội bộ, ta có thể đặt luôn client trong hosting servers. Nhưng nếu cho bên ngoài sử dụng, ta nên đặt cache client trong 1 service dành cho caching riêng.

Writing policy

Nhìn chung, mỗi lựa chọn cho chiến lược ghi đều có ưu nhược điểm riêng, nên ta cần sử dụng policy phù hợp với ứng dụng của ta.

Eviction policy

Thông thường, hệ thống cache hoạt động trên bộ nhớ RAM để tối ưu tốc độ đọc ghi, và thường phải cân nhắc tới giới hạn lưu trữ khắt khe hơn việc lưu dữ liệu bình thường. Ta cần phải quyết định cẩn thận cái gì có thể được lưu trong cache và làm sao để chuẩn bị đủ chỗ trống cho các entries mới.

Với việc dữ liệu mới được thêm vào, data cũ sẽ cần được cân nhắc xem có cái nào có thể xóa đi được không, nhằm đảm bảo tối ưu về mặt dung lượng lưu trữ.

Nhìn chung, ta cũng có thể định nghĩa nhiều quy tắc để xóa dữ liệu đi, mỗi quy tắc đều tối ưu phụ thuộc vào ứng dụng. Chẳng hạn, LRU cache là một lựa chọn không tồi cho các dịch vụ mạng xã hội, khi cần ưu tiên nội dung được truy cập nhiều nhất cho cache.

Một điều khác đáng lưu tâm là TTL cũng phải tối ưu.

Components

High-level design of distributed cache
High-level design of distributed cache

Detailed design

Limitations

Maintain cache servers list

Solution 1

Tạo configuration file ở mỗi host.

Solution 2

Lưu configuration file ở một service tập trung.

Solution 3

Tự động hóa service phân phối configuration file.

Improve availability

Một vấn đề nữa là cache servers cần đảm bảo độ sẵn sàng kể cả khi có một hoặc một vài máy chủ gặp sự cố. Giải pháp đơn giản là thêm node tạo nên các cụm cache servers.

Ưu điểm:

Internal of cache server

Mỗi cache client nên sử dụng 3 cơ chế sau để lưu và xóa các entries khỏi cache server:

Cache server internal illustration
Cache server internal illustration

Evaluation

High performance

Ta đã có các lựa chọn sau giúp đảm bảo hiệu năng cao:

Thuật toán để thu hồi dữ liệu cache vô cùng quan trọng vì số lượng cache hits và misses phụ thuộc vào nó. Tỷ lệ cache hit càng cao, hiệu năng càng cao.

Ví dụ

Hệ thống cache của ta có hiệu năng như sau:

Ta có công thức như sau:

EAT = Ratio[hit] * Rate[hit] + Ratio[miss] * Time[miss]
EAT

Effective access time

Ratio

The percentage of times a cache hit will occur

Ratio

The percentage of times a cache miss will occur

Time

Time required to serve a cache hit

Time

Time required to serve a cache miss

Với MFU, ta sẽ có

EAT = 0.9 * 5 + 0.1 * 30 = 7.5 (ms)

Với LRU, ta sẽ có

EAT = 0.95 * 5 + 0.05 * 30 = 6.25 (ms)

Scalability

Ta có thể tạo các shards dựa theo yêu cầu nhất định và thay đổi tải lên máy chủ.

Khi thêm các máy chủ mới vào cụm máy chủ, consistent hashing chỉ yêu cầu ta tính toán lại hash với một khối lượng tính toán giới hạn.

High availability

Bằng việc gia tăng số lượng cache servers, ta có thể tăng cường độ tin cậy của hệ thống cache lên.

Để quản lý các shard trong một cụm máy chủ, ta có thể thử thuật toán leader-follower. Tuy nhiên, phương thức này có điểm yếu là không đảm bảo được tính thống nhất do phải sử dụng cơ chế ghi bất đồng bộ.

Để khắc phục vấn đề đồng bộ, ta nên đặt replication trong data center để có được sự đồng nhất với hiệu năng cao.

Consistency

Trong trường hợp của caching, cơ chế ghi bất đồng bộ cho ta hiệu năng cao hơn nhiều cơ chế đồng bộ, nhưng đi kèm với đó là việc dữ liệu sẽ không đồng nhất được.

Ngoài ra, sự không đồng nhất có thể xảy ra bởi config cho các services bị sai đâu đó.