mm_cachebase 1.9.7 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/README.md +269 -559
  2. package/index.js +2075 -1324
  3. package/package.json +3 -3
  4. package/test.js +728 -536
package/README.md CHANGED
@@ -1,559 +1,269 @@
1
- # mm_cachebase
2
-
3
- 一个轻量级的本地缓存类库,提供了与Redis兼容的缓存操作接口,支持过期时间设置、哈希表操作、数值操作、字符串操作等功能,以及完整的事件通知系统。
4
-
5
- ## 项目信息
6
-
7
- - **当前版本**: 1.8.8
8
- - **更新日期**: 2024-12-23
9
- - **Gitee地址**: [https://gitee.com/qiuwenwu91/mm_cachebase](https://gitee.com/qiuwenwu91/mm_cachebase)
10
- - **Node.js 版本要求**: >= 14.0.0(推荐 16.0.0 及以上)
11
-
12
- ## 特点
13
-
14
- - **Redis兼容API**:实现了与npm redis模块相似的接口,便于无缝切换
15
- - **轻量级设计**:纯JavaScript实现,无外部依赖
16
- - **完整的事件系统**:支持前置/后置/错误事件,便于日志记录和访问控制
17
- - **过期时间管理**:支持设置和查询键的过期时间
18
- - **丰富的数据类型支持**:支持字符串、哈希表等Redis常见数据类型
19
- - **多文件持久化**:支持数据持久化到文件,通过scope参数实现多实例数据隔离
20
-
21
- ## 安装
22
-
23
- ```bash
24
- npm install mm_cachebase
25
- ```
26
-
27
- ## 基本使用
28
-
29
- ```javascript
30
- const CacheBase = require('mm_cachebase');
31
-
32
- // 创建缓存实例
33
- const cache = new CacheBase();
34
-
35
- // 基本操作示例
36
- async function example() {
37
- // 设置缓存,过期时间为10秒
38
- await cache.set("name", "张三", 10);
39
-
40
- // 获取缓存
41
- const value = await cache.get("name");
42
- $.log.debug(value); // 输出: 张三
43
-
44
- // 删除缓存
45
- await cache.del("name");
46
- }
47
- ```
48
-
49
- ## API 说明
50
-
51
- ### 构造函数
52
-
53
- ```javascript
54
- const cache = new CacheBase(scope, config);
55
- ```
56
-
57
- 创建一个新的缓存实例。缓存实例基于EventEmitter,支持完整的事件系统。
58
-
59
- - `scope`: 缓存作用域名称(默认'sys'),用于多文件持久化时的数据隔离
60
- - `config`: 配置选项对象,支持以下属性:
61
- - `dir`: 缓存文件存储目录(默认'./cache/')
62
- - `expire`: 默认过期时间(秒)(默认0,表示永不过期)
63
- - `max`: 最大缓存键数量(默认0,表示无限制)
64
- - `persist`: 是否启用持久化(默认false)
65
- - `saveInterval`: 定时保存间隔(毫秒)(默认60000)
66
-
67
- ### 基本操作
68
-
69
- #### 设置缓存
70
- ```javascript
71
- await cache.set(key, value, maxAge)
72
- ```
73
- - `key`: 缓存键名
74
- - `value`: 缓存的值
75
- - `maxAge`: 过期时间(秒),-1表示永不过期
76
- - 返回: 'OK'
77
-
78
- #### 获取缓存
79
- ```javascript
80
- await cache.get(key)
81
- ```
82
- - `key`: 缓存键名
83
- - 返回: 缓存值,不存在则返回null
84
-
85
- #### 删除缓存
86
- ```javascript
87
- await cache.del(key)
88
- ```
89
- - `key`: 缓存键名
90
- - 返回: 成功返回1,失败返回0
91
-
92
- #### 设置并获取旧值
93
- ```javascript
94
- await cache.getset(key, value, maxAge)
95
- ```
96
- - 先获取旧值,然后设置新值
97
- - 返回: 旧值,不存在则返回null
98
-
99
- #### 批量设置缓存
100
- ```javascript
101
- await cache.mset(keys, values, maxAge)
102
- ```
103
- - `keys`: 键名数组
104
- - `values`: 值数组
105
- - 返回: 'OK'
106
-
107
- #### 批量获取缓存
108
- ```javascript
109
- await cache.mget(...keys)
110
- ```
111
- - `keys`: 一个或多个键名
112
- - 返回: 值数组
113
-
114
- #### 判断键是否存在
115
- ```javascript
116
- await cache.exists(...keys)
117
- ```
118
- - `keys`: 一个或多个键名
119
- - 返回: 存在的键数量
120
-
121
- ### 过期时间操作
122
-
123
- #### 设置过期时间
124
- ```javascript
125
- await cache.expire(key, maxAge)
126
- ```
127
- - `maxAge`: 过期时间(秒)
128
- - 返回: 成功返回1,失败返回0
129
-
130
- #### 查询剩余过期时间
131
- ```javascript
132
- await cache.ttl(key)
133
- ```
134
- - 返回: 剩余秒数,不存在或永不过期返回-1
135
-
136
- #### 移除过期时间
137
- ```javascript
138
- await cache.persist(key)
139
- ```
140
- - 返回: 成功返回1,失败返回0
141
-
142
- ### 数值操作
143
-
144
- #### 增加整数
145
- ```javascript
146
- await cache.incr(key)
147
- ```
148
- - 将键的值加1
149
- - 返回: 增加后的值
150
-
151
- #### 增加指定整数
152
- ```javascript
153
- await cache.incrby(key, increment)
154
- ```
155
- - `increment`: 要增加的整数
156
- - 返回: 增加后的值
157
-
158
- #### 减少整数
159
- ```javascript
160
- await cache.decr(key)
161
- ```
162
- - 将键的值减1
163
- - 返回: 减少后的值
164
-
165
- #### 减少指定整数
166
- ```javascript
167
- await cache.decrby(key, decrement)
168
- ```
169
- - `decrement`: 要减少的整数
170
- - 返回: 减少后的值
171
-
172
- #### 增加浮点数
173
- ```javascript
174
- await cache.incrbyfloat(key, increment)
175
- ```
176
- - `increment`: 要增加的浮点数
177
- - 返回: 增加后的值
178
-
179
- ### 字符串操作
180
-
181
- #### 追加字符串
182
- ```javascript
183
- await cache.append(key, value)
184
- ```
185
- - 在已有字符串后追加新字符串
186
- - 返回: 追加后的字符串长度
187
-
188
- #### 获取字符串长度
189
- ```javascript
190
- await cache.strlen(key)
191
- ```
192
- - 返回: 字符串长度
193
-
194
- ### 哈希表操作
195
-
196
- #### 设置哈希表字段
197
- ```javascript
198
- await cache.hset(key, field, value)
199
- ```
200
- - `key`: 哈希表的键名
201
- - `field`: 字段名
202
- - `value`: 字段值
203
- - 返回: 成功返回1,失败返回0
204
-
205
- #### 获取哈希表字段
206
- ```javascript
207
- await cache.hget(key, field)
208
- ```
209
- - 返回: 字段值,不存在则返回null
210
-
211
- #### 获取哈希表所有字段和值
212
- ```javascript
213
- await cache.hgetall(key)
214
- ```
215
- - 返回: 包含所有字段和值的对象
216
-
217
- #### 删除哈希表字段
218
- ```javascript
219
- await cache.hdel(key, field)
220
- ```
221
- - 返回: 成功返回1,失败返回0
222
-
223
- ### 键操作
224
-
225
- #### 获取所有键名
226
- ```javascript
227
- await cache.keys(pattern)
228
- ```
229
- - `pattern`: 支持*通配符的匹配模式
230
- - 返回: 匹配的键名数组
231
-
232
- #### 获取键数量
233
- ```javascript
234
- await cache.dbsize()
235
- ```
236
- - 返回: 缓存中的键数量
237
-
238
- #### 清空缓存
239
- ```javascript
240
- await cache.flushdb()
241
- ```
242
- - 清空所有缓存
243
- - 返回: 'OK'
244
-
245
- #### 销毁缓存实例
246
- ```javascript
247
- await cache.dispose()
248
- ```
249
- - 清理所有资源,移除所有监听器
250
-
251
- ### 持久化操作
252
-
253
- #### 连接并启动定时保存
254
- ```javascript
255
- await cache.connect()
256
- ```
257
- - 启用持久化时启动定时保存功能
258
- - 返回: 连接成功返回true,失败返回false
259
-
260
- #### 手动保存数据
261
- ```javascript
262
- await cache.save()
263
- ```
264
- - 手动将缓存数据保存到文件
265
- - 返回: 保存成功返回true,失败返回false
266
-
267
- ### 兼容方法(保持向后兼容)
268
-
269
- #### 添加缓存(仅当键不存在时)
270
- ```javascript
271
- await cache.add(key, value, maxAge)
272
- ```
273
- - 返回: 添加成功返回值,已存在返回0
274
-
275
- #### 检查键是否存在
276
- ```javascript
277
- await cache.has(key)
278
- ```
279
- - 返回: 存在返回1,不存在返回0
280
-
281
- #### 增加浮点数(兼容方法)
282
- ```javascript
283
- await cache.addFloat(key, num, maxAge)
284
- ```
285
- - `num`: 要增加的浮点数
286
- - `maxAge`: 过期时间(秒),默认0表示永不过期
287
- - 返回: 计算后的结果
288
-
289
- #### 追加字符串(兼容方法)
290
- ```javascript
291
- await cache.addStr(key, str, maxAge)
292
- ```
293
- - `maxAge`: 过期时间(秒),默认0表示永不过期
294
- - 返回: 追加后的完整字符串
295
-
296
- #### 清空匹配缓存(兼容方法)
297
- ```javascript
298
- await cache.clear(pattern)
299
- ```
300
- - `pattern`: 可选,支持*通配符
301
-
302
- ## 事件系统
303
-
304
- CacheBase 提供了完整的事件系统,允许你监听各种缓存操作的前后事件,以便进行日志记录、数据验证或操作取消等功能。
305
-
306
- > **性能优化说明**:从版本 1.6.0 开始,查询类方法(如 get、hget、mget、exists、ttl 等)不再触发事件,以提高高频查询操作的性能。
307
-
308
- ### 事件监听方法
309
-
310
- ```javascript
311
- // 监听事件
312
- cache.on('event_name', callback);
313
-
314
- // 监听一次性事件
315
- cache.once('event_name', callback);
316
-
317
- // 移除事件监听
318
- cache.off('event_name', callback);
319
- ```
320
-
321
- ### 事件参数格式
322
-
323
- 所有事件的回调函数都会接收一个标准化的事件数据对象,包含以下属性:
324
-
325
- - `key`: 操作的缓存键名(如果适用)
326
- - `value`: 操作的值,可以是基本类型或包含多个属性的对象
327
- - `result`: 操作的结果
328
- - `error`: 错误信息(仅错误事件)
329
- - `cancel`: 用于取消操作的标志(仅前置事件)
330
- - `ttl`: 过期时间(秒)(仅过期时间相关操作)
331
-
332
- ### 支持的事件类型
333
-
334
- 每个缓存操作都有对应的前置事件(`_before`)、后置事件(`_after`)和错误事件(`_error`)。
335
-
336
- #### 基本操作事件
337
- - `set_before`, `set_after`, `set_error`
338
- - `del_before`, `del_after`, `del_error`
339
- - `mset_before`, `mset_after`, `mset_error`
340
-
341
- #### 过期时间操作事件
342
- - `expire_before`, `expire_after`, `expire_error`
343
- - `persist_before`, `persist_after`, `persist_error`
344
-
345
- #### 数值操作事件
346
- - `incr_before`, `incr_after`, `incr_error`
347
- - `decr_before`, `decr_after`, `decr_error`
348
- - `incrby_before`, `incrby_after`, `incrby_error`
349
- - `decrby_before`, `decrby_after`, `decrby_error`
350
- - `incrbyfloat_before`, `incrbyfloat_after`, `incrbyfloat_error`
351
-
352
- #### 字符串操作事件
353
- - `append_before`, `append_after`, `append_error`
354
-
355
- #### 哈希表操作事件
356
- - `hset_before`, `hset_after`, `hset_error`
357
- - `hdel_before`, `hdel_after`, `hdel_error`
358
-
359
- #### 键操作事件
360
- - `flushdb_before`, `flushdb_after`, `flushdb_error`
361
- - `dispose_before`, `dispose_after`, `dispose_error`
362
-
363
- ### 事件使用示例
364
-
365
- ```javascript
366
- const cache = new CacheBase();
367
-
368
- // 监听设置操作的前置事件
369
- cache.on('set_before', (data) => {
370
- $.log.debug('即将设置键:', data.key, '值:', data.value);
371
-
372
- // 数据验证示例
373
- if (typeof data.value === 'string' && data.value.length > 100) {
374
- $.log.debug('值长度过长,取消设置');
375
- data.cancel = true; // 取消操作
376
- }
377
- });
378
-
379
- // 错误事件监听
380
- cache.on('mset_error', (data) => {
381
- $.log.error(`批量设置出错: ${data.error.message}`);
382
- });
383
- ```
384
-
385
- ## 使用示例
386
-
387
- ### 基本缓存操作
388
- ```javascript
389
- const cache = new CacheBase();
390
-
391
- async function example() {
392
- // 设置缓存
393
- await cache.set("user", "张三", 60); // 60秒后过期
394
-
395
- // 获取缓存
396
- const user = await cache.get("user");
397
- $.log.debug(user); // 输出: 张三
398
-
399
- // 检查是否存在
400
- const exists = await cache.exists("user");
401
- $.log.debug(exists); // 输出: 1
402
-
403
- // 删除缓存
404
- await cache.del("user");
405
- }
406
- ```
407
-
408
- ### 哈希表操作示例
409
- ```javascript
410
- async function hashExample() {
411
- // 设置哈希表字段
412
- await cache.hset("user:123", "name", "张三");
413
- await cache.hset("user:123", "age", 30);
414
- await cache.hset("user:123", "email", "zhangsan@example.com");
415
-
416
- // 获取哈希表字段
417
- const name = await cache.hget("user:123", "name");
418
- $.log.debug(name); // 输出: 张三
419
-
420
- // 获取所有字段和值
421
- const user = await cache.hgetall("user:123");
422
- $.log.debug(user); // 输出: { name: "张三", age: 30, email: "zhangsan@example.com" }
423
-
424
- // 删除字段
425
- await cache.hdel("user:123", "email");
426
- }
427
- ```
428
-
429
- ### 数值操作示例
430
- ```javascript
431
- async function numberExample() {
432
- // 设置初始值
433
- await cache.set("counter", 10);
434
-
435
- // 增加1
436
- const incr = await cache.incr("counter");
437
- $.log.debug("增加后:", incr); // 输出: 11
438
-
439
- // 增加指定值
440
- const incrby = await cache.incrby("counter", 5);
441
- $.log.debug("增加5后:", incrby); // 输出: 16
442
-
443
- // 减少1
444
- const decr = await cache.decr("counter");
445
- $.log.debug("减少后:", decr); // 输出: 15
446
-
447
- // 浮点数操作
448
- await cache.set("price", 99.99);
449
- const incrFloat = await cache.incrbyfloat("price", 0.01);
450
- $.log.debug("浮点数增加后:", incrFloat); // 输出: 100
451
- }
452
- ```
453
-
454
- ### 多文件持久化示例
455
- ```javascript
456
- const CacheBase = require('mm_cachebase');
457
-
458
- async function persistenceExample() {
459
- // 创建启用持久化的缓存实例,指定不同的scope
460
- const userCache = new CacheBase('users', {
461
- persist: true,
462
- saveInterval: 30000, // 30秒保存一次
463
- dir: './test_cache/' // 自定义缓存目录
464
- });
465
-
466
- const productCache = new CacheBase('products', {
467
- persist: true,
468
- saveInterval: 30000,
469
- dir: './test_cache/'
470
- });
471
-
472
- // 启动定时保存
473
- await userCache.connect();
474
- await productCache.connect();
475
-
476
- // 向不同scope添加数据
477
- await userCache.set('user1', { name: '张三', age: 30 }, 3600);
478
- await productCache.set('product1', { id: 1, name: '商品A', price: 99.99 }, 3600);
479
-
480
- // 数据会分别保存到 users.cache.json 和 products.cache.json
481
- $.log.debug('数据已保存,不同scope的数据完全隔离');
482
-
483
- // 手动保存(可选)
484
- await userCache.save();
485
-
486
- // 应用重启后,可通过相同的scope加载对应的数据
487
- const loadedUserCache = new CacheBase('users', { persist: true, dir: './test_cache/' });
488
- const loadedUser = await loadedUserCache.get('user1');
489
- $.log.debug('加载的用户数据:', loadedUser);
490
-
491
- // 销毁实例时,会自动保存数据
492
- await userCache.dispose();
493
- await productCache.dispose();
494
- }
495
- ```
496
-
497
- ### 批量操作示例
498
- ```javascript
499
- async function batchExample() {
500
- // 批量设置
501
- await cache.mset(["key1", "key2", "key3"], ["value1", "value2", "value3"]);
502
-
503
- // 批量获取
504
- const values = await cache.mget("key1", "key2", "key3");
505
- $.log.debug("批量获取:", values); // 输出: ["value1", "value2", "value3"]
506
-
507
- // 检查多个键是否存在
508
- const existsCount = await cache.exists("key1", "key2", "nonexistent");
509
- $.log.debug("存在的键数量:", existsCount); // 输出: 2
510
-
511
- // 获取键数量
512
- const count = await cache.dbsize();
513
- $.log.debug("键总数:", count);
514
-
515
- // 清空所有缓存
516
- await cache.flushdb();
517
- }
518
- ```
519
-
520
- ## 注意事项
521
-
522
- 1. 所有操作方法都是异步的,需要使用async/await或Promise处理
523
- 2. 过期时间单位为秒,-1表示永不过期
524
- 3. 缓存数据默认存储在内存中,重启后数据会丢失
525
- 4. 启用持久化时,数据将保存到`{scope}.cache.json`文件,不同scope的数据存储在不同文件中,实现数据隔离
526
- 5. 缓存目录会在第一次使用时自动创建,无需手动创建
527
- 6. 事件回调函数中的 `cancel` 标志只在前置事件中有效,后置事件中修改不会产生效果
528
- 7. 所有事件参数都遵循统一的格式,包含key、value、result、error和cancel等字段
529
-
530
- ## 贡献指南
531
-
532
- 欢迎参与mm_cachebase项目的开发和改进!以下是贡献代码的基本步骤:
533
-
534
- 1. **Fork 仓库**:在Gitee上Fork项目到您的账户
535
- 2. **克隆仓库**:`git clone https://gitee.com/您的用户名/mm_cachebase.git`
536
- 3. **创建分支**:`git checkout -b feature/your-feature-name`
537
- 4. **提交更改**:`git commit -m "feat: 添加新功能描述"`
538
- 5. **推送分支**:`git push origin feature/your-feature-name`
539
- 6. **创建PR**:在Gitee上提交Pull Request
540
-
541
- ## 问题反馈
542
-
543
- 如果您在使用过程中遇到任何问题或有改进建议,请通过以下方式反馈:
544
-
545
- - **Gitee Issues**:[https://gitee.com/qiuwenwu91/mm_cachebase/issues](https://gitee.com/qiuwenwu91/mm_cachebase/issues)
546
- - **NPM 链接**:[https://www.npmjs.com/package/mm_cachebase](https://www.npmjs.com/package/mm_cachebase)
547
-
548
- ## 鸣谢
549
-
550
- 感谢所有为mm_cachebase项目做出贡献的开发者和用户!
551
-
552
- ## 相关链接
553
-
554
- - **Node.js 官方文档**:[https://nodejs.org/docs/latest/api/](https://nodejs.org/docs/latest/api/)
555
- - **Redis 命令参考**:[https://redis.io/commands/](https://redis.io/commands/)
556
-
557
- ## 许可证
558
-
559
- MIT
1
+ # mm_cachebase
2
+
3
+ 一个轻量级的本地缓存类库,提供与 **mm_redis 完全对齐** 的异步缓存操作接口,支持过期时间、哈希表、列表、集合、有序集合、发布订阅等功能,以及冒号风格的事件通知系统。
4
+
5
+ ## 项目信息
6
+
7
+ - **当前版本**: 2.0.0
8
+ - **更新日期**: 2026-08-04
9
+ - **Gitee地址**: [https://gitee.com/qiuwenwu91/mm_cachebase](https://gitee.com/qiuwenwu91/mm_cachebase)
10
+ - **Node.js 版本要求**: >= 14.0.0(推荐 16.0.0 及以上)
11
+
12
+ ## 特点
13
+
14
+ - **接口与 mm_redis 完全对齐**:全异步 API、冒号风格事件、统一方法签名与返回值,可与 mm_redis 无缝切换
15
+ - **全异步设计**:所有公共方法均为 `async`,返回 `Promise`
16
+ - **冒号风格事件**:`set:before` / `set:after` / `set:error`,与 mm_redis 一致
17
+ - **完整的数据类型支持**:字符串、哈希表、列表、集合、有序集合、发布订阅
18
+ - **过期时间管理**:支持秒级 `expire` 与毫秒级 `pexpire`
19
+ - **多文件持久化**:通过 `scope` 参数实现多实例数据隔离
20
+
21
+ ## 安装
22
+
23
+ ```bash
24
+ npm install mm_cachebase
25
+ ```
26
+
27
+ ## 基本使用
28
+
29
+ ```javascript
30
+ const { CacheBase } = require('mm_cachebase');
31
+
32
+ // 创建缓存实例(构造时自动初始化)
33
+ const cache = new CacheBase({ scope: 'myapp' });
34
+
35
+ async function example() {
36
+ // 设置缓存,10 秒过期
37
+ await cache.set("name", "张三", 10);
38
+
39
+ // 获取缓存
40
+ const value = await cache.get("name");
41
+ $.log.debug(value); // 输出: 张三
42
+
43
+ // 删除缓存(返回删除数量)
44
+ const deleted = await cache.del("name");
45
+ $.log.debug(deleted); // 输出: 1
46
+ }
47
+ ```
48
+
49
+ ## 连接管理
50
+
51
+ 与 mm_redis 一致的连接管理接口:
52
+
53
+ ```javascript
54
+ const cache = new CacheBase({ scope: 'myapp' });
55
+ await cache.init(); // 初始化(构造时已自动调用)
56
+ await cache.open(); // 打开连接(等同于 init)
57
+ const connected = cache.isConnected(); // 检查连接状态,返回 Boolean
58
+ await cache.close(); // 关闭连接(等同于 destroy)
59
+ cache.dispose(); // 同步销毁(清理定时器与数据)
60
+ ```
61
+
62
+ ## API 说明
63
+
64
+ 所有方法均为 `async`,返回 `Promise`。事件名采用冒号风格(`xxx:before` / `xxx:after` / `xxx:error`)。
65
+
66
+ ### 键值操作
67
+
68
+ | 方法 | 签名 | 返回值 |
69
+ |------|------|--------|
70
+ | set | `set(key, value, seconds=0)` | `Promise<Boolean>` |
71
+ | get | `get(key)` | `Promise<Object\|null>` |
72
+ | del | `del(key)` | `Promise<Number>` 删除数量 |
73
+ | exists | `exists(key)` | `Promise<Number>` 0/1 |
74
+ | has | `has(key)` | `Promise<Boolean>` |
75
+ | getset | `getset(key, value, seconds=0)` | `Promise<Object\|null>` 旧值 |
76
+ | add | `add(key, value, seconds=0)` | `Promise<Boolean>` SETNX 语义 |
77
+
78
+ ### 批量操作
79
+
80
+ | 方法 | 签名 | 返回值 |
81
+ |------|------|--------|
82
+ | mset | `mset(obj, seconds=0)` | `Promise<Boolean>` |
83
+ | mget | `mget(keys)` | `Promise<Array>` |
84
+
85
+ ### 过期时间管理
86
+
87
+ | 方法 | 签名 | 返回值 |
88
+ |------|------|--------|
89
+ | expire | `expire(key, seconds)` | `Promise<Boolean>` |
90
+ | pexpire | `pexpire(key, milliseconds)` | `Promise<Boolean>` |
91
+ | persist | `persist(key)` | `Promise<Boolean>` |
92
+ | ttl | `ttl(key, [seconds])` | `Promise<Number\|Boolean>` |
93
+
94
+ ### 哈希表操作
95
+
96
+ | 方法 | 签名 | 返回值 |
97
+ |------|------|--------|
98
+ | hset | `hset(key, field, value)` | `Promise<Boolean>` |
99
+ | hget | `hget(key, field)` | `Promise<Object\|null>` |
100
+ | hgetall | `hgetall(key)` | `Promise<Object>` |
101
+ | hdel | `hdel(key, field)` | `Promise<Number>` 删除字段数 |
102
+ | hmset | `hmset(key, obj)` | `Promise<Boolean>` |
103
+ | hmget | `hmget(key, fields)` | `Promise<Array>` |
104
+ | hlen | `hlen(key)` | `Promise<Number>` |
105
+
106
+ ### 数值操作
107
+
108
+ | 方法 | 签名 | 返回值 |
109
+ |------|------|--------|
110
+ | incr | `incr(key, seconds=0)` | `Promise<Number>` 错误返回 null |
111
+ | decr | `decr(key, seconds=0)` | `Promise<Number>` 错误返回 null |
112
+ | incrby | `incrby(key, increment, seconds=0)` | `Promise<Number>` 错误返回 null |
113
+ | decrby | `decrby(key, decrement, seconds=0)` | `Promise<Number>` 错误返回 null |
114
+ | incrbyfloat | `incrbyfloat(key, increment, seconds=0)` | `Promise<Number>` 错误返回 null |
115
+ | addInt | `addInt(key, value, seconds=0)` | `Promise<Number>` 兼容方法 |
116
+ | addFloat | `addFloat(key, num, seconds=0)` | `Promise<Number>` 兼容方法 |
117
+
118
+ ### 字符串操作
119
+
120
+ | 方法 | 签名 | 返回值 |
121
+ |------|------|--------|
122
+ | setrange | `setrange(key, value, seconds=0)` | `Promise<Number>` 追加后长度 |
123
+ | append | `append(key, value)` | `Promise<Number>` 长度 |
124
+ | strlen | `strlen(key)` | `Promise<Number>` |
125
+
126
+ ### 列表操作
127
+
128
+ | 方法 | 签名 | 返回值 |
129
+ |------|------|--------|
130
+ | setForList | `setForList(key, value, seconds=0)` | `Promise<Number>` 列表长度 |
131
+ | addForList | `addForList(key, value, seconds=0)` | `Promise<Number>` 列表长度 |
132
+ | getForList | `getForList(key, start=0, end=-1)` | `Promise<Array>` |
133
+ | hasForList | `hasForList(key, value)` | `Promise<Boolean>` |
134
+ | clearForList | `clearForList(key)` | `Promise<Boolean>` |
135
+
136
+ ### 集合操作
137
+
138
+ | 方法 | 签名 | 返回值 |
139
+ |------|------|--------|
140
+ | sadd | `sadd(key, members)` | `Promise<Number>` 添加数量 |
141
+ | srem | `srem(key, members)` | `Promise<Number>` 移除数量 |
142
+ | sismember | `sismember(key, member)` | `Promise<Boolean>` |
143
+ | smembers | `smembers(key)` | `Promise<Array>` |
144
+ | scard | `scard(key)` | `Promise<Number>` |
145
+ | sinter | `sinter(...keys)` | `Promise<Array>` 交集 |
146
+ | sunion | `sunion(...keys)` | `Promise<Array>` 并集 |
147
+ | sdiff | `sdiff(...keys)` | `Promise<Array>` 差集 |
148
+
149
+ ### 有序集合操作
150
+
151
+ | 方法 | 签名 | 返回值 |
152
+ |------|------|--------|
153
+ | zadd | `zadd(key, score, member)` | `Promise<Boolean>` 新成员返回 true |
154
+ | zrem | `zrem(key, members)` | `Promise<Number>` 移除数量 |
155
+ | zscore | `zscore(key, member)` | `Promise<Number\|null>` |
156
+ | zrank | `zrank(key, member)` | `Promise<Number\|null>` |
157
+ | zrange | `zrange(key, start, stop, withScores=false)` | `Promise<Array>` |
158
+ | zcard | `zcard(key)` | `Promise<Number>` |
159
+ | zincrby | `zincrby(key, increment, member)` | `Promise<Number>` |
160
+
161
+ ### 发布订阅
162
+
163
+ > **注意**:发布订阅为进程内实现,无跨进程能力,与 mm_redis 的跨进程语义不同。
164
+
165
+ | 方法 | 签名 | 返回值 |
166
+ |------|------|--------|
167
+ | subscribe | `subscribe(channel, func)` | `Promise<Boolean>` |
168
+ | unsubscribe | `unsubscribe(channel)` | `Promise<Boolean>` |
169
+ | publish | `publish(channel, message)` | `Promise<Number>` 接收者数量 |
170
+
171
+ ### 键管理
172
+
173
+ | 方法 | 签名 | 返回值 |
174
+ |------|------|--------|
175
+ | keys | `keys(pattern)` | `Promise<Array>` 支持 `*` 通配符 |
176
+ | dbsize | `dbsize()` | `Promise<Number>` |
177
+ | flushdb | `flushdb()` | `Promise<Boolean>` |
178
+ | clear | `clear()` | `Promise<Boolean>` flushdb 别名 |
179
+
180
+ ## 事件系统
181
+
182
+ 事件名采用**冒号风格**,与 mm_redis 完全一致。每个操作有 `:before`、`:after`、`:error` 三种事件。
183
+
184
+ ```javascript
185
+ const cache = new CacheBase({ scope: 'myapp' });
186
+
187
+ // 监听 set 前置事件,可修改参数或取消操作
188
+ cache.on('set:before', (ctx) => {
189
+ $.log.debug('即将设置键:', ctx.key, '值:', ctx.value);
190
+ // 可修改 ctx.key / ctx.value / ctx.seconds
191
+ // 设置 ctx.cancel = true 可取消操作
192
+ });
193
+
194
+ // 监听 set 后置事件
195
+ cache.on('set:after', (data) => {
196
+ $.log.debug('设置完成:', data.key, '成功:', data.success);
197
+ });
198
+
199
+ // 监听错误事件
200
+ cache.on('set:error', (data) => {
201
+ $.log.error('设置出错:', data.key, data.error);
202
+ });
203
+ ```
204
+
205
+ ### 支持的事件
206
+
207
+ 所有公共方法均有对应事件,命名规则为 `方法名:before` / `方法名:after` / `方法名:error`:
208
+
209
+ - 键值:`set`、`get`、`del`、`exists`、`add`
210
+ - 批量:`mset`、`mget`
211
+ - 过期:`expire`、`pexpire`、`persist`、`ttl`
212
+ - 哈希:`hset`、`hget`、`hgetall`、`hdel`、`hmset`、`hmget`、`hlen`
213
+ - 数值:`incr`、`decr`、`incrby`、`decrby`、`incrbyfloat`、`addInt`、`addFloat`
214
+ - 字符串:`setrange`、`append`
215
+ - 列表:`setForList`、`addForList`、`getForList`、`hasForList`、`clearForList`
216
+ - 集合:`sadd`、`srem`、`sismember`、`smembers`
217
+ - 有序集合:`zadd`、`zrem`
218
+ - 键管理:`keys`、`clear`
219
+
220
+ ## 使用示例
221
+
222
+ ### 集合操作
223
+
224
+ ```javascript
225
+ async function setExample() {
226
+ await cache.sadd('tags', ['node', 'js', 'cache']);
227
+ const isMember = await cache.sismember('tags', 'node'); // true
228
+ const members = await cache.smembers('tags'); // ['node', 'js', 'cache']
229
+ const count = await cache.scard('tags'); // 3
230
+ await cache.srem('tags', ['js']);
231
+ }
232
+ ```
233
+
234
+ ### 有序集合操作
235
+
236
+ ```javascript
237
+ async function zsetExample() {
238
+ await cache.zadd('ranking', 100, 'user1');
239
+ await cache.zadd('ranking', 200, 'user2');
240
+ const rank = await cache.zrank('ranking', 'user1'); // 0
241
+ const top = await cache.zrange('ranking', 0, -1, true); // [{member:'user1', score:100}, ...]
242
+ await cache.zincrby('ranking', 50, 'user1'); // 新分数 150
243
+ }
244
+ ```
245
+
246
+ ### 发布订阅
247
+
248
+ ```javascript
249
+ async function pubsubExample() {
250
+ await cache.subscribe('news', (message) => {
251
+ $.log.debug('收到消息:', message);
252
+ });
253
+ await cache.publish('news', 'hello world'); // 接收者数量: 1
254
+ }
255
+ ```
256
+
257
+ ## 与 mm_redis 的接口一致性
258
+
259
+ 本模块与 [mm_redis](../mm_redis) 提供完全对齐的接口,调用方可通过统一的方式使用内存缓存或 Redis 缓存:
260
+
261
+ - **全异步**:所有方法返回 `Promise`
262
+ - **事件命名**:冒号风格 `xxx:before` / `xxx:after` / `xxx:error`
263
+ - **方法签名**:`set(key, value, seconds=0)`、`mset(obj, seconds=0)`、`incrby(key, increment, seconds=0)` 等
264
+ - **返回值**:`hset` 返回 `Boolean`,`del`/`exists`/`hdel` 返回 `Number`,`hget` 不存在返回 `null`
265
+
266
+ **差异点**:
267
+ - 发布订阅为进程内实现(mm_redis 支持跨进程)
268
+ - 集合/有序集合用 JS 原生 `Set`/`Map` 实现,无 Redis 的 O(log N) 复杂度保证
269
+ - 构造函数自动初始化(内存缓存特性),mm_redis 需显式 `open()`