logo

Lộ trình

Khóa học

Tài liệu

Mock Interview

Liên hệ

Quay lại
  • Trang chủ

    /

  • Tài liệu

    /

  • Time-To-Live (TTL) trong Redis hoạt động như nào?
Tài liệu

Time-To-Live (TTL) trong Redis hoạt động như nào?

Ronin Engineer

9 Tháng 8 2023

<p>Redis là một công nghệ cool ngầu. Nó giải quyết nhiều bài toán khó về caching và distributed system (hệ phân tán). Ngoài ra, nó còn support nhiều cấu trúc dữ liệu đáp ứng cho nhiều use case khác nhau và nhiều algorithm ẩn bên trong.</p><p>Hôm nay mình và các bạn sẽ cùng tìm hiểu:</p><ul><li>Time-To-Live (TTL) trong Redis hoạt động như nào?</li><li>Những vấn đề mà các cách tiếp cận gặp phải</li><li>Best Practices khi đặt TTL</li></ul><h2 id="%C4%91%E1%BB%8Bnh-ngh%C4%A9a-time-to-live-ttl">Định nghĩa Time-To-Live (TTL)</h2><p>Time-To-Live là khái niệm phổ biến được sử dụng trong 2 lĩnh vực:</p><ul><li><strong>Mạng máy tính (Computer Networking)</strong>: Mỗi packet (network layer) chứa 1 trường TTL dùng để đếm số router (hop) mà packet có thể đi qua được. Khi đi qua mỗi router (hop), TTL sẽ bị trừ đi 1 đơn vị. Nếu TTL = 0 thì packet sẽ bị drop.</li><li><strong>Bộ nhớ đệm (Caching)</strong>: TTL ám chỉ khoảng thời gian mà dữ liệu được lưu trước khi dữ liệu đó bị xoá đi. Việc xoá dữ liệu này phản ánh <strong>dữ liệu có thể còn không hợp lệ</strong> và giúp <strong>giải phóng bộ nhớ</strong>.</li></ul><figure class="kg-card kg-image-card"><img src="https://images.viblo.asia/2fec62e4-53b5-4ef0-80c5-7023a89d7408.jpeg" class="kg-image" alt="" loading="lazy" width="825" height="413"></figure><h2 id="time-to-live-trong-redis-ho%E1%BA%A1t-%C4%91%E1%BB%99ng-nh%C6%B0-n%C3%A0o">Time-To-Live trong Redis hoạt động như nào?</h2><p>Khi một key được cài đặt Time-To-Live, sau khoảng thời gian TTL đó, key đó sẽ tự động được xoá đi.</p><h3 id="c%C3%A1ch-ti%E1%BA%BFp-c%E1%BA%ADn-ban-%C4%91%E1%BA%A7u">Cách tiếp cận ban đầu</h3><p>Redis sử dụng và kết hợp đồng thời 2 cách để xoá key khi hết hạn:</p><p><strong>Passive Way</strong>:</p><p>Redis <strong>không xoá key ngay khi hết hạn</strong>. Cho tới khi ta lấy (GET) key đó, Redis mới check key đã hết hạn chưa. Nếu đã hết hạn thì sẽ trả về null trước rồi <strong>xoá key đó đi một cách bất đồng bộ</strong>.</p><p>Cách này khá đơn giản nhưng gặp 1 vấn đề. Đó là có những key mà sẽ bao giờ được động tới, như vậy nó sẽ chiếm không gian nhớ.<br>Để khắc phục tình trạng này, Redis kết hợp với Active Way - xoá chủ động.</p><p><strong>Active Way</strong>:</p><p>Redis thực hiện job xoá key chủ động 10 lần / giây (trong code gọi là <code>activeExpireCycle</code>)</p><ul><li>Bước 1: Lấy random 20 keys có gắn TTL. Trong có thể có keys hết hạn và key chưa hết hạn.</li><li>Bước 2: Thử xoá 20 keys đó</li><li>Bước 3: Nếu có nhiều hơn 25% của 20 keys bị hết hạn, lặp lại bước 1.</li></ul><p></p><p>Do Redis hoạt động dựa trên single-thread, khi job xoá key chủ động chạy thì sẽ <strong>block các request khác</strong>. Do đó, Redis có <strong>cấu hình timeout cho job</strong> này tránh tình trạng bị treo do quá nhiều key đồng thời hết hạn.</p><p>Việc kết hợp 2 cách này hoạt động rất tốt trong hầu hết các trường hợp thực tế. Tuy nhiên vẫn có trường số lượng key expire lớn và việc lấy sampling random khiến job <code>activeExpireCycle</code> hoạt động không hiệu quả. Mọi người có thể đọc thêm ở reference [4].</p><h3 id="c%C3%A1ch-ti%E1%BA%BFp-c%E1%BA%ADn-m%E1%BB%9Bi">Cách tiếp cận mới</h3><p>Redis khắc phục nhược điểm của cách tiếp cận trên bằng cách: <strong>các key sẽ được sắp xếp bởi thời gian hết hạn (expiration time)</strong> và lưu trong Sorted Set (ZSET) giúp cho việc tìm kiếm key hết hạn nhanh chóng hơn.</p><p>*Lưu ý: Có người nói key được sort bởi Radix Tree. Nhưng phần này mình thấy trong code và document không nói rõ ràng. Nếu bạn biết chính xác keys được sort như nào thì comment bên dưới giúp mình để mọi người rõ hơn nhé.</p><h2 id="best-practices-khi-%C4%91%E1%BA%B7t-ttl">Best Practices khi đặt TTL</h2><ul><li><strong>Dựa trên yêu cầu nghiệp vụ</strong>: dựa vào ý nghĩa của dữ liệu mà ta đặt TTL cho phù hợp. Ví dụ dữ liệu về session thì có TTL ngắn hơn so với static content như ảnh, đường dẫn, …</li><li><strong>Đối với những TTL dài thì ta cần random các giá trị này để chúng được dải đều ra</strong>. Tránh tình trạng “thundering herd" xảy ra khi tất cả key đồng thời hết hạn, gây ra load cao ở các tầng app và DB</li><li><strong>Sử dụng đúng kiểu dữ liệu</strong>: Không phải tất cả kiểu dữ liệu điều có cơ chế TTL giống nhau. Ví dụ, List và Set hỗ trợ TTL theo từng phần tử, còn Sorted Set và Hash thì không.</li><li><strong>Chú ý cấu hình Eviction Policy</strong> dựa trên yêu cầu của hệ thống. Khi Redis ăn hết mem, nó sẽ evict key dựa trên cấu hình (LRU, LFU, …)</li><li>Nếu không có yêu cầu đặc biệt từ nghiệp vụ thì thông thường <strong>nên đặt TTL ngắn</strong> để tránh chiếm mem và dữ liệu được update.</li><li>Nếu bạn có bổ sung thêm best practice thì comment bên dưới giúp mình nhé.</li></ul><hr><p>🏢 System Design VN: <a href="https://fb.com/groups/systemdesign.vn?ref=roninhub.com">https://fb.com/groups/systemdesign.vn</a></p><hr><h2 id="tham-kh%E1%BA%A3o">Tham Khảo</h2><p>[1] <a href="https://redis.com/ebook/part-2-core-concepts/chapter-3-commands-in-redis/3-7-other-commands/3-7-3-expiring-keys/?ref=roninhub.com">https://redis.com/ebook/part-2-core-concepts/chapter-3-commands-in-redis/3-7-other-commands/3-7-3-expiring-keys/</a></p><p>[2] <a href="https://redis.io/commands/expire/?ref=roninhub.com">https://redis.io/commands/expire/</a></p><p>[3] <a href="https://github.com/redis/redis/blob/7.0.12/src/expire.c?ref=roninhub.com">https://github.com/redis/redis/blob/7.0.12/src/expire.c</a></p><p>[4] <a href="https://blog.twitter.com/engineering/en_us/topics/infrastructure/2019/improving-key-expiration-in-redis?ref=roninhub.com">https://blog.twitter.com/engineering/en_us/topics/infrastructure/2019/improving-key-expiration-in-redis</a></p>

Redis là một công nghệ cool ngầu. Nó giải quyết nhiều bài toán khó về caching và distributed system (hệ phân tán). Ngoài ra, nó còn support nhiều cấu trúc dữ liệu đáp ứng cho nhiều use case khác nhau và nhiều algorithm ẩn bên trong.

Hôm nay mình và các bạn sẽ cùng tìm hiểu:

  • Time-To-Live (TTL) trong Redis hoạt động như nào?
  • Những vấn đề mà các cách tiếp cận gặp phải
  • Best Practices khi đặt TTL

Định nghĩa Time-To-Live (TTL)

Time-To-Live là khái niệm phổ biến được sử dụng trong 2 lĩnh vực:

  • Mạng máy tính (Computer Networking): Mỗi packet (network layer) chứa 1 trường TTL dùng để đếm số router (hop) mà packet có thể đi qua được. Khi đi qua mỗi router (hop), TTL sẽ bị trừ đi 1 đơn vị. Nếu TTL = 0 thì packet sẽ bị drop.
  • Bộ nhớ đệm (Caching): TTL ám chỉ khoảng thời gian mà dữ liệu được lưu trước khi dữ liệu đó bị xoá đi. Việc xoá dữ liệu này phản ánh dữ liệu có thể còn không hợp lệ và giúp giải phóng bộ nhớ.

Time-To-Live trong Redis hoạt động như nào?

Khi một key được cài đặt Time-To-Live, sau khoảng thời gian TTL đó, key đó sẽ tự động được xoá đi.

Cách tiếp cận ban đầu

Redis sử dụng và kết hợp đồng thời 2 cách để xoá key khi hết hạn:

Passive Way:

Redis không xoá key ngay khi hết hạn. Cho tới khi ta lấy (GET) key đó, Redis mới check key đã hết hạn chưa. Nếu đã hết hạn thì sẽ trả về null trước rồi xoá key đó đi một cách bất đồng bộ.

Cách này khá đơn giản nhưng gặp 1 vấn đề. Đó là có những key mà sẽ bao giờ được động tới, như vậy nó sẽ chiếm không gian nhớ.
Để khắc phục tình trạng này, Redis kết hợp với Active Way - xoá chủ động.

Active Way:

Redis thực hiện job xoá key chủ động 10 lần / giây (trong code gọi là activeExpireCycle)

  • Bước 1: Lấy random 20 keys có gắn TTL. Trong có thể có keys hết hạn và key chưa hết hạn.
  • Bước 2: Thử xoá 20 keys đó
  • Bước 3: Nếu có nhiều hơn 25% của 20 keys bị hết hạn, lặp lại bước 1.

Do Redis hoạt động dựa trên single-thread, khi job xoá key chủ động chạy thì sẽ block các request khác. Do đó, Redis có cấu hình timeout cho job này tránh tình trạng bị treo do quá nhiều key đồng thời hết hạn.

Việc kết hợp 2 cách này hoạt động rất tốt trong hầu hết các trường hợp thực tế. Tuy nhiên vẫn có trường số lượng key expire lớn và việc lấy sampling random khiến job activeExpireCycle hoạt động không hiệu quả. Mọi người có thể đọc thêm ở reference [4].

Cách tiếp cận mới

Redis khắc phục nhược điểm của cách tiếp cận trên bằng cách: các key sẽ được sắp xếp bởi thời gian hết hạn (expiration time) và lưu trong Sorted Set (ZSET) giúp cho việc tìm kiếm key hết hạn nhanh chóng hơn.

*Lưu ý: Có người nói key được sort bởi Radix Tree. Nhưng phần này mình thấy trong code và document không nói rõ ràng. Nếu bạn biết chính xác keys được sort như nào thì comment bên dưới giúp mình để mọi người rõ hơn nhé.

Best Practices khi đặt TTL

  • Dựa trên yêu cầu nghiệp vụ: dựa vào ý nghĩa của dữ liệu mà ta đặt TTL cho phù hợp. Ví dụ dữ liệu về session thì có TTL ngắn hơn so với static content như ảnh, đường dẫn, …
  • Đối với những TTL dài thì ta cần random các giá trị này để chúng được dải đều ra. Tránh tình trạng “thundering herd" xảy ra khi tất cả key đồng thời hết hạn, gây ra load cao ở các tầng app và DB
  • Sử dụng đúng kiểu dữ liệu: Không phải tất cả kiểu dữ liệu điều có cơ chế TTL giống nhau. Ví dụ, List và Set hỗ trợ TTL theo từng phần tử, còn Sorted Set và Hash thì không.
  • Chú ý cấu hình Eviction Policy dựa trên yêu cầu của hệ thống. Khi Redis ăn hết mem, nó sẽ evict key dựa trên cấu hình (LRU, LFU, …)
  • Nếu không có yêu cầu đặc biệt từ nghiệp vụ thì thông thường nên đặt TTL ngắn để tránh chiếm mem và dữ liệu được update.
  • Nếu bạn có bổ sung thêm best practice thì comment bên dưới giúp mình nhé.

🏢 System Design VN: https://fb.com/groups/systemdesign.vn


Tham Khảo

[1] https://redis.com/ebook/part-2-core-concepts/chapter-3-commands-in-redis/3-7-other-commands/3-7-3-expiring-keys/

[2] https://redis.io/commands/expire/

[3] https://github.com/redis/redis/blob/7.0.12/src/expire.c

[4] https://blog.twitter.com/engineering/en_us/topics/infrastructure/2019/improving-key-expiration-in-redis

redis
beginner

Bài viết liên quan

Binary Search - Khi việc tìm kiếm cần nhanh hơn

by @ToanBui Mình thường thấy các bạn luôn sử dụng việc tìm kiếm tuyến tính (Linear Search) như một thói quen cho tất cả các trường hợp, nhưng việc này chỉ đúng khi tìm trong một mảng không được sắp xếp. Ví dụ rằng khi có một list sản phẩm, thường lúc này các sản phẩm sẽ được sắp xếp theo ID khi được trả ra, vậy nên khi tìm các sản phẩm trong list sử dụng Binary Search code của các bạn sẽ được tối ưu đáng kể từ O(n) xuống còn O(logn). Để mình đưa ra một ví dụ minh họa dễ tưởng tượng hơn. Một q

Counting - Dạng bài phỏng vấn thuật toán phổ biến của các công ty

by @ToanBui Các bài toán mang tư tưởng đếm xuất hiện phần lớn ở các bài phỏng vấn thuật toán của các công ty, các bài này thường ở mức dễ để xử lý. Một mẫu đề bài ví dụ là cho một chuỗi kí tự và trả về kí tự có số lượng xuất hiện nhiều thứ 2 trong chuỗi. Để bắt đầu với điều này, hãy trở về quá khứ tại thời điểm bản thân bắt đầu học đếm. Phần lớn mọi người đều biết tới que tính với rất nhiều màu sắc (lục, đỏ, xanh, vàng,…). Mình có một chuỗi ví dụ đơn giản là “abacca”, mình sẽ lấy kí tự “a” vớ

Cache strategies - Lựa chọn chiến lược nào cho dự án của bạn?

I. Giới thiệu Bạn hẳn đã quen thuộc với khái niệm cache rồi nhỉ? Khi ứng dụng chạy chậm, giải pháp thường nghĩ đến là dùng cache – nghe có vẻ đơn giản. Nhưng triển khai cache như thế nào để vừa đạt hiệu quả cao, vừa đảm bảo tính chính xác của dữ liệu lại là một bài toán không hề dễ. Trong bài viết này, chúng ta sẽ cùng tìm hiểu 5 chiến lược caching phổ biến, phân tích ưu nhược điểm của từng chiến lược và khám phá cách áp dụng chúng vào các tình huống thực tế để tối ưu hiệu suất hệ thống nhé.

Lost Update: Tồn kho còn 1, nhiều người cùng order thì xử lý thế nào?

by @HieuHocCode I. Giới thiệu Hãy tưởng tượng bạn đang xây dựng một sàn thương mại điện tử và gặp phải tình huống sản phẩm chỉ còn 1, nhưng có đến 2 khách hàng đặt hàng cùng lúc. Làm thế nào để hệ thống xử lý tình huống này một cách chính xác, tránh sai sót? Đây chính là một thách thức phổ biến khi xử lý nhiều transaction đồng thời. Vấn đề này thường liên quan đến khái niệm race condition, trong đó các giao dịch song song sẽ tranh chấp quyền thao tác trên dữ liệu, dẫn đến những tình trạng sa

Log tập trung là gì? Tại sao cần trong microservices (phần 1)

by @hieuhoccode I. Giới thiệu Để đáp ứng nhu cầu phát triển nhanh chóng, dự án mình làm đã chuyển từ mô hình monolithic sang microservices. Tuy nhiên, hệ thống ngày càng phức tạp cũng đặt ra nhiều thách thức. Một trong số đó là vấn đề quản lý và giám sát log: * Khó khăn trong việc debug: Một request có thể đi qua 5-10 services khác nhau, mỗi service sinh ra log riêng biệt. Khi có lỗi, việc truy vết theo các service mất rất nhiều thời gian. * Chậm trễ trong phản ứng sự cố: Team thường phát

Tất cả bài viết
logo

HỘ KINH DOANH LẬP VƯƠNG

Giấy chứng nhận đăng ký doanh nghiệp số: 8656162915-001. Cấp ngày 21/02/2024. Nơi cấp: Sở Kế hoạch và Đầu tư TP. Hà Nội

PHƯƠNG THỨC THANH TOÁN

vnpay

LIÊN HỆ

roninengineer88@gmail.com

0362228388

26 ngõ 156 Hồng Mai, Hai Bà Trưng, Hà Nội

THEO DÕI CHÚNG TÔI

Facebook

Youtube

Tiktok

CHÍNH SÁCH

Chính sách bảo mật

Chính sách thanh toán

Đổi trả/Hoàn tiền

Hướng dẫn thanh toán VNPAY

PHƯƠNG THỨC THANH TOÁN

vnpay

Ronin Engineer 2024