mm_redis 1.9.3 → 1.9.5

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.
package/README.md CHANGED
@@ -1,449 +1,466 @@
1
- # mm_redis
2
-
3
- mm_redis是一个高效的Redis客户端封装库,提供了全面的Redis功能支持,包括连接池管理、数据类型操作、错误处理和批量操作优化。
4
-
5
- [![npm version](https://badge.fury.io/js/mm_redis.svg)](https://badge.fury.io/js/mm_redis)
6
- [![npm downloads](https://img.shields.io/npm/dm/mm_redis.svg)](https://www.npmjs.com/package/mm_redis)
7
-
8
- ## 版本信息
9
-
10
- - **当前版本**: 1.9.0
11
- - **更新日期**: 2024-11-20
12
- - **作者**: 邱文武
13
- - **NPM**: [https://www.npmjs.com/package/mm_redis](https://www.npmjs.com/package/mm_redis)
14
-
15
- ## 功能特性
16
-
17
- - 完整的连接池管理,优化并发性能
18
- - 支持Pipeline批量操作,提升执行效率
19
- - 支持所有主要Redis数据类型:String、List、Hash、Set、Sorted Set等
20
- - 自动重连机制,使用指数退避策略
21
- - 全面的错误处理和日志记录
22
- - 自动JSON序列化/反序列化
23
- - 键前缀管理,支持多业务隔离
24
- - 自动连接管理,无需手动维护连接状态
25
- - 统一的事件系统,支持操作前后的事件监听
26
- - 支持数值增减操作
27
-
28
- ## 安装
29
-
30
- ```bash
31
- npm install mm_redis --save
32
- ```
33
-
34
- ## 基本配置
35
-
36
- ```javascript
37
- const Redis = require('mm_redis');
38
-
39
- // 创建Redis实例
40
- const redis = new Redis('default');
41
-
42
- // 配置Redis连接
43
- redis.setConfig({
44
- // 服务器地址
45
- "host": "localhost",
46
- // 端口号
47
- "port": 6379,
48
- // 密码
49
- "password": "",
50
- // 数据库
51
- "database": 0,
52
- // 前缀
53
- "prefix": "app:",
54
- // 连接超时时间(ms)
55
- "connect_timeout": 10000,
56
- // 重试次数
57
- "retry_count": 3,
58
- // 重试间隔(ms)
59
- "retry_delay": 1000,
60
- // 连接池配置
61
- "pool": {
62
- "max_clients": 10, // 最大连接数
63
- "min_idle": 2, // 最小空闲连接数
64
- "max_idle": 5, // 最大空闲连接数
65
- "idle_timeout": 30000 // 空闲超时时间(ms)
66
- }
67
- });
68
- ```
69
-
70
- ## 使用示例
71
-
72
- ### 基本操作
73
-
74
- ```javascript
75
- // 连接Redis
76
- await redis.open();
77
-
78
- // 设置缓存
79
- await redis.set('user:1', { name: '张三', age: 25 }, 3600);
80
-
81
- // 获取缓存
82
- const user = await redis.get('user:1');
83
- $.log.debug('[Redis] 获取用户信息:', user);
84
-
85
- // 判断键是否存在
86
- const exists = await redis.has('user:1');
87
-
88
- // 删除缓存
89
- await redis.del('user:1');
90
-
91
- // 关闭连接
92
- await redis.close();
93
- ```
94
-
95
- ### 列表操作
96
-
97
- ```javascript
98
- // 设置列表
99
- await redis.list_set('users', ['user1', 'user2', 'user3']);
100
-
101
- // 添加元素到列表
102
- await redis.list_push('users', 'user4');
103
-
104
- // 获取列表
105
- const users = await redis.list_get('users');
106
- $.log.debug('[Redis] 用户列表:', users);
107
-
108
- // 获取列表的部分元素
109
- const partialUsers = await redis.list_get('users', 0, 2);
110
-
111
- // 清空列表
112
- await redis.list_clear('users');
113
- ```
114
-
115
- ### Hash操作
116
-
117
- ```javascript
118
- // 设置哈希字段
119
- await redis.hset('user:profile:1', 'name', '张三');
120
- await redis.hset('user:profile:1', 'age', 25);
121
-
122
- // 批量设置哈希字段
123
- await redis.hmset('user:profile:1', {
124
- 'email': 'zhangsan@example.com',
125
- 'phone': '13800138000'
126
- });
127
-
128
- // 获取哈希字段
129
- const name = await redis.hget('user:profile:1', 'name');
130
-
131
- // 获取哈希的所有字段和值
132
- const profile = await redis.hgetall('user:profile:1');
133
- $.log.debug('[Redis] 用户资料:', profile);
134
-
135
- // 获取哈希的所有字段名
136
- const fields = await redis.hkeys('user:profile:1');
137
-
138
- // 获取哈希的所有字段值
139
- const values = await redis.hvals('user:profile:1');
140
-
141
- // 判断哈希字段是否存在
142
- const hasEmail = await redis.hexists('user:profile:1', 'email');
143
-
144
- // 获取哈希字段数量
145
- const fieldCount = await redis.hlen('user:profile:1');
146
-
147
- // 删除哈希字段
148
- await redis.hdel('user:profile:1', ['email', 'phone']);
149
- ```
150
-
151
- ### 批量操作
152
-
153
- ```javascript
154
- // 批量获取
155
- const data = await redis.mget(['user:1', 'user:2', 'user:3']);
156
- $.log.debug('[Redis] 批量获取结果:', data);
157
-
158
- // 批量设置
159
- await redis.mset({
160
- 'user:4': { name: '李四', age: 30 },
161
- 'user:5': { name: '王五', age: 35 }
162
- }, 3600);
163
- ```
164
-
165
- ### 使用Pipeline优化批量操作
166
-
167
- ```javascript
168
- // 创建Pipeline
169
- const pipeline = redis.pipeline();
170
-
171
- // 添加多个命令
172
- pipeline.set('counter:1', 100);
173
- pipeline.ttl('counter:1', 3600);
174
- pipeline.hset('stats:today', 'visits', 500);
175
- pipeline.hset('stats:today', 'users', 100);
176
-
177
- // 执行所有命令
178
- const results = await pipeline.exec();
179
- $.log.debug('[Redis] Pipeline执行结果:', results);
180
- ```
181
-
182
- ### 发布订阅
183
-
184
- ```javascript
185
- // 订阅频道
186
- await redis.subscribe('notifications', async (message) => {
187
- $.log.debug('[Redis] 收到通知:', message);
188
- // 处理接收到的消息
189
- });
190
-
191
- // 发布消息
192
- const receivedCount = await redis.publish('notifications', JSON.stringify({
193
- type: 'info',
194
- content: '系统更新成功'
195
- }));
196
-
197
- $.log.debug(`[Redis] 消息已发布,${receivedCount}个客户端接收`);
198
-
199
- // 取消订阅
200
- await redis.unsubscribe('notifications');
201
- ```
202
-
203
- ### 事件系统
204
-
205
- mm_redis提供了完善的事件系统,可以监听各种操作的前后事件,用于日志记录、数据修改或操作拦截。
206
-
207
- ```javascript
208
- // 监听设置操作前的事件
209
- redis.on('set_before', (data) => {
210
- $.log.debug('[Redis] 设置缓存前:', data);
211
- // 可以修改data中的值
212
- // data.value = JSON.stringify(data.value);
213
- // 可以通过设置data.cancel = true来取消操作
214
- });
215
-
216
- // 监听设置操作后的事件
217
- redis.on('set_after', (data) => {
218
- $.log.debug('[Redis] 设置缓存后:', data);
219
- // data包含key, value, ttl, success等信息
220
- });
221
-
222
- // 监听设置操作的错误事件
223
- redis.on('set_error', (data) => {
224
- $.log.error('[Redis] 设置缓存错误:', data);
225
- // data包含key, value, ttl, error等信息
226
- });
227
- ```
228
-
229
- #### 事件属性规范
230
-
231
- 所有事件都遵循统一的属性命名规范:
232
-
233
- 1. **通用属性**:
234
- - `key`: 操作的键名
235
- - `value`: 操作的值(替代str、fields、obj等)
236
- - `ttl`: 过期时间(替代seconds)
237
- - `result`: 操作结果(替代length)
238
- - `success`: 操作是否成功
239
- - `cancel`: 是否取消操作(仅限前置事件)
240
- - `error`: 错误信息(仅限错误事件)
241
-
242
- 2. **特定属性**:
243
- - `deleted`: 删除的键列表(用于del操作)
244
- - `index`: 索引位置(用于setrange操作)
245
- - `field`: 哈希字段名(用于hset操作)
246
-
247
- 3. **事件命名模式**:
248
- - 前置事件: `${methodName}_before`
249
- - 后置事件: `${methodName}_after`
250
- - 错误事件: `${methodName}_error`
251
-
252
- #### 支持的事件列表
253
-
254
- | 操作方法 | 前置事件 | 后置事件 | 错误事件 |
255
- |---------|---------|---------|--------|
256
- | set | set_before | set_after | set_error |
257
- | get | get_before | get_after | get_error |
258
- | del | del_before | del_after | del_error |
259
- | add | add_before | add_after | add_error |
260
- | addInt | addInt_before | addInt_after | addInt_error |
261
- | addFloat | addFloat_before | addFloat_after | addFloat_error |
262
- | addStr | addStr_before | addStr_after | addStr_error |
263
- | setrange | setrange_before | setrange_after | setrange_error |
264
- | clear | clear_before | clear_after | clear_error |
265
- | list_set | list_set_before | list_set_after | list_set_error |
266
- | list_push | list_push_before | list_push_after | list_push_error |
267
- | list_clear | list_clear_before | list_clear_after | list_clear_error |
268
- | mset | mset_before | mset_after | mset_error |
269
- | mget | mget_before | mget_after | mget_error |
270
- | hset | hset_before | hset_after | hset_error |
271
- | hmset | hmset_before | hmset_after | hmset_error |
272
- | hdel | hdel_before | hdel_after | hdel_error |
273
- | hget | hget_before | hget_after | hget_error |
274
- | hgetall | hgetall_before | hgetall_after | hgetall_error |
275
- | incr | incr_before | incr_after | incr_error |
276
- | decr | decr_before | decr_after | decr_error |
277
- | incrby | incrby_before | incrby_after | incrby_error |
278
- | decrby | decrby_before | decrby_after | decrby_error |
279
- | expire | expire_before | expire_after | expire_error |
280
- | sadd | sadd_before | sadd_after | sadd_error |
281
- | srem | srem_before | srem_after | srem_error |
282
- | zadd | zadd_before | zadd_after | zadd_error |
283
-
284
- ## API文档
285
-
286
- ### 连接管理
287
-
288
- - `setConfig(config)`: 设置Redis配置
289
- - `open()`: 连接Redis
290
- - `close()`: 关闭连接
291
- - `isConnected()`: 检查连接状态
292
-
293
- ### 字符串操作
294
-
295
- - `set(key, value, seconds)`: 设置缓存
296
- - `get(key)`: 获取缓存
297
- - `has(key)`: 判断键是否存在
298
- - `del(key)`: 删除缓存
299
- - `add(key, value, seconds)`: 仅当键不存在时设置缓存
300
- - `ttl(key, seconds)`: 设置或获取过期时间
301
- - `addInt(key, num)`: 增加整数值
302
- - `addFloat(key, num)`: 增加浮点数值
303
- - `addStr(key, str)`: 追加字符串
304
- - `getrange(key, start, end)`: 获取字符串子串
305
- - `setrange(key, index, value)`: 设置字符串子串
306
-
307
- ### 列表操作
308
-
309
- - `list_set(key, value, seconds)`: 设置列表
310
- - `list_push(key, value)`: 添加元素到列表
311
- - `list_get(key, start, end)`: 获取列表
312
- - `list_has(key, value)`: 判断列表中是否存在元素
313
- - `list_clear(key, value)`: 清空列表或重置列表
314
-
315
- ### Hash操作
316
-
317
- - `hset(key, field, value)`: 设置哈希字段
318
- - `hmset(key, obj)`: 批量设置哈希字段
319
- - `hget(key, field)`: 获取哈希字段值
320
- - `hgetall(key)`: 获取哈希的所有字段和值
321
- - `hkeys(key)`: 获取哈希的所有字段名
322
- - `hvals(key)`: 获取哈希的所有字段值
323
- - `hdel(key, fields)`: 删除哈希字段
324
- - `hexists(key, field)`: 判断哈希字段是否存在
325
- - `hlen(key)`: 获取哈希字段数量
326
-
327
- ### 批量操作
328
-
329
- - `mget(keys)`: 批量获取缓存
330
- - `mset(obj, seconds)`: 批量设置缓存
331
- - `pipeline()`: 创建Pipeline对象进行批量操作优化
332
-
333
- ### 高级操作
334
-
335
- - `subscribe(channel, func)`: 订阅频道
336
- - `unsubscribe(channel)`: 取消订阅
337
- - `publish(channel, message)`: 发布消息
338
- - `clear(key)`: 清空缓存或当前数据库
339
- - `sort(key, options)`: 排序
340
- - `keys(pattern)`: 获取所有键名
341
-
342
- ### 集合(Set)操作
343
-
344
- - `sadd(key, members)`: 添加成员到集合
345
- - `srem(key, members)`: 从集合中移除成员
346
- - `sismember(key, member)`: 检查成员是否在集合中
347
- - `smembers(key)`: 获取集合中的所有成员
348
- - `scard(key)`: 获取集合中的成员数量
349
- - `sinter(keys)`: 获取多个集合的交集
350
- - `sunion(keys)`: 获取多个集合的并集
351
- - `sdiff(keys)`: 获取多个集合的差集
352
-
353
- ### 有序集合(Sorted Set)操作
354
-
355
- - `zadd(key, score, member)`: 添加成员到有序集合
356
- - `zrem(key, members)`: 从有序集合中移除成员
357
- - `zscore(key, member)`: 获取有序集合中成员的分数
358
- - `zrank(key, member)`: 获取有序集合中成员的排名
359
- - `zrange(key, start, stop, withScores)`: 获取有序集合中指定范围的成员
360
- - `zcard(key)`: 获取有序集合中的成员数量
361
- - `zincrby(key, increment, member)`: 增加有序集合中成员的分数
362
-
363
- ### 数值操作
364
-
365
- - `incr(key)`: 将键的值增加1
366
- - `decr(key)`: 将键的值减少1
367
- - `incrby(key, increment)`: 将键的值增加指定的整数
368
- - `decrby(key, decrement)`: 将键的值减少指定的整数
369
- - `expire(key, seconds)`: 设置键的过期时间
370
-
371
- ## 连接池管理
372
-
373
- 本模块内置了高效的连接池管理,可自动处理连接的创建、回收和复用。连接池配置可在初始化时设置:
374
-
375
- ```javascript
376
- {
377
- "pool": {
378
- "max_clients": 10, // 最大连接数
379
- "min_idle": 2, // 最小空闲连接数
380
- "max_idle": 5, // 最大空闲连接数
381
- "idle_timeout": 30000 // 空闲超时时间(ms)
382
- }
383
- }
384
- ```
385
-
386
- ## 错误处理
387
-
388
- 所有方法都包含了完善的错误处理机制,并提供详细的日志输出。在发生错误时,会自动记录错误信息,并在可能的情况下提供回退方案。
389
-
390
- ## 最佳实践
391
-
392
- 1. **使用连接池**: 对于高并发应用,连接池配置至关重要,合理设置最大连接数和空闲连接数
393
- 2. **使用Pipeline**: 对于批量操作,使用Pipeline可显著提升性能
394
- 3. **合理设置过期时间**: 避免Redis中数据无限增长
395
- 4. **使用键前缀**: 通过键前缀进行业务隔离,避免键冲突
396
- 5. **及时关闭连接**: 在应用结束时调用close()方法关闭所有连接
397
- 6. **利用事件系统**: 使用事件系统进行日志记录、数据验证和操作拦截
398
-
399
- ## 版本更新
400
-
401
- ### 1.9.0 (2024-11-20)
402
- - 适配Redis v4 API,确保与最新版Redis客户端兼容
403
- - 重写pipeline方法,使用Redis v4推荐的实现方式
404
- - 优化mget方法,直接使用Redis v4的mGet API
405
- - 修复集合操作(srem)和有序集合操作(zadd/zrange/zscore/zrank)的兼容性问题
406
- - 完善测试用例,确保所有功能正常工作
407
- - 更新依赖版本,优化连接管理
408
- - 完善事件系统,为incr、decr、incrby、decrby方法添加前置事件(_before)支持
409
- - 确保所有非查询方法都有完整的_before、_after、_error事件触发机制
410
- - 更新文档,添加新支持的事件到事件列表中
411
- - 版本号更新和发布日期更新
412
-
413
- ### 1.8.1 (2024-10-09)
414
- - 修复mget方法返回格式问题,确保与原生Redis保持一致
415
- - 修复mset方法参数验证逻辑,优化批量设置功能
416
- - 优化Pipeline实现,确保命令正确执行
417
- - 修复连接池初始化和管理逻辑
418
- - 修复存储机制,确保数据正确持久化
419
- - 准备npm发布,优化文档格式和结构
420
- - 添加npm徽章和下载统计
421
-
422
- ### 1.8.0 (2024-10-08)
423
- - 新增集合(Set)操作支持:sadd、srem、sismember、smembers、scard、sinter、sunion、sdiff
424
- - 新增有序集合(Sorted Set)操作支持:zadd、zrem、zscore、zrank、zrange、zcard、zincrby
425
- - 新增数值操作支持:incr、decr、incrby、decrby、expire
426
- - 更新文档,添加新功能的API说明
427
- - 更新版本号和发布日期
428
-
429
- ### 1.7.0 (2024-10-07)
430
- - 统一事件系统的属性命名规范
431
- - 更新所有方法的事件emit属性,使用统一的key、value、ttl、result等命名
432
- - 增加事件系统的详细文档
433
- - 修复部分方法中的拼写错误
434
-
435
- ### 1.6.0 (2024-01-10)
436
- - 添加完整的连接池管理功能
437
- - 新增Pipeline批量操作优化
438
- - 增加Hash数据类型支持
439
- - 增强错误处理和日志记录
440
- - 优化重连机制,实现指数退避策略
441
-
442
- ### 1.5.0
443
- - 优化连接管理
444
- - 完善错误处理
445
- - 提升代码稳定性
446
-
447
- ### 1.0.0
448
- - 初始版本发布
1
+ # mm_redis
2
+
3
+ mm_redis是一个高效的Redis客户端封装库,提供了全面的Redis功能支持,包括连接池管理、数据类型操作、错误处理和批量操作优化。
4
+
5
+ [![npm version](https://badge.fury.io/js/mm_redis.svg)](https://badge.fury.io/js/mm_redis)
6
+ [![npm downloads](https://img.shields.io/npm/dm/mm_redis.svg)](https://www.npmjs.com/package/mm_redis)
7
+
8
+ ## 版本信息
9
+
10
+ - **当前版本**: 1.9.4
11
+ - **更新日期**: 2024-12-20
12
+ - **作者**: 邱文武
13
+ - **NPM**: [https://www.npmjs.com/package/mm_redis](https://www.npmjs.com/package/mm_redis)
14
+
15
+ ## 功能特性
16
+
17
+ - 完整的连接池管理,优化并发性能
18
+ - 支持Pipeline批量操作,提升执行效率
19
+ - 支持所有主要Redis数据类型:String、List、Hash、Set、Sorted Set等
20
+ - 自动重连机制,使用指数退避策略
21
+ - 全面的错误处理和日志记录
22
+ - 自动JSON序列化/反序列化
23
+ - 键前缀管理,支持多业务隔离
24
+ - 自动连接管理,无需手动维护连接状态
25
+ - 统一的事件系统,支持操作前后的事件监听
26
+ - 支持数值增减操作
27
+
28
+ ## 安装
29
+
30
+ ```bash
31
+ npm install mm_redis --save
32
+ ```
33
+
34
+ ## 配置引入方式
35
+
36
+ mm_redis支持多种配置引入方式:
37
+
38
+ 1. **对象配置(推荐)**:直接传入配置对象
39
+ ```javascript
40
+ const Redis = require('mm_redis');
41
+ const redis = new Redis('default');
42
+ redis.setConfig({
43
+ // 服务器地址
44
+ host: "localhost",
45
+ // 端口号
46
+ port: 6379,
47
+ // 密码
48
+ password: "",
49
+ // 数据库
50
+ database: 0,
51
+ // 前缀
52
+ prefix: "app:",
53
+ // 连接超时时间(ms)
54
+ connect_timeout: 10000,
55
+ // 重试次数
56
+ retry_count: 3,
57
+ // 重试间隔(ms)
58
+ retry_delay: 1000,
59
+ // 连接池配置
60
+ pool: {
61
+ max_clients: 10, // 最大连接数
62
+ min_idle: 2, // 最小空闲连接数
63
+ max_idle: 5, // 最大空闲连接数
64
+ idle_timeout: 30000 // 空闲超时时间(ms)
65
+ }
66
+ });
67
+ ```
68
+
69
+ 2. **文件配置**:传入配置文件路径
70
+ ```javascript
71
+ const Redis = require('mm_redis');
72
+ const redis = new Redis('default');
73
+ redis.setConfig('./config.json');
74
+ ```
75
+ ## 变更日志
76
+
77
+ ### v1.9.4 (2024-12-20)
78
+ - 优化了配置引入方式,支持对象配置和文件路径配置两种方式
79
+ - 改进了setConfig方法的实现,使用Object.assign替代原来的合并方式
80
+ - 修复了连接池相关的警告信息
81
+ - 增强了错误处理机制
82
+
83
+ ### v1.9.0 (2024-11-20)
84
+ - 初始版本发布
85
+ - 支持完整的连接池管理
86
+ - 实现Pipeline批量操作
87
+ - 支持所有主要Redis数据类型操作
88
+
89
+ ## 使用示例
90
+
91
+ ```javascript
92
+ // 连接Redis
93
+ await redis.open();
94
+
95
+ // 设置缓存
96
+ await redis.set('user:1', { name: '张三', age: 25 }, 3600);
97
+
98
+ // 获取缓存
99
+ const user = await redis.get('user:1');
100
+ $.log.debug('[Redis] 获取用户信息:', user);
101
+
102
+ // 判断键是否存在
103
+ const exists = await redis.has('user:1');
104
+
105
+ // 删除缓存
106
+ await redis.del('user:1');
107
+
108
+ // 关闭连接
109
+ await redis.close();
110
+ ```
111
+
112
+ ### 列表操作
113
+
114
+ ```javascript
115
+ // 设置列表
116
+ await redis.list_set('users', ['user1', 'user2', 'user3']);
117
+
118
+ // 添加元素到列表
119
+ await redis.list_push('users', 'user4');
120
+
121
+ // 获取列表
122
+ const users = await redis.list_get('users');
123
+ $.log.debug('[Redis] 用户列表:', users);
124
+
125
+ // 获取列表的部分元素
126
+ const partialUsers = await redis.list_get('users', 0, 2);
127
+
128
+ // 清空列表
129
+ await redis.list_clear('users');
130
+ ```
131
+
132
+ ### Hash操作
133
+
134
+ ```javascript
135
+ // 设置哈希字段
136
+ await redis.hset('user:profile:1', 'name', '张三');
137
+ await redis.hset('user:profile:1', 'age', 25);
138
+
139
+ // 批量设置哈希字段
140
+ await redis.hmset('user:profile:1', {
141
+ 'email': 'zhangsan@example.com',
142
+ 'phone': '13800138000'
143
+ });
144
+
145
+ // 获取哈希字段
146
+ const name = await redis.hget('user:profile:1', 'name');
147
+
148
+ // 获取哈希的所有字段和值
149
+ const profile = await redis.hgetall('user:profile:1');
150
+ $.log.debug('[Redis] 用户资料:', profile);
151
+
152
+ // 获取哈希的所有字段名
153
+ const fields = await redis.hkeys('user:profile:1');
154
+
155
+ // 获取哈希的所有字段值
156
+ const values = await redis.hvals('user:profile:1');
157
+
158
+ // 判断哈希字段是否存在
159
+ const hasEmail = await redis.hexists('user:profile:1', 'email');
160
+
161
+ // 获取哈希字段数量
162
+ const fieldCount = await redis.hlen('user:profile:1');
163
+
164
+ // 删除哈希字段
165
+ await redis.hdel('user:profile:1', ['email', 'phone']);
166
+ ```
167
+
168
+ ### 批量操作
169
+
170
+ ```javascript
171
+ // 批量获取
172
+ const data = await redis.mget(['user:1', 'user:2', 'user:3']);
173
+ $.log.debug('[Redis] 批量获取结果:', data);
174
+
175
+ // 批量设置
176
+ await redis.mset({
177
+ 'user:4': { name: '李四', age: 30 },
178
+ 'user:5': { name: '王五', age: 35 }
179
+ }, 3600);
180
+ ```
181
+
182
+ ### 使用Pipeline优化批量操作
183
+
184
+ ```javascript
185
+ // 创建Pipeline
186
+ const pipeline = redis.pipeline();
187
+
188
+ // 添加多个命令
189
+ pipeline.set('counter:1', 100);
190
+ pipeline.ttl('counter:1', 3600);
191
+ pipeline.hset('stats:today', 'visits', 500);
192
+ pipeline.hset('stats:today', 'users', 100);
193
+
194
+ // 执行所有命令
195
+ const results = await pipeline.exec();
196
+ $.log.debug('[Redis] Pipeline执行结果:', results);
197
+ ```
198
+
199
+ ### 发布订阅
200
+
201
+ ```javascript
202
+ // 订阅频道
203
+ await redis.subscribe('notifications', async (message) => {
204
+ $.log.debug('[Redis] 收到通知:', message);
205
+ // 处理接收到的消息
206
+ });
207
+
208
+ // 发布消息
209
+ const receivedCount = await redis.publish('notifications', JSON.stringify({
210
+ type: 'info',
211
+ content: '系统更新成功'
212
+ }));
213
+
214
+ $.log.debug(`[Redis] 消息已发布,${receivedCount}个客户端接收`);
215
+
216
+ // 取消订阅
217
+ await redis.unsubscribe('notifications');
218
+ ```
219
+
220
+ ### 事件系统
221
+
222
+ mm_redis提供了完善的事件系统,可以监听各种操作的前后事件,用于日志记录、数据修改或操作拦截。
223
+
224
+ ```javascript
225
+ // 监听设置操作前的事件
226
+ redis.on('set_before', (data) => {
227
+ $.log.debug('[Redis] 设置缓存前:', data);
228
+ // 可以修改data中的值
229
+ // data.value = JSON.stringify(data.value);
230
+ // 可以通过设置data.cancel = true来取消操作
231
+ });
232
+
233
+ // 监听设置操作后的事件
234
+ redis.on('set_after', (data) => {
235
+ $.log.debug('[Redis] 设置缓存后:', data);
236
+ // data包含key, value, ttl, success等信息
237
+ });
238
+
239
+ // 监听设置操作的错误事件
240
+ redis.on('set_error', (data) => {
241
+ $.log.error('[Redis] 设置缓存错误:', data);
242
+ // data包含key, value, ttl, error等信息
243
+ });
244
+ ```
245
+
246
+ #### 事件属性规范
247
+
248
+ 所有事件都遵循统一的属性命名规范:
249
+
250
+ 1. **通用属性**:
251
+ - `key`: 操作的键名
252
+ - `value`: 操作的值(替代str、fields、obj等)
253
+ - `ttl`: 过期时间(替代seconds)
254
+ - `result`: 操作结果(替代length)
255
+ - `success`: 操作是否成功
256
+ - `cancel`: 是否取消操作(仅限前置事件)
257
+ - `error`: 错误信息(仅限错误事件)
258
+
259
+ 2. **特定属性**:
260
+ - `deleted`: 删除的键列表(用于del操作)
261
+ - `index`: 索引位置(用于setrange操作)
262
+ - `field`: 哈希字段名(用于hset操作)
263
+
264
+ 3. **事件命名模式**:
265
+ - 前置事件: `${methodName}_before`
266
+ - 后置事件: `${methodName}_after`
267
+ - 错误事件: `${methodName}_error`
268
+
269
+ #### 支持的事件列表
270
+
271
+ | 操作方法 | 前置事件 | 后置事件 | 错误事件 |
272
+ |---------|---------|---------|--------|
273
+ | set | set_before | set_after | set_error |
274
+ | get | get_before | get_after | get_error |
275
+ | del | del_before | del_after | del_error |
276
+ | add | add_before | add_after | add_error |
277
+ | addInt | addInt_before | addInt_after | addInt_error |
278
+ | addFloat | addFloat_before | addFloat_after | addFloat_error |
279
+ | addStr | addStr_before | addStr_after | addStr_error |
280
+ | setrange | setrange_before | setrange_after | setrange_error |
281
+ | clear | clear_before | clear_after | clear_error |
282
+ | list_set | list_set_before | list_set_after | list_set_error |
283
+ | list_push | list_push_before | list_push_after | list_push_error |
284
+ | list_clear | list_clear_before | list_clear_after | list_clear_error |
285
+ | mset | mset_before | mset_after | mset_error |
286
+ | mget | mget_before | mget_after | mget_error |
287
+ | hset | hset_before | hset_after | hset_error |
288
+ | hmset | hmset_before | hmset_after | hmset_error |
289
+ | hdel | hdel_before | hdel_after | hdel_error |
290
+ | hget | hget_before | hget_after | hget_error |
291
+ | hgetall | hgetall_before | hgetall_after | hgetall_error |
292
+ | incr | incr_before | incr_after | incr_error |
293
+ | decr | decr_before | decr_after | decr_error |
294
+ | incrby | incrby_before | incrby_after | incrby_error |
295
+ | decrby | decrby_before | decrby_after | decrby_error |
296
+ | expire | expire_before | expire_after | expire_error |
297
+ | sadd | sadd_before | sadd_after | sadd_error |
298
+ | srem | srem_before | srem_after | srem_error |
299
+ | zadd | zadd_before | zadd_after | zadd_error |
300
+
301
+ ## API文档
302
+
303
+ ### 连接管理
304
+
305
+ - `setConfig(config)`: 设置Redis配置
306
+ - `open()`: 连接Redis
307
+ - `close()`: 关闭连接
308
+ - `isConnected()`: 检查连接状态
309
+
310
+ ### 字符串操作
311
+
312
+ - `set(key, value, seconds)`: 设置缓存
313
+ - `get(key)`: 获取缓存
314
+ - `has(key)`: 判断键是否存在
315
+ - `del(key)`: 删除缓存
316
+ - `add(key, value, seconds)`: 仅当键不存在时设置缓存
317
+ - `ttl(key, seconds)`: 设置或获取过期时间
318
+ - `addInt(key, num)`: 增加整数值
319
+ - `addFloat(key, num)`: 增加浮点数值
320
+ - `addStr(key, str)`: 追加字符串
321
+ - `getrange(key, start, end)`: 获取字符串子串
322
+ - `setrange(key, index, value)`: 设置字符串子串
323
+
324
+ ### 列表操作
325
+
326
+ - `list_set(key, value, seconds)`: 设置列表
327
+ - `list_push(key, value)`: 添加元素到列表
328
+ - `list_get(key, start, end)`: 获取列表
329
+ - `list_has(key, value)`: 判断列表中是否存在元素
330
+ - `list_clear(key, value)`: 清空列表或重置列表
331
+
332
+ ### Hash操作
333
+
334
+ - `hset(key, field, value)`: 设置哈希字段
335
+ - `hmset(key, obj)`: 批量设置哈希字段
336
+ - `hget(key, field)`: 获取哈希字段值
337
+ - `hgetall(key)`: 获取哈希的所有字段和值
338
+ - `hkeys(key)`: 获取哈希的所有字段名
339
+ - `hvals(key)`: 获取哈希的所有字段值
340
+ - `hdel(key, fields)`: 删除哈希字段
341
+ - `hexists(key, field)`: 判断哈希字段是否存在
342
+ - `hlen(key)`: 获取哈希字段数量
343
+
344
+ ### 批量操作
345
+
346
+ - `mget(keys)`: 批量获取缓存
347
+ - `mset(obj, seconds)`: 批量设置缓存
348
+ - `pipeline()`: 创建Pipeline对象进行批量操作优化
349
+
350
+ ### 高级操作
351
+
352
+ - `subscribe(channel, func)`: 订阅频道
353
+ - `unsubscribe(channel)`: 取消订阅
354
+ - `publish(channel, message)`: 发布消息
355
+ - `clear(key)`: 清空缓存或当前数据库
356
+ - `sort(key, options)`: 排序
357
+ - `keys(pattern)`: 获取所有键名
358
+
359
+ ### 集合(Set)操作
360
+
361
+ - `sadd(key, members)`: 添加成员到集合
362
+ - `srem(key, members)`: 从集合中移除成员
363
+ - `sismember(key, member)`: 检查成员是否在集合中
364
+ - `smembers(key)`: 获取集合中的所有成员
365
+ - `scard(key)`: 获取集合中的成员数量
366
+ - `sinter(keys)`: 获取多个集合的交集
367
+ - `sunion(keys)`: 获取多个集合的并集
368
+ - `sdiff(keys)`: 获取多个集合的差集
369
+
370
+ ### 有序集合(Sorted Set)操作
371
+
372
+ - `zadd(key, score, member)`: 添加成员到有序集合
373
+ - `zrem(key, members)`: 从有序集合中移除成员
374
+ - `zscore(key, member)`: 获取有序集合中成员的分数
375
+ - `zrank(key, member)`: 获取有序集合中成员的排名
376
+ - `zrange(key, start, stop, withScores)`: 获取有序集合中指定范围的成员
377
+ - `zcard(key)`: 获取有序集合中的成员数量
378
+ - `zincrby(key, increment, member)`: 增加有序集合中成员的分数
379
+
380
+ ### 数值操作
381
+
382
+ - `incr(key)`: 将键的值增加1
383
+ - `decr(key)`: 将键的值减少1
384
+ - `incrby(key, increment)`: 将键的值增加指定的整数
385
+ - `decrby(key, decrement)`: 将键的值减少指定的整数
386
+ - `expire(key, seconds)`: 设置键的过期时间
387
+
388
+ ## 连接池管理
389
+
390
+ 本模块内置了高效的连接池管理,可自动处理连接的创建、回收和复用。连接池配置可在初始化时设置:
391
+
392
+ ```javascript
393
+ {
394
+ "pool": {
395
+ "max_clients": 10, // 最大连接数
396
+ "min_idle": 2, // 最小空闲连接数
397
+ "max_idle": 5, // 最大空闲连接数
398
+ "idle_timeout": 30000 // 空闲超时时间(ms)
399
+ }
400
+ }
401
+ ```
402
+
403
+ ## 错误处理
404
+
405
+ 所有方法都包含了完善的错误处理机制,并提供详细的日志输出。在发生错误时,会自动记录错误信息,并在可能的情况下提供回退方案。
406
+
407
+ ## 最佳实践
408
+
409
+ 1. **使用连接池**: 对于高并发应用,连接池配置至关重要,合理设置最大连接数和空闲连接数
410
+ 2. **使用Pipeline**: 对于批量操作,使用Pipeline可显著提升性能
411
+ 3. **合理设置过期时间**: 避免Redis中数据无限增长
412
+ 4. **使用键前缀**: 通过键前缀进行业务隔离,避免键冲突
413
+ 5. **及时关闭连接**: 在应用结束时调用close()方法关闭所有连接
414
+ 6. **利用事件系统**: 使用事件系统进行日志记录、数据验证和操作拦截
415
+
416
+ ## 版本更新
417
+
418
+ ### 1.9.0 (2024-11-20)
419
+ - 适配Redis v4 API,确保与最新版Redis客户端兼容
420
+ - 重写pipeline方法,使用Redis v4推荐的实现方式
421
+ - 优化mget方法,直接使用Redis v4的mGet API
422
+ - 修复集合操作(srem)和有序集合操作(zadd/zrange/zscore/zrank)的兼容性问题
423
+ - 完善测试用例,确保所有功能正常工作
424
+ - 更新依赖版本,优化连接管理
425
+ - 完善事件系统,为incr、decr、incrby、decrby方法添加前置事件(_before)支持
426
+ - 确保所有非查询方法都有完整的_before、_after、_error事件触发机制
427
+ - 更新文档,添加新支持的事件到事件列表中
428
+ - 版本号更新和发布日期更新
429
+
430
+ ### 1.8.1 (2024-10-09)
431
+ - 修复mget方法返回格式问题,确保与原生Redis保持一致
432
+ - 修复mset方法参数验证逻辑,优化批量设置功能
433
+ - 优化Pipeline实现,确保命令正确执行
434
+ - 修复连接池初始化和管理逻辑
435
+ - 修复存储机制,确保数据正确持久化
436
+ - 准备npm发布,优化文档格式和结构
437
+ - 添加npm徽章和下载统计
438
+
439
+ ### 1.8.0 (2024-10-08)
440
+ - 新增集合(Set)操作支持:sadd、srem、sismember、smembers、scard、sinter、sunion、sdiff
441
+ - 新增有序集合(Sorted Set)操作支持:zadd、zrem、zscore、zrank、zrange、zcard、zincrby
442
+ - 新增数值操作支持:incr、decr、incrby、decrby、expire
443
+ - 更新文档,添加新功能的API说明
444
+ - 更新版本号和发布日期
445
+
446
+ ### 1.7.0 (2024-10-07)
447
+ - 统一事件系统的属性命名规范
448
+ - 更新所有方法的事件emit属性,使用统一的key、value、ttl、result等命名
449
+ - 增加事件系统的详细文档
450
+ - 修复部分方法中的拼写错误
451
+
452
+ ### 1.6.0 (2024-01-10)
453
+ - 添加完整的连接池管理功能
454
+ - 新增Pipeline批量操作优化
455
+ - 增加Hash数据类型支持
456
+ - 增强错误处理和日志记录
457
+ - 优化重连机制,实现指数退避策略
458
+
459
+ ### 1.5.0
460
+ - 优化连接管理
461
+ - 完善错误处理
462
+ - 提升代码稳定性
463
+
464
+ ### 1.0.0
465
+ - 初始版本发布
449
466
  - 基础Redis功能支持
@@ -0,0 +1,64 @@
1
+ ```markdown
2
+ # 三种缓存方式方法兼容性对比表格
3
+
4
+ ## 核心缓存方法
5
+
6
+ | 方法名 | Redis | MongoDB | CacheBase | 状态说明 |
7
+ |-------|-------|---------|-----------|----------|
8
+ | set | ✅ | ✅ | ✅ | 完全兼容 |
9
+ | get | ✅ | ✅ | ✅ | 完全兼容 |
10
+ | del | ✅ | ✅ | ✅ | 完全兼容 |
11
+ | has | ❌ | ✅ | ✅ | Redis无此方法,CacheBase保持兼容 |
12
+ | clear | ❌ | ✅ | ✅ | Redis无此方法,CacheBase保持兼容 |
13
+ | keys | ✅ | ✅ | ✅ | 完全兼容 |
14
+ | ttl | ✅ | ❌ | ✅ | Redis原生支持,CacheBase模拟实现 |
15
+ | persist | ✅ | ❌ | ✅ | Redis原生支持,CacheBase模拟实现 |
16
+ | add | ❌ | ✅ | ✅ | Redis无此方法,CacheBase保持兼容 |
17
+ | addInt | ❌ | ✅ | ✅ | Redis无此方法,CacheBase保持兼容 |
18
+ | addStr | ❌ | ✅ | ✅ | Redis无此方法,CacheBase保持兼容 |
19
+ | sort | ✅ | ❌ | ✅ | Redis原生支持,CacheBase模拟实现 |
20
+
21
+ ## Redis兼容方法 - 哈希表操作
22
+
23
+ | 方法名 | Redis | MongoDB | CacheBase | 状态说明 |
24
+ |-------|-------|---------|-----------|----------|
25
+ | hset | ✅ | ✅ | ✅ | 模拟实现,通过set对象方式 |
26
+ | hget | ✅ | ✅ | ✅ | 模拟实现,通过get对象方式 |
27
+ | hgetall | ✅ | ✅ | ✅ | 模拟实现,返回完整对象 |
28
+ | hdel | ✅ | ✅ | ✅ | 模拟实现,删除对象属性 |
29
+ | hexists | ✅ | ❌ | ❌ | Redis原生支持,CacheBase未实现 |
30
+ | hkeys | ✅ | ❌ | ❌ | Redis原生支持,CacheBase未实现 |
31
+ | hvals | ✅ | ❌ | ❌ | Redis原生支持,CacheBase未实现 |
32
+
33
+ ## Redis兼容方法 - 集合操作
34
+
35
+ | 方法名 | Redis | MongoDB | CacheBase | 状态说明 |
36
+ |-------|-------|---------|-----------|----------|
37
+ | sadd | ✅ | ❌ | ❌ | Redis原生支持,CacheBase未实现 |
38
+ | srem | ✅ | ❌ | ❌ | Redis原生支持,CacheBase未实现 |
39
+ | sismember | ✅ | ❌ | ❌ | Redis原生支持,CacheBase未实现 |
40
+ | smembers | ✅ | ❌ | ❌ | Redis原生支持,CacheBase未实现 |
41
+ | scard | ✅ | ❌ | ❌ | Redis原生支持,CacheBase未实现 |
42
+
43
+ ## Redis兼容方法 - 有序集合操作
44
+
45
+ | 方法名 | Redis | MongoDB | CacheBase | 状态说明 |
46
+ |-------|-------|---------|-----------|----------|
47
+ | zadd | ✅ | ❌ | ❌ | Redis原生支持,CacheBase未实现 |
48
+ | zrem | ✅ | ❌ | ❌ | Redis原生支持,CacheBase未实现 |
49
+ | zrange | ✅ | ❌ | ❌ | Redis原生支持,CacheBase未实现 |
50
+ | zscore | ✅ | ❌ | ❌ | Redis原生支持,CacheBase未实现 |
51
+
52
+ ## Redis兼容方法 - 其他常用命令
53
+
54
+ | 方法名 | Redis | MongoDB | CacheBase | 状态说明 |
55
+ |-------|-------|---------|-----------|----------|
56
+ | expire | ✅ | ❌ | ✅ | Redis原生支持,CacheBase通过ttl模拟 |
57
+ | incr | ✅ | ⚠️ | ✅ | Redis原生支持,MongoDB返回undefined,CacheBase通过addInt模拟 |
58
+ | decr | ✅ | ⚠️ | ✅ | Redis原生支持,MongoDB返回undefined,CacheBase通过addInt模拟 |
59
+ | exists | ✅ | ✅ | ✅ | 兼容,Redis原生支持 |
60
+ | mget | ✅ | ⚠️ | ✅ | Redis原生支持,CacheBase实现兼容 |
61
+ | mset | ✅ | ✅ | ✅ | Redis原生支持,CacheBase实现兼容 |
62
+
63
+ 注:✅ 完全兼容/功能正常 | ⚠️ 部分兼容/有异常 | ❌ 不兼容/未实现
64
+ ```
package/index.js CHANGED
@@ -632,7 +632,8 @@ Redis.prototype.addInt = async function (key, num) {
632
632
  // 触发错误事件
633
633
  this.emit('addInt_error', { key, value: num, error: err });
634
634
  $.log.error(`[Redis] 增加整数值失败 [${key}]:`, err);
635
- throw err;
635
+ // 与CacheBase保持一致,错误时返回默认值而不是抛出异常
636
+ return 0;
636
637
  }
637
638
  };
638
639
 
@@ -648,10 +649,10 @@ Redis.prototype.addFloat = async function (key, num) {
648
649
  const beforeEventData = { key, value: num, cancel: false };
649
650
  this.emit('addFloat_before', beforeEventData);
650
651
 
651
- // 如果事件处理器标记为取消,则抛出错误
652
+ // 如果事件处理器标记为取消,则返回默认值
652
653
  if (beforeEventData.cancel) {
653
654
  $.log.debug(`[Redis] addFloat操作被事件处理器取消 [${key}]`);
654
- throw new Error('addFloat操作被取消');
655
+ return 0;
655
656
  }
656
657
 
657
658
  // 使用可能被修改的值
@@ -707,7 +708,8 @@ Redis.prototype.addFloat = async function (key, num) {
707
708
  // 触发错误事件
708
709
  this.emit('addFloat_error', { key, value: num, error: err });
709
710
  $.log.error(`[Redis] 增加浮点数值失败 [${key}]:`, err);
710
- throw err;
711
+ // 与CacheBase保持一致,错误时返回默认值而不是抛出异常
712
+ return 0;
711
713
  }
712
714
  };
713
715
 
@@ -2054,7 +2056,7 @@ Redis.prototype._releaseConnection = function (connection) {
2054
2056
  } else {
2055
2057
  $.log.debug('[Redis] 连接对象没有可用的关闭方法');
2056
2058
  }
2057
- $.log.debug('[Redis] 关闭多余连接:', connection.id);
2059
+ // $.log.debug('[Redis] 关闭多余连接:', connection.id);
2058
2060
  } catch (e) {
2059
2061
  $.log.error('[Redis] 关闭多余连接失败:', e);
2060
2062
  }
@@ -2065,6 +2067,9 @@ Redis.prototype._releaseConnection = function (connection) {
2065
2067
  }
2066
2068
  };
2067
2069
 
2070
+ // 确保_recycleConnection方法是_releaseConnection的别名
2071
+ Redis.prototype._recycleConnection = Redis.prototype._releaseConnection;
2072
+
2068
2073
  // 添加Hash操作相关方法
2069
2074
 
2070
2075
  /**
@@ -2891,7 +2896,7 @@ Redis.prototype._createConnection = function () {
2891
2896
 
2892
2897
  // 连接Redis
2893
2898
  connection.connect().then(() => {
2894
- $.log.debug('[Redis] 新连接已创建并连接:', connection.id);
2899
+ // $.log.debug('[Redis] 新连接已创建并连接:', connection.id);
2895
2900
  resolve(connection);
2896
2901
  }).catch(err => {
2897
2902
  $.log.error('[Redis] 创建连接失败:', err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mm_redis",
3
- "version": "1.9.3",
3
+ "version": "1.9.5",
4
4
  "description": "高效的Redis客户端封装库,提供连接池管理、数据类型操作、错误处理和批量操作优化",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -35,7 +35,7 @@
35
35
  "homepage": "https://www.npmjs.com/package/mm_redis",
36
36
  "dependencies": {
37
37
  "mm_logs": "^1.5.2",
38
- "redis": "^4.7.0"
38
+ "redis": "^5.8.3"
39
39
  },
40
40
  "engines": {
41
41
  "node": ">=14.0.0"