"王工,首页加载又超时了!"测试小张急匆匆地跑过来,"特别是秒杀活动开始后,整个系统几乎瘫痪..."
作为项目负责人的你很清楚,这已经是本周第三次因为高并发导致MySQL数据库扛不住压力了,你想起上周技术分享会上,隔壁团队提到他们用Redis解决了类似问题,但Redis到底该怎么配置?如何优雅地集成到现有项目中?我们就来彻底解决这些问题。
Redis的安装其实很简单,但很多人在第一步就踩坑,以Linux系统为例,正确的姿势应该是:
# 下载最新稳定版(2025年7月最新为7.2.5) wget https://download.redis.io/releases/redis-7.2.5.tar.gz tar xzf redis-7.2.5.tar.gz cd redis-7.2.5 make
安装完成后,别急着启动,先看看redis.conf
这个核心配置文件里有哪些关键项需要调整:
# 绑定IP,生产环境不要用0.0.0.0! bind 127.0.0.1 # 保护模式,生产环境必须开启 protected-mode yes # 端口号,建议改掉默认的6379 port 6380 # 最大内存限制,根据服务器内存设置 maxmemory 4gb # 内存淘汰策略 maxmemory-policy volatile-lru # 持久化设置 appendonly yes appendfsync everysec
很多开发者会忽略Redis的安全配置,直到被黑客入侵才后悔莫及,以下配置必须检查:
# 一定要设置密码 requirepass YourStrongPasswordHere # 重命名危险命令 rename-command FLUSHALL "" rename-command CONFIG "" # 限制最大客户端连接数 maxclients 10000
现在主流的Java项目大多使用Spring Boot,集成Redis非常简单,首先在pom.xml
中添加依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
然后在application.yml
中配置Redis连接:
spring: redis: host: 127.0.0.1 port: 6380 password: YourStrongPasswordHere database: 0 lettuce: pool: max-active: 20 max-idle: 10 min-idle: 5
直接使用RedisTemplate虽然方便,但不够优雅,我推荐封装一个工具类:
@Component public class RedisUtil { @Autowired private RedisTemplate<String, Object> redisTemplate; // 设置缓存 public boolean set(String key, Object value, long time) { try { if (time > 0) { redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); } else { redisTemplate.opsForValue().set(key, value); } return true; } catch (Exception e) { e.printStackTrace(); return false; } } // 获取缓存 public Object get(String key) { return key == null ? null : redisTemplate.opsForValue().get(key); } // 分布式锁实现 public boolean lock(String key, String value, long expireTime) { Boolean result = redisTemplate.opsForValue().setIfAbsent(key, value, expireTime, TimeUnit.SECONDS); return Boolean.TRUE.equals(result); } }
缓存穿透解决方案:布隆过滤器+空值缓存
public Object getProductById(Long id) { // 1. 先查布隆过滤器 if (!bloomFilter.mightContain(id)) { return null; } // 2. 查缓存 Object value = redisUtil.get("product:" + id); if (value != null) { return "".equals(value) ? null : value; // 空值处理 } // 3. 查数据库 Product product = productMapper.selectById(id); if (product == null) { // 缓存空值防止穿透 redisUtil.set("product:" + id, "", 300); return null; } // 4. 写入缓存 redisUtil.set("product:" + id, product, 3600); return product; }
缓存击穿解决方案:互斥锁
public Object getHotProduct(Long id) { Object value = redisUtil.get("hot_product:" + id); if (value != null) { return value; } // 获取分布式锁 String lockKey = "lock:product:" + id; String lockValue = UUID.randomUUID().toString(); try { if (redisUtil.lock(lockKey, lockValue, 10)) { // 二次检查 value = redisUtil.get("hot_product:" + id); if (value != null) { return value; } // 查数据库 Product product = productMapper.selectById(id); // 写入缓存 redisUtil.set("hot_product:" + id, product, 3600); return product; } else { // 没拿到锁,稍后重试 Thread.sleep(100); return getHotProduct(id); } } finally { // 释放锁 redisUtil.unlock(lockKey, lockValue); } }
Redis是秒杀系统的核心组件,这里展示一个简化版的秒杀实现:
public boolean seckill(Long productId, Long userId) { // 1. 校验库存 String stockKey = "seckill:stock:" + productId; Long stock = redisTemplate.opsForValue().decrement(stockKey); if (stock < 0) { // 库存不足,回滚 redisTemplate.opsForValue().increment(stockKey); return false; } // 2. 防止重复购买 String userKey = "seckill:user:" + productId; if (redisTemplate.opsForSet().isMember(userKey, userId.toString())) { // 已购买过,回滚库存 redisTemplate.opsForValue().increment(stockKey); return false; } // 3. 记录购买用户 redisTemplate.opsForSet().add(userKey, userId.toString()); // 4. 发送MQ消息进行异步下单 sendOrderMessage(productId, userId); return true; }
使用Hash结构存储对象时,如果字段较多,考虑使用ziplist编码:
hash-max-ziplist-entries 512 hash-max-ziplist-value 64
对于大量小字符串,启用内存压缩:
list-compress-depth 1 set-max-intset-entries 512
根据业务需求选择合适的持久化策略:
RDB:适合大规模数据恢复,但可能丢失最后几分钟数据
save 900 1 # 900秒内至少1个key变化 save 300 10 # 300秒内至少10个key变化
AOF:数据更安全,但文件更大
appendonly yes appendfsync everysec # 折中方案
混合持久化(Redis 4.0+推荐):
aof-use-rdb-preamble yes
这些Redis指标必须纳入监控系统:
used_memory
/ maxmemory
keyspace_hits
/ (keyspace_hits
+ keyspace_misses
)connected_clients
aof_delayed_fsync
used_cpu_sys
+ used_cpu_user
问题1:Redis突然变慢
检查步骤:
SLOWLOG GET 10
查看慢查询redis-cli --latency
查看网络延迟INFO commandstats
查看命令统计问题2:内存持续增长
解决方案:
redis-cli --bigkeys
volatile-lru
INFO memory
回到开头的场景,通过合理配置Redis并将其集成到电商项目中,王工团队成功将首页响应时间从原来的2秒降低到200毫秒,秒杀活动的并发处理能力提升了20倍,Redis不是简单的键值存储,而是需要精心调教的高性能工具,从配置文件的每一个参数,到项目中的每一次调用,都值得我们认真对待。
最后的小建议:定期review你的Redis配置,随着业务增长,去年合适的配置今年可能就成瓶颈了,保持学习,持续优化,这才是工程师的成长之道。
本文由 刘又莲 于2025-07-30发表在【云服务器提供商】,文中图片由(刘又莲)上传,本平台仅提供信息存储服务;作者观点、意见不代表本站立场,如有侵权,请联系我们删除;若有图片侵权,请您准备原始证明材料和公证书后联系我方删除!
本文链接:https://vps.7tqx.com/wenda/482480.html
发表评论