面试系列 - Redis使用详解

目录

一、Redis的数据结构

二、Redis事务

[1. 开启事务:MULTI](#1. 开启事务:MULTI)

[2. 添加事务命令](#2. 添加事务命令)

[3. 执行事务:EXEC](#3. 执行事务:EXEC)

[4. 回滚事务:DISCARD](#4. 回滚事务:DISCARD)

[5. 事务中的错误处理](#5. 事务中的错误处理)

[6. 监视键:WATCH](#6. 监视键:WATCH)

[7. 返回值](#7. 返回值)

[8. 嵌套事务](#8. 嵌套事务)

[9. 实例](#9. 实例)

[三、redis 分布式锁如何实现](#三、redis 分布式锁如何实现)

1、基于Redis的分布式锁实现步骤:


Redis(Remote Dictionary Server)是一个高性能的开源键值存储数据库。它以键值对的形式存储数据,并提供了丰富的数据结构和操作,使其不仅可以用作缓存服务器,还可以用于消息队列、分布式锁、实时统计等各种用途。

一、Redis的数据结构

Redis支持多种数据结构,包括字符串、列表、集合、散列(哈希表)、有序集合和位图等。你可以根据需要选择合适的数据结构。

  • 字符串(String):可以存储文本或二进制数据。
  • 列表(List):有序的字符串元素列表,可以进行插入、删除和切片操作。
  • 集合(Set):无序的唯一字符串集合,支持交集、并集和差集等操作。
  • 散列(Hash):键值对的无序集合,适合存储对象属性。
  • 有序集合(Sorted Set):类似于集合,但每个元素都有一个分数,用于排序。
  • 位图(Bitmap):可以用于位操作,例如计算用户的在线状态。

二、Redis事务

Redis支持事务,事务允许你将一系列命令打包成一个单一的操作单元,要么全部执行成功,要么全部回滚。在Redis中,事务的实现是通过MULTI、EXEC、DISCARD和WATCH等命令来完成的。

1. 开启事务:MULTI

事务开始于MULTI命令的执行,该命令表示接下来的一系列命令将被打包成一个事务。在MULTI执行后,Redis进入了事务模式,此时不会立即执行事务命令,而是将它们排队等待执行。

2. 添加事务命令

在MULTI之后,你可以依次添加多个命令,这些命令会被放入一个事务队列中,但不会立即执行。

3. 执行事务:EXEC

一旦你添加了所有要执行的命令,使用EXEC命令来执行整个事务。当EXEC执行时,Redis会按照命令添加的顺序依次执行它们。如果某个命令执行失败,整个事务将被回滚,即不会有任何命令被执行。

4. 回滚事务:DISCARD

如果在事务执行之前,你意识到需要取消这个事务,可以使用DISCARD命令来回滚整个事务。这将取消所有已添加的命令。

5. 事务中的错误处理

在Redis事务中,如果某个命令执行失败,不会影响其他命令的执行。事务会继续执行余下的命令,但最终结果是不会提交的,即所有命令都不会应用到数据上。

6. 监视键:WATCH

Redis的WATCH命令用于监视一个或多个键,如果在执行EXEC之前,被监视的键发生了变化,事务将被取消。WATCH命令可以用来实现乐观锁,确保在事务执行期间数据没有被其他客户端修改。

7. 返回值

EXEC命令的返回值是一个包含事务中每个命令的执行结果的列表。如果事务被回滚(例如,其中一个命令执行失败或被监视的键发生了变化),EXEC将返回一个空列表。

8. 嵌套事务

Redis不支持嵌套事务。如果在一个事务中执行了MULTI命令,那么在该事务执行完之前,不能再次执行MULTI命令。

9. 实例

下面是一个使用Redis事务的Java示例代码:

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class TransactionService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public void performTransaction(String key1, String key2) {
        redisTemplate.multi(); // 开启事务
        redisTemplate.opsForValue().set(key1, "value1");
        redisTemplate.opsForValue().get(key2);
        redisTemplate.exec(); // 执行事务
    }
}

在上面的示例中,我们使用Spring Data Redis来执行Redis事务。首先,我们通过调用multi()方法开启一个事务,然后添加多个命令,最后通过exec()方法执行事务。

Redis事务是一种强大的工具,可以用于确保多个命令的原子性操作。但需要注意的是,Redis事务不同于传统数据库事务,不支持回滚到保存点(savepoint),因此在使用事务时要谨慎考虑原子性需求。

三、redis 分布式锁如何实现

在Redis中实现分布式锁是一种常见的用例,用于确保多个客户端在分布式环境中对共享资源的访问互斥。这里有一种简单的方法可以实现分布式锁:

1、基于Redis的分布式锁实现步骤:

  1. 获取锁 :当一个客户端想要获得锁时,它可以使用Redis的SET命令来设置一个带有过期时间的键(锁)。只有一个客户端能够成功设置这个键,其他客户端会失败。

SET lock_key unique_identifier NX PX lock_timeout

  • lock_key:锁的键名,可以是唯一的。
  • unique_identifier:客户端标识符,用于区分不同的客户端。
  • NX:表示只有在键不存在时才能设置成功。
  • PX:设置锁的过期时间,以毫秒为单位,确保锁在一定时间后会自动释放。
  • lock_timeout:锁的超时时间,一般设置为合理的值,以防止客户端异常而没有释放锁。
  1. 释放锁 :当客户端完成工作或不再需要锁时,可以使用DEL命令来删除锁。

DEL lock_key

Java示例:

以下是一个使用Java和Spring Data Redis实现分布式锁的示例代码:

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

@Component
public class DistributedLock {

    @Autowired
    private StringRedisTemplate redisTemplate;

    public boolean acquireLock(String lockKey, String clientId, long lockTimeout) {
        // 使用SET命令尝试获取锁
        Boolean isLocked = redisTemplate.opsForValue().setIfAbsent(lockKey, clientId);
        
        // 如果成功获得锁,设置过期时间
        if (isLocked != null && isLocked) {
            redisTemplate.expire(lockKey, lockTimeout, TimeUnit.MILLISECONDS);
            return true;
        }
        
        return false;
    }

    public void releaseLock(String lockKey, String clientId) {
        // 首先验证锁是否仍然属于客户端
        String currentLockOwner = redisTemplate.opsForValue().get(lockKey);
        if (clientId.equals(currentLockOwner)) {
            // 删除锁
            redisTemplate.delete(lockKey);
        }
    }
}

在上述代码中,acquireLock方法尝试获取锁,releaseLock方法释放锁。在acquireLock方法中,我们使用setIfAbsent命令来尝试设置锁。如果成功获得锁,我们设置了过期时间以确保锁会自动释放。

需要注意的是,这个简单的实现仍然存在一些问题,如无法处理锁的续租、不可重入等情况。在实际应用中,你可能需要更复杂的锁实现或使用现成的分布式锁库,如Redlock或Curator。这些库提供了更多的功能和保护机制,以确保分布式锁的可靠性和性能。

相关推荐
Knight_AL2 小时前
本地服务连接 SaaS 测试环境实践:Docker 部署 Redis 与 RocketMQ 完成接口联调
redis·docker·rocketmq
夕除4 小时前
redis--服务器优化
redis
xiaoqiMikko5 小时前
Redis 实战(一):内存满了 —— 拒写、淘汰、被系统杀掉,以及删了 key 内存为什么不降(6.2.4 实测)
redis·后端
子林super5 小时前
MySQL三大日志(binlog、redo log和undo log)详解
面试
wefg16 小时前
【Redis】安装与启动
数据库·redis·缓存
大圣编蚕7 小时前
常见的 Redis 面试题(高频整理)
数据库·redis·缓存
小猿姐8 小时前
KubeBlocks Enterprise v2.3 发布!
redis·kubernetes·aiops
梅菲塔亚8 小时前
博客_Redis入门到实战
数据库·redis·缓存
蓝胖的四次元口袋9 小时前
Redis 知识梳理(3)
数据库·redis·缓存