京东自营 618 + 国补 iPhone 历史最低价          领 618 红包,最高25618元

Redis 缓存设计+高并发实战

为啥Redis是DBA的“新宠”?

你肯定听过这句话:“缓存用得好,升职加薪早”。作为DBA,MySQL、Oracle玩得溜,但Redis才是高并发场景下的“扛把子”。

举个 :

假设你的服务器每秒要处理10万次请求,MySQL扛不住怎么办?这时候Redis的内存读写能力(每秒读10万次、写8万次)就能救命!它能像“闪电侠”一样,把热点数据存在内存里,让用户秒开页面,数据库压力瞬间减半。

#一、Redis入门:5分钟搞定安装+基础命令

1. 安装Redis(Aimalinux版)

用你擅长的Shell脚本,一条命令搞定:

# 下载+编译安装 wget http://download.redis.io/releases/redis-7.0.0.tar.gz tar xzf redis-7.0.0.tar.gz cdredis-7.0.0 make && make install # 启动Redis服务(后台运行) nohupsrc/redis-server &

Tips:Redis默认端口6379,记得开防火墙哦!

2. 必会的5个Redis命令

连上Redis客户端(redis-cli),试试这些命令:

小白提问:Redis和MySQL有啥区别?

答案:MySQL数据存硬盘,Redis存内存,速度差100倍!

#二、缓存设计实战:3种模式避坑指南

场景1:缓存穿透(查不存在的数据)

问题:黑客疯狂查不存在的ID,导致数据库被打爆。

解决:用空值缓存或布隆过滤器拦截。

// Java代码示例:查不到时缓存空值 publicStringgetProduct(String id){ Stringkey="product:"+ id; Stringvalue=redis.get(key); if(value ==null) { value = db.query("SELECT * FROM product WHERE id=?", id); if(value ==null) { redis.setex(key,300,"");// 空值缓存5分钟 }else{ redis.setex(key,3600, value);// 正常数据缓存1小时 } } returnvalue; }

(代码参考:缓存空值防止穿透)

场景2:缓存雪崩(大量缓存同时过期)

解决:随机过期时间,比如300秒±60秒随机。

# Shell脚本批量设置随机过期时间 foriin{1..1000};do redis-cli SET"key_$i""value"EX $((300+ RANDOM `)) done

场景3:热点Key扛不住(比如爆款商品)

解决:本地缓存+Redis多副本。比如用Java的Guava Cache:

LoadingCache<String, String> localCache = CacheBuilder.newBuilder() .maximumSize(1000) .expireAfterWrite(10, TimeUnit.SECONDS) .build(key -> redis.get(key));// 本地缓存10秒

Redis核心玩法:5种数据结构+Java实战

“别光会set/get!Redis数据结构才是精髓!”

Redis不是简单的Key-Value存储,它支持5种数据结构,DBA必须玩明白:

  1. String(字符串)

    :存数字、JSON、甚至图片二进制

// Java代码:用Jedis操作String Jedisjedis=newJedis("localhost"); jedis.set("user:1001","{'name':'老王','age':28}");// 存用户信息 Stringuser=jedis.get("user:1001");// 0.1毫秒读取!
  1. Hash(哈希表)

    :存对象属性,避免多次查询

// 存商品详情 Map<String, String> product =newHashMap<>(); product.put("price","99.99"); product.put("stock","1000"); jedis.hset("product:888", product);
  1. List(列表)

    :实现消息队列、最新订单

// 模拟订单队列 jedis.lpush("order:queue","order1001","order1002"); StringlatestOrder=jedis.rpop("order:queue");// 从右边弹出
  1. Set(集合)

    :去重+交集运算,搞UV统计

#Shell脚本:统计当日活跃用户 redis-cli SADD active_users:20240507 "user1001" "user1002" redis-cli SCARD active_users:20240507 # 直接拿到总数!
  1. ZSet(有序集合)

    :排行榜神器

// 游戏玩家积分排行 jedis.zadd("game_rank",5000,"player1"); jedis.zadd("game_rank",8000,"player2"); Set<String> top3 = jedis.zrevrange("game_rank",0,2);// 前三名秒出!

#三、Java+Redis高并发实战:分布式锁+秒杀

1. 分布式锁(防止超卖)

用Redis的SETNX命令实现锁:

// 加锁 publicbooleanlock(String key, String value,intexpireTime){ Stringresult=jedis.set(key, value,"NX","EX", expireTime); return"OK".equals(result); } // 解锁(Lua脚本保证原子性) Stringscript="if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; jedis.eval(script, Collections.singletonList(key), Collections.singletonList(value));

注意:锁的value用UUID,防止误删其他线程的锁。

2. 秒杀系统设计

步骤

  1. 库存预热:提前把库存扣减到Redis。

SET stock:1001 1000
  1. 用户抢购时,用Lua脚本原子性扣减库存:

-- Lua脚本(保证原子性) localstock =tonumber(redis.call('GET', KEYS[1])) ifstock >0then redis.call('DECR', KEYS[1]) return1-- 成功 else return0-- 失败 end

#四、Redis集群搭建:主从+哨兵+Cluster

1. 主从复制(一主二从)

配置文件redis.conf

# 主节点 bind0.0.0.0 port 6379 # 从节点配置 replicaof 主节点IP 6379

启动后,主节点写数据,从节点自动同步。

2. 哨兵模式(自动故障转移)

哨兵配置文件sentinel.conf

sentinel monitor mymaster 主节点IP 6379 2 sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 60000

效果:主节点挂了,哨兵自动选新主,业务无感知。

3. Cluster集群(分片存储)

启动6个节点(3主3从),用命令创建集群:

redis-cli --cluster create 节点1IP:端口 节点2IP:端口 ... --cluster-replicas 1

数据自动分片到不同节点,支持横向扩展。

#五、运维必备:备份+监控+调优

1. 数据持久化

  • ?RDB快照

    :定时全量备份,适合灾难恢复。

  • ?AOF日志

    :记录每条写命令,数据更安全。

配置redis.conf

save 900 1 # 15分钟内有1次写操作就备份 appendonlyyes# 开启AOF

2. 性能监控

redis-cli info查看关键指标:

redis-cli info stats | grep instantaneous_ops_per_sec # 每秒操作数 redis-cli info memory | grep used_memory_human # 内存使用量

3. 连接池优化(Java版)

JedisPoolConfigconfig=newJedisPoolConfig(); config.setMaxTotal(100); // 最大连接数 config.setMaxIdle(20); // 最大空闲连接 JedisPoolpool=newJedisPool(config,"redis-host",6379);
展开阅读全文

本文系作者在时代Java发表,未经许可,不得转载。

如有侵权,请联系nowjava@qq.com删除。

编辑于

关注时代Java

关注时代Java