Một trong những tính năng bí mật tốt nhất của Redis là giao thức dây của nó. Đó là lý do mà Redis có một trong những hệ sinh thái lớn nhất gồm các thư viện khách hàng chất lượng cao. Giao thức dây Redis rất đơn giản, giúp bạn dễ dàng xây dựng một ứng dụng khách triển khai tất cả các tính năng chính của Redis. Nó cũng được thiết kế theo cách giúp bạn dễ dàng viết các thư việnclient nhanh chóng và hiệu quả.
RESP là gì?
RESP ( RE dis S erialization P rotocol) là tên của giao thức dựa trên văn bản mà máy khách và máy chủ Redis sử dụng để giao tiếp với nhau quaTCP. Tất cả giao tiếp giữa máy chủ và máy khách bao gồm năm loại cơ bản:
- Chuỗi đơn giản được sử dụng cho các câu trả lời phổ biến của máy chủ, chẳng hạn như “OK” (sau lệnh ghi không thành công) hoặc “PONG” (phản hồi thành công cho lệnh PING).
- Chuỗi hàng loạt được trả về cho hầu hết tất cả các lệnh đọc giá trị đơn suchas GET, LPOP và HGET. Chuỗi số lượng lớn khác với chuỗi đơn giản ở chỗ chúng có thể chứa bất kỳ thứ gì - dòng mới, ký tự điều khiển hoặc thậm chí là RESP hợp lệ, tất cả đều không được thoát hoặc mã hóa.
- Số nguyên được sử dụng làm câu trả lời cho bất kỳ loại lệnh đếm nào nhưSTRLEN, HLEN hoặc BITCOUNT.
- Mảng có thể chứa bất kỳ số lượng đối tượng RESP nào, bao gồm cả các mảng khác, được sử dụng để gửi lệnh tới máy chủ cũng như cho bất kỳ câu trả lời nào trả về nhiều hơn một phần tử như HGETALL, LRANGE hoặc MGET.
- Lỗi được trả về bất cứ khi nào Redis gặp lỗi trong khi xử lý lệnh của bạn, chẳng hạn như khi cố gắng chạy lệnh đối với một khóa giữ sai loại dữ liệu.
Khi viết và đọc RESP, chúng tôi không phải thực hiện bất kỳ quá trình thoát hoặc mã hóa các khóa hoặc giá trị của chúng tôi. Phần duy nhất của RESP mà chúng ta cần thực sự phân tích cú pháp là siêu dữ liệu đơn giản được bao gồm trong mỗi đối tượng RESP.
RESP trông như thế nào?
Tất cả các đối tượng RESP đều bắt đầu bằng ký tự tiền tố và kết thúc bằng dấu chấm cuối dòng (ngoại trừ mảng không bao gồm dấu chấm cuối dòng của riêng chúng). Ví dụ đơn giản của đối tượng RESP là OK
phản hồi chuỗi đơn giản:
+OK\r\n
(RESP là một giao thức con người có thể đọc được nhưng vì lý do rõ ràng, tôi sẽ viết rõ ràng các dấu ngắt dòng (\r\n
) trong tất cả các ví dụ về RESP.)
Trong chuỗi đơn giản ở trên, +
là tiền tố chuỗi đơn giản, OK
là phần thân của chuỗi đơn giản và \r\n
là dấu chấm cuối dòng đánh dấu phần cuối của chuỗi đơn giản.
Để đọc một chuỗi đơn giản, chúng tôi đọc đến \r\n
tiếp theo lineterminator, trả về các byte trước (tối đa +
) dưới dạng chuỗi trả lời được trả lại. Điều này hoạt động vì chuỗi đơn giản RESP không thể bao gồm nhiều ký tự dòng mới.
Lỗi và số nguyên được định dạng tương tự như các chuỗi đơn giản, nhưng chúng sử dụng các tiền tố khác nhau. Các lỗi có tiền tố là -
:
-ERR unknown command 'GETT'\r\n
Và các số nguyên có tiền tố là :
:
:99\r\n
Chuỗi số lượng lớn là duy nhất ở chỗ chúng có hai phần. Cụ thể về độ dài và nội dung:
$13\r\nHello, World!\r\n
$
là tiền tố chuỗi số lượng lớn, 13
là số byte trong chuỗi thực tế và sau đó là \r\n
chấm dứt đặc điểm kỹ thuật độ dài. Hello, World!
là phần thân của chuỗi 13 byte và cũng được kết thúc bằng \r\n
(không phải là phần của phần nội dung chuỗi).
Vì vùng chứa chuỗi số lượng lớn cung cấp độ dài chính xác cho phần nội dung, nên chúng tôi không bao giờ phải phân tích cú pháp phần nội dung chuỗi thực tế để tìm phần cuối - chúng tôi có thể đọc thêm 13 byte khác (cộng với dấu chấm cuối dòng cuối cùng) từ ổ cắm mà không cần kiểm tra nội dung của chuỗi. Điều này có nghĩa là chúng tôi có thể sử dụng bất kỳ dữ liệu nào mà chúng tôi muốn trong phần nội dung của chuỗi mà không cần mã hóa hoặc thoát khỏi nội dung.
Mảng cũng bắt đầu bằng đặc tả độ dài, ngoại trừ trường độ dài cho biết số lượng đối tượng trong mảng chứ không phải số byte trong nội dung của mảng.
*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n
Trong ví dụ trên, chúng ta có một mảng chứa hai chuỗi số lượng lớn (foo
và bar
). Mặc dù đặc tả độ dài mảng không cho phép chúng ta bỏ qua những gì chúng ta có thể làm khi đọc một chuỗi số lượng lớn, nhưng nó giúp dễ dàng triển khai trong ứng dụng khách của chúng ta. Chúng tôi đọc kích thước mảng, đọc nhiều đối tượng và sau đó trả về tất cả các đối tượng đó trong mảng cuối cùng.
Tất cả các lệnh Redis được gửi dưới dạng mảng chuỗi số lượng lớn. Ví dụ:lệnh “SET mykey‘ my value ’” sẽ được viết và gửi dưới dạng:
*3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$8\r\nmy value\r\n
Chi tiết RESP khác
Độ dài có tiền tố được sử dụng trong RESP cho phép thực hiện các trình phân tích cú pháp mà không cần thực hiện mô hình trạng thái phức tạp hoặc nhiều lần truyền qua dữ liệu, cho phép xây dựng các trình phân tích cú pháp rất nhanh.
Có một số chi tiết tôi chưa trình bày ở đây, chẳng hạn như chuỗi số lượng lớn rỗng và mảng rỗng. Để biết thêm thông tin, tài liệu chính thức (như thường lệ) có một trang tài liệu rất dễ đọc và toàn diện cho RESP.
Một cách tuyệt vời để hiểu rõ hơn về quy trình là thử tự thực hiện một bệnh nhân đơn giản. Xem hướng dẫn của chúng tôi để đọc và viết giao thức Redis trong phần Tiếp theo.