Redis全面指南:数据类型、高可用配置与缓存问题解决方案

Redis全面指南:数据类型、高可用配置与缓存问题解决方案

一、Redis概述与应用场景

Redis(Remote Dictionary Server)是一个开源的基于内存的键值存储系统,支持多种数据结构,读写性能可达10万+ QPS1,8。主要应用场景包括:

  • 缓存热点数据:减轻数据库压力
  • 会话存储:分布式Session共享
  • 排行榜:利用Zset实现实时排名
  • 分布式锁:通过SETNX命令实现
  • 消息队列:基于List/Stream实现

二、核心数据类型与命令详解

1. 五种基础数据结构

数据类型 结构 常用命令 应用场景
String 二进制安全字符串 SET key value, GET key, INCR key, SETEX key 10 value 计数器、分布式锁
Hash 字段-值映射表 HSET user name John, HGETALL user, HINCRBY user age 1 存储对象属性
List 双向链表 LPUSH list 1, RPOP list, LRANGE list 0 -1 消息队列、时间轴
Set 无序唯一集合 SADD tags Java, SINTER tags1 tags2, SMEMBERS tags 标签系统、共同好友
Zset 带权重的有序集合 ZADD rank 95 Alice, ZRANGE rank 0 10, ZREVRANK rank Bob 排行榜、延时队列

Java操作示例(Jedis)

// String操作
jedis.set("counter", "100");
jedis.incr("counter");

// Hash操作
Map<String, String> user = new HashMap<>();
user.put("name", "John");
user.put("age", "30");
jedis.hset("user:1001", user);

// Zset操作
jedis.zadd("leaderboard", 95.0, "Alice");
Set<String> topUsers = jedis.zrevrange("leaderboard", 0, 10);

###2. 高级数据结构
1.​​Geospatial(地理空间)
```bash
GEOADD cities 116.40 39.90 Beijing
GEODIST cities Beijing Shanghai km

2.​​HyperLogLog(基数统计)

PFADD uv 192.168.1.1 192.168.1.2
PFCOUNT uv

​​3.Bitmap(位图)

SETBIT login:2025-06-30 1001 1 # 用户1001登录
BITCOUNT login:2025-06-30      # 当日登录用户数

三、持久化与主从复制配置

1. 持久化策略

方式 触发机制 配置示例 特点
​​AOF​​ 记录写命令 appendonly yes 数据更安全,文件较大
​​RDB​​ 定时快照 save 900 1 二进制紧凑,恢复快

2. 主从复制配置(Linux)

主服务器配置(/etc/redis/redis.conf)

bind 0.0.0.0
requirepass master_password

从服务器配置​​:

bind 0.0.0.0
replicaof 192.168.1.100 6379
masterauth master_password

重启服务​​:

sudo systemctl restart redis-server

拓扑结构​​:
主节点(写入) -> 从节点1(读取)
|--> 从节点2(读取)

四、哨兵模式高可用方案

  1. 哨兵配置(sentinel.conf)
sentinel monitor mymaster 192.168.1.100 6379 2
sentinel auth-pass mymaster master_password
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
  1. Java客户端连接哨兵
JedisPoolConfig poolConfig = new JedisPoolConfig();
Set<String> sentinels = new HashSet<>();
sentinels.add("192.168.1.101:26379");
sentinels.add("192.168.1.102:26379");

JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels, poolConfig);
try (Jedis jedis = pool.getResource()) {
    jedis.set("key", "value"); // 自动路由到主节点
}

故障转移流程​​:

  1. 哨兵检测到主节点下线
  2. 哨兵集群投票选举领导者
  3. 领导者哨兵执行故障转移
  4. 切换从节点为新主节点
  5. 客户端更新连接信息

五、缓存问题解决方案与Java实现

  1. 缓存穿透(访问不存在数据)
    ​​解决方案​​:
  • ​​布隆过滤器​​:预加载数据指纹
  • 空值缓存​​:设置短过期时间
public String getData(String key) {
    // 1. 尝试从缓存获取
    String value = jedis.get(key);
    if (value == null) {
        // 2. 布隆过滤器校验
        if (!bloomFilter.mightContain(key)) {
            return null; 
        }
        // 3. 空值缓存
        jedis.setex(key, 60, "NULL"); 
    }
    return value;
}
  1. 缓存击穿(热点Key失效)
    解决方案​​:
  • ​​互斥锁​​:仅允许一个线程重建缓存
  • ​​逻辑过期​​:异步更新缓存
public String getHotData(String key) {
    String value = jedis.get(key);
    if (value == null) {
        // 尝试获取分布式锁
        if (lock.tryLock()) {
            try {
                // 双重检查
                value = jedis.get(key);
                if (value == null) {
                    value = db.getData(key); 
                    jedis.setex(key, 300, value);
                }
            } finally {
                lock.unlock();
            }
        }
    }
    return value;
}
  1. 缓存雪崩(大量Key同时失效)
    解决方案​​:
  • ​​随机过期时间​​:分散失效时间点
  • ​​多级缓存​​:本地缓存+Redis
  • ​​熔断降级​​:Hystrix实现服务降级
// 设置随机过期时间
int expireTime = 3600 + new Random().nextInt(600); // 3600~4200秒
jedis.setex(key, expireTime, value);

六、Redis使用最佳实践

1.​​内存优化

maxmemory 2gb # 限制最大内存
maxmemory-policy volatile-lru # 使用LRU淘汰策略

2.管道批处理

Pipeline p = jedis.pipelined();
for (int i=0; i<1000; i++) {
    p.set("key" + i, "value" + i);
}
p.sync();

3.Lua脚本保证原子性

-- 限流脚本
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local count = tonumber(redis.call('get', key) or "0")
if count + 1 > limit then
    return 0
else
    redis.call('INCR', key)
    return 1
end

扩展建议

  • 生产环境建议使用Redis 6.0+的多线程IO模型
  • 集群规模较大时采用Redis Cluster分片方案
  • 监控重要指标:内存使用率、命中率、延迟
posted @ 2025-06-30 20:35  念笙  阅读(10)  评论(0)    收藏  举报