1. Redis 基础解析从原理到实战作为一名长期使用 Redis 的 Java 开发者我经常被问到Redis 到底快在哪里为什么我们项目要用它 这个问题看似简单但真正理解 Redis 的核心优势才能在实际开发中做出正确的技术决策。1.1 Redis 的本质与定位Redis 本质上是一个内存优先的键值存储系统但它的价值远不止于此。在我的项目经验中Redis 通常扮演着三个关键角色高性能缓存层作为数据库前面的缓冲减轻后端压力实时数据处理中心利用丰富的数据结构处理瞬时高并发请求分布式系统协调器通过原子操作实现简单的分布式协调与传统关系型数据库相比Redis 的独特之处在于数据模型简单但灵活Key-Value 多种数据结构所有操作在内存中完成避免磁盘 I/O 瓶颈单线程模型消除了锁竞争开销实际案例我们电商系统的商品详情页使用 Redis 缓存后QPS 从 200 提升到 8000而服务器资源消耗反而降低了30%1.2 Redis 高性能的四大支柱1.2.1 纯内存操作Redis 将所有数据保存在内存中这意味着数据访问速度在纳秒级别DRAM 访问延迟约 100ns避免了传统数据库的磁盘寻道约 10ms和页面调度开销但这也带来了两个关键问题数据持久化策略需要精心设计内存成本较高需要合理控制数据量1.2.2 单线程命令处理Redis 采用单线程处理命令的核心原因避免多线程上下文切换和锁竞争的开销简化数据结构的实现无需考虑线程安全顺序执行命令保证原子性但要注意的是长命令会阻塞整个服务如 KEYS *实际实现中仍有后台线程处理持久化等任务1.2.3 I/O 多路复用Redis 使用 epoll/kqueue 实现高效的网络 I/O单个线程可以处理数万并发连接事件驱动模型避免为每个连接创建线程非阻塞 I/O 最大化利用 CPU 资源1.2.4 优化的数据结构Redis 对每种数据结构都做了极致优化SDS (Simple Dynamic String) 减少内存分配次数压缩列表 (ziplist) 对小数据的高效存储跳跃表 (skiplist) 实现高效的区间查询1.3 Redis 的基本操作模型Redis 的核心抽象是 Key-Value 存储但它的 Value 支持多种数据结构key - value其中 value 可以是简单字符串 (String)哈希表 (Hash)列表 (List)集合 (Set)有序集合 (ZSet)这种设计使得 Redis 既能作为简单缓存又能处理复杂的数据操作需求。2. Redis 五大核心数据结构深度解析2.1 String不只是字符串2.1.1 底层实现与特性String 是 Redis 最基础的数据类型但其实现相当精巧使用 SDS (Simple Dynamic String) 实现预分配和惰性释放策略优化内存使用最大支持 512MB 的数据String 可以存储文本字符串数字自动识别为整数或浮点数二进制数据如图片、序列化对象2.1.2 典型使用场景缓存对象SET user:1001 {name:Tom,age:18} GET user:1001计数器INCR article:1001:views DECR inventory:product:5001分布式锁基础版SET lock:order 1 NX EX 302.1.3 Java 开发者注意事项大 Key 问题避免存储过大的 JSON超过 10KB考虑使用 Hash 结构拆分大对象原子操作// Java 中使用 Jedis jedis.incr(counter); // 等同于原子性的 // value get(counter) // set(counter, value1)批量操作// 使用 pipeline 提升性能 Pipeline p jedis.pipelined(); p.set(key1, value1); p.set(key2, value2); p.sync();2.2 Hash对象存储的最佳选择2.2.1 结构特点Hash 是一个 string 类型的 field-value 映射表user:1001 - { name: Tom, age: 18, email: tomexample.com }底层实现小数据量使用 ziplist内存紧凑大数据量使用 hashtableO(1) 访问2.2.2 与 String 存储 JSON 的对比特性HashString(JSON)部分更新✅ HSET field value❌ 需全量替换内存效率更高共享key前缀较低访问速度O(1) per fieldO(1) 全量序列化开销无需要JSON解析2.2.3 实战示例// 存储用户信息 jedis.hset(user:1001, name, Tom); jedis.hset(user:1001, age, 18); // 获取单个字段 String name jedis.hget(user:1001, name); // 获取所有字段 MapString, String user jedis.hgetAll(user:1001);2.2.4 使用建议适合存储对象用户信息、商品属性等避免 field 过多超过1000个考虑拆分注意 HSET/HGET 与 HMSET/HMGET 的性能差异2.3 List简单的消息队列2.3.1 数据结构特点双向链表实现插入删除操作 O(1)按索引访问 O(n)元素可重复2.3.2 使用场景消息队列简单场景LPUSH orders order1 RPOP orders最新N条记录LPUSH logs log1 LTRIM logs 0 99 # 保留最近100条阻塞队列// Java中实现阻塞获取 ListString messages jedis.blpop(30, queue);2.3.3 注意事项不是可靠的MQ缺少消息确认机制重试机制死信队列大列表性能问题LINDEX 命令避免频繁使用考虑分片或使用其他数据结构2.4 Set去重与集合运算2.4.1 核心特性无序的字符串集合元素唯一性保证支持交并差集运算O(1) 时间复杂度的添加、删除、查找2.4.2 典型应用标签系统SADD article:1001:tags tech database nosql共同好友SINTER user:1001:friends user:1002:friends抽奖去重SADD lottery:2023:users user1 user22.4.3 Java 实现技巧// 判断是否已点赞 boolean isLiked jedis.sismember(article:1001:likes, user1001); // 获取所有标签 SetString tags jedis.smembers(article:1001:tags); // 计算共同好友 jedis.sinterstore(tmp:common, user:1001:friends, user:1002:friends);2.5 ZSet排行榜的终极解决方案2.5.1 数据结构剖析成员唯一分数(score)可重复按分数排序默认升序底层使用跳跃表哈希表实现范围查询效率高 O(logN)2.5.2 排行榜实现# 添加成绩 ZADD leaderboard 100 player1 200 player2 # 获取Top 10 ZREVRANGE leaderboard 0 9 WITHSCORES # 获取玩家排名 ZREVRANK leaderboard player12.5.3 高级用法时间窗口统计ZADD events 1630000000 event1 1630000001 event2 ZCOUNT events 1630000000 1630000005延迟队列ZADD delay_queue 1630000000 task1 ZRANGEBYSCORE delay_queue 0 1630000000 LIMIT 0 12.5.4 使用注意分数精度问题使用整数避免浮点精度问题必要时乘以固定系数转为整数大集合性能避免超大ZSet百万级以上考虑按时间或其他维度分片3. 数据结构选型与实战建议3.1 数据结构选择速查表场景推荐结构替代方案不适用场景简单键值缓存String-需要部分更新的对象对象缓存HashString(JSON)嵌套复杂对象消息队列ListStreams可靠消息系统去重/标签系统Set-需要排序的场景排行榜/范围查询ZSet-简单键值存储时间序列数据ZSetTimeSeries模块需要聚合计算的场景3.2 Key 设计最佳实践命名规范业务:子业务:实体类型:ID[:子实体]例如user:auth:session:1001 order:payment:20230201:1001:items避免大Key单个Key的Value不超过10KBHash/Set/ZSet元素不超过5000个过期策略// 设置过期时间 jedis.setex(temp:key, 3600, value); // 批量设置过期 Pipeline p jedis.pipelined(); p.set(key1, value1); p.expire(key1, 60); p.sync();3.3 性能优化技巧Pipeline批量操作Pipeline p jedis.pipelined(); for (int i 0; i 100; i) { p.set(key i, value i); } p.sync();Lua脚本保证原子性-- 库存扣减脚本 local stock tonumber(redis.call(GET, KEYS[1])) if stock tonumber(ARGV[1]) then return redis.call(DECRBY, KEYS[1], ARGV[1]) else return -1 end连接池配置JedisPoolConfig config new JedisPoolConfig(); config.setMaxTotal(100); // 最大连接数 config.setMaxIdle(20); // 最大空闲连接 config.setMinIdle(5); // 最小空闲连接 JedisPool pool new JedisPool(config, localhost);4. 常见问题与解决方案4.1 缓存穿透问题现象查询不存在的数据导致每次请求都打到数据库解决方案缓存空值String value jedis.get(key); if (value null) { value db.get(key); if (value null) { jedis.setex(key, 300, ); // 缓存空值5分钟 } else { jedis.setex(key, 3600, value); } }布隆过滤器// 使用Redisson的布隆过滤器 RBloomFilterString filter redisson.getBloomFilter(userFilter); filter.tryInit(100000L, 0.01); filter.add(user1); if (!filter.contains(user2)) { return null; // 肯定不存在 }4.2 缓存雪崩问题现象大量key同时过期导致数据库瞬时压力激增解决方案差异化过期时间// 基础过期时间 随机偏移量 int expireTime 3600 new Random().nextInt(600); jedis.setex(key, expireTime, value);永不过期后台更新// 不设置过期时间 jedis.set(key, value); // 后台线程定期更新 scheduler.scheduleAtFixedRate(() - { String newValue db.get(key); jedis.set(key, newValue); }, 1, TimeUnit.HOURS);4.3 大Key问题排查诊断方法# 扫描大Key redis-cli --bigkeys # 查看内存详情 redis-cli memory usage keyname优化方案拆分大KeyHash拆分为多个小HashList/Set/ZSet分片存储使用SCAN替代KEYSString cursor 0; do { ScanResultString result jedis.scan(cursor); cursor result.getCursor(); // 处理结果 } while (!cursor.equals(0));5. Redis 在 Java 生态中的集成5.1 客户端选型比较客户端特点适用场景Jedis简单直接同步阻塞简单应用快速原型Lettuce异步非阻塞Netty实现高并发响应式应用Redisson分布式特性丰富封装完善分布式系统Spring Data与Spring生态集成RepositorySpring应用5.2 Spring Boot 集成示例配置类Configuration public class RedisConfig { Bean public RedisTemplateString, Object redisTemplate(RedisConnectionFactory factory) { RedisTemplateString, Object template new RedisTemplate(); template.setConnectionFactory(factory); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return template; } }使用示例RestController public class UserController { Autowired private RedisTemplateString, User redisTemplate; GetMapping(/user/{id}) public User getUser(PathVariable String id) { ValueOperationsString, User ops redisTemplate.opsForValue(); User user ops.get(user: id); if (user null) { user userRepository.findById(id).orElseThrow(); ops.set(user: id, user, 1, TimeUnit.HOURS); } return user; } }5.3 高级特性使用发布订阅// 发布消息 jedis.publish(channel, message); // 订阅频道 new Thread(() - { jedis.subscribe(new JedisPubSub() { Override public void onMessage(String channel, String message) { // 处理消息 } }, channel); }).start();事务处理Transaction t jedis.multi(); try { t.set(key1, value1); t.incr(counter); t.exec(); } catch (Exception e) { t.discard(); }Lua脚本执行String script return redis.call(GET, KEYS[1]); Object result jedis.eval(script, 1, key1);在实际项目中Redis 的性能表现往往取决于数据结构的选择和使用方式。经过多年的实践我发现合理使用 Hash 结构替代 String 存储对象、利用 ZSet 实现复杂排行榜、避免大 Key 等问题可以显著提升系统性能。
企业数字化 ERP 产品动态
相关推荐
SAP EWM110定制主线:部署集成、策略配置与易漏点 简介:SAP EWM110基础定制参与者手册(课程版本17)面向SAP EWM顾问、仓库信息化实施人员及供应链系统学习者,围绕扩展仓库管理系统的基础配置与业务落地,帮助读者建立从系统环境搭建到仓内作业优化的配置框架。压缩包内为… · 2026/11/3 8:24:07
电力系统虚假数据注入攻击原理与防御实践 1. 电力系统安全防线的新威胁:虚假数据注入攻击去年某区域电网调度中心发生了一起诡异事件——状态估计系统持续显示线路负荷正常,实际却发生了多台变压器过载跳闸。事后溯源发现,攻击者通过入侵量测终端,向SCADA系统注入了精心构… · 2026/11/3 8:24:07
智慧交通边缘计算架构设计与优化实践 1. 项目背景与挑战城市交通监控系统正在经历一场数据革命。去年我在参与某特大城市智慧交通升级项目时,首次接触到规模达到数十万级交互点的监控网络。这个数字意味着什么?相当于要在全市2000多个路口部署感知设备,每个路口平均需要处理150个… · 2026/11/3 8:24:07
网络安全-Javascript基础 网络安全-Javascript基础一般简称JS,然后用于嵌套在网页中,给网页添加动态效果用的node凭条,开发服务器也是用js
后期会用到recat、vue框架。常见的前端
HTML(结构层) 利用语言去搭建网页
CSS(样式层)利用样式美化网页… · 2026/11/3 19:27:23
别再复制粘贴代码了!Python 函数从封装到递归、lambda,老哥一次讲透 写程序最忌讳的就是复制粘贴—— 同一段代码贴三遍,改起来要改三处,累不说还容易漏。Python 给出的答案是函数:把一段会重复用的代码 "封装" 起来,起个名字,想用就调用。一、为什么用函数print() 其实就是个… · 2026/11/3 19:27:23
AdMergeX 获信通院多项认可,市场部负责人受聘铸基计划技术专家 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 19:27:23
客户复购预测真的值得做吗?从业务目标、方案取舍到上线验收 上一篇《从一家小店看懂数仓与机器学习:先理业务,再串技术》,沿着小林的店,把交易、客户状态、数仓与预测连接了起来。
接下来还有一组更难的问题:这件事值得投入吗?普通规则是否已经够用?模型… · 2026/11/3 19:27:23
什么是Unlimited-OCR-2?OCR-3.0时代百度无限文档解析模型完整指南 人工智能计算机视觉OCR多模态大模型 【免费下载链接】Unlimited-OCR-2 项目地址: https://ai.gitcode.com/hf_mirrors/baidu/Unlimited-OCR-2 点击查看 免费下载 Unlimited-OCR-2 是百度开源的超长文档解析模型(OCR 模型),主打&q… · 2026/11/3 19:26:23
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46
STM32F411RE与MAX14431实现SPI隔离:工业现场抗共模干扰实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
ESP32+大模型AI硬件开发:从Demo到产品的8个工程问题 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
基于MAX14431BAEE+与PIC18F85J10的SPI隔离方案设计与实践 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46