Redis

关注公众号 jb51net

关闭
首页 > 数据库 > Redis > Redis知识详解

Redis核心知识点详解及解析(附 Java 项目实践案例)

作者:冉成未来

Redis是一款高性能的内存键值数据库,支持多种数据结构和持久化机制,下面这篇文章主要介绍了Redis核心知识点及解析的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

前言

Redis(Remote Dictionary Server)是一个基于内存的高性能键值存储系统,以其卓越的读写性能、丰富的数据结构和强大的功能特性,成为现代分布式系统中不可或缺的基础设施。本文将系统讲解 Redis 的核心知识,并结合 Java 项目实践,帮助读者从理论到实战全面掌握 Redis。

1. Redis 核心概念与架构

1.1 什么是 Redis

Redis 是一种由 C 语言开发的 NoSQL 数据库,将所有数据存储在内存中,因此读写速度极快(可达每秒数万到数十万次操作)。它支持数据持久化、多种数据结构、高可用集群等特性,被广泛应用于缓存、会话存储、实时分析等场景。

1.2 主要功能特性

1.3 典型应用场景

2. 五种核心数据类型详解

Redis 支持五种基本数据类型,每种类型都有对应的操作命令。

类型存储内容常用命令应用场景
String(字符串)字符串、整数、浮点数、二进制数据SET/GET, INCR/DECR, MSET/MGET, SETEX缓存数据、计数器、分布式锁
Hash(哈希)键值对集合(适合存储对象)HSET/HGET, HMSET/HMGET, HGETALL, HDEL用户信息、商品详情
List(列表)有序可重复的字符串列表LPUSH/RPUSH, LPOP/RPOP, LRANGE, LLEN消息队列、最新消息列表
Set(集合)无序不重复的字符串集合SADD, SMEMBERS, SISMEMBER, SINTER标签系统、共同好友
ZSet(有序集合)带分数的有序集合(唯一元素 + 分数排序)ZADD, ZRANGE, ZREVRANGE, ZSCORE排行榜、延迟队列

2.1 String 类型

2.2 Hash 类型

2.3 List 类型

2.4 Set 类型

2.5 ZSet 类型

3. 高级特性与工作原理

3.1 持久化机制

3.2 主从复制与高可用

3.3 分布式集群

3.4 事务与 Lua 脚本

3.5 发布订阅(Pub/Sub)

4. Java 集成 Redis 的两种主流方式

在 Java 生态中,操作 Redis 主要有两种客户端选择:

客户端特点适用场景
Jedis轻量级,API 与 Redis 命令高度一致简单操作,无需高级功能
Redisson功能丰富,内置分布式锁、集合、限流器等高级抽象分布式系统、复杂业务场景
Spring Data RedisSpring 官方集成,统一模板操作Spring Boot 项目

4.1 Spring Data Redis 配置与使用

4.1.1 添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

4.1.2 配置文件

spring:
  redis:
    host: localhost
    port: 6379
    password:       # 可选
    database: 0     # 默认数据库索引
    timeout: 3000ms
    lettuce:
      pool:
        max-active: 8   # 连接池最大连接数
        max-idle: 8     # 最大空闲连接
        min-idle: 0     # 最小空闲连接

4.1.3 使用 StringRedisTemplate

@Autowired
private StringRedisTemplate redisTemplate;

// 字符串操作
public void setValue(String key, String value) {
    redisTemplate.opsForValue().set(key, value);
}

public String getValue(String key) {
    return redisTemplate.opsForValue().get(key);
}

// 计数器
public Long increment(String key) {
    return redisTemplate.opsForValue().increment(key);
}

// Hash 操作
public void setHash(String key, String field, String value) {
    redisTemplate.opsForHash().put(key, field, value);
}

public Map<Object, Object> getHash(String key) {
    return redisTemplate.opsForHash().entries(key);
}

4.2 Redisson 配置与高级功能

Redisson 提供了丰富的分布式对象和服务,特别适合构建分布式系统。

4.2.1 添加依赖

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.24.2</version>
</dependency>

4.2.2 配置 RedissonClient

@Configuration
public class RedissonConfig {

    @Bean
    public RedissonClient redissonClient() {
        Config config = new Config();
        config.useSingleServer()
              .setAddress("redis://127.0.0.1:6379")
              .setConnectionPoolSize(10)
              .setConnectionMinimumIdleSize(5)
              .setConnectTimeout(3000)
              .setTimeout(3000);
        return Redisson.create(config);
    }
}

5. Java 项目实践案例

下面通过三个典型业务场景,展示 Redis 在 Java 项目中的实际应用。

案例一:商品详情缓存(String + Hash)

场景:电商系统需要缓存商品信息,减少数据库压力。

@Service
public class ProductService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private ProductMapper productMapper;  // MyBatis 数据库操作

    private static final String CACHE_KEY_PREFIX = "product:";

    /**
     * 根据商品ID获取商品详情(先查缓存,再查数据库)
     */
    public Product getProductById(Long id) {
        String key = CACHE_KEY_PREFIX + id;

        // 1. 尝试从缓存获取
        Map<Object, Object> cachedMap = redisTemplate.opsForHash().entries(key);
        if (!cachedMap.isEmpty()) {
            // 将 Map 转换为 Product 对象
            return convertMapToProduct(cachedMap);
        }

        // 2. 缓存未命中,查询数据库
        Product product = productMapper.selectById(id);
        if (product != null) {
            // 3. 写入缓存(使用 Hash 结构存储对象字段)
            Map<String, Object> productMap = convertProductToMap(product);
            redisTemplate.opsForHash().putAll(key, productMap);
            // 设置缓存过期时间(例如 1 小时)
            redisTemplate.expire(key, 1, TimeUnit.HOURS);
        }
        return product;
    }

    /**
     * 更新商品信息(更新数据库同时更新缓存)
     */
    @Transactional
    public void updateProduct(Product product) {
        // 1. 更新数据库
        productMapper.updateById(product);

        // 2. 更新缓存
        String key = CACHE_KEY_PREFIX + product.getId();
        Map<String, Object> productMap = convertProductToMap(product);
        redisTemplate.opsForHash().putAll(key, productMap);
    }
}

案例二:分布式锁实现(Redisson)

场景:高并发下扣减库存,需要保证同一时间只有一个线程处理同一商品的库存。

@Service
public class InventoryService {

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 扣减库存
     * @param productId 商品ID
     * @param quantity  扣减数量
     * @return 是否成功
     */
    public boolean decreaseStock(Long productId, Integer quantity) {
        String lockKey = "lock:product:" + productId;
        RLock lock = redissonClient.getLock(lockKey);

        try {
            // 尝试加锁,最多等待 5 秒,锁自动释放时间 10 秒
            boolean isLocked = lock.tryLock(5, 10, TimeUnit.SECONDS);
            if (!isLocked) {
                return false;  // 获取锁失败
            }

            // 执行业务逻辑:查询库存并扣减(需配合数据库操作)
            Integer stock = getStockFromDB(productId);
            if (stock >= quantity) {
                updateStockInDB(productId, stock - quantity);
                return true;
            }
            return false;

        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        } finally {
            // 确保锁释放
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    // 模拟数据库操作
    private Integer getStockFromDB(Long productId) { return 100; }
    private void updateStockInDB(Long productId, int newStock) {}
}

案例三:基于令牌桶的分布式限流器

场景:API 接口需要限制每个用户的访问频率,防止刷接口。

@Service
public class RateLimitService {

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 判断请求是否允许通过
     * @param userId 用户ID
     * @return true 允许,false 拒绝
     */
    public boolean tryAcquire(String userId) {
        // 每个用户独立的限流器
        String key = "rate:limiter:user:" + userId;
        RRateLimiter limiter = redissonClient.getRateLimiter(key);

        // 初始化:每秒 5 个请求,共享配额(只需初始化一次)
        limiter.trySetRate(RateType.OVERALL, 5, 1, TimeUnit.SECONDS);

        // 设置限流器自动过期(避免 Redis 内存泄漏)
        limiter.expire(30, TimeUnit.MINUTES);

        // 尝试获取一个令牌
        return limiter.tryAcquire();
    }
}

// 在 Controller 中使用
@RestController
public class ApiController {

    @Autowired
    private RateLimitService rateLimitService;

    @GetMapping("/api/data")
    public String getData(@RequestParam String userId) {
        if (!rateLimitService.tryAcquire(userId)) {
            throw new RuntimeException("请求过于频繁,请稍后再试");
        }
        return "请求成功,数据返回";
    }
}

6. 生产环境最佳实践

6.1 性能优化建议

6.2 集群模式配置

Config config = new Config();
config.useClusterServers()
      .addNodeAddress("redis://192.168.1.1:7000", "redis://192.168.1.2:7001")
      .setMasterConnectionPoolSize(20)
      .setSlaveConnectionPoolSize(10);

6.3 监控与运维

7. 总结

Redis 作为内存数据存储的标杆,以其高性能、丰富的数据结构和强大的分布式能力,成为现代应用架构的核心组件。本文从核心概念、数据类型、高级特性到 Java 项目实践,全面解析了 Redis 的知识体系。

在实际开发中,开发者应根据业务场景选择合适的数据结构和客户端:

掌握 Redis 不仅需要理解其原理,更需要通过实战项目积累经验,合理设计数据模型和缓存策略,才能充分发挥其性能优势。

到此这篇关于Redis核心知识点详解及解析的文章就介绍到这了,更多相关Redis知识详解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文