Redis là một máy chủ cơ sở dữ liệu mã nguồn mở đã trở nên phổ biến gần đây. Đó là kho lưu trữ khóa-giá trị trong bộ nhớ. Nó giữ tất cả dữ liệu trong bộ nhớ để truy cập nhanh, nhưng cũng giữ dữ liệu trong đĩa nếu bạn bảo nó. Đó là kho lưu trữ khóa-giá trị cơ bản trong đó khóa và giá trị là các chuỗi, nhưng nó cũng chứa nhiều cấu trúc thú vị hơn như số nguyên, danh sách, bộ, bộ được sắp xếp và từ điển, đồng thời cũng chứa một số tính năng nâng cao như pub-sub, chặn pop, giám sát khóa
Redis là con dao Thụy Sĩ của cơ sở dữ liệu trong bộ nhớ. bạn có thể sử dụng nó để triển khai nhiều trường hợp sử dụng khác nhau, từ bộ đệm dữ liệu hoặc hàng đợi công việc đến nhật ký thống kê
Redis nguyên thủyTrong Node, để truy cập Redis, bạn sẽ cần cài đặt thư viện máy khách. Cái được sử dụng và thử nghiệm nhiều nhất là
redis.get['key', function[err, value] {
if [err] {
console.error['error getting key:', err];
}
else {
console.log['key has the value %s', value];
}
}];
8$ npm install redis --save
“Nếu bạn chưa thực hiện, để tự cài đặt Redis, bạn nên làm theo hướng dẫn trên trang web chính thức tại http. //redis. io/tải xuống. ”
làm lại. js
var redis = require['redis'];module.exports = redis.createClient[];
Mô-đun
redis.get['key', function[err, value] {
if [err] {
console.error['error getting key:', err];
}
else {
console.log['key has the value %s', value];
}
}];
8 cục bộ này sử dụng mô-đun NPM redis.get['key', function[err, value] {
if [err] {
console.error['error getting key:', err];
}
else {
console.log['key has the value %s', value];
}
}];
8 chính thức đã cài đặt để tạo một đối tượng máy khách, đây là đối tượng mà mô-đun này xuất raTheo tùy chọn, bạn có thể chuyển vào một số tùy chọn máy khách nếu bạn đang lưu trữ Redis ở một cổng khác hoặc trong một máy chủ mạng khác
var redis = require['redis'];var port = process.env.REDIS_PORT || 6379;
var host = process.env.REDIS_HOST || '127.0.0.1';module.exports = redis.createClient[port, host];
Để sử dụng mô-đun này từ bất kỳ tệp nào khác, bạn chỉ cần yêu cầu nó như thế này
client_example. js
var redis = require['./redis'];
var assert = require['assert'];redis.set['key', 'value', function[err] {
if [err] {
throw err
} redis.get['key', function[err, value] {
if [err] {
throw err
} assert.equal[value, 'value']; console.log['it works!']; redis.quit[];
}];
}];
Ở đây trong ví dụ cuối cùng này, chúng tôi đang đặt một khóa và sau đó nhận giá trị cho khóa đó, khẳng định rằng đó thực sự là những gì chúng tôi đã chèn
Bây giờ, hãy xem xét một số nguyên hàm hữu ích của Redis và cách sử dụng chúng trong Node
DâyTrong Redis, tất cả các khóa đều là chuỗi và giá trị thường là chuỗi. [Chúng ta sẽ thấy một số ví dụ sử dụng số và đối tượng sau. ] Như chúng ta đã thấy, để đặt khóa cho chuỗi bạn sử dụng
var redis = require['./redis'];redis.set['some key', 'some value'];1, cung cấp khóa và chuỗi giá trị________số 8
redis.expire['some key', 2];setInterval[function[] {
redis.get['some key', function[err, value] {
if [err] {
throw err;
}
if [value] {
console.log['value:', value];
}
else {
console.log['value is gone'];
process.exit[];
}
}];
}, 1e3];
Đối với mọi lệnh Redis, bạn có thể chuyển vào một lệnh gọi lại để được gọi khi lệnh hoàn thành hoặc có lỗi
redis.put['key', 'value', function[err] {
if [err] {
console.error['error putting key:', err]
}
else {
console.log['key saved with success'];
}
}];
Bạn cũng có thể lấy giá trị chuỗi của bất kỳ khóa nào bằng lệnh
var redis = require['./redis'];redis.set['some key', 'some value'];2
redis.expire['some key', 2];setInterval[function[] {
redis.get['some key', function[err, value] {
if [err] {
throw err;
}
if [value] {
console.log['value:', value];
}
else {
console.log['value is gone'];
process.exit[];
}
}];
}, 1e3];
redis.get['key', function[err, value] {
if [err] {
console.error['error getting key:', err];
}
else {
console.log['key has the value %s', value];
}
}];
Khóa hết hạnBên cạnh các hoạt động khóa-giá trị cơ bản, Redis có vô số chức năng hữu ích. Một trong số đó là hết hạn khóa. Bạn có thể xác định thời gian hết hạn mà sau đó mục nhập sẽ bị xóa khỏi Redis. Hãy xem điều này trong hành động
hết hạn. js
var redis = require['./redis'];redis.set['some key', 'some value'];
redis.expire['some key', 2];setInterval[function[] {
redis.get['some key', function[err, value] {
if [err] {
throw err;
}
if [value] {
console.log['value:', value];
}
else {
console.log['value is gone'];
process.exit[];
}
}];
}, 1e3];
Ở đây, chúng tôi đang đặt một khóa và sau đó hết hạn sau hai giây trôi qua. Sau đó, chúng tôi thăm dò Redis về giá trị trên khóa đó cho đến khi Redis xóa bản ghi đó, tại thời điểm đó chúng tôi chấm dứt tập lệnh hiện tại
“Bạn có thể nhận thấy rằng trong ví dụ trước, đôi khi chúng tôi gọi Redis mà không cung cấp lệnh gọi lại. Điều này có an toàn không? . khi phát hành một số lệnh trên cùng một máy khách, máy khách chỉ thực hiện một lệnh tại một thời điểm; . Điều này xảy ra vì giao thức Redis chỉ cho phép một lệnh đang chạy trên mỗi kết nối. Nếu xảy ra lỗi và bạn không cung cấp lệnh gọi lại, lỗi sẽ được phát ra trên máy khách. Khi điều này xảy ra, bạn sẽ mất tất cả ngữ cảnh của lỗi. Đây là lý do tại sao bạn phải luôn cung cấp lệnh gọi lại trong các lệnh. ”
Bạn có thể kiểm tra điều này bằng cách làm
$ npm install redis --save
3Nếu bạn cần đặt thời gian hết hạn khi đặt khóa, bạn có thể sử dụng lệnh
var redis = require['./redis'];redis.set['some key', 'some value'];3 để thay thế
redis.expire['some key', 2];setInterval[function[] {
redis.get['some key', function[err, value] {
if [err] {
throw err;
}
if [value] {
console.log['value:', value];
}
else {
console.log['value is gone'];
process.exit[];
}
}];
}, 1e3];
hết hạn_setex. js
$ npm install redis --save
5Giao dịchTrong ví dụ trước, chúng ta đã thấy một lệnh kết hợp hai lệnh thành một [
var redis = require['./redis'];redis.set['some key', 'some value'];4 và
redis.expire['some key', 2];setInterval[function[] {
redis.get['some key', function[err, value] {
if [err] {
throw err;
}
if [value] {
console.log['value:', value];
}
else {
console.log['value is gone'];
process.exit[];
}
}];
}, 1e3];
var redis = require['./redis'];redis.set['some key', 'some value'];5]. Bạn cũng có thể chọn kết hợp bất kỳ lệnh nào bạn muốn vào một giao dịch nguyên tử bằng cách sử dụng lệnh
redis.expire['some key', 2];setInterval[function[] {
redis.get['some key', function[err, value] {
if [err] {
throw err;
}
if [value] {
console.log['value:', value];
}
else {
console.log['value is gone'];
process.exit[];
}
}];
}, 1e3];
var redis = require['./redis'];redis.set['some key', 'some value'];6. Chẳng hạn, nếu bạn muốn đặt nguyên tử hai khóa và đặt ngày hết hạn của một khóa khác, bạn có thể soạn nó như thế này
redis.expire['some key', 2];setInterval[function[] {
redis.get['some key', function[err, value] {
if [err] {
throw err;
}
if [value] {
console.log['value:', value];
}
else {
console.log['value is gone'];
process.exit[];
}
}];
}, 1e3];
đa. js
var redis = require['redis'];module.exports = redis.createClient[];0
Ở đây, chúng tôi đang xây dựng một lệnh MULTI bằng cách sử dụng
var redis = require['./redis'];redis.set['some key', 'some value'];7. Sau đó, chúng tôi sẽ thêm các lệnh vào giao dịch này bằng API Redis, nhưng trên nhiều lệnh đã tạo. Sau đó, chúng tôi thực hiện giao dịch bằng cách gọi
redis.expire['some key', 2];setInterval[function[] {
redis.get['some key', function[err, value] {
if [err] {
throw err;
}
if [value] {
console.log['value:', value];
}
else {
console.log['value is gone'];
process.exit[];
}
}];
}, 1e3];
var redis = require['./redis'];redis.set['some key', 'some value'];8, cung cấp cho nó một cuộc gọi lại
redis.expire['some key', 2];setInterval[function[] {
redis.get['some key', function[err, value] {
if [err] {
throw err;
}
if [value] {
console.log['value:', value];
}
else {
console.log['value is gone'];
process.exit[];
}
}];
}, 1e3];
Nếu bạn gặp lỗi, nghĩa là không có lệnh nào hiệu quả. Nếu bạn không gặp lỗi, điều này có nghĩa là mỗi lệnh đã thành công
“Tất cả các lệnh này được ghi lại trên trang web chính thức của Redis. http. //redis. io/lệnh. Với một vài ngoại lệ, ứng dụng khách
var redis = require['./redis'];redis.set['some key', 'some value'];9 tuân theo thứ tự đối số chính xác và nhập như được ghi lại. ”Kết quả lệnh trong Multi
redis.expire['some key', 2];setInterval[function[] {
redis.get['some key', function[err, value] {
if [err] {
throw err;
}
if [value] {
console.log['value:', value];
}
else {
console.log['value is gone'];
process.exit[];
}
}];
}, 1e3];
Bên cạnh việc thực hiện nhiều lệnh, bạn cũng có thể thực hiện nhiều truy vấn hoặc kết hợp các lệnh và truy vấn, nhận kết quả ở cuối. Hãy xem điều này trong hành động
multi_read. js
var redis = require['redis'];module.exports = redis.createClient[];1
Nếu bạn thực hiện điều này, bạn sẽ nhận được đầu ra sau
var redis = require['redis'];module.exports = redis.createClient[];2
Ở đây bạn có thể thấy rằng kết quả được chuyển đến cuộc gọi lại của chúng tôi là một mảng chứa vị trí cho kết quả của từng thao tác trong giao dịch của chúng tôi. Thao tác
var redis = require['./redis'];redis.set['some key', 'some value'];4 [vị trí 0 và 2] dẫn đến chuỗi
redis.expire['some key', 2];setInterval[function[] {
redis.get['some key', function[err, value] {
if [err] {
throw err;
}
if [value] {
console.log['value:', value];
}
else {
console.log['value is gone'];
process.exit[];
}
}];
}, 1e3];
$ npm install redis --save
31 [đây là cách Redis biểu thị thành công]; Khóa lạc quan bằng WATCHLệnh
var redis = require['./redis'];redis.set['some key', 'some value'];6 có thể mạnh, nhưng bạn vẫn không thể đưa ra các thao tác so sánh và thiết lập nguyên tử. Ví dụ: giả sử bạn muốn thực hiện một thao tác trong đó bạn đọc một giá trị số nguyên từ khóa
redis.expire['some key', 2];setInterval[function[] {
redis.get['some key', function[err, value] {
if [err] {
throw err;
}
if [value] {
console.log['value:', value];
}
else {
console.log['value is gone'];
process.exit[];
}
}];
}, 1e3];
$ npm install redis --save
34, sau đó bạn thêm 1 vào giá trị đó và lưu trữ lạivar redis = require['redis'];module.exports = redis.createClient[];3
Cách tiếp cận này có một vấn đề rõ ràng mặc dù. nó không cho phép khách hàng đồng thời an toàn. Nếu có nhiều máy khách đang thực hiện thao tác này song song, thì nhiều máy khách có thể đọc cùng một giá trị, tăng giá trị đó và sau đó lưu cùng một kết quả. Điều này có nghĩa là, thay vì tăng giá trị một cách nguyên tử, chúng ta sẽ mất các giá trị gia tăng. Điều này có thể được giải quyết bằng cách sử dụng kết hợp
$ npm install redis --save
35 và var redis = require['./redis'];redis.set['some key', 'some value'];6
redis.expire['some key', 2];setInterval[function[] {
redis.get['some key', function[err, value] {
if [err] {
throw err;
}
if [value] {
console.log['value:', value];
}
else {
console.log['value is gone'];
process.exit[];
}
}];
}, 1e3];
var redis = require['redis'];module.exports = redis.createClient[];4
Ở đây chúng ta đang định nghĩa một hàm
$ npm install redis --save
37 chung nhận một khóa và một hàm gọi lại. Sau khi xác định chức năng này, chúng tôi sử dụng nó để tăng khóa $ npm install redis --save
34. Khi điều này được thực hiện, chúng tôi chấm dứt kết nối máy khách RedisHàm
$ npm install redis --save
37 bắt đầu bằng cách xem phím, sau đó bắt đầu lệnh var redis = require['./redis'];redis.set['some key', 'some value'];6. Sau đó, chúng tôi tính toán giá trị mới cho A và nối lệnh
redis.expire['some key', 2];setInterval[function[] {
redis.get['some key', function[err, value] {
if [err] {
throw err;
}
if [value] {
console.log['value:', value];
}
else {
console.log['value is gone'];
process.exit[];
}
}];
}, 1e3];
var redis = require['./redis'];redis.set['some key', 'some value'];4 vào đa. Sau đó, chúng tôi thực thi đa lệnh một lệnh này, chuyển hàm
redis.expire['some key', 2];setInterval[function[] {
redis.get['some key', function[err, value] {
if [err] {
throw err;
}
if [value] {
console.log['value:', value];
}
else {
console.log['value is gone'];
process.exit[];
}
}];
}, 1e3];
$ npm install redis --save
52 của chúng tôi dưới dạng gọi lại. Chức năng này phát hiện xung đột. Lệnh var redis = require['./redis'];redis.set['some key', 'some value'];6 trả về giá trị
redis.expire['some key', 2];setInterval[function[] {
redis.get['some key', function[err, value] {
if [err] {
throw err;
}
if [value] {
console.log['value:', value];
}
else {
console.log['value is gone'];
process.exit[];
}
}];
}, 1e3];
$ npm install redis --save
54 [thay vì $ npm install redis --save
31 truyền thống] khi phát hiện xung đột. Xung đột xảy ra khi bất kỳ khóa nào đã xem [trong trường hợp của chúng tôi, chỉ một khóa] được ghi bởi một kết nối khác. Trong trường hợp này, chúng tôi phát hiện xung đột và đưa ra lỗi thích hợp với thông báo cho biết đã phát hiện xung độtTuy nhiên, có một số khía cạnh phút và có lẽ không rõ ràng đối với kịch bản này. Đầu tiên, chúng tôi đang sử dụng một kết nối cho mỗi giao dịch. Điều này là do Redis giữ một danh sách theo dõi trên mỗi kết nối và thực thi
var redis = require['./redis'];redis.set['some key', 'some value'];6 chỉ bị hủy bỏ nếu thao tác ghi trên khóa đã xem được thực hiện trên một kết nối máy khách khác. Ngoài ra, sau khi multi đã được thực thi, danh sách theo dõi sẽ bị loại bỏ. Về cơ bản, sẽ không an toàn khi chia sẻ kết nối nếu bạn đang dựa vào hành vi của danh sách theo dõi
redis.expire['some key', 2];setInterval[function[] {
redis.get['some key', function[err, value] {
if [err] {
throw err;
}
if [value] {
console.log['value:', value];
}
else {
console.log['value is gone'];
process.exit[];
}
}];
}, 1e3];
“Phát hành thêm một lệnh
$ npm install redis --save
57 sẽ thêm một khóa vào danh sách theo dõi kết nối. Bạn có thể xóa danh sách theo dõi bằng lệnh $ npm install redis --save
58. ”Cũng xin lưu ý rằng, vì chúng tôi đang tạo một kết nối Redis cho mỗi lần tăng, nên chúng tôi đặc biệt cẩn thận khi đóng kết nối đó. Điều này có nghĩa là, trong trường hợp có lỗi, chúng tôi luôn gọi hàm
$ npm install redis --save
52, chịu trách nhiệm đóng kết nối với Redis. Chúng tôi phải bao gồm tất cả các tình trạng lỗi – rất dễ rò rỉ các kết nối có thời gian sử dụng ngắn“Một kết nối cho mỗi giao dịch có nghĩa là cần thêm tài nguyên phía máy khách và phía máy chủ. Hãy cẩn thận với việc đo kích thước hệ thống của bạn khi sử dụng tính năng này, vì nó dễ gây gánh nặng cho các quy trình Node hoặc máy chủ Redis trong thời gian lưu lượng truy cập cao nhất. ”
Chúng tôi có thể kiểm tra khả năng phát hiện xung đột bằng cách phát hành đồng thời nhiều hơn một số gia ở cuối tệp cuối cùng
kết thúc của increment_watch. js
var redis = require['redis'];module.exports = redis.createClient[];5
Hãy chạy tập lệnh này
var redis = require['redis'];module.exports = redis.createClient[];6
Nhưng bây giờ chúng tôi có thể phát hiện xung đột đúng cách, chúng tôi có thể xử lý chúng và thử thực hiện lại giao dịch
tăng đồng hồ thử lại. js
var redis = require['redis'];module.exports = redis.createClient[];7
Ở đây, chúng tôi đã đổi tên hàm
$ npm install redis --save
37 của mình thành var redis = require['redis'];module.exports = redis.createClient[];01 và tạo một hàm
$ npm install redis --save
37 mới xử lý trường hợp đặc biệt khi phát hiện xung đột. Vì chúng tôi được đảm bảo rằng Redis sẽ không cam kết nếu có xung đột, chúng tôi có thể thử gọi lại hàm var redis = require['redis'];module.exports = redis.createClient[];01 một cách an toàn
Bây giờ chúng tôi có thể kiểm tra phiên bản mới này và xác minh rằng tất cả các giao dịch cuối cùng đã thành công, mặc dù chúng được phát đồng thời
var redis = require['redis'];module.exports = redis.createClient[];8
Ở đây, chúng tôi đã sử dụng một số gia đơn giản, nhưng bạn có thể dễ dàng thấy rằng chúng tôi có thể sử dụng khóa tối ưu để tạo bất kỳ loại giao dịch tùy chỉnh nào miễn là chúng tôi đang sử dụng các kết nối Redis khác nhau cho mỗi giao dịch và chúng tôi đang xem các khóa cần thiết
Giao dịch sử dụng tập lệnh LuaMột cách khác để thực hiện các thao tác phức tạp tùy ý theo cách nguyên tử trong Redis là sử dụng các tập lệnh được viết bằng Lua. Redis cung cấp một cách để chúng ta chèn và chạy các tập lệnh Lua bên trong nó. Khi thực thi tập lệnh Lua trong Redis, chúng tôi được đảm bảo rằng không có lệnh hoặc tập lệnh nào khác đang thực thi đồng thời, đó chính xác là điều chúng tôi muốn
Lua là một ngôn ngữ kịch bản đơn giản, hơi giống với JavaScript [mặc dù các mảng bắt đầu ở chỉ mục 1, không phải 0…]
“Nếu bạn không biết Lua, có một số tài nguyên ngoài kia nếu bạn muốn tìm hiểu về nó — nhưng nó rõ ràng nằm ngoài phạm vi của cuốn sách này. Tuy nhiên, chúng tôi sẽ trình bày ở đây một số ví dụ mà bạn có thể thấy hữu ích để làm cơ sở cho các tập lệnh của riêng mình. ”
Trước tiên, chúng tôi sẽ chuyển giao dịch
$ npm install redis --save
37 của mình thành tập lệnh Redis Lualua_scripts/tăng. lúa
var redis = require['redis'];module.exports = redis.createClient[];9
Ở đây bạn có thể thấy rằng tập lệnh đơn giản này bắt đầu bằng cách lấy tên của khóa từ biến
var redis = require['redis'];module.exports = redis.createClient[];05. Đây là một biến ẩn đặc biệt mà Redis chuyển đến tập lệnh, xuất phát từ lệnh gọi của máy khách. Sau đó, chúng tôi nhận được giá trị được lưu trữ trong khóa đó bằng cách gọi công cụ Redis. Các hoạt động Redis có sẵn để được gọi bằng cách sử dụng
var redis = require['redis'];module.exports = redis.createClient[];06;
Sau khi nhận được giá trị hiện tại, chúng tôi tăng giá trị đó, lưu trữ và sau đó trả lại giá trị đó dưới dạng kết quả của hoạt động
Đây là phần Nút triển khai chức năng
$ npm install redis --save
37 và ủy quyền cho tập lệnh Luagia_lua. js
var redis = require['redis'];var port = process.env.REDIS_PORT || 6379;0
var host = process.env.REDIS_HOST || '127.0.0.1';module.exports = redis.createClient[port, host];
Điều đầu tiên chúng tôi làm là tải tập lệnh Lua vào bộ nhớ. Chúng tôi làm điều này bằng cách sử dụng
var redis = require['redis'];module.exports = redis.createClient[];08
“Ở đâu đó bạn có thể đã nghe nói rằng việc sử dụng các chức năng đồng bộ của Node là sai - bạn phải luôn sử dụng phiên bản không đồng bộ của các chức năng để không chặn vòng lặp sự kiện của Node. Bạn có thể sử dụng các chức năng đồng bộ trong thời gian chuẩn bị mô-đun - chúng tồn tại ở đây vì điều đó. Theo nguyên tắc thông thường, bạn chỉ cần tránh gọi các hàm đồng bộ từ bên trong hàm gọi lại hoặc trình xử lý sự kiện. ”
Bây giờ chúng ta đã có tập lệnh Lua trong bộ nhớ, chúng ta có thể triển khai hàm
$ npm install redis --save
37, hàm này sẽ tải tập lệnh vào Redis và gọi nó bằng cách sử dụng lệnh var redis = require['redis'];module.exports = redis.createClient[];10. Đối số đầu tiên của
var redis = require['redis'];module.exports = redis.createClient[];11 là chính mã script và sau đó là số lượng khóa chúng ta sẽ chuyển. Trong trường hợp của chúng tôi, chúng tôi sẽ chỉ chuyển một đối số chính. Cuối cùng, có một cuộc gọi lại để chúng tôi biết khi thao tác thất bại hoặc thành công và trong trường hợp cuối cùng, kết quả là gì
“Bên cạnh các khóa, bạn cũng có thể truyền các đối số tùy ý mà tập lệnh Lua có thể truy cập bằng cách sử dụng biến mảng ẩn
var redis = require['redis'];module.exports = redis.createClient[];12. ”
Bây giờ chúng ta có thể kiểm tra tập lệnh của mình
var redis = require['redis'];var port = process.env.REDIS_PORT || 6379;1
var host = process.env.REDIS_HOST || '127.0.0.1';module.exports = redis.createClient[port, host];
Lưu trữ các tập lệnh Lua
Có một vấn đề với lần triển khai cuối cùng của chúng tôi. chúng tôi luôn chuyển tập lệnh Lua trước khi gọi. Điều này chịu trách nhiệm truyền tập lệnh vào Redis, tải Redis, phân tích cú pháp và chạy tập lệnh. Chúng tôi có thể tối ưu hóa điều này bằng cách sử dụng lệnh Redis
var redis = require['redis'];module.exports = redis.createClient[];13, lệnh này cho phép chúng tôi gọi một tập lệnh dựa trên thông báo SHA1 của nó. Hãy sử dụng nó để tránh tải cùng một tập lệnh mọi lúc
lua_scripts/chỉ mục. js
var redis = require['redis'];var port = process.env.REDIS_PORT || 6379;2
var host = process.env.REDIS_HOST || '127.0.0.1';module.exports = redis.createClient[port, host];
Mã này là một mô-đun chung quản lý việc thực thi các tập lệnh cho bạn. Biến có tên
var redis = require['redis'];module.exports = redis.createClient[];14 là một mảng chứa tất cả tên của các tập lệnh có sẵn. Trong trường hợp đơn giản của chúng tôi, chúng tôi chỉ có một tập lệnh có tên
$ npm install redis --save
37, nhưng chúng tôi có thể có nhiều hơn. Khi mô-đun này tải, nó sẽ tải các phần thân của tập lệnh và tính toán thông báo SHA1 của từng phầnNgoài ra, mô-đun này xuất một hàm
var redis = require['redis'];module.exports = redis.createClient[];16 nhận kết nối Redis, tên tập lệnh và một tập hợp các đối số thực thi tập lệnh tùy ý, được hoàn thiện bằng một lệnh gọi lại. Chức năng này bắt đầu bằng cách thử thực thi tập lệnh bằng cách sử dụng
var redis = require['redis'];module.exports = redis.createClient[];17, chuyển vào tập lệnh thông báo SHA1. Nếu Redis không thể tìm thấy tập lệnh, quá trình thực thi sẽ tạo ra một thông báo lỗi cụ thể có chứa chuỗi "NOSCRIPT". Khi chúng tôi gặp lỗi như vậy, Redis cho chúng tôi biết rằng nó chưa chứa tập lệnh. sau đó chúng tôi quay lại sử dụng
var redis = require['redis'];module.exports = redis.createClient[];11, chuyển vào nội dung tập lệnh thay vì thông báo tập lệnh
Bây giờ chúng ta có thể chỉ cần sử dụng mô-đun này từ tập lệnh máy khách như thế này
tăng luasha. js
var redis = require['redis'];var port = process.env.REDIS_PORT || 6379;3
var host = process.env.REDIS_HOST || '127.0.0.1';module.exports = redis.createClient[port, host];
Khi thực thi tập lệnh này, một lần nữa, bạn sẽ thấy kết quả đầu ra giống như trước đây — nhưng bây giờ bạn biết rằng bạn nên cố gắng hết sức để sử dụng lại tập lệnh đã lưu trong bộ nhớ cache
var redis = require['redis'];var port = process.env.REDIS_PORT || 6379;4
var host = process.env.REDIS_HOST || '127.0.0.1';module.exports = redis.createClient[port, host];
Hiệu suất
Vì chúng tôi biết rằng tất cả các lệnh và truy vấn Redis được thực hiện trong bộ nhớ và các tập lệnh Lua cũng được thực thi nhanh chóng, nên nếu chúng tôi cẩn thận với số lượng và loại thao tác chúng tôi thực hiện, chúng tôi cũng có thể đảm bảo rằng mỗi giao dịch được thực hiện đủ nhanh để
Mỗi lệnh Redis có độ phức tạp về thời gian được cung cấp cho chúng tôi trong ký hiệu O[]. Chẳng hạn, nếu một thao tác đã cho là O[1], chúng ta biết rằng nó sẽ luôn mất cùng một khoảng thời gian cố định
Chẳng hạn, lệnh Redis
var redis = require['redis'];module.exports = redis.createClient[];19, lấy phần tử thứ N của danh sách, có độ phức tạp là O[N], trong đó N là số phần tử mà danh sách có. Nếu bạn đang sử dụng lệnh này, bằng cách nào đó bạn phải đảm bảo rằng số phần tử trong danh sách này không bị chặnsố nguyên
Trước đó chúng ta đã thấy cách thực hiện các thao tác nguyên tử trong Redis và chúng ta đã cho thấy ví dụ về việc tăng giá trị số nguyên của một bản ghi. Ví dụ này chỉ được trình bày với mục đích hiển thị một ví dụ đơn giản, vì thực tế là Redis đã có các lệnh tăng và giảm
gia tăng. js
var redis = require['redis'];var port = process.env.REDIS_PORT || 6379;5
var host = process.env.REDIS_HOST || '127.0.0.1';module.exports = redis.createClient[port, host];
Nếu bạn thực thi tệp này, bạn sẽ nhận được loại kết quả giống như trong phiên bản tùy chỉnh trước đó
var redis = require['redis'];var port = process.env.REDIS_PORT || 6379;6
var host = process.env.REDIS_HOST || '127.0.0.1';module.exports = redis.createClient[port, host];
Bên cạnh việc tăng thêm một, Redis cũng cho phép tăng theo một giá trị số nguyên cụ thể bằng cách sử dụng lệnh
var redis = require['redis'];module.exports = redis.createClient[];20
gia tăng. js
var redis = require['redis'];var port = process.env.REDIS_PORT || 6379;7
var host = process.env.REDIS_HOST || '127.0.0.1';module.exports = redis.createClient[port, host];
Trong trường hợp này, chúng tôi đang tăng bản ghi lên giá trị 2 mười lần
var redis = require['redis'];var port = process.env.REDIS_PORT || 6379;8
var host = process.env.REDIS_HOST || '127.0.0.1';module.exports = redis.createClient[port, host];
Bên cạnh việc tăng, chúng ta cũng có thể giảm
quyết định. js
var redis = require['redis'];var port = process.env.REDIS_PORT || 6379;9
var host = process.env.REDIS_HOST || '127.0.0.1';module.exports = redis.createClient[port, host];
Điều này mang lại kết quả mong đợi sau đây
var redis = require['./redis'];0
var assert = require['assert'];redis.set['key', 'value', function[err] {
if [err] {
throw err
} redis.get['key', function[err, value] {
if [err] {
throw err
} assert.equal[value, 'value']; console.log['it works!']; redis.quit[];
}];
}];
Redis cũng có lệnh
var redis = require['redis'];module.exports = redis.createClient[];21 cho phép chúng tôi giảm một lượng cụ thể
giải mã. js
var redis = require['./redis'];1
var assert = require['assert'];redis.set['key', 'value', function[err] {
if [err] {
throw err
} redis.get['key', function[err, value] {
if [err] {
throw err
} assert.equal[value, 'value']; console.log['it works!']; redis.quit[];
}];
}];
Và chạy tập lệnh cuối cùng này mang lại kết quả như sau
var redis = require['./redis'];2Sử dụng bộ đếm
var assert = require['assert'];redis.set['key', 'value', function[err] {
if [err] {
throw err
} redis.get['key', function[err, value] {
if [err] {
throw err
} assert.equal[value, 'value']; console.log['it works!']; redis.quit[];
}];
}];
Những nguyên thủy này đưa ra những cách tuyệt vời để thực hiện các bộ đếm cơ bản để lưu trữ và đọc số liệu thống kê. Chẳng hạn, bạn có thể lưu trữ số liệu thống kê theo người dùng về số lượng yêu cầu API. Nếu bạn muốn tăng mức sử dụng API cho mỗi người dùng, bạn có thể sử dụng Redis để lưu trữ bộ đếm yêu cầu API cho mỗi người dùng, bộ đếm này sẽ tự động được đặt lại sau một khoảng thời gian cố định
Chẳng hạn, đây là cách bạn có thể triển khai một chức năng để tăng bộ đếm mức sử dụng API cho một người dùng cụ thể
apithrottling/incrapiusagecounter. js
var redis = require['./redis'];3
var assert = require['assert'];redis.set['key', 'value', function[err] {
if [err] {
throw err
} redis.get['key', function[err, value] {
if [err] {
throw err
} assert.equal[value, 'value']; console.log['it works!']; redis.quit[];
}];
}];
Ở đây, chúng tôi đang sử dụng lệnh gọi đa Redis để thực hiện hai thao tác. một để tăng bản ghi và một để lấy TTL [thời gian tồn tại] của bản ghi. Nếu bản ghi TTL chưa được thiết lập, chúng tôi sẽ thiết lập nó bằng cách sử dụng
var redis = require['redis'];module.exports = redis.createClient[];22. Nếu TTL đã được đặt, chúng tôi chỉ cần kết thúc hoạt động
“Lệnh TTL mang lại giá trị
var redis = require['redis'];module.exports = redis.createClient[];23 cho các bản ghi tồn tại và chưa có TTL. Nếu bản ghi không tồn tại, nó sẽ trả về
var redis = require['redis'];module.exports = redis.createClient[];24. Chúng tôi chỉ cần kiểm tra giá trị
var redis = require['redis'];module.exports = redis.createClient[];23 vì chúng tôi đang truy vấn TTL trong nhiều quyền sau khi bản ghi được cập nhật, đảm bảo rằng bản ghi tồn tại. ”
Bạn chỉ cần gọi chức năng này trước bất kỳ yêu cầu nào do khách hàng xác thực và nó sẽ tăng bộ đếm sử dụng API của người dùng
Bây giờ chúng ta phải tạo một hàm truy vấn bộ đếm này để xác định xem người dùng có thể sử dụng API hay không
apithrottling/canuseruseapi. js
var redis = require['./redis'];4
var assert = require['assert'];redis.set['key', 'value', function[err] {
if [err] {
throw err
} redis.get['key', function[err, value] {
if [err] {
throw err
} assert.equal[value, 'value']; console.log['it works!']; redis.quit[];
}];
}];
Mô-đun này nhận giá trị cho bộ đếm yêu cầu API của người dùng. Nếu nó vượt quá mức tối đa nhất định, chúng tôi nói rằng nó hiện được cho phép. Bây giờ, ứng dụng chỉ cần gọi chức năng này trước bất kỳ xử lý yêu cầu API ứng dụng khách được xác thực nào, đại loại như thế này
điều chỉnh_example. js
var redis = require['./redis'];5
var assert = require['assert'];redis.set['key', 'value', function[err] {
if [err] {
throw err
} redis.get['key', function[err, value] {
if [err] {
throw err
} assert.equal[value, 'value']; console.log['it works!']; redis.quit[];
}];
}];
Trong quá trình triển khai, chúng tôi sẽ thất bại nếu có lỗi, nhưng thay vào đó, bạn có thể chọn bỏ qua lỗi từ Redis và tiếp tục, cải thiện tính khả dụng của dịch vụ trong trường hợp Redis ngừng hoạt động
điều tiết ví dụ đàn hồi. js
var redis = require['./redis'];6
var assert = require['assert'];redis.set['key', 'value', function[err] {
if [err] {
throw err
} redis.get['key', function[err, value] {
if [err] {
throw err
} assert.equal[value, 'value']; console.log['it works!']; redis.quit[];
}];
}];
Bằng cách sử dụng Redis làm nơi lưu trữ bộ đếm sử dụng API, chúng tôi có thể triển khai một cách tập trung và nhanh chóng để kiểm tra xem người dùng có vượt quá hạn ngạch sử dụng API hay không. Bằng cách sử dụng TTL tích hợp của Redis, chúng tôi không cần thêm công việc để hết hạn bản ghi. Redis làm điều đó cho chúng tôi
từ điểnBên cạnh các giá trị chuỗi đơn giản, Redis cũng cho phép bạn lưu trữ từ điển chuỗi trong đó khóa và giá trị là chuỗi. Tập hợp các lệnh Redis bắt đầu bằng
var redis = require['redis'];module.exports = redis.createClient[];26 và bao gồm
var redis = require['redis'];module.exports = redis.createClient[];27,
var redis = require['redis'];module.exports = redis.createClient[];28 và
var redis = require['redis'];module.exports = redis.createClient[];29, trong số những lệnh khác. Các lệnh này có thể ánh xạ tốt từ và vào các đối tượng nông của JavaScript
Chẳng hạn, bạn có thể lưu trữ hồ sơ người dùng bằng một lệnh set duy nhất như thế này
Thông tin người dùng. js
var redis = require['./redis'];7
var assert = require['assert'];redis.set['key', 'value', function[err] {
if [err] {
throw err
} redis.get['key', function[err, value] {
if [err] {
throw err
} assert.equal[value, 'value']; console.log['it works!']; redis.quit[];
}];
}];
Bạn có thể sử dụng mô-đun này, chúng tôi đã nghĩ ra từ ứng dụng của bạn
var redis = require['./redis'];8
var assert = require['assert'];redis.set['key', 'value', function[err] {
if [err] {
throw err
} redis.get['key', function[err, value] {
if [err] {
throw err
} assert.equal[value, 'value']; console.log['it works!']; redis.quit[];
}];
}];
Tất nhiên, thay vì sử dụng từ điển Redis, bạn chỉ cần mã hóa JSON và giải mã JSON cho đối tượng hồ sơ người dùng. Sử dụng từ điển Redis ở đây có thể hữu ích nếu bạn muốn lấy hoặc đặt các thuộc tính riêng lẻ mà không cần phải lấy và đặt toàn bộ đối tượng
Chẳng hạn, để lấy email người dùng trong ví dụ này, bạn chỉ cần
var redis = require['./redis'];9
var assert = require['assert'];redis.set['key', 'value', function[err] {
if [err] {
throw err
} redis.get['key', function[err, value] {
if [err] {
throw err
} assert.equal[value, 'value']; console.log['it works!']; redis.quit[];
}];
}];
“Với các thuộc tính bền bỉ và khả dụng, tôi không nghĩ rằng Redis phù hợp với công cụ lưu trữ chính cho bất kỳ ứng dụng nào. Thay vào đó, Redis có thể khá hữu ích với vai trò là bộ lưu trữ thứ cấp nhanh hơn và được sử dụng làm lớp bộ nhớ đệm. ”
Máy đếm từ điển RedisMột cách sử dụng khác cho từ điển Redis là giúp đặt tên cho các khóa bằng cách lưu trữ một số bộ đếm dưới cùng một khóa. Chẳng hạn, nếu bạn muốn theo dõi quyền truy cập API, bạn có thể tăng nguyên tử một số bộ đếm người dùng như thế này
quầy. js
redis.put['key', 'value'];
0Ở đây, chúng tôi đang xuất một hàm có tên là
var redis = require['redis'];module.exports = redis.createClient[];30 mà khách hàng gọi khi họ muốn đếm số lần truy cập API của một người dùng cụ thể. Hàm này tạo một giao dịch
var redis = require['./redis'];redis.set['some key', 'some value'];6 mang một số lệnh
redis.expire['some key', 2];setInterval[function[] {
redis.get['some key', function[err, value] {
if [err] {
throw err;
}
if [value] {
console.log['value:', value];
}
else {
console.log['value is gone'];
process.exit[];
}
}];
}, 1e3];
var redis = require['redis'];module.exports = redis.createClient[];32. Đối với mỗi lệnh này, khóa cơ sở luôn giống nhau – và được tạo riêng cho ID người dùng đã cho. Mỗi khóa thuộc tính sau đó được soạn dựa trên ngày hiện tại. Ví dụ: nếu ngày hiện tại là
var redis = require['redis'];module.exports = redis.createClient[];33, điều này sẽ tăng số lượng bộ đếm có tên là
var redis = require['redis'];module.exports = redis.createClient[];34,
var redis = require['redis'];module.exports = redis.createClient[];35,
var redis = require['redis'];module.exports = redis.createClient[];36,
var redis = require['redis'];module.exports = redis.createClient[];33 và
var redis = require['redis'];module.exports = redis.createClient[];38, tất cả đều nằm trong bản ghi bộ đếm dành riêng cho người dùng. Bằng cách này, bạn sẽ có các thùng truy cập cho mỗi ngày, tháng và năm, cũng như tổng cộng
danh sáchBạn sẽ phải cẩn thận khi duy trì các khóa bên trong mỗi Hash. Sau một thời gian, số lượng khóa cho mỗi người dùng đang hoạt động sẽ tăng lên, chiếm bộ nhớ Redis và tăng độ trễ hoạt động
Redis có một loại thú vị khác. danh sách. Một danh sách trong Redis được triển khai nội bộ dưới dạng danh sách được liên kết, điều đó có nghĩa là việc chèn và xóa các phần tử khỏi nó không tốn kém
Ví dụ, điều này làm cho danh sách trở nên hữu ích để triển khai hàng đợi công việc. Bạn chèn công việc vào một đầu của danh sách và nhân viên lấy ra công việc từ đầu kia của danh sách. Hãy xem cách chúng ta có thể triển khai hàng đợi công việc bằng Redis
xếp hàng. js
redis.put['key', 'value'];
1Mô-đun
var redis = require['redis'];module.exports = redis.createClient[];39 này xuất hai chức năng.
var redis = require['redis'];module.exports = redis.createClient[];40 và
var redis = require['redis'];module.exports = redis.createClient[];41. Cái đầu tiên làm nhiệm vụ đẩy các hạng mục công việc cho công nhân. Cái thứ hai là để công nhân bật công việc khỏi hàng đợi
Đây là một số mã thực hiện mô-đun này
queue_test. js
redis.put['key', 'value'];
2Tập lệnh này ở trên chèn 10 mục công việc vào hàng đợi. Sau khi tất cả chúng được chèn vào, nó sẽ bật chúng ra ngoài. Nếu không còn công việc nào nữa, nó sẽ đợi một giây trước khi thử bật một mục khác. Nếu không, nó sẽ cố gắng bật một cái khác ngay sau đó. Bạn có thể thực thi tập tin này
redis.put['key', 'value'];
3Tránh bỏ phiếu
Trong giải pháp cuối cùng này, các công nhân phải thăm dò ý kiến của Redis cho công việc, điều này thật xấu xí, gây ra một chút chi phí và cũng dễ bị lỗi. Thay vào đó, kết nối máy khách Redis có thể sử dụng một trong các lệnh pop chặn danh sách để chặn trên danh sách khi không có phần tử nào. Với kiến thức mới này, đây là cách chúng tôi sẽ triển khai lại mô-đun hàng đợi
queue_block. js
redis.put['key', 'value'];
4Ở đây, thay vì hiển thị hàm
var redis = require['redis'];module.exports = redis.createClient[];41, chúng tôi hiển thị hàm tạo cho worker. Hàm tạo này nhận một hàm sẽ được gọi khi một mục công việc được bật lên hoặc khi xảy ra lỗi khi thực hiện nó
Bạn có thể thấy ở đây chúng tôi tạo một kết nối Redis cho mỗi worker. Điều này là do cửa sổ bật lên chặn kết nối, chỉ trả lời khi hết thời gian chờ nhất định hoặc khi một mục được bật lên
Không mất công
Một vấn đề có thể phát sinh từ bất kỳ triển khai hàng đợi công việc nào trước đó là công việc có thể bị mất nếu quy trình worker ngừng hoạt động. Nếu một công nhân chết trong khi xử lý một số công việc, thì phần công việc đó đã xuất hiện từ Redis và chúng tôi đã mất nó. Trong một số ứng dụng, điều này có thể không thành vấn đề nếu hiếm khi xảy ra;
“Thông thường, công việc phải được thực hiện nhiều nhất một lần hay ít nhất một lần. Nếu bạn phải thực hiện công việc ít nhất một lần, thì các hoạt động phát sinh từ công việc này phải là bình thường. nghĩa là, nếu cùng một hoạt động xảy ra nhiều lần, nó sẽ mang lại kết quả như nhau. Một ví dụ về điều này là hoạt động tuyên truyền thay đổi mật khẩu người dùng sang hệ thống nước ngoài. Sẽ không có vấn đề gì nếu thay đổi được lan truyền nhiều lần, vì nó sẽ mang lại kết quả tương tự, đó là đặt mật khẩu trong một hệ thống nước ngoài
Thường có một cách để thực hiện các thao tác thực thi chính xác một lần và thường liên quan đến việc tạo một mã định danh thao tác duy nhất và đảm bảo thao tác tương tự không được áp dụng hai lần. ”
Hãy xem cách chúng ta có thể tạo một hệ thống như vậy bằng hàng đợi Redis. Trước tiên, bạn sẽ cần cài đặt
var redis = require['redis'];module.exports = redis.createClient[];43 này để tạo ID duy nhất
redis.put['key', 'value'];
5Chúng tôi hiện đã sẵn sàng để tạo một phiên bản hàng đợi an toàn hơn
queueblocksafe. js
redis.put['key', 'value'];
6Ở đây, hàm
var redis = require['redis'];module.exports = redis.createClient[];44 của chúng tôi sử dụng lệnh
var redis = require['redis'];module.exports = redis.createClient[];45, lệnh này bật nguyên tử từ một danh sách và đẩy vào một danh sách khác. Điều này đảm bảo rằng chúng tôi luôn có công việc trong Redis khi nó đang được xử lý. Khi worker xử lý xong mục, nó gọi hàm gọi lại [
var redis = require['redis'];module.exports = redis.createClient[];46], hàm này sẽ xóa mục khỏi hàng đợi
var redis = require['redis'];module.exports = redis.createClient[];47
Bây giờ, để khôi phục từ các công nhân đã chết, một quy trình có thể chịu trách nhiệm xem qua danh sách
var redis = require['redis'];module.exports = redis.createClient[];47 và sắp xếp lại các hạng mục công việc đã vượt quá thời gian thực hiện nhất định
“Một điều cần lưu ý là, trong trường hợp có sự cố về tải trọng mà công nhân không đủ năng lực để tiêu thụ sản phẩm kịp thời, thì các hạng mục công việc có thể hết thời gian chờ và được yêu cầu, chỉ làm cho vấn đề về tải trọng. . Để tránh điều này, bạn nên a] đặt thời gian chờ đủ dài và b] ghi lại mọi sự kiện được yêu cầu và theo dõi tần suất của nó để bạn được cảnh báo khi nó quá cao. ”
bộRedis có các loại dữ liệu khác cho phép nhiều giá trị. Bộ Redis cho phép bạn lưu trữ nhiều giá trị chưa sắp xếp. Chúng cũng cho phép bạn nhanh chóng kiểm tra tư cách thành viên hoặc tính giao của hai tập hợp
Các bộ thường được sử dụng để nhóm các bản ghi. Chẳng hạn, giả sử rằng ứng dụng của bạn có một số nhóm người dùng. một cho người dùng đã đăng ký, một cho người dùng trả tiền, một cho người kiểm duyệt và một cho quản trị viên. Sau đó, chúng tôi có thể tạo một mô-đun để quản lý thuộc về các nhóm này
user_sets. js
redis.put['key', 'value'];
7Ở đây, chúng tôi đang sử dụng một số chức năng có tiền tố s của Redis để quản lý các bộ.
var redis = require['redis'];module.exports = redis.createClient[];49 thêm thành viên vào nhóm và
var redis = require['redis'];module.exports = redis.createClient[];50 sử dụng
var redis = require['redis'];module.exports = redis.createClient[];51 để xóa thành viên khỏi nhóm. Chúng tôi cũng có thể kiểm tra xem một người dùng nhất định có thuộc một nhóm nhất định hay không. Chúng tôi có thể sử dụng điều này để xác minh xem người dùng được cấp có quyền thực hiện một số hoạt động hợp lý hay không
usersetexample. js
redis.put['key', 'value'];
8“Truy vấn
var redis = require['redis'];module.exports = redis.createClient[];52 Redis có chi phí thời gian cố định, làm cho nó rất hiệu quả để kiểm tra xem một thành viên nhất định có thuộc một tập hợp nhất định hay không. Trong trường hợp của chúng tôi, điều này làm cho nó hiệu quả hơn, chẳng hạn như kiểm tra xem người dùng có thuộc nhóm người dùng nhất định hay không trước khi thực hiện một thao tác đặc quyền
Thêm một thành viên vào một tập hợp là một hoạt động bình thường. theo định nghĩa, một tập hợp sẽ không chứa các mục lặp lại. ”
Bây giờ chúng ta có thể chạy ví dụ này
redis.put['key', 'value'];
9tập hợp giao nhau
Bộ Redis cho phép bạn tính toán giao điểm. được cung cấp hai hoặc nhiều bộ, Redis có thể cho bạn biết thành viên nào là chung cho tất cả chúng. Chẳng hạn, chúng tôi có thể tính toán người dùng nào vừa là người kiểm duyệt vừa là người dùng trả tiền
redis.put['key', 'value', function[err] {
if [err] {
console.error['error putting key:', err]
}
else {
console.log['key saved with success'];
}
}];
0Bộ đã sắp xếpRedis giữ các phần tử trong một tập hợp không theo thứ tự cụ thể. thứ tự mà bạn thêm chúng không nhất thiết phải là thứ tự mà Redis truy xuất chúng, làm cho chúng rất hữu ích cho các hoạt động khác liên quan đến tư cách thành viên
Nếu bạn cần các bộ được sắp xếp, Redis sẽ hỗ trợ bạn. có một nhóm các hoạt động có tiền tố Z đến giải cứu bạn
Mỗi phần tử của một tập hợp có một số điểm, là một số nguyên tự nhiên. Tất cả các phần tử được lưu trữ, sắp xếp và lập chỉ mục theo giá trị này, điều đó có nghĩa là bạn có thể truy xuất tất cả các phần tử trong một phạm vi điểm, tất cả được sắp xếp theo điểm
Giả sử rằng bạn đang chạy một trò chơi thời gian thực hợp tác trực tuyến và bạn muốn giữ thứ hạng điểm số cho mỗi trò chơi nhất định. Mỗi người chơi có một số điểm có thể tăng hoặc giảm và bạn muốn trình bày một bảng xếp hạng cập nhật với số điểm đó. Hãy tạo một mô-đun để quản lý điều đó
game_scores. js
redis.put['key', 'value', function[err] {
if [err] {
console.error['error putting key:', err]
}
else {
console.log['key saved with success'];
}
}];
1Mô-đun này xuất hai chức năng. Cái đầu tiên, tên là
var redis = require['redis'];module.exports = redis.createClient[];53, chấp nhận tên của một trò chơi, tên của một người chơi và một con số;
“Nếu người chơi trong phòng đó không tồn tại, nó sẽ được tạo bởi Redis với số điểm là 0. ”
Hàm thứ hai có tên là
var redis = require['redis'];module.exports = redis.createClient[];54 và cung cấp cho bạn thứ hạng của một trò chơi nhất định. Ở đây, chúng tôi đang sử dụng truy vấn
var redis = require['redis'];module.exports = redis.createClient[];55 Redis trả về một loạt các phần tử trong tập hợp đó, được sắp xếp theo thứ tự ngược lại của điểm số. Nếu chúng tôi muốn điều này trả về người dùng có số điểm thấp nhất trước tiên, chúng tôi sẽ sử dụng
var redis = require['redis'];module.exports = redis.createClient[];56 để thay thế. Chúng tôi đang yêu cầu mọi phần tử của tập hợp bằng cách chỉ định
var redis = require['redis'];module.exports = redis.createClient[];57 là phạm vi tối thiểu và
var redis = require['redis'];module.exports = redis.createClient[];58 là phạm vi tối đa. Đặt giá trị lớn nhất là
var redis = require['redis'];module.exports = redis.createClient[];58 làm cho phạm vi không có giới hạn trên, trả về hiệu quả tất cả các phần tử của tập hợp đó
Chúng tôi cũng chuyển vào tùy chọn
var redis = require['redis'];module.exports = redis.createClient[];60, giúp Redis xen kẽ các điểm số trong phản hồi [một phần tử mảng cho mục nhập, một phần tử mảng cho điểm số, v.v. ]. Ở đây, chúng tôi đang phân tích phản hồi và xây dựng một mảng xếp hạng phù hợp hơn trong đó mỗi phần tử có thuộc tính
var redis = require['redis'];module.exports = redis.createClient[];61 và thuộc tính
var redis = require['redis'];module.exports = redis.createClient[];53
Bây giờ chúng ta có thể mô phỏng một trò chơi bằng mô-đun này
gamescoresví dụ. js
redis.put['key', 'value', function[err] {
if [err] {
console.error['error putting key:', err]
}
else {
console.log['key saved with success'];
}
}];
2Ở đây, chúng tôi đang tăng ngẫu nhiên điểm số của một người chơi ngẫu nhiên cứ sau 100 mili giây. Chúng tôi cũng đang in thứ hạng hiện tại của trò chơi mỗi giây
redis.put['key', 'value', function[err] {
if [err] {
console.error['error putting key:', err]
}
else {
console.log['key saved with success'];
}
}];
3Pub-subBên cạnh tất cả các khóa-giá trị, danh sách, hàng đợi, loại tập hợp và hoạt động này, bạn cũng có thể sử dụng Redis để quản lý giao tiếp giữa các quá trình. Redis cung cấp mô hình đăng ký xuất bản trên các kênh được đặt tên cho phép người tạo tin nhắn và người tiêu dùng tin nhắn giao tiếp bằng cách sử dụng Redis làm nhà môi giới tin nhắn
Để xuất bản tin nhắn lên một kênh, bạn sử dụng lệnh
var redis = require['redis'];module.exports = redis.createClient[];63, chuyển tên kênh và chuỗi tin nhắn
redis.put['key', 'value', function[err] {
if [err] {
console.error['error putting key:', err]
}
else {
console.log['key saved with success'];
}
}];
4Bên cạnh các chuỗi trần, bạn cũng có thể xuất bản các đối tượng phức tạp bằng cách mã hóa JSON cho chúng
redis.put['key', 'value', function[err] {
if [err] {
console.error['error putting key:', err]
}
else {
console.log['key saved with success'];
}
}];
5Để nhận tin nhắn, bạn phải dành riêng một kết nối Redis cho nó, bật chế độ người đăng ký bằng cách đưa ra lệnh
var redis = require['redis'];module.exports = redis.createClient[];64 hoặc
var redis = require['redis'];module.exports = redis.createClient[];65. Từ thời điểm đó, kết nối chỉ cho phép các lệnh thay đổi bộ đăng ký. Hãy xem điều này trong hành động
redis.put['key', 'value', function[err] {
if [err] {
console.error['error putting key:', err]
}
else {
console.log['key saved with success'];
}
}];
6Ở đây chúng tôi đang đăng ký hai kênh có tên là “một số kênh” và “một số kênh khác”. Mỗi khi một thông báo được xuất bản trong Redis tới bất kỳ kênh nào trong số này, Redis sẽ phân phối thông báo tới tất cả các kết nối đang hoạt động có đăng ký kênh này
Như bạn có thể thấy từ ví dụ trước, bạn có thể tự động thêm đăng ký vào kết nối. Bạn cũng có thể tự động xóa đăng ký khỏi kết nối bằng cách gọi
var redis = require['redis'];module.exports = redis.createClient[];66
redis.put['key', 'value', function[err] {
if [err] {
console.error['error putting key:', err]
}
else {
console.log['key saved with success'];
}
}];
7Nếu bạn muốn nhận các đối tượng được mã hóa JSON phức tạp thay vì các chuỗi, bạn có thể phân tích cú pháp chuỗi như thế này
redis.put['key', 'value', function[err] {
if [err] {
console.error['error putting key:', err]
}
else {
console.log['key saved with success'];
}
}];
8Bộ phát phân tánNút có mẫu tương tự như Redis Pub-sub. Trình phát sự kiện. Trình phát sự kiện cho phép bạn tách trình tạo sự kiện khỏi trình tiêu thụ sự kiện, nhưng tất cả đều hoạt động trong cùng một quy trình Node. Chúng tôi có thể thay đổi nó để làm cho nó hoạt động giữa các quy trình
phân phối_emitter. js
redis.put['key', 'value', function[err] {
if [err] {
console.error['error putting key:', err]
}
else {
console.log['key saved with success'];
}
}];
9Ở đây chúng tôi đã tạo một mô-đun chỉ xuất một chức năng. một hàm tạo cho trình phát phân tán của chúng tôi, trả về một trình phát sự kiện đã sửa đổi
Khi tạo bộ phát phân tán, chúng tôi bắt đầu bằng cách thiết lập hai kết nối Redis. Một kết nối đóng vai trò là kết nối của nhà xuất bản và kết nối còn lại đóng vai trò là kết nối dành riêng cho người đăng ký. Điều này phải như thế này vì giao thức Redis. khi kết nối Redis chuyển sang chế độ thuê bao, nó không thể phát ra các lệnh khác với các lệnh thay đổi đăng ký
Sau đó, chúng tôi gọi
var redis = require['redis'];module.exports = redis.createClient[];67 trên mỗi kết nối này. Điều này đảm bảo quy trình Nút không thoát chỉ vì chúng tôi có một trong các kết nối máy khách này đang mở
Sau đó, chúng tôi tiếp tục lắng nghe các sự kiện
var redis = require['redis'];module.exports = redis.createClient[];68 trên mỗi kết nối Redis, mà chúng tôi chỉ truyền tới trình phát sự kiện được trả lại. Điều này cho phép khách hàng lắng nghe và xử lý các lỗi dành riêng cho Redis
Chúng tôi cũng lắng nghe các sự kiện
var redis = require['redis'];module.exports = redis.createClient[];69 mà ứng dụng khách Redis phát ra khi các sự kiện đến từ hệ thống Redis Pub-sub thông qua kết nối ứng dụng khách. Khi điều này xảy ra, chúng tôi chỉ truyền sự kiện vào trình phát sự kiện cục bộ, cho phép người đăng ký trình phát sự kiện nhận được sự kiện đó
Tiếp theo, chúng tôi sửa đổi bộ phát sự kiện được trả về, thay thế các phương thức
var redis = require['redis'];module.exports = redis.createClient[];70,
var redis = require['redis'];module.exports = redis.createClient[];71,
var redis = require['redis'];module.exports = redis.createClient[];72 và
var redis = require['redis'];module.exports = redis.createClient[];73. Khi phát sự kiện, thay vì phát cục bộ, chúng tôi chỉ xuất bản sự kiện lên Redis, sử dụng tên sự kiện làm tên kênh
Chúng tôi cũng bọc các phương thức
var redis = require['redis'];module.exports = redis.createClient[];71 và
var redis = require['redis'];module.exports = redis.createClient[];72, được sử dụng để nghe các loại sự kiện. Khi bất kỳ sự kiện nào trong số này được gọi, nếu đó là lần đăng ký đầu tiên cho loại sự kiện cụ thể này, chúng tôi sẽ đăng ký kênh tương ứng trên Redis. Sau đó, chúng tôi trở lại hành vi mặc định, đó là thêm chức năng nghe vào Redis
Tương tự, chúng tôi bọc phương thức
var redis = require['redis'];module.exports = redis.createClient[];73 để nắm bắt trường hợp khi không còn người nghe nào cho một loại sự kiện cụ thể, trong trường hợp đó, chúng tôi hủy đăng ký kênh tương ứng trên kết nối máy khách Redis của mình
Chúng tôi giữ xung quanh các phương thức cũ của trình phát sự kiện trong biến
var redis = require['redis'];module.exports = redis.createClient[];77 để chúng tôi có thể gọi chúng từ bên trong các phương thức của trình bao bọc
Cuối cùng, chúng tôi triển khai một phương thức cụ thể
var redis = require['redis'];module.exports = redis.createClient[];78 để đóng kết nối Redis
Bây giờ, hãy tạo một mô-đun máy khách để khởi tạo hai trình phát phân tán, sử dụng Redis để liên lạc giữa chúng, như sẽ xảy ra nếu chúng ở trong hai quy trình riêng biệt
được phân phối_emitter_example. js
redis.get['key', function[err, value] {
if [err] {
console.error['error getting key:', err];
}
else {
console.log['key has the value %s', value];
}
}];
0Mô-đun máy khách mẫu này tạo hai bộ phát phân tán này. Cái đầu tiên đăng ký hai loại sự kiện, in ra những sự kiện này khi chúng đến. Cái thứ hai phát ra hai loại sự kiện này mỗi giây. Tải trọng của sự kiện chỉ là dấu thời gian. Hãy chạy cái này
redis.get['key', function[err, value] {
if [err] {
console.error['error getting key:', err];
}
else {
console.log['key has the value %s', value];
}
}];
1Cẩn thận với điều kiện cuộc đua
Trình phát sự kiện phân tán này hoạt động khác với trình phát sự kiện thông thường theo một cách cơ bản. nó tuyên truyền các sự kiện bằng cách thực hiện I/O. Trong Node, I/O là một hoạt động không đồng bộ, trong khi tất cả các hoạt động điển hình của trình phát sự kiện chỉ là cục bộ và đồng bộ. Điều này có tác động đến thời gian cho các quy trình cục bộ. Chẳng hạn, hãy xem xét đoạn mã sau bằng cách sử dụng bộ phát sự kiện bình thường
local_event_emitter. js
redis.get['key', function[err, value] {
if [err] {
console.error['error getting key:', err];
}
else {
console.log['key has the value %s', value];
}
}];
2Chạy này sẽ mang lại, như mong đợi
redis.get['key', function[err, value] {
if [err] {
console.error['error getting key:', err];
}
else {
console.log['key has the value %s', value];
}
}];
3Tốt, tất cả đều bình thường. Bây giờ, hãy thử thay thế bộ phát sự kiện bằng một trong những bộ phát phân tán của chúng tôi
được phân phốievenemitter_race. js
redis.get['key', function[err, value] {
if [err] {
console.error['error getting key:', err];
}
else {
console.log['key has the value %s', value];
}
}];
4Hãy thử chạy phiên bản này sau đó
redis.get['key', function[err, value] {
if [err] {
console.error['error getting key:', err];
}
else {
console.log['key has the value %s', value];
}
}];
5Quá trình chỉ thoát mà không xuất ra bất cứ thứ gì. Điều này có nghĩa là, khi chúng ta gọi phương thức
var redis = require['redis'];module.exports = redis.createClient[];72, trình phát phân tán sẽ đăng ký kênh lần đầu tiên. Nhưng điều đó liên quan đến một số I/O, vì vậy điều này không được thực hiện ngay lập tức. lệnh phải đi đến lớp mạng, phải được Redis nhận, phân tích cú pháp và thực thi, sau đó phản hồi sẽ quay trở lại Node. Tuy nhiên, trước khi tất cả I/O này xảy ra, chúng tôi đã phát ra một sự kiện [dòng cuối cùng của tệp trước đó]. Sự kiện này cũng liên quan đến I/O, cũng không đồng bộ. Điều xảy ra là cả hai lệnh đang chạy đua để đến được Redis bằng hai kết nối máy khách khác nhau. Nếu lệnh
var redis = require['redis'];module.exports = redis.createClient[];63 đến Redis trước lệnh
var redis = require['redis'];module.exports = redis.createClient[];64, khách hàng của chúng tôi sẽ không bao giờ nhìn thấy sự kiện đó
Để xem chính xác chuỗi sự kiện trong Redis, chúng ta có thể sử dụng một mẹo nhỏ là sử dụng ứng dụng khách dòng lệnh Redis đi kèm với Redis. Với nó, bạn có thể theo dõi máy chủ Redis để kiểm tra lệnh nào đang được ban hành
redis.get['key', function[err, value] {
if [err] {
console.error['error getting key:', err];
}
else {
console.log['key has the value %s', value];
}
}];
6Bây giờ bạn có thể thực thi tập lệnh nút trước đó và quan sát lệnh nào xảy ra trên Redis
redis.get['key', function[err, value] {
if [err] {
console.error['error getting key:', err];
}
else {
console.log['key has the value %s', value];
}
}];
7của bạn đi. lệnh
var redis = require['redis'];module.exports = redis.createClient[];82 đến sau lệnh
var redis = require['redis'];module.exports = redis.createClient[];83, thua cuộc đua
“Điều này dùng để minh họa rằng cơ chế Pub-sub không phải là hàng đợi liên tục. người nghe sẽ chỉ nhận được các sự kiện mới sau khi yêu cầu đăng ký được máy chủ xử lý chứ không phải trước đó. Ghi nhớ điều này có thể sẽ giúp bạn tiết kiệm rất nhiều đau đầu trong tương lai. ”
Viết bởi Pedro Teixeira [trích từ Cơ sở dữ liệu-Tập I, sê-ri Mô hình nút] — xuất bản cho YLD