Redis cung cấp nhiều loại dữ liệu, mỗi loại dữ liệu có hỗ trợ các lệnh phong phú.
Khi sử dụng Redis, không chỉ cần hiểu các đặc điểm của các loại dữ liệu, mà còn cần linh hoạt và hiệu quả trong việc sử dụng các loại dữ liệu này để xây dựng mô hình dữ liệu phù hợp với kịch bản kinh doanh.
1. Các kiểu dữ liệu cơ bản của Redis
Kiểu dữ liệu
Giá trị có thể lưu trữ
Các hoạt động
STRING
Chuỗi, số nguyên hoặc số thực
Thực hiện các hoạt động trên toàn bộ chuỗi hoặc một phần của chuỗi Thực hiện tăng hoặc giảm giá trị số nguyên hoặc số thực
LIST
Danh sách
Thêm hoặc lấy ra phần tử từ hai đầu Đọc một hoặc nhiều phần tử Thực hiện cắt tỉa, chỉ giữ lại một phạm vi phần tử
SET
Tập hợp không thứ tự
Thêm, lấy và xóa một phần tử Kiểm tra xem một phần tử có tồn tại trong tập hợp hay không Tính toán giao, hợp, hiệu Lấy ngẫu nhiên một phần tử từ tập hợp
HASH
Bảng băm không thứ tự
Thêm, lấy và xóa một cặp khóa-giá trị Lấy tất cả các cặp khóa-giá trị Kiểm tra xem một khóa có tồn tại trong bảng hay không
ZSET
Tập hợp có thứ tự
Thêm, lấy và xóa phần tử Lấy phần tử dựa trên phạm vi hoặc thành viên Tính hạng của một khóa
Lệnh EXPIRE của Redis được sử dụng để đặt thời gian hết hạn cho một khóa, khi đạt đến thời gian hết hạn, Redis sẽ tự động xóa khóa đó.
Lệnh
Mô tả
PERSIST
PERSIST key-name—Xóa thời gian hết hạn của khóa
TTL
TTL key-name—Xem còn bao nhiêu giây nữa thì khóa sẽ hết hạn
EXPIRE
EXPIRE key-name seconds—Đặt thời gian hết hạn cho khóa trong số giây đã cho
EXPIREAT
EXPIREAT key-name timestamp—Đặt thời gian hết hạn cho khóa dựa trên timestamp UNIX đã cho
PTTL
PTTL key-name—Xem còn bao nhiêu mili giây nữa thì khóa sẽ hết hạn (lệnh này chỉ có sẵn trong Redis phiên bản 2.6 trở lên)
PEXPIRE
PEXPIRE key-name milliseconds—Đặt thời gian hết hạn cho khóa trong số mili giây đã cho (lệnh này chỉ có sẵn trong Redis phiên bản 2.6 trở lên)
PEXPIREAT
PEXPIREAT key-name timestamp-milliseconds—Đặt thời gian hết hạn cho khóa dựa trên timestamp UNIX với độ chính xác mili giây (lệnh này chỉ có sẵn trong Redis phiên bản 2.6 trở lên)
Ví dụ:
2. Các kiểu dữ liệu nâng cao trong Redis
BitMap
BitMap là một cấu trúc dữ liệu được sử dụng để thao tác bit trên các chuỗi dữ liệu. BitMap không phải là một cấu trúc dữ liệu thực sự, mà là một tập hợp các hoạt động bit trên chuỗi dữ liệu kiểu STRING. Vì STRING là một chuỗi nhị phân an toàn và có độ dài tối đa là 512MB, nên BitMap có thể lưu trữ tối đa 232 bit khác nhau.
Ưu điểm lớn nhất của BitMap là tiết kiệm không gian lưu trữ thông tin. Ví dụ, trong một hệ thống, người dùng được đại diện bằng một ID người dùng tăng dần. Với 40 tỷ (232 = 4∗1024∗1024∗1024 ≈ 40 tỷ) người dùng, chỉ cần 512MB bộ nhớ để ghi nhớ thông tin như người dùng đã đăng nhập hay chưa.
Các lệnh BitMap
SETBIT - Đặt hoặc xóa bit tại vị trí đã cho trong giá trị chuỗi được lưu trữ bởi key.
GETBIT - Lấy giá trị bit tại vị trí đã cho trong giá trị chuỗi được lưu trữ bởi key.
BITCOUNT - Đếm số bit có giá trị là 1 trong chuỗi đã cho.
BitMap rất hiệu quả đối với một số tính toán đặc biệt. Ví dụ: sử dụng BitMap để thống kê số lần người dùng đã đăng nhập.
Giả sử chúng ta muốn ghi nhớ tần suất đăng nhập của người dùng trên trang web của mình, ví dụ: tính toán số ngày người dùng A đã đăng nhập, số ngày người dùng B đã đăng nhập, và cũng như vậy. Chúng ta có thể sử dụng lệnh SETBIT key offset value và [BITCOUNT key start] [end] để thực hiện điều này.
Ví dụ, mỗi khi người dùng đăng nhập vào một ngày nào đó, chúng ta sử dụng SETBIT key offset value với key là tên người dùng, offset là ngày đại diện cho ngày đăng nhập trên trang web và đặt bit tại offset đó thành 1.
HyperLogLog là một cấu trúc dữ liệu xác suất được sử dụng để ước lượng số lượng phần tử duy nhất trong một tập hợp (được gọi là cardinality). Khi đếm số lượng phần tử duy nhất, số lượng phần tử càng nhiều thì cần nhiều bộ nhớ hơn vì cần ghi nhớ các phần tử đã xem trước đó để tránh đếm lại chúng.
Các lệnh HyperLogLog
PFADD - Thêm một hoặc nhiều phần tử vào HyperLogLog đã cho.
PFCOUNT - Trả về ước lượng số lượng phần tử duy nhất trong HyperLogLog.
PFMERGE - Kết hợp (merge) nhiều HyperLogLog thành một HyperLogLog, kết quả HyperLogLog có độ chính xác gần với hợp của tất cả các HyperLogLog đầu vào. HyperLogLog kết quả sẽ được lưu trữ trong destkey, nếu destkey không tồn tại, Redis sẽ tạo một HyperLogLog trống trước khi thực hiện merge.
Ví dụ:
GEO
Chức năng này cho phép lưu trữ thông tin vị trí địa lý (kinh độ và vĩ độ) mà người dùng cung cấp và thực hiện các hoạt động trên dữ liệu này.
Các lệnh GEO
GEOADD - Thêm một vị trí địa lý (kinh độ, vĩ độ, tên) vào key đã cho.
GEOPOS - Trả về tọa độ (kinh độ và vĩ độ) của các thành phần đã cho trong key.
GEODIST - Trả về khoảng cách giữa hai thành phần đã cho trong key.
GEOHASH - Trả về giá trị Geohash chuẩn của một hoặc nhiều thành phần vị trí, có thể sử dụng tại http://geohash.org/.
Để chọn ra các bài viết phổ biến nhất, cần hỗ trợ việc đánh giá bài viết.
Bình chọn cho bài viết
(1) Lưu trữ bài viết bằng HASH
Sử dụng kiểu dữ liệu HASH để lưu trữ thông tin của bài viết. Trong đó: key là ID của bài viết; field là khóa thuộc tính của bài viết; value là giá trị tương ứng của thuộc tính.
Các thao tác:
Lưu trữ thông tin bài viết - Sử dụng lệnh HSET hoặc HMSET
Truy vấn thông tin bài viết - Sử dụng lệnh HGETALL
Thêm phiếu bình chọn - Sử dụng lệnh HINCRBY
(2) Sử dụng ZSET để sắp xếp tập hợp bài viết theo các tiêu chí khác nhau
Sử dụng kiểu dữ liệu ZSET để lưu trữ tập hợp các ID bài viết được sắp xếp theo thời gian và điểm số.
Các thao tác:
Thêm bản ghi - Sử dụng lệnh ZADD
Thêm điểm - Sử dụng lệnh ZINCRBY
Lấy ra nhiều bài viết - Sử dụng lệnh ZREVRANGE
(3) Để tránh việc bình chọn trùng lặp, sử dụng kiểu dữ liệu SET để ghi lại tập hợp các bài viết đã được bình chọn.
Các thao tác:
Thêm người bình chọn - Sử dụng lệnh SADD
Đặt thời gian hiệu lực - Sử dụng lệnh EXPIRE
(4) Giả sử user:115423 bình chọn cho article:100408, cần cập nhật cả tập hợp sắp xếp theo điểm số và tập hợp bình chọn.
Khi cần bình chọn cho một bài viết, chương trình cần sử dụng lệnh ZSCORE để kiểm tra tập hợp sắp xếp theo thời gian đăng bài viết và xác định xem thời gian đăng bài viết có vượt quá thời gian hiệu lực của bình chọn (ví dụ: một tuần) hay không.
Đăng và lấy bài viết
Đăng bài viết:
Thêm bài viết - Sử dụng lệnh INCR để tính toán ID mới cho bài viết, điền thông tin bài viết và sử dụng lệnh HSET hoặc HMSET để ghi vào cấu trúc HASH.
Thêm ID tác giả vào danh sách bình chọn - Sử dụng lệnh SADD để thêm vào cấu trúc SET đại diện cho danh sách bình chọn.
Đặt thời gian hiệu lực của bình chọn - Sử dụng lệnh EXPIRE để đặt thời gian hiệu lực của bình chọn.
Truy vấn phân trang cho các bài viết phổ biến:
Sử dụng lệnh ZINTERSTORE để truy vấn danh sách ID bài viết theo trang, số bài viết trên mỗi trang và số thứ tự sắp xếp theo điểm số từ cao xuống thấp.
Phân nhóm bài viết
Nếu bài viết cần được phân nhóm, chức năng sẽ được chia thành hai phần:
Ghi nhận bài viết thuộc nhóm nào
Trích xuất các bài viết trong nhóm
Thêm và xóa nhóm cho bài viết:
Trích xuất các bài viết trong nhóm:
Bằng cách thực hiện lệnh ZINTERSTORE trên tập hợp các bài viết trong nhóm và tập hợp sắp xếp theo điểm số của bài viết, chúng ta có thể nhận được các bài viết trong nhóm được sắp xếp theo điểm số.
Bằng cách thực hiện lệnh ZINTERSTORE trên tập hợp các bài viết trong nhóm và tập hợp sắp xếp theo thời gian đăng bài viết, chúng ta có thể nhận được các bài viết trong nhóm được sắp xếp theo thời gian đăng.
Case study - Quản lý token
Trang web thường lưu trữ thông tin xác thực người dùng dưới dạng Cookie, Session, Token và các thông tin tương tự.
Có thể lưu trữ mappinng giữa Cookie/Session/Token và người dùng trong cấu trúc HASH.
Dưới đây là ví dụ với Token.
Kiểm tra Token
Cập nhật Token
Mỗi lần người dùng truy cập trang, có thể ghi lại mapping giữa token và timestamp hiện tại, lưu vào một cấu trúc ZSET để phân tích xem người dùng có hoạt động hay không, sau đó có thể định kỳ xóa các token cũ nhất, thống kê số người dùng đang trực tuyến, v.v.
Nếu người dùng đang xem sản phẩm, có thể ghi lại các sản phẩm đã xem gần đây vào một cấu trúc ZSET (có thể giới hạn số lượng, vượt quá số lượng sẽ bị cắt bỏ), lưu vào một cấu trúc ZSET để phân tích xem người dùng có thể quan tâm đến sản phẩm nào gần đây, từ đó có thể gợi ý sản phẩm.
Xóa Token
Như đã đề cập ở phần trước, khi cập nhật token, mapping giữa token và timestamp hiện tại được lưu vào cấu trúc ZSET. Do đó, có thể biết được những token nào là cũ nhất. Nếu không xóa, việc cập nhật token sẽ tiếp tục chiếm dụng bộ nhớ cho đến khi gây ra sự cố.
Ví dụ: Cho phép lưu trữ tối đa 10 triệu thông tin token, kiểm tra định kỳ, nếu số lượng token vượt quá 10 triệu, sắp xếp ZSET từ mới đến cũ và xóa các thông tin vượt quá 10 triệu.
Case study - Giỏ hàng
Có thể sử dụng cấu trúc HASH để triển khai chức năng giỏ hàng.
Mỗi giỏ hàng của người dùng lưu trữ ánh xạ giữa ID sản phẩm và số lượng sản phẩm.
Thêm và xóa sản phẩm trong giỏ hàng
Xóa toàn bộ giỏ hàng
Dựa trên Xóa Token, khi xóa phiên làm việc, cũng xóa luôn giỏ hàng.
Case study - Bộ nhớ cache trang web
Hầu hết nội dung trang web không thay đổi thường xuyên, nhưng khi truy cập, phía máy chủ cần tính toán động, điều này có thể tốn thời gian. Trong trường hợp này, có thể sử dụng cấu trúc STRING để lưu trữ bộ nhớ cache trang web.
Case study - Bộ nhớ cache dòng dữ liệu
Các trang web thương mại điện tử có thể có các hoạt động khuyến mãi, giảm giá, rút thăm may mắn, v.v. Những trang web này chỉ cần tải vài dòng dữ liệu từ cơ sở dữ liệu, chẳng hạn như thông tin người dùng, thông tin sản phẩm.
Có thể sử dụng cấu trúc STRING để lưu trữ bộ nhớ cache cho các dòng dữ liệu này, sử dụng JSON để lưu trữ thông tin có cấu trúc.
Ngoài ra, cần có hai cấu trúc ZSET để ghi lại thời điểm cập nhật bộ nhớ cache:
Cấu trúc ZSET thứ nhất là tập hợp lịch trình;
Cấu trúc ZSET thứ hai là tập hợp trễ.
Ghi lại thời điểm cập nhật bộ nhớ cache:
Cập nhật bộ nhớ cache dòng dữ liệu theo định kỳ:
Case study - Phân tích trang web
Trang web có thể thu thập hành vi truy cập, tương tác và mua hàng của người dùng, sau đó phân tích thói quen và sở thích của người dùng để đánh giá tình hình thị trường và cơ hội kinh doanh tiềm năng.
Vậy làm thế nào để ghi lại các trang sản phẩm mà người dùng đã truy cập trong một khoảng thời gian nhất định?
Tham khảo ví dụ mã code Cập nhật Token, ghi lại số lần truy cập của người dùng vào các trang sản phẩm khác nhau và sắp xếp chúng.
Để xác định xem trang có cần được lưu vào bộ nhớ cache hay không, dựa trên điểm đánh giá để xác định xem trang sản phẩm có phổ biến hay không:
Case study - Ghi log
Có thể sử dụng cấu trúc LIST để lưu trữ dữ liệu nhật ký (log).
Case study - Thống kê dữ liệu
Cập nhật bộ đếm:
Xem dữ liệu bộ đếm:
Case study - Tìm địa chỉ IP thuộc về đâu
Tìm địa chỉ IP thuộc về đâu bằng cách sử dụng Redis nhanh hơn so với cách thực hiện trên cơ sở dữ liệu quan hệ.
Tải dữ liệu IP
Chuyển đổi địa chỉ IP thành giá trị số nguyên:
Tạo ánh xạ giữa địa chỉ IP và ID thành phố:
Lưu trữ thông tin thành phố:
Tìm địa chỉ IP thuộc về thành phố nào
Các bước thực hiện:
Chuyển đổi địa chỉ IP cần tìm thành giá trị số nguyên;
Tìm tất cả các địa chỉ có điểm số nhỏ hơn hoặc bằng địa chỉ IP cần tìm, lấy ra bản ghi có điểm số lớn nhất;
Sử dụng ID thành phố tìm thấy để truy vấn thông tin thành phố.
Case study - Phát hiện và cấu hình dịch vụ
Case study - Tự động hoàn chỉnh
Yêu cầu: Tự động hoàn chỉnh thông tin dựa trên đầu vào của người dùng, ví dụ: tên liên lạc, tên sản phẩm, v.v.
Tình huống điển hình 1: Hệ thống mạng xã hội ghi lại 100 người bạn gần đây nhất mà người dùng đã liên lạc, khi người dùng tìm kiếm bạn bè, tự động hoàn chỉnh tên dựa trên từ khóa nhập vào.
Tình huống điển hình 2: Hệ thống thương mại điện tử ghi lại 10 sản phẩm mà người dùng đã xem gần đây, khi người dùng tìm kiếm sản phẩm, tự động hoàn chỉnh tên sản phẩm dựa trên từ khóa nhập vào.
Mô hình dữ liệu: Sử dụng kiểu dữ liệu LIST của Redis để lưu trữ danh sách liên lạc gần đây.
Xây dựng danh sách hoàn chỉnh tự động thường bao gồm các hoạt động sau:
Nếu người liên hệ đã được chỉ định tồn tại trong danh sách liên lạc gần đây, hãy loại bỏ nó khỏi danh sách. Tương ứng với lệnh LREM.
Thêm người liên hệ đã chỉ định vào đầu danh sách liên lạc gần đây. Tương ứng với lệnh LPUSH.
Sau khi hoạt động thêm đã hoàn thành, nếu số lượng người liên hệ trong danh sách vượt quá 100, thực hiện cắt tỉa. Tương ứng với lệnh LTRIM.
Case study - Định hướng quảng cáo
Case study - Tìm kiếm vị trí công việc
Yêu cầu: Trên một trang web tuyển dụng, người tìm việc có một danh sách kỹ năng của riêng mình; các công ty tuyển dụng có một danh sách kỹ năng cần thiết cho vị trí công việc. Các công ty tuyển dụng cần tìm kiếm người tìm việc phù hợp với yêu cầu công việc của mình; người tìm việc cần tìm kiếm các vị trí công việc mà mình có thể nộp đơn.
Mô hình dữ liệu quan trọng: Sử dụng kiểu dữ liệu SET để lưu trữ danh sách kỹ năng của người tìm việc và danh sách kỹ năng của vị trí công việc.
Hoạt động quan trọng: Sử dụng lệnh SDIFF để so sánh sự khác biệt giữa hai SET, trả về empty nếu đáp ứng yêu cầu.