Bạn có biết?
Bạn viết redis.get("key") nhưng không biết tại sao nó "thỉnh thoảng" timeout? Hay muốn pipeline 1000 lệnh để tăng tốc gấp 10 lần mà không biết bắt đầu từ đâu? ioredis là thư viện Redis phổ biến và mạnh nhất cho Node.js — và bài này sẽ đưa bạn từ kết nối đầu tiên đến những pattern production thực thụ.
ioredis được chọn vì: hỗ trợ đầy đủ data types, cluster và sentinel ngay trong thư viện, promises tự nhiên, pipeline, và cơ chế reconnect thông minh. Đây là thư viện bạn nên dùng thay vì redis (node-redis) khi cần tính năng đầy đủ.
Cài đặt và kết nối
npm install ioredis
import Redis from "ioredis";
// Kết nối mặc định: localhost:6379
const redis = new Redis();
// Kết nối có cấu hình
const redis2 = new Redis({
host: "redis.example.com",
port: 6379,
password: "secret",
db: 0, // Cluster chỉ hỗ trợ db 0
connectTimeout: 10_000, // timeout kết nối (ms)
maxRetriesPerRequest: 3, // số lần retry mỗi request
});
// Kiểm tra kết nối
await redis.ping(); // "PONG"
Map data types sang method
Mọi lệnh Redis đều có method tương ứng — tên viết hoa thành tên method camelCase, tham số giữ nguyên thứ tự:
// Strings
await redis.set("user:1001:name", "Tan");
await redis.get("user:1001:name");
await redis.incr("counter:visits"); // INCR
await redis.set("key", "value", "EX", 60); // SET key value EX 60
// Hashes
await redis.hset("user:1001", { name: "Tan", age: 28 });
const user = await redis.hgetall("user:1001");
const age = await redis.hget("user:1001", "age");
// Lists
await redis.rpush("queue:jobs", "job-1", "job-2");
const job = await redis.lpop("queue:jobs");
// Sets
await redis.sadd("post:101:tags", "redis", "nodejs");
const hasTag = redis.(, );
redis.(, , , , );
top10 = redis.(, , );
redis.(, );
ttl = redis.();
Điểm đặc biệt: ioredis tự động serialize object cho hset, và trả về object cho hgetall — code gọn hơn hẳn so với gọi raw command.
Pipeline: tăng tốc batch operations
Mỗi lệnh Redis đi qua mạng là một round-trip. 1000 lệnh = 1000 round-trip. Pipeline gộp tất cả vào một request duy nhất — giảm latency đến 10 lần (xem chi tiết bài Pipeline):
const pipeline = redis.pipeline();
for (let i = 0; i < 1000; i++) {
pipeline.set(`batch:key:${i}`, i);
}
const results = await pipeline.exec(); // 1 round-trip duy nhất
// Hoặc dùng chain:
const results2 = await redis
.multi()
.set("a", 1)
.incr("a")
.get("a")
.exec();
Lưu ý: multi() trong ioredis chính là pipeline + transaction (MULTI/EXEC) — các lệnh chạy atomic. Xem thêm Transactions trong Redis.
Lệnh tùy biến và Lua Script
// Gọi bất kỳ lệnh Redis nào qua sendCommand
await redis.sendCommand(new Command("SET", ["foo", "bar"]));
// Lua Script — atomic, chạy trong Redis
const script = `
local current = redis.call("get", KEYS[1])
if not current then
redis.call("set", KEYS[1], ARGV[1])
return 1
end
return 0
`;
const result = await redis.eval(script, 1, "lock:job", "owner");
// defineCommand: đặt tên cho script, dùng như method
redis.defineCommand("setIfAbsent", {
numberOfKeys: 1,
lua: script,
});
await redis.setIfAbsent("lock:job", "owner");
defineCommand là pattern gọn gàng nhất: viết Lua một lần, gọi như method thường — an toàn, atomic, dễ test. Chi tiết trong bài Lua Scripts.
Xử lý lỗi và sự kiện kết nối
redis.on("connect", () => console.log("connected"));
redis.on("ready", () => console.log("ready to accept commands"));
redis.on("error", (err) => console.error("redis error:", err.message));
redis.on("close", () => console.log("connection closed"));
redis.on("reconnecting", (delay) => console.log(`reconnecting in ${delay}ms`));
redis.on("end", () => console.log("connection ended"));
try {
await redis.get("some-key");
} catch (err) {
// maxRetriesPerRequest đã cạn, request thất bại
console.error("request failed:", err.message);
}
0 bình luận
Đang tải bình luận...
Để lại bình luận