npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@fastcar/redis

v0.2.0

Published

`@fastcar/redis` 是 `@fastcar/core` 框架下的 Redis 组件,基于 `redis@5`,提供多数据源、常用缓存操作、Redis 数据结构操作以及 pipeline、transaction、pub/sub、Lua 等高级能力。

Readme

@fastcar/redis

@fastcar/redis@fastcar/core 框架下的 Redis 组件,基于 redis@5,提供多数据源、常用缓存操作、Redis 数据结构操作以及 pipeline、transaction、pub/sub、Lua 等高级能力。

安装

npm install @fastcar/redis

版本要求

  • Node.js >= 20
  • redis npm package >= 5
  • @fastcar/core >= 0.3.20

配置

在应用的 resource/application.yml 中配置 Redis 数据源。source 是数据源名称,默认模板方法会使用 default

兼容旧版扁平配置:

application:
  name: "simple"
settings:
  redis:
    - { source: "default", host: "localhost", port: 6379, password: "123456" }

也支持 redis@5socket 配置:

settings:
  redis:
    - source: "default"
      password: "123456"
      socket:
        host: "localhost"
        port: 6379

如果本地 Redis 没有密码,不要配置 password

启用组件

import { FastCarApplication } from "@fastcar/core";
import { Application } from "@fastcar/core/annotation";
import { EnableRedis } from "@fastcar/redis/annotation";

@Application
@EnableRedis
class APP {
  app!: FastCarApplication;
}

new APP();

声明 RedisTemplate

import { Repository, DS } from "@fastcar/core/annotation";
import { RedisTemplate } from "@fastcar/redis";

@Repository
@DS("default")
export default class TestRedisTemplate extends RedisTemplate {}

基础使用

import { Service, Autowired } from "@fastcar/core/annotation";
import TestRedisTemplate from "./TestRedisTemplate";

@Service
export default class SimpleService {
  @Autowired
  private redisTemplate!: TestRedisTemplate;

  async setHello() {
    await this.redisTemplate.set("hello", "world");
  }

  async getHello() {
    return this.redisTemplate.get("hello");
  }
}

常用 API

String / Cache

| 方法 | 说明 | | --- | --- | | set(key, value, source?) | 设置字符串或对象值,对象会自动 JSON.stringify | | get(key, source?) | 获取字符串值 | | setEx(key, value, seconds, source?) | 设置值并设置过期时间 | | setExpire(key, value, seconds, source?) | setEx 的兼容旧名 | | setNx(key, value, seconds?, source?) | key 不存在时才设置,可选过期时间 | | setJson(key, value, seconds?, source?) | 设置 JSON 对象 | | getJson<T>(key, source?) | 获取并解析 JSON | | mSet(values, source?) | 批量设置 | | mGet(keys, source?) | 批量获取 | | incr(key, source?) / decr(key, source?) | 自增 / 自减 | | incrKey(key, source?) / decrKey(key, source?) | 兼容旧名 |

await redisTemplate.setEx("token:1", { id: 1 }, 3600);
const token = await redisTemplate.getJson<{ id: number }>("token:1");

const ok = await redisTemplate.setNx("lock:job", "1", 30);

Key / TTL

| 方法 | 说明 | | --- | --- | | exists(key, source?) | 判断 key 是否存在 | | existKey(key, source?) | 兼容旧名 | | del(keys, source?) | 删除多个 key,返回删除数量 | | delKey(key, source?) | 删除单个 key,返回 boolean | | delKeys(pattern, source?) | 使用 SCAN + DEL 按 pattern 批量删除 | | expire(key, seconds, source?) | 设置过期时间 | | ttl(key, source?) | 获取剩余过期时间 | | persist(key, source?) | 移除过期时间 | | rename(key, newKey, source?) | 重命名 key | | type(key, source?) | 获取 key 类型 | | keys(pattern, source?) | 使用 KEYS 获取 key | | getBulkKey(pattern, source?) | keys 的兼容旧名 | | scan(pattern?, count?, source?) | 使用 SCAN 获取 key |

生产环境批量匹配 key 时优先使用 scandelKeys,避免直接使用 KEYS 扫描大 key 空间。

Hash

| 方法 | 说明 | | --- | --- | | hSet(key, field, value, source?) | 设置 hash 字段 | | hGet(key, field, source?) | 获取 hash 字段 | | hGetAll(key, source?) | 获取整个 hash | | hDel(key, fields, source?) | 删除字段 | | hExists(key, field, source?) | 判断字段是否存在 | | hIncrBy(key, field, increment, source?) | 字段自增 |

List

| 方法 | 说明 | | --- | --- | | lPush(key, values, source?) | 从左侧推入 | | rPush(key, values, source?) | 从右侧推入 | | lPop(key, source?) | 从左侧弹出 | | rPop(key, source?) | 从右侧弹出 | | lRange(key, start, stop, source?) | 获取范围 | | lLen(key, source?) | 获取长度 |

Set

| 方法 | 说明 | | --- | --- | | sAdd(key, members, source?) | 添加成员 | | sRem(key, members, source?) | 删除成员 | | sMembers(key, source?) | 获取所有成员 | | sIsMember(key, member, source?) | 判断成员是否存在 | | sCard(key, source?) | 获取成员数量 |

ZSet

| 方法 | 说明 | | --- | --- | | zAdd(key, score, member, source?) | 添加成员 | | zRem(key, members, source?) | 删除成员 | | zRange(key, start, stop, source?) | 正序获取 | | zRevRange(key, start, stop, source?) | 倒序获取 | | zRangeWithScores(key, start, stop, source?) | 正序获取并返回 score | | zScore(key, member, source?) | 获取成员分数 |

RedisTemplate 方法示例说明

下面示例假设已经在业务类中注入了 redisTemplate。所有方法最后一个参数都可以传入 source 指定 Redis 数据源,例如 await redisTemplate.get("user:1", "default")

字符串与缓存

字符串方法适合保存普通缓存、JSON 对象、计数器、短期 token 和简单分布式锁。

// 设置普通字符串,底层执行 SET。
await redisTemplate.set("cache:name", "fastcar");

// 设置对象时会自动 JSON.stringify,读取时可以用 getJson 解析。
await redisTemplate.setJson("user:1", { id: 1, name: "Tom" }, 3600);
const user = await redisTemplate.getJson<{ id: number; name: string }>("user:1");

// 设置带过期时间的缓存,单位是秒。
await redisTemplate.setEx("token:1", "token-value", 1800);
const ttl = await redisTemplate.ttl("token:1");

// key 不存在时才设置,常用于锁或幂等控制。
const locked = await redisTemplate.setNx("lock:order:1", "1", 30);
if (locked) {
  try {
    // 执行业务逻辑
  } finally {
    await redisTemplate.delKey("lock:order:1");
  }
}

// 批量设置和批量读取。
await redisTemplate.mSet({
  "profile:1": { id: 1 },
  "profile:2": { id: 2 },
});
const profiles = await redisTemplate.mGet(["profile:1", "profile:2"]);

// 计数器自增 / 自减。
const views = await redisTemplate.incr("article:1:views");
const remaining = await redisTemplate.decr("stock:sku:1");

Key 与过期时间

Key 方法适合判断缓存是否存在、管理 TTL、批量扫描和清理缓存。

const exists = await redisTemplate.exists("user:1");

await redisTemplate.expire("user:1", 600);
const seconds = await redisTemplate.ttl("user:1");

// 移除过期时间,让 key 变成永久 key。
await redisTemplate.persist("user:1");

// 重命名 key,目标 key 已存在时会被 Redis 覆盖。
await redisTemplate.rename("user:1", "user:10001");

// 获取 key 的 Redis 类型,例如 string、hash、list、set、zset、none。
const type = await redisTemplate.type("user:10001");

// 生产环境建议使用 scan,而不是 keys。
const keys = await redisTemplate.scan("user:*", 100);
const deletedCount = await redisTemplate.delKeys("temp:*");

Hash

Hash 适合保存对象的多个字段,例如用户信息、配置项、统计字段。

await redisTemplate.hSet("user:1:info", "name", "Tom");
await redisTemplate.hSet("user:1:info", "age", 18);

const name = await redisTemplate.hGet("user:1:info", "name");
const info = await redisTemplate.hGetAll("user:1:info");

const hasAge = await redisTemplate.hExists("user:1:info", "age");
const loginCount = await redisTemplate.hIncrBy("user:1:info", "loginCount", 1);

await redisTemplate.hDel("user:1:info", ["age"]);

List

List 适合简单队列、消息列表、最近访问记录等按顺序存取的场景。

// 从右侧入队,从左侧出队,可以实现 FIFO 队列。
await redisTemplate.rPush("queue:email", ["job-1", "job-2"]);
const job = await redisTemplate.lPop("queue:email");

// 从左侧推入,读取前 10 条,适合最近记录。
await redisTemplate.lPush("recent:user:1", ["page:home"]);
const recentPages = await redisTemplate.lRange("recent:user:1", 0, 9);
const length = await redisTemplate.lLen("recent:user:1");

// 也可以从右侧弹出。
const last = await redisTemplate.rPop("recent:user:1");

Set

Set 适合去重集合、标签、用户分组、权限集合等不需要顺序的场景。

await redisTemplate.sAdd("article:1:tags", ["redis", "cache", "nodejs"]);

const tags = await redisTemplate.sMembers("article:1:tags");
const hasRedis = await redisTemplate.sIsMember("article:1:tags", "redis");
const tagCount = await redisTemplate.sCard("article:1:tags");

await redisTemplate.sRem("article:1:tags", ["nodejs"]);

ZSet

ZSet 适合排行榜、带权重排序、延迟任务时间戳排序等场景。

await redisTemplate.zAdd("rank:score", 100, "user:1");
await redisTemplate.zAdd("rank:score", 88, "user:2");

// 正序和倒序获取成员。
const asc = await redisTemplate.zRange("rank:score", 0, -1);
const desc = await redisTemplate.zRevRange("rank:score", 0, 9);

// 同时获取成员和分数。
const rank = await redisTemplate.zRangeWithScores("rank:score", 0, -1);
const score = await redisTemplate.zScore("rank:score", "user:1");

await redisTemplate.zRem("rank:score", ["user:2"]);

Pipeline、Transaction、Pub/Sub、Lua 与原始命令

高级方法适合减少网络往返、批量原子提交、频道消息通知、自定义 Lua 逻辑和调用未封装 Redis 命令。

// Pipeline:批量发送命令,减少网络往返,但不保证事务原子性。
const pipelineResult = await redisTemplate.pipeline([
  ["SET", "pipeline:key", "ok"],
  ["GET", "pipeline:key"],
]);

// Transaction:使用 MULTI/EXEC 提交事务。
const transactionResult = await redisTemplate.transaction([
  ["SET", "tx:key", "ok"],
  ["INCR", "tx:count"],
]);

// Pub/Sub:subscribe 会返回取消订阅函数,记得在不需要时调用。
const unsubscribe = await redisTemplate.subscribe("notice", async (message, channel) => {
  console.log(channel, message);
});
await redisTemplate.publish("notice", { type: "created", id: 1 });
await unsubscribe();

// Pattern 订阅可以匹配多个频道。
const pUnsubscribe = await redisTemplate.pSubscribe("notice:*", (message, channel) => {
  console.log(channel, message);
});
await pUnsubscribe();

// Lua:keys 会映射到 KEYS,args 会映射到 ARGV。
const luaResult = await redisTemplate.eval(
  "return redis.call('GET', KEYS[1]) or ARGV[1]",
  ["missing:key"],
  ["default-value"]
);

// 原始命令:用于调用 RedisTemplate 暂未封装的命令。
const pong = await redisTemplate.rawCommand<string>(["PING"]);

高级能力

Pipeline / Transaction

const pipelineResult = await redisTemplate.pipeline([
  ["SET", "pipeline:key", "ok"],
  ["GET", "pipeline:key"],
]);

const transactionResult = await redisTemplate.transaction([
  ["SET", "transaction:key", "ok"],
  ["GET", "transaction:key"],
]);

Pub/Sub

订阅会创建独立 Redis 连接,返回的函数用于取消订阅并关闭连接。

const unsubscribe = await redisTemplate.subscribe("notice", (message, channel) => {
  console.log(channel, message);
});

await redisTemplate.publish("notice", "hello");
await unsubscribe();

也支持 pattern 订阅:

const unsubscribe = await redisTemplate.pSubscribe("notice:*", (message, channel) => {
  console.log(channel, message);
});

Lua / Raw Command

const result = await redisTemplate.eval("return ARGV[1]", [], ["hello"]);
const shaResult = await redisTemplate.evalSha("script-sha", ["key1"], ["arg1"]);

const raw = await redisTemplate.rawCommand(["PING"]);

execLua(luaStr, keysLength, param, source?) 保留为兼容旧版本的 Lua 方法;新代码建议使用 eval / evalSha

多数据源

所有模板方法最后一个参数都支持 source?: string,用于指定数据源。通常配合 @DS("sourceName") 使用;特殊场景也可以在调用时显式传入。

await redisTemplate.set("hello", "world", "default");

测试示例

项目内置示例位于 fastcar-redis/test/example,可直接运行:

npx ts-node -r tsconfig-paths/register test/example/app.ts

示例覆盖 String、Hash、List、Set、ZSet、SCAN、Lua、Pipeline、Transaction、Pub/Sub 等能力。

开源地址