关于Redis的学习笔记一:名称解释
本文最后更新于7 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com

1.session

  • Session 用于维持状态:

Session 是一种在服务器端存储用户特定信息的机制,用于在多次请求间识别和跟踪用户。

  • 工作流程
    1. 用户首次登录或访问时,服务器会创建一个唯一的 Session ID
    2. 这个 Session ID 通过 Set-Cookie 头部发送给浏览器,通常存储在名为 JSESSIONID 或类似的 Cookie 中。
    3. 浏览器的后续每个请求都会自动带上这个包含 Session ID 的 Cookie。
    4. 服务器接收到请求后,通过 Session ID 找到对应的服务器端存储的 Session 数据(如用户ID、用户名、权限等),从而知道是谁在请求。
  • Redis 作为 Session 存储的优势:
  1. 集中式管理:所有应用服务器(节点 A、B、C…)都连接同一个 Redis 实例/集群。无论请求被分发到哪个节点,它们都能从同一个地方读写 Session 数据,完美解决了分布式 Session 共享问题。
  2. 高性能:Redis 是基于内存的数据存储,读写速度极快,与直接读本地内存相差无几,不会成为性能瓶颈。
  3. 持久化:虽然 Redis 是内存数据库,但它支持 RDB 快照和 AOF 日志两种持久化机制,可以防止服务器重启或宕机导致所有 Session 丢失。
  4. 自动过期:Redis 原生支持为每个键设置生存时间(TTL)。这与 Session 的超时机制天然契合。只需在存储 Session 时设置一个过期时间(如 30 分钟),Redis 会自动清理过期的 Session,无需额外代码。
  5. 丰富的数据结构:Session 数据本质上是一个键值对对象。Redis 的 Hash 数据结构非常适合存储这种对象,可以方便地对单个字段进行读写,而不用每次都序列化/反序列化整个对象。
  • 优点总结与注意事项

1.分布式友好

2.高性能

3.自动过期

4.持久化可能性

  • 注意事项:

Redis 高可用:由于 Session 集中存储在 Redis,它成为了一个关键的单点。在生产环境中,必须配置 Redis 哨兵(Sentinel)或集群(Cluster)模式来保证高可用性;

网络延迟:相比本地内存,多了一次网络 I/O,但在内网环境下,这个延迟通常可以忽略不计;

序列化/反序列化:存储复杂对象时需要考虑序列化方式(如 JSON、MessagePack、Java 原生序列化等);内存大小:所有 Session 都存储在内存中,需要监控 Redis 的内存使用情况,确保有足够的内存。

  • 结论

Redis + Session 是一个强大、高效且成熟的组合,是构建现代无状态、可扩展的 Web 应用的基石之一。它解决了分布式系统中的状态共享难题,同时保持了极高的性能。只要做好 Redis 本身的高可用和容量规划,它就是 Session 存储的最佳选择之一。

2.socket

1. 什么是 Socket?

Socket(套接字)是网络通信的端点,是支持 TCP/IP 协议的网络通信的基本操作单元。你可以把它想象成一个网络连接的电话听筒

  • IP 地址:相当于电话号码
  • 端口号:相当于分机号
  • Socket:就是连接这两端的通话设备

在 Redis 的语境中,Socket 特指 Redis 客户端与 Redis 服务器之间的网络连接

2.总结

Redis Socket 是 Redis 通信的基石:

  • 网络 Socket:用于跨机器通信,灵活通用
  • Unix Socket:用于本机通信,性能更高
  • 连接池:管理 Socket 连接,提高效率
  • 配置调优:超时、keepalive、最大连接数等参数对稳定性至关重要

理解 Redis Socket 的工作原理对于诊断连接问题、优化性能以及构建稳定的 Redis 应用至关重要。

3.ThreadLocal

  • 什么是 ThreadLocal?

ThreadLocal 是 Java 中提供的一个线程级别的变量隔离机制。它允许你创建一个变量,每个访问该变量的线程都会有自己独立的副本,线程之间不会相互干扰。

  • ThreadLocal 的局限性
  1. 不适合线程池:线程复用会导致数据混乱
  2. 内存泄漏风险:必须手动清理
  3. 调试困难:数据流不明确
  4. 上下文传递复杂:异步编程中需要额外处理
  • 总结

ThreadLocal 是一个强大的线程隔离工具:

1.核心价值:为每个线程提供独立的变量副本

2.典型应用:用户上下文、数据库连接、事务管理

3.关键注意:必须及时清理,防止内存泄漏

4.适用场景:Web 请求上下文、线程封闭的资源配置等

正确使用 ThreadLocal 可以大大简化多线程编程的复杂度,但需要对其原理和潜在问题有清晰的认识。

4.Token

  • 什么是 Token?

Token 是一个代表用户身份和权限的凭证,通常是一串加密的字符串。客户端在登录后获得 Token,并在后续请求中携带它来证明自己的身份。

  • 为什么需要 Token?

传统 Session 的问题:

1. 服务器内存存储压力大
2. 分布式环境下需要 Session 共享
3. CSRF 攻击风险
4. 移动端支持不友好

  • Token 的优势
  1. 无状态:服务器不需要存储会话信息
  2. 跨域友好:轻松支持 CORS
  3. 移动端友好:天然适合 App
  4. 防止 CSRF:可存储在 localStorage
  5. 微服务友好:易于在服务间传递身份
  • Token 的类型

1. JWT (JSON Web Token)

// JWT 结构:Header.Payload.Signature
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

// Header: {"alg": "HS256", "typ": "JWT"}
// Payload: {"sub": "1234567890", "name": "John Doe", "iat": 1516239022}
// Signature: HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

2. Access Token & Refresh Token

// 双 Token 机制
public class TokenPair {
    private String accessToken;  // 短期访问令牌 (30分钟)
    private String refreshToken; // 长期刷新令牌 (7天)
    private String tokenType = "Bearer";
    private Long expiresIn;
}

3. Opaque Token(不透明令牌)

// 自定义格式的 Token
public class CustomToken {
    private String token;        // 随机字符串
    private Long userId;         // 用户ID
    private Long expireTime;     // 过期时间
    private String device;       // 设备信息
}
  • 总结

Token 是现代 Web 应用和移动应用身份认证的首选方案:

1.JWT:适合无状态场景,自包含信息

2.Redis Token:适合需要服务端控制的情景

3.双 Token 机制:平衡安全性和用户体验

4.安全存储:根据场景选择合适的客户端存储方案

5.及时刷新:实现滑动会话过期

Token 技术的正确实施能够构建安全、可扩展的认证授权系统。

5.setnx

SETNX 是 Redis 中非常重要的命令,用于实现分布式锁

1.命令语法:SETNX key value

2.作用:当 key 不存在时设置值,返回 1;key 已存在时不做任何操作,返回 0

3.基础分布式锁

@Service
public class DistributedLockService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    
    /**
     * 尝试获取锁
     */
    public boolean tryLock(String lockKey, String requestId, long expireTime) {
        return Boolean.TRUE.equals(
            redisTemplate.opsForValue().setIfAbsent(lockKey, requestId, 
                Duration.ofSeconds(expireTime))
        );
    }
    
    /**
     * 释放锁
     */
    public boolean releaseLock(String lockKey, String requestId) {
        String currentValue = redisTemplate.opsForValue().get(lockKey);
        if (requestId.equals(currentValue)) {
            redisTemplate.delete(lockKey);
            return true;
        }
        return false;
    }

4.安全的分布式锁(Lua 脚本实现)

@Service
public class SafeDistributedLock {
    
    @Autowired
    private StringRedisTemplate redisTemplate;
    
    // 加锁 Lua 脚本
    private static final String LOCK_SCRIPT = 
        "if redis.call('setnx', KEYS[1], ARGV[1]) == 1 then " +
        "   return redis.call('expire', KEYS[1], ARGV[2]) " +
        "else " +
        "   return 0 " +
        "end";
    
    // 释放锁 Lua 脚本
    private static final String UNLOCK_SCRIPT = 
        "if redis.call('get', KEYS[1]) == ARGV[1] then " +
        "   return redis.call('del', KEYS[1]) " +
        "else " +
        "   return 0 " +
        "end";
    
    private final RedisScript<Long> lockScript = 
        RedisScript.of(LOCK_SCRIPT, Long.class);
    private final RedisScript<Long> unlockScript = 
        RedisScript.of(UNLOCK_SCRIPT, Long.class);
    
    /**
     * 安全的获取锁
     */
    public boolean safeLock(String lockKey, String requestId, int expireSeconds) {
        Long result = redisTemplate.execute(
            lockScript,
            Collections.singletonList(lockKey),
            requestId,
            String.valueOf(expireSeconds)
        );
        return result != null && result == 1;
    }
    
    /**
     * 安全的释放锁
     */
    public boolean safeUnlock(String lockKey, String requestId) {
        Long result = redisTemplate.execute(
            unlockScript,
            Collections.singletonList(lockKey),
            requestId
        );
        return result != null && result == 1;
    }
}

5.总结

SETNX 是 Redis 分布式锁的基础,但在生产环境中建议:

  1. 简单场景:使用 setIfAbsent 带过期时间
  2. 复杂场景:使用 Lua 脚本保证原子性
  3. 生产环境:推荐使用 Redisson 等成熟框架

这样可以避免常见的分布式锁问题,如死锁、误释放、锁续期等。

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇