uploads/Home/RedisHelper-guide.md
... ...
@@ -0,0 +1,510 @@
1
+# RedisHelper 缓存工具类开发文档
2
+
3
+## 1. 概述
4
+
5
+### 1.1 简介
6
+RedisHelper 是基于 Redis 的缓存工具类,为 Java 应用提供统一的缓存操作接口。支持单机、集群和哨兵三种 Redis 部署模式,提供 String、List、Set、Hash 等数据结构的操作,以及分布式锁功能。
7
+
8
+### 1.2 核心特性
9
+- ✅ 支持 Redis 单机、集群、哨兵模式
10
+- ✅ 提供多种数据结构的封装操作
11
+- ✅ 内置分布式锁实现
12
+- ✅ 支持自动续期和过期时间设置
13
+- ✅ 线程安全的缓存操作
14
+
15
+## 2. 环境配置
16
+
17
+### 2.1 依赖配置
18
+确保项目中已引入 sie-iidp-cache App
19
+
20
+### 2.2 配置文件
21
+在 `application-dev.properties` 中配置 Redis 连接:
22
+
23
+#### 2.2.1 单机模式配置
24
+```properties
25
+#单机模式
26
+redis.mode=single
27
+redis.host=127.0.0.1
28
+redis.port=6379
29
+redis.db=0
30
+redis.password=your_password
31
+```
32
+
33
+#### 2.2.2 集群模式配置
34
+```properties
35
+#集群模式
36
+redis.mode=cluster
37
+#多个节点以英文逗号分隔,请勿输入空格
38
+redis.cluster.nodes=127.0.0.1:7000,127.0.0.1:7001,127.0.0.1:7002
39
+#集群节点扫描间隔,单位为毫秒
40
+redis.cluster.scanInterval=2000
41
+redis.db=0
42
+redis.password=
43
+```
44
+
45
+#### 2.2.3 哨兵模式配置
46
+```properties
47
+#哨兵模式
48
+redis.mode=sentinel
49
+#哨兵模式主节点名称配置
50
+redis.master=mymaster
51
+#多个节点以英文逗号分隔,请勿输入空格,这里用哨兵的端口
52
+redis.cluster.nodes=127.0.0.1:26379,127.0.0.1:26380,127.0.0.1:26381
53
+#集群节点扫描间隔,单位为毫秒
54
+redis.cluster.scanInterval=2000
55
+redis.db=0
56
+redis.password=
57
+```
58
+
59
+### 2.3 参数说明
60
+| 参数名 | 类型 | 必填 | 默认值 | 说明 |
61
+| ------------------- | ------- | ----------------- | --------- | ----------------------------------- |
62
+| redis.mode | String | 是 | single | Redis 模式:single/cluster/sentinel |
63
+| redis.host | String | 单机模式必填 | 127.0.0.1 | Redis 主机地址 |
64
+| redis.port | Integer | 单机模式必填 | 6379 | Redis 端口 |
65
+| redis.cluster.nodes | String | 集群/哨兵模式必填 | - | 节点地址,逗号分隔 |
66
+| redis.master | String | 哨兵模式必填 | - | 哨兵主节点名称 |
67
+| redis.db | Integer | 否 | 0 | 数据库索引 |
68
+| redis.password | String | 否 | - | 认证密码 |
69
+| redis.timeout | Integer | 否 | 2000 | 连接超时时间(ms) |
70
+| | | | | |
71
+
72
+## 3. 命名规范
73
+
74
+### 3.1 Key 命名规范
75
+1. **格式要求**:使用英文冒号 `:` 作为分隔符
76
+2. **命名结构**:`应用名:模块名:业务名:唯一标识`
77
+3. **示例**:
78
+ - `newSdkApp:User:Session:userId_001`
79
+ - `newSdkApp:Product:Cache:category_001`
80
+ - `newSdkApp:Order:Lock:order_1001`
81
+
82
+### 3.2 推荐命名模式
83
+```java
84
+// 统一前缀定义
85
+public interface CacheKeys {
86
+ String APP_PREFIX = "newSdkApp";
87
+
88
+ // 用户模块
89
+ String USER_SESSION = APP_PREFIX + ":User:Session:";
90
+ String USER_ONLINE = APP_PREFIX + ":User:Online";
91
+ String USER_INFO = APP_PREFIX + ":User:Info:";
92
+
93
+ // 产品模块
94
+ String PRODUCT_CACHE = APP_PREFIX + ":Product:Cache:";
95
+ String PRODUCT_LIST = APP_PREFIX + ":Product:List:";
96
+
97
+ // 订单模块
98
+ String ORDER_LOCK = APP_PREFIX + ":Order:Lock:";
99
+ String ORDER_CACHE = APP_PREFIX + ":Order:Cache:";
100
+
101
+ // 系统配置
102
+ String SYS_CONFIG = APP_PREFIX + ":Sys:Config:";
103
+}
104
+```
105
+
106
+## 4. API 参考手册
107
+
108
+● 类名: `com.sie.snest.sdk.cache.RedisHelper`
109
+● 类型: 静态工具类
110
+● 功能: 提供统一的Redis缓存操作接口
111
+
112
+### 4.1 基础缓存操作
113
+
114
+#### 4.1.1 读取缓存
115
+
116
+```java
117
+/**
118
+ * 读取缓存
119
+ * @param key 缓存key
120
+ * @return 缓存返回值(Object类型)
121
+ */
122
+public static Object get(String key)
123
+```
124
+
125
+**使用示例**:
126
+
127
+```java
128
+Object value = RedisHelper.get("user:1001");
129
+if (value != null) {
130
+ // 需要手动类型转换
131
+}
132
+```
133
+
134
+#### 4.1.2 设置缓存
135
+
136
+```java
137
+/**
138
+ * 设置缓存
139
+ * @param key 缓存key
140
+ * @param value 缓存值
141
+ * @param expired 缓存过期时间,单位为秒(-1永久)
142
+ */
143
+public static void set(String key, Object value, Long expired)
144
+```
145
+
146
+**特性说明**:
147
+
148
+1. **自动类型转换**:
149
+ - 当value是`BaseModel`类型时,自动转换为Map存储
150
+ - 当value是`List<BaseModel>`类型时,自动转换为`List<Map>`存储
151
+ - 其他类型直接存储
152
+
153
+2. **序列化机制**:
154
+
155
+```java
156
+// BaseModel处理流程
157
+if (value instanceof BaseModel) {
158
+ v = JSON.parseObject(JSON.toJSONString(value), Map.class);
159
+}
160
+// List<BaseModel>处理流程
161
+if (value instanceof List && 列表第一个元素是BaseModel) {
162
+ v = JSON.parseArray(JSONObject.toJSONString(value), Map.class);
163
+}
164
+```
165
+
166
+#### 4.1.3 设置缓存(默认过期时间)
167
+
168
+```java
169
+public static void set(String key, Object value)
170
+```
171
+
172
+**说明**: 调用`set(key, value, null)`,使用底层默认过期时间
173
+
174
+### 4.2 类型化缓存操作
175
+
176
+#### 4.2.1 读取指定类型的缓存
177
+
178
+```java
179
+/**
180
+ * 读取缓存并转换为指定BaseModel类型
181
+ * @param key 缓存key
182
+ * @param c 模型class(必须是BaseModel的子类)
183
+ * @return 缓存返回值(指定类型)
184
+ */
185
+public static <T> T get(String key, Class<? extends BaseModel> c)
186
+```
187
+
188
+**转换逻辑**:
189
+
190
+```java
191
+if (obj instanceof Map) {
192
+ return (T) copy(c, (Map) obj); // 调用copy方法创建BaseModel实例
193
+}
194
+```
195
+
196
+#### 4.2.2 读取BaseModel列表缓存
197
+
198
+```java
199
+/**
200
+ * 读取缓存并转换为BaseModel列表
201
+ * @param key 缓存key
202
+ * @param c 模型class
203
+ * @return BaseModel列表
204
+ */
205
+public static <T> List<T> getArray(String key, Class<? extends BaseModel> c)
206
+```
207
+
208
+**转换逻辑**:
209
+
210
+```java
211
+if (obj instanceof List) {
212
+ return (List<T>) copys(c, (List) obj); // 批量转换
213
+}
214
+```
215
+
216
+### 4.3 字符串操作
217
+
218
+#### 4.3.1 读取字符串
219
+
220
+```java
221
+public static String getString(String key)
222
+```
223
+
224
+#### 4.3.2 设置字符串
225
+
226
+```java
227
+public static void setString(String key, String value, Long expired)
228
+public static void setString(String key, String value)
229
+```
230
+
231
+### 4.4 List列表操作
232
+
233
+#### 4.4.1 获取List
234
+
235
+```java
236
+public static <T> List<T> getList(String key)
237
+```
238
+
239
+#### 4.4.2 添加List
240
+
241
+```java
242
+public static void addList(String key, List value, Long expired)
243
+public static void addList(String key, List value)
244
+```
245
+
246
+#### 4.4.3 删除List操作
247
+
248
+```java
249
+public static void removeList(String key, List value) // 移除指定元素
250
+public static void deleteList(String key) // 删除整个List
251
+```
252
+
253
+### 4.5 Hash哈希表操作
254
+
255
+#### 4.5.1 读取操作
256
+
257
+```java
258
+public static String hGet(String key, String field) // 获取单个字段
259
+public static Map<String, String> hMGet(String key, Set<String> field) // 获取多个字段
260
+public static Map<String, String> hGetAll(String key) // 获取所有字段
261
+public static Integer hLen(String key) // 获取字段数量
262
+public static Set<String> hKeys(String key) // 获取所有字段名
263
+```
264
+
265
+#### 4.5.2 写入操作
266
+
267
+```java
268
+public static void hSetAll(String key, Map<String, String> value, Long expired)
269
+public static void hSetAll(String key, Map<String, String> value)
270
+public static String hSet(String key, String field, String value, Long expired)
271
+public static String hSet(String key, String field, String value)
272
+```
273
+
274
+#### 4.5.3 删除操作
275
+
276
+```java
277
+public static String hDel(String key, String field) // 删除单个字段
278
+public static Long hDelKeys(String key, String[] fields) // 删除多个字段
279
+```
280
+
281
+### 4.6 Set集合操作
282
+
283
+#### 4.6.1 查询操作
284
+
285
+```java
286
+public static Boolean sExists(String key) // 判断Set是否存在
287
+public static Boolean sIsMember(String key, String field) // 判断是否为成员
288
+public static Integer sCard(String key) // 获取成员数量
289
+public static Set<String> sMembers(String key) // 获取所有成员
290
+```
291
+
292
+#### 4.6.2 修改操作
293
+
294
+```java
295
+public static Boolean sAdd(String key, String field, Long expired) // 添加单个成员
296
+public static Boolean sAdd(String key, String field)
297
+public static Boolean sAddAll(String key, Collection<String> field, Long expired) // 批量添加
298
+public static Boolean sAddAll(String key, Collection<String> field)
299
+public static Boolean sRemove(String key, String field) // 移除成员
300
+```
301
+
302
+### 4.7 缓存管理
303
+
304
+#### 4.7.1 删除缓存
305
+
306
+```java
307
+public static void remove(String key)
308
+```
309
+
310
+#### 4.7.2 过期时间管理
311
+
312
+```java
313
+public static Boolean expire(String key, Long expired) // 设置过期时间
314
+public static Boolean exists(String key) // 判断key是否存在
315
+```
316
+
317
+### 4.8 分布式锁
318
+
319
+#### 4.8.1 加锁操作
320
+
321
+```java
322
+public static void lock(String key, Long timeout) // 阻塞式加锁
323
+```
324
+
325
+#### 4.8.2 尝试加锁
326
+
327
+```java
328
+public static Boolean tryLock(String key, Long waitTime, Long leaseTime)
329
+```
330
+
331
+**参数说明**:
332
+
333
+- `waitTime`: 等待获取锁的最长时间(秒)
334
+- `leaseTime`: 锁的持有时间(秒)
335
+
336
+#### 4.8.3 解锁操作
337
+
338
+```java
339
+public static void unlock(String key)
340
+```
341
+
342
+#### 4.8.4 注意事项
343
+
344
+- 如果leaseTime释放时间传固定的时间,锁不会自动续期,要确保释放时间足够大于业务逻辑处理时间,避免锁到期释放。 首先要考虑业务本身的执行时间,还要考虑因为网络延迟、系统负载高、数据量递增等原因可能会导致业务执行时间变长,适当增加锁的释放时间
345
+- 如果希望锁自动续期,leaseTime释放时间传-1L
346
+- 锁的key会自动加上前缀 lock:
347
+
348
+#### 4.8.5 分布式锁示例
349
+
350
+**阻塞式加锁示例:**
351
+
352
+```java
353
+public static void lockDemo() {
354
+ Boolean isLocked=false;
355
+ try {
356
+ // 加锁,堵塞线程,加锁600秒后自动释放
357
+ RedisHelper.lock("myLock",600L);
358
+ isLocked=true;
359
+ System.out.println("成功获取锁,执行业务逻辑...");
360
+ } catch (Exception e) {
361
+ // 获取锁失败
362
+ e.printStackTrace();
363
+ } finally {
364
+ // 释放锁
365
+ if(isLocked){
366
+ RedisHelper.unlock("myLock");
367
+ System.out.println("锁已释放");
368
+ }
369
+ }
370
+ }
371
+
372
+```
373
+
374
+**尝试加锁示例:**
375
+
376
+```
377
+public static void tryLockDemo() {
378
+ Boolean isLocked=false;
379
+ try {
380
+ // 尝试加锁,最多等待100秒,加锁600秒后自动释放
381
+ isLocked = RedisHelper.tryLock("mylock",100L, 600L);
382
+ if (isLocked) {
383
+ // 成功获取锁,执行业务逻辑
384
+ System.out.println("成功获取锁,执行业务逻辑...");
385
+ } else {
386
+ // 获取锁失败
387
+ System.out.println("获取锁失败,可能有其他线程持有锁");
388
+ }
389
+ } catch (Exception e) {
390
+ e.printStackTrace();
391
+ } finally {
392
+ // 释放锁
393
+ if(isLocked){
394
+ RedisHelper.unlock("mylock");
395
+ System.out.println("锁已释放");
396
+ }
397
+ }
398
+ }
399
+```
400
+
401
+
402
+
403
+### 4.9 内部辅助方法
404
+
405
+#### 4.9.1 单个对象转换
406
+
407
+```java
408
+private static <T extends BaseModel> T copy(Class<? extends BaseModel> modelClass,
409
+ Map<String, Object> value)
410
+```
411
+
412
+**实现逻辑**:
413
+
414
+```java
415
+BaseModel<?> ar = modelClass.newInstance(); // 反射创建实例
416
+ar.putAll(value); // 复制属性
417
+return (T) ar;
418
+```
419
+
420
+#### 4.9.2 批量对象转换
421
+
422
+```java
423
+private static <T> List<T> copys(Class<? extends BaseModel> modelClass,
424
+ List<Map<String, Object>> values)
425
+```
426
+
427
+**实现逻辑**: 遍历列表,对每个Map调用`copy`方法转换
428
+
429
+#### 4.9.3. BaseModel使用规范
430
+
431
+1. **存储时**: BaseModel会自动转换为Map存储
432
+
433
+2. **读取时**: 使用`get(String key, Class<T> c)`方法可自动转换回BaseModel
434
+
435
+3. **列表读取**: 使用`getArray(String key, Class<T> c)`方法
436
+
437
+
438
+
439
+## 5. 典型使用示例
440
+
441
+### 5.1 BaseModel缓存示例
442
+
443
+```java
444
+// 定义模型
445
+public class User extends BaseModel<User> {
446
+ private String id;
447
+ private String name;
448
+ // getter/setter省略
449
+}
450
+
451
+// 存储用户
452
+User user = new User();
453
+user.setId("1001");
454
+user.setName("张三");
455
+RedisHelper.set("user:1001", user, 3600L); // 自动转换为Map存储
456
+
457
+// 读取用户
458
+User cachedUser = RedisHelper.get("user:1001", User.class); // 自动转换回User对象
459
+```
460
+
461
+### 5.2 List缓存示例
462
+
463
+```java
464
+// 存储列表
465
+List<User> userList = Arrays.asList(user1, user2);
466
+RedisHelper.addList("user:online", userList, 1800L);
467
+
468
+// 读取列表
469
+List<User> cachedList = RedisHelper.getList("user:online");
470
+```
471
+
472
+### 5.3 分布式锁示例
473
+
474
+```java
475
+
476
+public static void tryLockDemo() {
477
+ Boolean isLocked=false;
478
+ try {
479
+ // 尝试加锁,最多等待100秒,加锁600秒后自动释放
480
+ isLocked = RedisHelper.tryLock("mylock",100L, 600L);
481
+ if (isLocked) {
482
+ // 成功获取锁,执行业务逻辑
483
+ System.out.println("成功获取锁,执行业务逻辑...");
484
+ } else {
485
+ // 获取锁失败
486
+ System.out.println("获取锁失败,可能有其他线程持有锁");
487
+ }
488
+ } catch (Exception e) {
489
+ e.printStackTrace();
490
+ } finally {
491
+ // 释放锁
492
+ if(isLocked){
493
+ RedisHelper.unlock("mylock");
494
+ System.out.println("锁已释放");
495
+ }
496
+ }
497
+ }
498
+```
499
+
500
+## 6. 常见问题
501
+
502
+### 6.1 类型转换失败
503
+
504
+**问题**: 使用`get(key, Class<T> c)`但缓存中存储的不是BaseModel
505
+**解决**: 先使用`get(key)`检查类型,或确保存储时使用BaseModel
506
+
507
+### 6.2 序列化异常
508
+
509
+**问题**: 存储非BaseModel的复杂对象
510
+**解决**: 自行处理序列化,或转换为Map结构存储
... ...
\ No newline at end of file