尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Redis从入门到实战:核心数据结构、缓存策略与高并发解决方案

Redis从入门到实战:核心数据结构、缓存策略与高并发解决方案 1. 从“慢查询”到“快如闪电”为什么你的Web项目需要Redis如果你刚开始接触Web开发可能还在和MySQL、PostgreSQL这类关系型数据库打交道写写SQL做做增删改查。但当你第一次部署一个稍微有点人气的项目或者尝试实现一个“秒杀”功能时很可能会遇到一个让你头疼的问题数据库响应变慢了页面加载卡顿用户体验直线下降。这背后的核心原因往往不是你的SQL写得不好而是关系型数据库的“天性”使然——它的一切设计都围绕着数据的强一致性和持久化每一次查询都可能涉及磁盘I/O、复杂的锁机制和事务处理。在高并发、需要快速读写的场景下这就成了性能瓶颈。这时一个叫做Redis的工具就会频繁出现在各种解决方案和面试题里。你可能听过它被称作“缓存”、“内存数据库”或“NoSQL”。但简单来说Redis的核心价值就是把你最常访问、最需要快速响应的那部分数据从速度相对较慢的磁盘数据库里“搬到”速度极快的内存里。它像一个设在数据库前面的“超级高速缓冲区”当用户请求数据时Web应用首先向这个内存缓冲区询问如果找到了缓存命中就直接返回完全绕过后端数据库只有没找到时才去查询数据库并将结果存一份到Redis里以备下次使用。看看那些热搜词“企业级web开发”、“web安全”、“高并发”这些场景正是Redis大显身手的地方。比如电商网站的商品详情页、社交媒体的用户动态流、游戏服务器的玩家状态这些数据读远多于写且对延迟极其敏感。直接用数据库扛分分钟宕机而引入Redis性能提升往往是几个数量级的。我刚开始做Web项目时曾为一个简单的文章列表接口优化头疼不已数据库查询需要200毫秒引入Redis后同样的查询直接降到2毫秒以内这种体验的提升是颠覆性的。所以对于Web菜鸟而言学习Redis不是选修课而是迈向高性能Web开发的必修课。它解决的就是从“能用”到“好用且抗压”的关键一跃。2. Redis核心概念速览不仅仅是简单的Key-Value在深入安装和实操之前我们必须先打破一个常见的误解Redis不仅仅是一个简单的键值Key-Value缓存。如果只是存一个字符串那和用个Map没什么区别。Redis的强大在于它提供了丰富的数据结构每一种都对应着不同的应用场景这也是它区别于Memcached等纯缓存系统的关键。2.1 五大核心数据结构与应用场景String字符串最基础的类型可以存文本、数字甚至二进制数据。除了基本的SET/GET它支持原子性的增减操作INCR/DECR这使其成为计数器的绝佳选择比如文章阅读量、用户点赞数。设置过期时间SETEX又能轻松实现验证码过期、会话管理等功能。# 示例记录文章阅读量 SET article:1001:views 0 INCR article:1001:views # 原子性增加完全避免并发问题 GET article:1001:viewsHash哈希表类似于编程语言中的Map适合存储一个对象的多个字段。比如存储用户信息user:1001其内部包含name、age、email等字段。相较于将整个用户对象序列化成JSON字符串存为String使用Hash可以独立存取、更新单个字段更节省网络开销和内存。# 示例存储用户信息 HSET user:1001 name 张三 age 28 email zhangsanexample.com HGET user:1001 name # 只获取名字无需传输整个对象 HINCRBY user:1001 age 1 # 只更新年龄字段List列表一个双向链表支持从头部或尾部插入/弹出元素。这天然契合消息队列、最新列表如朋友圈动态、最新评论的场景。LPUSH左边插入和LRANGE范围查询的组合能轻松实现一个“时间线”。# 示例实现一个简单的消息队列 LPUSH task_queue task1 # 生产者发布任务 RPOP task_queue # 消费者获取并移除任务 # 示例存储最新10条微博ID LPUSH user:1001:feeds 12345 12346 12347 LRANGE user:1001:feeds 0 9 # 获取最新的10条Set集合无序且元素唯一的集合。核心操作是求交集、并集、差集。这使其成为实现共同关注、标签系统、抽奖去重的利器。# 示例求共同好友 SADD user:A:friends B C D SADD user:B:friends C D E SINTER user:A:friends user:B:friends # 结果: C, DSorted Set有序集合在Set的基础上为每个元素关联一个分数score并据此排序。这是实现排行榜如游戏积分榜、热搜榜的终极数据结构。ZADD添加元素ZREVRANGE获取排名。# 示例游戏积分排行榜 ZADD leaderboard 2500 PlayerA 1800 PlayerB 3000 PlayerC ZREVRANGE leaderboard 0 2 WITHSCORES # 获取前三名理解这些数据结构你才能在设计缓存方案时“对症下药”而不是把所有数据都无脑转成JSON字符串塞进去。比如要缓存一篇博客文章文章本身标题、内容可以用String或Hash文章的标签集合用Set文章的评论ID列表用List而全站的热门文章排行榜则用Sorted Set。这种精细化的设计是高效使用Redis的第一步。2.2 持久化内存数据如何“落地”既然Redis数据主要存在内存服务器重启或断电岂不是全丢了这就是持久化要解决的问题。Redis提供了两种主要策略RDBRedis Database在指定的时间间隔内生成内存数据的快照Snapshot文件.rdb。这是一个紧凑的二进制文件非常适合用于备份和灾难恢复。恢复大数据集时速度比AOF快。但缺点是可能会丢失最后一次快照之后的所有数据比如5分钟备份一次那么在故障前的4分59秒内的数据会丢失。AOFAppend Only File记录每一次写操作命令以日志的形式追加到文件末尾。Redis重启时会重新执行AOF文件中的所有命令来重建数据。数据安全性更高默认配置下每秒同步一次最多丢失1秒数据。但AOF文件通常比RDB文件大且恢复速度慢。生产环境通常两者结合使用用AOF保证数据安全用RDB做冷备和快速恢复。在redis.conf配置文件中你可以灵活配置# RDB配置900秒内至少1个key变化则触发保存 save 900 1 save 300 10 save 60 10000 # AOF配置开启AOF并设置同步策略为每秒 appendonly yes appendfsync everysec对于新手项目可以先使用默认的RDB方式对数据可靠性要求高的场景再启用AOF。3. 手把手搭建Redis环境从安装到跑通第一个Demo理论懂了接下来就是实战。我们以最常用的Linux环境如CentOS/Ubuntu为例演示从零安装和配置Redis。Windows用户可以考虑使用WSL2或直接下载微软维护的Windows版本但生产环境强烈推荐Linux。3.1 编译安装与基础配置首先通过包管理器安装是最快的方式以Ubuntu为例sudo apt update sudo apt install redis-server -y安装完成后Redis服务会自动启动。你可以通过以下命令检查状态sudo systemctl status redis-server如果想使用最新版本或进行自定义编译也可以从官网下载源码编译安装wget https://download.redis.io/redis-stable.tar.gz tar -xzvf redis-stable.tar.gz cd redis-stable make # 编译 sudo make install # 安装到系统目录安装后关键的配置文件是redis.conf通常位于/etc/redis/或源码目录下。我们先做几个基础的安全和性能配置绑定IP与保护模式默认Redis监听127.0.0.1本地外部无法访问。如果其他服务器需要连接需修改bind配置但务必设置密码并谨慎开放端口。# 在redis.conf中 # bind 127.0.0.1 ::1 # 注释掉这行或改为 bind 0.0.0.0 (允许所有IP危险生产环境建议绑定具体IP) protected-mode no # 如果bind注释了保护模式要设为no但必须设密码设置访问密码这是必须的在配置文件中找到并取消注释requirepass行requirepass YourStrongPassword123!以守护进程运行确保daemonize设置为yes让Redis在后台运行。daemonize yes修改完配置后重启服务使配置生效sudo systemctl restart redis-server # 或如果编译安装指定配置文件启动 redis-server /path/to/your/redis.conf3.2 客户端连接与基本操作服务跑起来后我们可以用Redis自带的命令行客户端redis-cli进行连接和测试。# 连接本地Redis redis-cli # 如果设置了密码连接后需要认证 AUTH YourStrongPassword123! # 测试连接 PING # 服务器应返回 PONG # 开始我们的数据结构之旅 # 1. String - 计数器 SET page:home:visits 0 INCR page:home:visits GET page:home:visits # 2. Hash - 用户对象 HSET user:1001 username zhangsan score 100 HGETALL user:1001 HINCRBY user:1001 score 20 # 3. List - 消息队列 LPUSH my:task:queue send_email_1 process_image_2 RPOP my:task:queue # 4. Set - 标签系统 SADD article:500:tags tech database redis SMEMBERS article:500:tags # 5. Sorted Set - 排行榜 ZADD game:leaderboard 150 Alice 220 Bob 190 Charlie ZREVRANGE game:leaderboard 0 2 WITHSCORES通过这些命令你可以直观地感受每种数据结构的用法。记住Redis命令是原子性的这在并发环境下至关重要。3.3 可视化工具推荐对于新手命令行可能不够直观。一些图形化管理工具能极大提升效率RedisInsightRedis官方推出的免费可视化工具功能强大支持监控、命令行操作、内存分析等跨平台。这是目前最推荐的选择。Another Redis Desktop Manager一个开源、跨平台的桌面客户端界面简洁响应快速。phpRedisAdmin如果你熟悉PHP环境可以部署一个网页版的管理工具。使用这些工具你可以像操作传统数据库一样浏览键值、查看内存占用、执行命令对学习和调试非常有帮助。4. 在Web项目中集成Redis以Java Spring Boot为例知道了Redis怎么用下一步就是把它集成到你的Web项目中。这里以最流行的Java Spring Boot框架为例演示如何将Redis作为缓存和会话存储集成进来。其他语言Python/Django/Flask, Node.js, Go等的客户端库也很成熟集成思路大同小异。4.1 项目依赖与基础配置首先在一个Spring Boot项目中添加Spring Data Redis的起步依赖。如果你使用Maven在pom.xml中加入dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-redis/artifactId /dependency !-- 连接池推荐使用Lettuce默认或Jedis -- dependency groupIdio.lettuce/groupId artifactIdlettuce-core/artifactId /dependency然后在application.yml或application.properties中配置Redis连接信息spring: redis: host: localhost # Redis服务器地址 port: 6379 # 端口 password: YourStrongPassword123! # 密码如果没有则省略 database: 0 # 默认数据库索引0-15 lettuce: pool: max-active: 8 # 连接池最大连接数 max-idle: 8 # 最大空闲连接 min-idle: 0 # 最小空闲连接这样Spring Boot就会自动配置一个RedisTemplate和StringRedisTemplateBean供你使用。4.2 使用RedisTemplate进行数据操作RedisTemplate是Spring操作Redis的核心类它提供了高度封装的API。但直接使用它时需要注意序列化器。默认的JDK序列化器会产生二进制值在redis-cli中不易读。通常我们会配置为StringRedisSerializer键和Jackson2JsonRedisSerializer值。Configuration public class RedisConfig { Bean public RedisTemplateString, Object redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplateString, Object template new RedisTemplate(); template.setConnectionFactory(connectionFactory); // 设置key的序列化器 template.setKeySerializer(new StringRedisSerializer()); // 设置value的序列化器为JSON Jackson2JsonRedisSerializerObject serializer new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.activateDefaultTyping(om.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL); serializer.setObjectMapper(om); template.setValueSerializer(serializer); // 设置hash key和value的序列化器 template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(serializer); template.afterPropertiesSet(); return template; } }配置好后就可以在Service中注入使用了Service public class UserService { Autowired private RedisTemplateString, Object redisTemplate; public User getUserById(Long id) { String key user: id; // 1. 先查缓存 User user (User) redisTemplate.opsForValue().get(key); if (user ! null) { System.out.println(从缓存获取用户: id); return user; } // 2. 缓存没有查数据库 System.out.println(缓存未命中查询数据库: id); user userRepository.findById(id).orElse(null); // 假设从JPA查询 if (user ! null) { // 3. 写入缓存并设置30分钟过期 redisTemplate.opsForValue().set(key, user, 30, TimeUnit.MINUTES); } return user; } public void updateUser(User user) { // 更新数据库 userRepository.save(user); // 删除缓存保证下次读取时获取最新数据缓存失效模式 String key user: user.getId(); redisTemplate.delete(key); } }这是一个最经典的“缓存-数据库”读写模式Cache-Aside Pattern。读请求先读缓存命中则返回未命中则读数据库并回写缓存。写请求则直接更新数据库并删除对应的缓存数据而不是更新它以避免复杂的并发更新问题。4.3 使用Spring Cache注解简化缓存逻辑Spring提供了更优雅的声明式缓存抽象Cacheable、CacheEvict等可以极大简化代码。 首先在主类上启用缓存EnableCaching。 然后在方法上使用注解Service public class ProductService { Cacheable(value product, key #id) // 缓存名为product键为id public Product getProductById(Long id) { System.out.println(查询数据库获取产品: id); // 模拟数据库查询 return productRepository.findById(id).orElse(null); } CacheEvict(value product, key #product.id) // 更新或删除时清除缓存 public void updateProduct(Product product) { productRepository.save(product); } CachePut(value product, key #product.id) // 方法总被执行结果放入缓存用于更新缓存 public Product saveProduct(Product product) { return productRepository.save(product); } }你需要配置一个CacheManager来告诉Spring使用Redis作为缓存后端。在之前的RedisConfig中补充Bean public CacheManager cacheManager(RedisConnectionFactory connectionFactory) { RedisCacheConfiguration config RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofMinutes(30)) // 默认过期时间30分钟 .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())) .disableCachingNullValues(); // 不缓存null值 return RedisCacheManager.builder(connectionFactory) .cacheDefaults(config) .build(); }这样所有缓存操作如Cacheable都会自动使用Redis存储代码变得非常简洁。在Redis中你会看到以product::1001为键的缓存数据。5. 实战避坑指南缓存穿透、击穿、雪崩与数据一致性集成Redis后性能飞升但新的挑战也随之而来。如果不注意可能会引入比数据库慢查询更严重的问题。下面是我在项目中真实踩过的坑和解决方案。5.1 缓存穿透查询不存在的数据问题恶意请求或异常流量频繁查询一个数据库中根本不存在的数据如id-1。由于数据不存在缓存永远不会被写入导致每次请求都穿透到数据库给数据库造成巨大压力。解决方案缓存空对象即使数据库查不到也在缓存中设置一个空值或特殊标记并设置一个较短的过期时间如30秒。这样后续短时间内的相同请求会命中缓存直接返回空。public User getUserById(Long id) { String key user: id; User user (User) redisTemplate.opsForValue().get(key); if (user ! null) { // 注意需要判断是否是空对象标记 if (user.getId() null) { // 假设用一个特殊User对象标记空 return null; // 直接返回空不查DB } return user; } user userRepository.findById(id).orElse(null); if (user null) { // 缓存空对象过期时间短一些 User nullUser new User(); // 一个特殊的空对象 redisTemplate.opsForValue().set(key, nullUser, 30, TimeUnit.SECONDS); return null; } else { redisTemplate.opsForValue().set(key, user, 30, TimeUnit.MINUTES); } return user; }布隆过滤器Bloom Filter在查询缓存前先用一个布隆过滤器判断该key是否存在。布隆过滤器是一个概率型数据结构能告诉你“某个元素一定不存在”或“可能存在”。将所有可能存在的key如所有有效的用户ID预先加载到布隆过滤器中。请求来时先用过滤器判断如果判断为“不存在”则直接返回不再查询缓存和数据库。这种方式内存占用极小但有一定误判率判断为“存在”的元素可能实际不存在但不会漏判。5.2 缓存击穿热点key过期问题某个热点key如爆款商品信息在缓存过期的瞬间有大量并发请求同时到来。此时缓存失效所有请求同时穿透到数据库导致数据库瞬时压力激增。解决方案永不过期 逻辑过期不给热点key设置物理过期时间而是设置一个逻辑过期时间字段存储在value中。当发现数据逻辑过期时程序异步发起一个线程去更新缓存其他请求仍然返回旧的缓存数据。这避免了大量请求同时等待缓存重建。互斥锁Mutex Lock在缓存失效后第一个发现缓存失效的线程去获取一个分布式锁可以用Redis的SETNX命令实现获取锁的线程负责查询数据库并重建缓存其他线程等待锁释放后重新读取缓存。这保证了只有一个线程去查数据库。public User getUserByIdWithLock(Long id) { String cacheKey user: id; String lockKey lock:user: id; User user (User) redisTemplate.opsForValue().get(cacheKey); if (user ! null) { return user; } // 尝试获取分布式锁 Boolean locked redisTemplate.opsForValue().setIfAbsent(lockKey, 1, 10, TimeUnit.SECONDS); if (locked ! null locked) { try { // 双重检查防止其他线程已经更新了缓存 user (User) redisTemplate.opsForValue().get(cacheKey); if (user ! null) { return user; } // 查数据库 user userRepository.findById(id).orElse(null); if (user ! null) { redisTemplate.opsForValue().set(cacheKey, user, 30, TimeUnit.MINUTES); } else { // 缓存空对象防穿透 redisTemplate.opsForValue().set(cacheKey, new NullUser(), 30, TimeUnit.SECONDS); } } finally { // 释放锁 redisTemplate.delete(lockKey); } } else { // 未获取到锁等待一小段时间后重试 try { Thread.sleep(50); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return getUserByIdWithLock(id); // 递归重试注意控制深度 } return user; }5.3 缓存雪崩大量key同时过期问题在某个时间点缓存中大量key集中过期导致所有对这些数据的请求同时穿透到数据库数据库压力瞬间过大甚至宕机。解决方案差异化过期时间这是最简单有效的方法。在设置缓存过期时间时不要全部设置成一样的值比如都30分钟而是加上一个随机值让过期时间分散开。// 基础过期时间 随机偏移量如0-300秒 int expireTime 30 * 60 new Random().nextInt(300); redisTemplate.opsForValue().set(key, value, expireTime, TimeUnit.SECONDS);热点数据永不过期同缓存击穿的解决方案对核心热点数据不设置过期时间通过后台任务或逻辑过期来更新。服务降级与熔断当检测到数据库压力过大或大量缓存失效时通过熔断器如Hystrix、Resilience4j暂时“熔断”对数据库的访问直接返回降级内容如默认值、友好提示保护数据库。5.4 缓存与数据库的数据一致性这是最复杂的问题。当你更新了数据库如何保证缓存里的数据也是最新的前面我们采用了“先更新数据库再删除缓存”的策略Cache-Aside Pattern中的写策略这能解决大部分问题但在极端高并发下仍可能出问题如A线程读旧缓存B线程更新数据库并删缓存A线程再将旧数据写入缓存。更严谨的方案有延迟双删更新数据库后先删一次缓存然后延迟几百毫秒再删一次以清理可能在此期间被其他线程写入的脏数据。基于消息队列的最终一致性将更新数据库和删除缓存的操作放到一个本地事务中然后发送一个删除缓存的消息到消息队列如RabbitMQ、Kafka由一个专门的消费者来异步执行缓存删除。这保证了最终一致性对业务代码侵入小。订阅数据库变更日志如MySQL Binlog使用Canal、Debezium等工具监听数据库的变更一旦有数据更新自动触发缓存删除或更新。这是解耦最彻底、可靠性很高的方案但架构复杂。对于大多数初创项目或中小型应用采用“更新数据库后删除缓存”并结合合理的重试机制如删除失败后记录日志定时任务重试已经足够应对。不要过早追求完美的强一致性那会带来巨大的复杂度。6. 性能调优与监控让Redis真正“高性能”要让Redis稳定高效地运行除了正确使用还需要关注一些运维层面的调优和监控点。6.1 内存管理与淘汰策略Redis是内存数据库内存是核心资源。当内存用满时Redis会根据配置的maxmemory-policy进行数据淘汰。你需要根据业务特点选择合适的策略volatile-lru从已设置过期时间的键中移除最近最少使用的LRU。allkeys-lru从所有键中移除最近最少使用的。这是最常用的策略。volatile-ttl从已设置过期时间的键中移除即将过期的。noeviction不淘汰新写入操作会报错。生产环境慎用。在redis.conf中配置maxmemory 2gb # 根据你的服务器内存设置建议留出部分内存给系统 maxmemory-policy allkeys-lru同时可以使用INFO memory命令监控内存使用情况关注used_memory_human和maxmemory。6.2 持久化配置权衡如前所述RDB和AOF各有优劣。生产环境建议同时开启。save 900 1 save 300 10 save 60 10000 appendonly yes appendfsync everysec # 在性能和数据安全间取得平衡 auto-aof-rewrite-percentage 100 # AOF文件增长比例超过100%时重写 auto-aof-rewrite-min-size 64mb # AOF文件最小重写大小这样既利用了RDB快速恢复和紧凑备份的优点又通过AOF保证了数据安全。记得定期将RDB文件备份到异地。6.3 连接池与网络优化确保客户端使用了连接池如Spring Boot默认的Lettuce或Jedis Pool并合理配置参数避免频繁创建和销毁连接的开销。在application.yml中我们已经配置了Lettuce连接池。 对于网络延迟敏感的应用可以考虑将Redis部署在和应用服务器同一个可用区AZ甚至同一台物理机通过Unix Socket连接但牺牲了灵活性。6.4 监控与慢查询日志没有监控的系统就是“盲人骑瞎马”。Redis提供了INFO命令可以查看几乎所有运行状态。更推荐使用redis-cli --stat获取实时统计信息或通过MONITOR命令谨慎使用影响性能查看所有命令。 启用慢查询日志可以帮助你发现潜在的性能问题# 在redis.conf中 slowlog-log-slower-than 10000 # 执行时间超过10毫秒的命令被记录单位微秒 slowlog-max-len 128 # 最多记录128条慢日志然后通过SLOWLOG GET命令查看慢查询。对于生产环境集成到现有的监控系统如Prometheus Grafana是更好的选择。可以使用redis_exporter将Redis指标暴露给Prometheus在Grafana上制作丰富的监控看板监控QPS、内存使用、连接数、命中率、延迟等关键指标。7. 进阶之路从单机到集群与高可用当你的业务持续增长单机Redis可能会遇到内存不足、QPS瓶颈或单点故障问题。这时就需要考虑Redis的集群和高可用方案。7.1 主从复制Replication这是最基础的高可用和数据备份方案。一个主节点Master负责写操作多个从节点Slave复制主节点的数据负责读操作。这样实现了读写分离和数据备份。 配置非常简单在从节点的redis.conf中添加一行replicaof masterip masterport # 如果主节点有密码 masterauth master-password主从复制是异步的所以从节点的数据会有轻微延迟通常毫秒级适用于对一致性要求不是绝对实时的读多写少场景。7.2 Redis Sentinel哨兵主从复制解决了数据备份和读扩展但如果主节点挂了需要手动切换从节点为主节点无法自动故障转移。Sentinel哨兵就是用来解决这个问题的。Sentinel是一个分布式系统用于监控Redis主从节点并在主节点故障时自动将一个从节点升级为主节点并让其他从节点指向新的主节点客户端也会被通知到新的连接地址。 部署至少三个Sentinel节点防止脑裂它们通过投票机制决定是否进行故障转移。对于客户端需要支持Sentinel协议或者通过一个代理来连接。7.3 Redis Cluster集群这是Redis官方提供的分布式解决方案用于解决海量数据存储和高并发写的问题。它将数据自动分片到多个节点上默认16384个槽slot每个节点负责一部分槽。客户端可以直接连接任意节点如果请求的key不在该节点上节点会返回重定向信息MOVED错误引导客户端连接到正确的节点。 Cluster模式也内置了高可用每个分片slot子集通常由一个主节点和若干个从节点组成主节点故障时从节点会自动接替。 部署Cluster至少需要6个节点3主3从。使用redis-cli --cluster create命令可以快速创建集群。redis-cli --cluster create 192.168.1.101:6379 192.168.1.102:6379 192.168.1.103:6379 \ 192.168.1.104:6379 192.168.1.105:6379 192.168.1.106:6379 \ --cluster-replicas 1对于Spring Boot项目连接Cluster只需要在配置中指定所有集群节点即可spring: redis: cluster: nodes: 192.168.1.101:6379,192.168.1.102:6379,192.168.1.103:6379,192.168.1.104:6379,192.168.1.105:6379,192.168.1.106:6379 password: YourStrongPassword123!选择哪种方案对于刚入门和中小型项目主从哨兵模式已经能很好地满足高可用需求。只有当数据量单机根本存不下或者写QPS远超单机上限时才需要考虑Cluster模式因为它带来了更高的复杂性和一些命令限制如涉及多个key的操作除非这些key在同一个slot否则无法执行。从我自己的经验来看从单机Redis到主从哨兵再到Cluster每一步的升级都需要充分的测试和预案。尤其是在切换到Cluster时一定要仔细评估现有代码中是否使用了多key操作如集合的交并差、事务、Lua脚本这些在Cluster中需要确保所有key位于同一个slot通过hash tag实现如{user1001}.order和{user1001}.profile会被分配到同一个slot。盲目升级可能会导致服务不可用。
返回列表