Skip to content

Commit

Permalink
🎈 perf: 优化 Redis 策略
Browse files Browse the repository at this point in the history
  • Loading branch information
imsyy committed Dec 7, 2024
1 parent 4897239 commit a05578f
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 43 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@
"dayjs": "^1.11.13",
"dotenv": "^16.4.6",
"feed": "^4.2.2",
"flatted": "^3.3.2",
"hono": "^4.6.12",
"iconv-lite": "^0.6.3",
"ioredis": "^5.4.1",
"md5": "^2.3.0",
"node-cache": "^5.1.2",
"rss-parser": "^3.13.0",
"user-agents": "^1.1.379",
"uuid": "^11.0.3",
"winston": "^3.17.0"
},
"devDependencies": {
Expand Down
12 changes: 3 additions & 9 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

73 changes: 40 additions & 33 deletions src/utils/cache.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { config } from "../config.js";
import { stringify, parse } from "flatted";
import logger from "./logger.js";
import NodeCache from "node-cache";
import Redis from "ioredis";
Expand All @@ -25,6 +26,9 @@ const redis = new Redis({
host: config.REDIS_HOST,
port: config.REDIS_PORT,
password: config.REDIS_PASSWORD,
maxRetriesPerRequest: 5,
// 重试策略:最小延迟 50ms,最大延迟 2s
retryStrategy: (times) => Math.min(times * 50, 2000),
// 仅在第一次建立连接
lazyConnect: true,
});
Expand All @@ -33,7 +37,24 @@ const redis = new Redis({
let isRedisAvailable: boolean = false;
let isRedisTried: boolean = false;

// Redis 连接错误
// Redis 连接状态
const ensureRedisConnection = async () => {
if (isRedisTried) return;
try {
if (redis.status !== "ready" && redis.status !== "connecting") await redis.connect();
isRedisAvailable = true;
isRedisTried = true;
logger.info("📦 [Redis] connected successfully.");
} catch (error) {
isRedisAvailable = false;
isRedisTried = true;
logger.error(
`📦 [Redis] connection failed: ${error instanceof Error ? error.message : "Unknown error"}`,
);
}
};

// Redis 事件监听
redis.on("error", (err) => {
if (!isRedisTried) {
isRedisAvailable = false;
Expand All @@ -44,23 +65,14 @@ redis.on("error", (err) => {
}
});

// Redis 连接状态
const ensureRedisConnection = async () => {
if (!isRedisTried) {
try {
await redis.connect();
isRedisAvailable = true;
isRedisTried = true;
logger.info("📦 [Redis] connected successfully.");
} catch (error) {
isRedisAvailable = false;
isRedisTried = true;
logger.error(
`📦 [Redis] connection failed: ${error instanceof Error ? error.message : "Unknown error"}`,
);
}
}
};
// NodeCache 事件监听
cache.on("expired", (key) => {
logger.info(`⏳ [NodeCache] Key "${key}" has expired.`);
});

cache.on("del", (key) => {
logger.info(`🗑️ [NodeCache] Key "${key}" has been deleted.`);
});

/**
* 从缓存中获取数据
Expand All @@ -72,10 +84,7 @@ export const getCache = async (key: string): Promise<CacheData | undefined> => {
if (isRedisAvailable) {
try {
const redisResult = await redis.get(key);
if (redisResult) {
const data = JSON.parse(redisResult);
return data;
}
if (redisResult) return parse(redisResult);
} catch (error) {
logger.error(
`📦 [Redis] get error: ${error instanceof Error ? error.message : "Unknown error"}`,
Expand All @@ -100,7 +109,7 @@ export const setCache = async (
// 尝试写入 Redis
if (isRedisAvailable && !Buffer.isBuffer(value?.data)) {
try {
await redis.set(key, JSON.stringify(value), "EX", ttl);
await redis.set(key, stringify(value), "EX", ttl);
if (logger) logger.info(`💾 [REDIS] ${key} has been cached`);
} catch (error) {
logger.error(
Expand All @@ -120,16 +129,14 @@ export const setCache = async (
*/
export const delCache = async (key: string): Promise<boolean> => {
let redisSuccess = true;
if (isRedisAvailable) {
try {
await redis.del(key);
if (logger) logger.info(`🗑️ [REDIS] ${key} has been deleted from Redis`);
} catch (error) {
logger.error(
`📦 [Redis] del error: ${error instanceof Error ? error.message : "Unknown error"}`,
);
redisSuccess = false;
}
try {
await redis.del(key);
logger.info(`🗑️ [REDIS] ${key} has been deleted from Redis`);
} catch (error) {
redisSuccess = false;
logger.error(
`📦 [Redis] del error: ${error instanceof Error ? error.message : "Unknown error"}`,
);
}
// 尝试删除 NodeCache
const nodeCacheSuccess = cache.del(key) > 0;
Expand Down

0 comments on commit a05578f

Please sign in to comment.