Bạn đã thực sự hiểu về các kiểu dữ liệu trong Redis ?
Bài đăng này đã không được cập nhật trong 5 năm
Giới thiệu kiểu dữ liệu của redis
Redis có 5 kiểu dữ liệu chính là String, List, set, hash, zset được lưu dưới dạng key-value. Ở bài viết này, mình sẽ đề cập đến cách quản lý các kiểu dữ liệu này của redis và những câu lệnh dành riêng cho việc đó.
String
Redis hỗ trợ 3 lệnh đối với kiểu dữ liệu String (là kiểu dữ liệu cơ bản nhất của Redis) là GET, SET, DEL
Chức năng:
- GET: Lấy ra giá trị value của key truyền vào
- SET: Thiết lập giá trị cho key
- DEL: Xóa key-value (không chỉ là String mà tất cả các kiểu dữ liệu khác cũng sử dụng)
Ví dụ
127.0.0.1:6379> SET employee "Pham Viet Anh"
OK
127.0.0.1:6379> GET employee
"Pham Viet Anh"
127.0.0.1:6379> DEL employee
(integer) 1
127.0.0.1:6379> GET employee
(nil)
String trong redis là kiểu dữ liệu cấu trúc chứ không đơn thuần là char*, có chứa sẵn phần tử lưu độ dài của String. Do đó thao tác lấy độ dài có độ phức tạp tính toán là O(1). Ngoài ra lệnh GET, SET cũng có độ phức tạp là O(1). Đương nhiên với kiểu dữ liệu key-value dưới dạng hash table của redis sẽ vượt trội hơn so với MySQL sử dụng BTree với INSERT và SEARCH có độ phức tạp O(log(n)).
LIST
Việc lưu trữ một danh sách theo thứ tự của các String (trước, sau) trong Redis là linked list. Ưu điểm của nó là việc add thêm 1 phần từ vào đầu hoặc cuối của List khá là dễ dàng mà không quan tâm đến kích thước của list. Tuy nhiên, cách làm này thì việc tìm kiếm phần tử theo index lại khó khăn hơn so với array.
Một số lệnh của List là:
- RPUSH: Thêm vào phía bên phải của list 1 giá trị
- LRANGE: Lấy 1 dải giá trị của list
- LINDEX: Truy xuất phần tử của list dựa theo index
- LPOP: Lấy ra giá trị ở phái ngoài cùng bên trái của list và xóa giá trị đó đi
Ví dụ:
127.0.0.1:6379> RPUSH employee 'Pham Viet Anh'
(integer) 1
127.0.0.1:6379> RPUSH employee 'Pham Van A'
(integer) 2
127.0.0.1:6379> RPUSH employee 'Pham Van B'
(integer) 3
127.0.0.1:6379> LRANGE employee 0 1
1) "Pham Viet Anh"
2) "Pham Van A"
127.0.0.1:6379> LRANGE employee 0 -1
1) "Pham Viet Anh"
2) "Pham Van A"
3) "Pham Van B"
127.0.0.1:6379> LINDEX employee 1
"Pham Van A"
127.0.0.1:6379> LPOP employee
"Pham Viet Anh"
127.0.0.1:6379> LRANGE employee 0 -1
1) "Pham Van A"
2) "Pham Van B"
Ứng dụng nổi tiếng nhất cho việc sử dụng list là:
- Lưu lại các Post mới nhất trên mạng xã hội của users (ví dụ là Twitter)
- Xây dựng mô hình sự tương tác giữa producer và consumer (producer đưa item vào trong List để consumer lấy ra theo thứ tự).
List trong Redis có thêm thuộc tính lưu chiều dài của list. Do đó câu lệnh LLEN (lấy ra chiều dài của list) có độ phức tạp tính toán là O(1).
SET
Sự khác nhau giữa SET và LIST là thứ tự của các phần tử trong SET không được sắp xếp theo trước sau như LIST, mà là bất quy tắc. Các phần tử của SET thì được lưu trữ dưới dạng hash table (bảng băm) để tăng performance. Nói cách khác là mỗi phần tử này sẽ là 1 key trong hash table và không có value => tăng tốc độ truy xuất dữ liệu mà không bị trùng lặp phần tử.
4 lệnh cơ bản của SET là:
- SADD: Add thêm 1 phần tử vào set
- SMEMBERS: Lấy ra tất cả các phần tử của set
- SISMEMBER: Check xem 1 phần tử có tồn tại trong set hay không
- SREM: Xóa đi 1 phần tử của set (nếu nó tồn tại)
127.0.0.1:6379> SADD employee 'Pham Viet Anh'
(integer) 1
127.0.0.1:6379> SADD employee 'Pham Van A1'
(integer) 1
127.0.0.1:6379> SADD employee 'Pham Van B1'
(integer) 1
127.0.0.1:6379> SMEMBERS employee
1) "Pham Van A1"
2) "Pham Viet Anh"
3) "Pham Van B1"
127.0.0.1:6379> SISMEMBER employee 'Pham Viet Anh'
(integer) 1
127.0.0.1:6379> SISMEMBER employee 'A1'
(integer) 0
127.0.0.1:6379> SREM employee 'Pham Viet Anh'
(integer) 1
127.0.0.1:6379> SMEMBERS employee
1) "Pham Van A1"
2) "Pham Van B1"
SET trong Redis được lưu trữ dưới dạng hash table, trong đó key là phần tử của set, còn value thì không có. Do đó các câu lệnh SADD, SREM, SISMEMBER khi làm việc với 1 phần tử đều có độ phức tạp tính toán là O(1).
HASH
HASH lưu trữ các tập các map của key-value với Key: String và value: String hoặc số.
- HSET: Thêm 1 cặp key-value vào hash hoặc thay đổi giá trị của key đã có.
- HGET: Lấy giá trị của key trong hash có sẵn
- HGETALL: Lấy ra tất cả các phần tử của hash
- HDEL: Xóa cặp key-value ra khỏi hash (nếu key tồn tại) Ví dụ:
127.0.0.1:6379> HSET ages 'viet anh' 27
(integer) 1
127.0.0.1:6379> HSET ages 'hung' 20
(integer) 1
127.0.0.1:6379> HSET ages 'hoang' 35
(integer) 1
127.0.0.1:6379> HGET ages 'hung'
"20"
127.0.0.1:6379> HGETALL ages
1) "viet anh"
2) "27"
3) "hung"
4) "20"
5) "hoang"
6) "35"
127.0.0.1:6379> HDEL ages 'hoang'
(integer) 1
127.0.0.1:6379> HGETALL ages
1) "viet anh"
2) "27"
3) "hung"
4) "20"
Độ phức tạp tính toán của HASH cũng là O(1).
SORTED SET
Sorted Set (ZSET) là 1 phiên bản đầy đủ của set, khi mà phần value của item được thiết lập, và bắt buộc là 1 số (float number) được gọi là score. Ở điểm này thì zset khá giống với hash khi lưu trữ 1 cặp key, value (trong zset gọi là member và score). Và vì là “sorted”, nên các cặp member-score được add vào sorted set sẽ được sắp xếp theo thứ tự của các score, nếu score trùng nhau thì tiếp tục sắp xếp theo member. Ngoài ra cũng cần chú ý là không cho phép 2 phần tử khác nhau của zset có member trùng nhau. Sau đây là 4 câu lệnh cơ bản với zset.
Sorted Set (ZSET) là 1 phiên bản đầy đủ của set, nó bắt buộc phần value của item phải có giá trị là 1 số kiểu float number, cái này được gọi là score. Về thứ tự sắp xếp sẽ được sắp theo thứ tự các score, nếu score trùng nhau thì sắp xếp theo member. Các phần tử của zset không được cso member trùng nhau.
Các lệnh của ZSET:
- ZADD: Thêm 1 phần tử vào tập hợp với score của nó.
- ZRANGE: Lấy ra các phần tử của tập hợp theo vị trí của chúng trong zset
- ZRANGEBYSCORE: Lấy ra các phần tử của tập hợp theo phạm vi của score
- ZREM: Xóa 1 phần tử khỏi tập hợp (nếu nó tồn tại)
Ví dụ:
127.0.0.1:6379> ZADD scores 100 vietanh
(integer) 1
127.0.0.1:6379> ZADD scores 80 hung
(integer) 1
127.0.0.1:6379> ZADD scores 90 hoang
(integer) 1
127.0.0.1:6379> ZRANGE scores 0 -1 WITHSCORES
1) "hung"
2) "80"
3) "hoang"
4) "90"
5) "vietanh"
6) "100"
127.0.0.1:6379> ZRANGEBYSCORE scores 89 100 WITHSCORES
1) "hoang"
2) "90"
3) "vietanh"
4) "100"
127.0.0.1:6379> ZREM scores hoang
(integer) 1
127.0.0.1:6379> ZRANGE scores 0 -1 WITHSCORES
1) "hung"
2) "80"
3) "vietanh"
4) "100"
Ứng dụng của ZSET là xử lý cho các bài toán tìm "TOP". Top theo số lượng view, score, sub ...
Kết Luận
Việc sử dụng redis sẽ giúp tối ưu perfomance của ứng dụng, Bài viết trên đã giới thiệu một số câu lệnh cơ bản để thao tác với các kiểu dữ liệu khác nhau trong redis. Bạn đọc có thể tham khảo https://redis.io/ để tìm hiểu thêm các câu lệnh khác mà nó hỗ trợ.
Tài liệu tham khảo
http://redis.io/topics/data-types-intro
http://stackoverflow.com/questions/9625246/what-are-the-underlying-data-structures-used-for-redis
All rights reserved