2026-01-28 22:40:37

一、Redis核心特性与架构1. Redis核心优势​内存存储​:数据存储在内存中,读写性能极高(10万+ QPS)​丰富数据结构​:支持String、Hash、List、Set、SortedSet等​持久化支持​:RDB快照和AOF日志两种方式​高可用​:支持主从复制、哨兵模式和集群模式​原子操作​:单线程模型保证命令原子性​发布订阅​:支持消息的发布/订阅模式​Lua脚本​:支持执行原子性Lua脚本2. Redis架构模式对比模式特点适用场景单机模式简单部署,无高可用开发测试环境主从复制读写分离,数据冗余读多写少的业务场景哨兵模式自动故障转移对可用性有要求的业务Cluster集群数据分片,水平扩展大数据量高并发场景二、Redis持久化机制1. RDB(Redis Database)​原理​:定时生成内存快照

# redis.conf配置示例

save 900 1 # 900秒内至少1个key变化

save 300 10 # 300秒内至少10个key变化

save 60 10000 # 60秒内至少10000个key变化

​优点​:

紧凑的二进制文件,恢复速度快适合灾难恢复最大化Redis性能​缺点​:

可能丢失最后一次快照后的数据大数据量时fork过程可能阻塞服务2. AOF(Append Only File)​原理​:记录所有写操作命令

# redis.conf配置示例

appendonly yes

appendfsync everysec # 每秒同步

# appendfsync always # 每个命令同步

# appendfsync no # 由操作系统决定

​优点​:

数据安全性更高(最多丢失1秒数据)AOF文件易于理解和解析后台重写不会影响客户端请求​缺点​:

文件体积通常比RDB大恢复速度比RDB慢3. 混合持久化(Redis 4.0+)

# redis.conf配置

aof-use-rdb-preamble yes

结合RDB和AOF优势,先使用RDB格式存储快照,后续增量使用AOF格式

三、Redis集群方案1. 主从复制架构

​特点​:

读写分离:主节点写,从节点读数据冗余:从节点备份数据故障需手动切换2. 哨兵模式(Sentinel)

# sentinel.conf配置示例

sentinel monitor mymaster 127.0.0.1 6379 2

sentinel down-after-milliseconds mymaster 5000

sentinel failover-timeout mymaster 60000

​功能​:

监控:持续检查主从节点状态通知:通过API发送故障警报自动故障转移:主节点故障时选举新主配置提供者:客户端查询获取当前主节点地址3. Cluster集群模式​数据分片​:

16384个哈希槽(slot)每个节点负责部分slot支持自动重分片(resharding)

# 集群节点通信端口比数据端口大10000

redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 \

127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \

--cluster-replicas 1

​优势​:

自动数据分片部分节点不可用时继续工作支持线性扩展四、Redis常见问题解决方案1. 缓存雪崩​场景​:大量key同时过期,请求直接打到数据库

​解决方案​:

// 1. 随机过期时间

jedis.setex("key", 3600 + new Random().nextInt(600), "value");

// 2. 多级缓存

// 本地缓存(Caffeine) -> Redis -> DB

LoadingCache localCache = Caffeine.newBuilder()

.maximumSize(10_000)

.expireAfterWrite(5, TimeUnit.MINUTES)

.build(key -> getFromRedisOrDB(key));

// 3. 熔断降级

CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("redis");

Supplier supplier = CircuitBreaker.decorateSupplier(circuitBreaker,

() -> getFromRedis(key));

2. 缓存穿透​场景​:大量查询不存在的数据

​解决方案​:

// 1. 布隆过滤器

BloomFilter filter = BloomFilter.create(

Funnels.stringFunnel(Charset.defaultCharset()),

1000000,

0.01);

if(!filter.mightContain(key)) {

return null;

}

// 2. 缓存空值

Object value = jedis.get(key);

if(value == null) {

jedis.setex("null_"+key, 300, "");

return null;

}

3. 缓存击穿​场景​:热点key突然失效,大量并发请求数据库

​解决方案​:

// 1. 互斥锁

String value = jedis.get(key);

if(value == null) {

if(jedis.setnx("lock_"+key, "1") == 1) {

jedis.expire("lock_"+key, 10);

try {

value = db.query(key);

jedis.setex(key, 3600, value);

} finally {

jedis.del("lock_"+key);

}

} else {

Thread.sleep(100);

return getFromCache(key);

}

}

// 2. 永不过期+后台刷新

jedis.set(key, value);

// 后台线程定期更新

scheduler.scheduleAtFixedRate(() -> {

String newValue = db.query(key);

jedis.set(key, newValue);

}, 30, 30, TimeUnit.MINUTES);

4. 数据一致性​场景​:数据库更新后缓存未同步

​解决方案​:

// 1. 双写策略

@Transactional

public void updateUser(User user) {

userDao.update(user);

redisTemplate.opsForValue().set("user:"+user.getId(), user);

}

// 2. 延迟双删

public void updateProduct(Product product) {

redisTemplate.delete("product:"+product.getId());

productDao.update(product);

executor.schedule(() -> {

redisTemplate.delete("product:"+product.getId());

}, 1, TimeUnit.SECONDS);

}

// 3. Canal监听binlog

@CanalEventListener

public class RedisUpdateListener {

@UpdateListenPoint

public void onUpdate(User user) {

redisTemplate.opsForValue().set("user:"+user.getId(), user);

}

}

5. 大Key问题​场景​:单个Key存储数据过大(>1MB)

​解决方案​:

// 1. 拆分大Key

// 原始大Hash -> 多个小Hash

Map bigMap = new HashMap<>();

for(int i=0; i part = new HashMap<>();

for(int j=0; j scanResult = jedis.scan(cursor,

new ScanParams().match("user:*").count(100));

cursor = scanResult.getCursor();

List keys = scanResult.getResult();

// 处理keys

} while(!cursor.equals("0"));

6. 热Key问题​场景​:某些Key访问量远超其他Key

​解决方案​:

// 1. 本地缓存热Key

LoadingCache localCache = Caffeine.newBuilder()

.maximumSize(1000)

.expireAfterWrite(10, TimeUnit.SECONDS)

.build(key -> jedis.get(key));

// 2. Redis集群分片+副本

// 对热Key增加副本

jedis.set("hotKey:1", value);

jedis.set("hotKey:2", value); // 相同值的副本

// 3. 使用Redis代理中间件

// 如Twemproxy或Redis Cluster自动分片

五、Redis性能优化1. 内存优化

# redis.conf关键配置

hash-max-ziplist-entries 512 # Hash元素数量≤512使用ziplist

hash-max-ziplist-value 64 # Hash元素值大小≤64字节使用ziplist

list-max-ziplist-entries 512

list-max-ziplist-value 64

set-max-intset-entries 512

zset-max-ziplist-entries 128

zset-max-ziplist-value 64

2. 网络优化

# 1. 使用pipeline批量操作

Pipeline p = jedis.pipelined();

p.set("key1", "value1");

p.set("key2", "value2");

p.sync();

# 2. 避免大Value(超过1MB)

# 3. 使用连接池

JedisPool pool = new JedisPool(new JedisPoolConfig(), "localhost");

try (Jedis jedis = pool.getResource()) {

// 操作Redis

}

3. 命令优化使用MGET/MSET替代多次GET/SET使用SCAN替代KEYS使用DEL异步删除大Key(Redis 4.0+)

redis-cli --bigkeys # 查找大Key

redis-cli --memkeys # 分析内存使用

redis-cli --latency-history # 监控延迟

六、Redis监控与运维1. 关键监控指标指标说明健康值参考used_memory已用内存< 80% maxmemorymem_fragmentation_ratio内存碎片率1.0-1.5instantaneous_ops_per_sec每秒操作数根据业务特点keyspace_hits缓存命中数越高越好keyspace_misses缓存未命中数越低越好connected_clients客户端连接数< 10000rejected_connections拒绝的连接数02. 常用运维命令

# 内存分析

redis-cli info memory

redis-cli --bigkeys

# 性能测试

redis-benchmark -t set,get -n 100000 -q

# 慢查询分析

redis-cli slowlog get 10

config set slowlog-log-slower-than 10000 # 设置慢查询阈值(微秒)

# 持久化监控

redis-cli info persistence

七、Redis应用场景示例1. 分布式锁

public boolean tryLock(String key, String value, long expireTime) {

return "OK".equals(jedis.set(key, value, "NX", "PX", expireTime));

}

public boolean unlock(String key, String value) {

String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then " +

"return redis.call('del', KEYS[1]) else return 0 end";

Object result = jedis.eval(luaScript, Collections.singletonList(key),

Collections.singletonList(value));

return result.equals(1L);

}

2. 限流器

public boolean isAllowed(String key, int max, int intervalSec) {

String luaScript = "local current = redis.call('incr', KEYS[1])\n" +

"if current == 1 then\n" +

" redis.call('expire', KEYS[1], ARGV[1])\n" +

"end\n" +

"return current <= tonumber(ARGV[2])";

Object result = jedis.eval(luaScript, Collections.singletonList(key),

Arrays.asList(String.valueOf(intervalSec),

String.valueOf(max)));

return (Long)result <= max;

}

3. 排行榜

// 添加分数

jedis.zadd("leaderboard", 100, "user1");

jedis.zadd("leaderboard", 200, "user2");

// 获取排名

Set topUsers = jedis.zrevrangeWithScores("leaderboard", 0, 9);

八、Redis版本特性Redis 6.0+​多线程I/O​:提高网络IO性能(执行命令仍单线程)​客户端缓存​:服务端辅助的客户端缓存​ACL​:更完善的访问控制​SSL​:支持加密连接Redis 7.0+​Function​:支持服务端脚本(替代部分Lua使用场景)​Multi-part AOF​:AOF文件分块存储​Sharded Pub/Sub​:分片发布订阅总结Redis作为高性能的内存数据库,在缓存、会话存储、排行榜等场景有广泛应用。合理使用Redis需要:

根据业务特点选择合适的数据结构设计合理的过期策略和缓存更新机制针对雪崩、穿透、击穿等问题实施防御措施做好监控和容量规划及时升级版本获取新特性通过以上最佳实践,可以充分发挥Redis的性能优势,同时避免常见的陷阱和问题。

Copyright © 2088 次元时空特惠站 - 二次元游戏活动特区 All Rights Reserved.
友情链接