2024-08-28

Redis 是一个开源的使用 C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。

安装 Redis 的步骤取决于你的操作系统。以下是在 Linux 系统上安装 Redis 的简要步骤:

  1. 更新包管理器索引:



sudo apt-get update
  1. 安装 Redis:



sudo apt-get install redis-server
  1. 确认 Redis 已经安装并运行:



redis-cli ping

如果安装成功,你将收到一个响应:




PONG
  1. (可选)配置 Redis 以便于自启动和持久化:

    编辑 Redis 配置文件 /etc/redis/redis.conf,然后根据需要进行配置。

  2. (可选)保存配置并重启 Redis 服务:



sudo systemctl restart redis.service

以上步骤在大多数基于 Debian 的 Linux 发行版(如 Ubuntu)上适用。其他操作系统(如 CentOS、Fedora 等)可能需要使用不同的包管理器命令(如 yumdnf)或从源代码编译安装。

2024-08-28

在Redis中,你可以使用Sorted Set或者Hash表结构来存储日期相关的数据,并使用ZRANGEBYSCORE命令来查询特定日期范围内的数据。

以下是使用Sorted Set存储日期并进行范围查询的示例代码:




import redis
from datetime import datetime
 
# 连接到Redis
r = redis.Redis(host='localhost', port=6379, db=0)
 
# 存储数据:将日期转换为时间戳存入Sorted Set
def store_data(redis_key, date, value):
    timestamp = datetime.strptime(date, "%Y-%m-%d").timestamp()
    r.zadd(redis_key, {value: timestamp})
 
# 查询日期范围内的数据
def query_data(redis_key, start_date, end_date):
    start_timestamp = datetime.strptime(start_date, "%Y-%m-%d").timestamp()
    end_timestamp = datetime.strptime(end_date, "%Y-%m-%d").timestamp()
    # 使用ZRANGEBYSCORE命令查询
    return r.zrangebyscore(redis_key, min=start_timestamp, max=end_timestamp)
 
# 示例数据
store_data('mydates', '2021-01-01', 'event1')
store_data('mydates', '2022-02-02', 'event2')
store_data('mydates', '2023-03-03', 'event3')
 
# 查询2022年1月1日到2023年3月31日之间的事件
results = query_data('mydates', '2022-01-01', '2023-03-31')
 
# 输出结果
for result in results:
    print(result)

在这个例子中,我们首先连接到Redis,然后定义了两个函数:store_data用于存储数据,query_data用于查询指定日期范围内的数据。我们将日期转换为时间戳,并使用ZADD命令将值与时间戳关联。查询时,我们使用ZRANGEBYSCORE命令来获取指定时间范围内的所有元素。

请注意,这个例子假设你已经有了Redis服务器在运行,并且已经安装了redis-py库。

2024-08-28

为了设置一个Redis 2.x版本的哨兵和Redis集群,你需要遵循以下步骤:

  1. 安装和配置Redis服务器。
  2. 设置Redis主从复制。
  3. 配置Redis哨兵。
  4. 安装和配置Redis集群。

以下是示例配置:

Redis主服务器(master.conf):




# 基本配置
port 6379
daemonize yes

Redis从服务器(slave.conf):




# 基本配置
port 6380
daemonize yes
slaveof 127.0.0.1 6379

Redis哨兵(sentinel.conf):




# 基本配置
port 26379
daemonize yes
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000

Redis集群配置(使用Redis Cluster):

  • 首先,确保你的Redis版本支持集群。
  • 然后,使用redis-cli创建集群:



redis-cli --cluster create 127.0.0.1:6379 127.0.0.1:6380 --cluster-replicas 1

确保替换上面的IP地址和端口号以匹配你的环境配置。

请注意,Redis 2.x版本已经非常旧,不再被官方支持。建议升级到更新的Redis版本,比如至少Redis 6.x,以获得官方支持和最新特性。

2024-08-28

Redis 7.2.3 引入了一些重要的改进和新特性,包括对 RESP3 协议的支持,新的集群代理,以及对 TLS 的改进。

关于你的问题,官方提供了默认的配置文件 redis.confsentinel.conf,你可以在 Redis 的 GitHub 仓库或者官网下载到这些文件。

  • redis.conf: 这是 Redis 服务器的配置文件,包含了 Redis 服务器的基本配置选项。
  • sentinel.conf: 这是 Redis Sentinel 的配置文件,它是一个用于监控 Redis 主服务器以及在主服务器宕机时自动进行故障转移的系统。

这些文件的默认内容可能会随着 Redis 版本的更新而更改,因此建议直接从官方资源获取最新的配置文件。

以下是两个配置文件的部分内容:

redis.conf




# Redis 配置文件示例
 
# 设置 Redis 以守护进程方式运行
daemonize yes
 
# 设置 Redis 监听的端口号
port 6379
 
# 设置 Redis 的日志文件路径
logfile "/var/log/redis/redis-server.log"
 
# 设置数据库数量
databases 16
 
# 设置 Redis 的持久化策略
save 900 1
save 300 10
save 60 10000
 
# 设置 RDB 文件名
dbfilename dump.rdb
 
# 设置 Redis 的工作目录
dir /var/lib/redis

sentinel.conf




# Sentinel 配置文件示例
 
# 设置 Sentinel 以守护进程方式运行
daemonize yes
 
# 设置 Sentinel 监听的端口号
port 26379
 
# 设置 Sentinel 的日志文件路径
logfile "/var/log/redis/redis-sentinel.log"
 
# 设置 Sentinel 的工作目录
dir /tmp
 
# 设置监控的主 Redis 服务器
sentinel monitor mymaster 127.0.0.1 6379 2
 
# 设置主服务器故障转移的最小投票数
sentinel down-after-milliseconds mymaster 30000
 
# 设置新的主服务器选举时间窗口
sentinel failover-timeout mymaster 180000

这些只是配置文件的一部分,实际配置可能会根据你的服务器环境和需求进行更多的自定义设置。

2024-08-28



import redis
 
# 连接到Redis服务器
r = redis.Redis(host='localhost', port=6379, db=0)
 
# 设置键值对
r.set('key', 'value')
 
# 获取并打印出键对应的值
value = r.get('key')
print(value)
 
# 批量设置键值对
r.mset({'key1': 'value1', 'key2': 'value2'})
 
# 批量获取键的值
values = r.mget(['key1', 'key2'])
print(values)
 
# 计数器操作
r.incr('counter')  # 递增
r.decr('counter')  # 递减
 
# 获取并打印出键对应的值,并在原来的基础上递增
new_value = r.incrbyfloat('key', 1.5)
print(new_value)
 
# 设置键的过期时间
r.expire('key', 3600)  # 设置键的过期时间为3600秒
 
# 查询键的剩余生存时间
ttl = r.ttl('key')
print(ttl)
 
# 删除键
r.delete('key')
 
# 查询键是否存在
exists = r.exists('key')
print(exists)

这段代码展示了如何使用Python的redis模块来连接Redis服务器,并执行一些基本的Redis操作,如设置和获取键值对,批量设置和获取键值对,键的过期时间设置,以及使用Redis计数器等功能。

2024-08-28

在Redis中,修改key的名称可以使用RENAME命令。如果新的key名称已经存在,则新的key的内容会被旧的key的内容覆盖。

下面是使用RENAME命令修改key名称的例子:




# 假设你想将 key "old_key_name" 改名为 "new_key_name"
RENAME old_key_name new_key_name

在Redis客户端或者任何支持Redis命令的接口中,你可以直接使用上述命令。

如果你在使用某种编程语言的Redis客户端库,例如在Python中,你可以使用如下代码:




import redis
 
# 连接到Redis
r = redis.Redis(host='localhost', port=6379, db=0)
 
# 修改key名称
r.rename('old_key_name', 'new_key_name')

请注意,在实际应用中,修改key名称应该谨慎进行,以免造成数据混乱或丢失。如果新旧key名称存在于不同的数据库中,RENAME命令无法直接执行,需要先切换到包含旧key的数据库,执行DUMP导出旧key的值,再切换到新key所在的数据库,使用RESTORE导入到新key。

2024-08-28

Redis 的持久化主要有两种方式:RDB 和 AOF。

  1. RDB 持久化:

RDB 是 Redis 默认的持久化方式。在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是 Snapshot 快照。

配置文件示例:




save 900 1      # 900 秒内至少 1 个键被修改则触发保存
save 300 10     # 300 秒内至少 10 个键被修改则触发保存
save 60 10000   # 60 秒内至少 10000 个键被修改则触发保存
 
dbfilename dump.rdb                      # RDB 文件名
dir /path/to/your/redis/directory/       # RDB 文件存储目录
  1. AOF 持久化:

AOF 持久化是通过保存 Redis 服务器所执行的命令来记录数据库的状态。

配置文件示例:




appendonly yes                   # 开启 AOF 持久化
appendfilename "appendonly.aof"  # AOF 文件名
dir /path/to/your/redis/directory/  # AOF 文件存储目录
 
# AOF 文件的更新频率
appendfsync everysec              # 每秒钟同步一次至磁盘

在实际应用中,通常会同时使用 RDB 和 AOF 两种持久化方式,以此来保证数据的持久性和完整性。

2024-08-28

在SpringBoot项目中使用SaToken进行前后端分离登录认证,你需要做以下几个步骤:

  1. 引入SaToken依赖
  2. 配置Redis
  3. 配置SaToken
  4. 创建登录接口
  5. 创建拦截器进行权限校验

以下是一个简化的示例:

1. 引入SaToken依赖(pom.xml)




<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-spring-boot-starter</artifactId>
    <version>你的版本号</version>
</dependency>

2. 配置Redis(application.yml)




spring:
  redis:
    host: 你的Redis地址
    port: 6379
    password: 你的Redis密码
    database: 0
    timeout: 5000

3. 配置SaToken(SaTokenConfig.java)




@Configuration
public class SaTokenConfig {
    @Bean
    public SaTokenInterceptor getSaTokenInterceptor() {
        return new SaTokenInterceptor();
    }
}

4. 创建登录接口(LoginController.java)




@RestController
public class LoginController {
 
    @PostMapping("/login")
    public Object login(String username, String password) {
        // 登录验证逻辑
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(new UsernamePasswordToken(username, password));
            return SaResult.ok("登录成功");
        } catch (AuthenticationException e) {
            return SaResult.error("登录失败");
        }
    }
}

5. 创建拦截器(SaTokenInterceptor.java)




@Component
public class SaTokenInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 拦截请求进行权限校验
        if (handler instanceof HandlerMethod) {
            SaStrategy saStrategy = SaManager.getSaTokenStrategy();
            // 判断是否需要校验
            if (saStrategy.match(request, response)) {
                // 检查登录
                if (saStrategy.isLogin(request, response)) {
                    return true; // 登录成功,继续执行
                } else {
                    response.setContentType("application/json;charset=UTF-8");
                    response.getWriter().write(SaResult.error("未登录或登录失效").toJsonString());
                    return false; // 登录失败,不继续执行
                }
            }
        }
        return true; // 不需要校验,继续执行
    }
}

在配置了SaToken和Redis之后,你可以通过拦截器对每个请求进行权限校验,如果请求需要登录,则检查用户是否已经登录,未登录则拒绝访问。登录接口使用SaToken提供的Subject进行登录验证,登录成功后返回Token,用于后续请求的身份标识。

2024-08-28

在Spring Boot中使用Redis实现分布式锁通常涉及到RedisTemplateStringRedisTemplate。以下是一个简单的示例,展示了在Spring Boot应用中如何在事务提交后释放Redis分布式锁:




import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
public class DistributedLockController {
 
    @Autowired
    private StringRedisTemplate redisTemplate;
 
    private static final String LOCK_KEY = "distributed_lock";
 
    @GetMapping("/acquireLock")
    public String acquireLock() {
        boolean locked = tryLock(LOCK_KEY);
        if (locked) {
            // 模拟业务逻辑处理
            doBusinessLogic();
            // 释放锁
            unlock(LOCK_KEY);
            return "Lock released";
        } else {
            return "Failed to acquire lock";
        }
    }
 
    private boolean tryLock(String key) {
        // 尝试获取锁,使用 SET key value NX PX milliseconds 命令
        Boolean locked = redisTemplate.opsForValue().setIfAbsent(key, "lock_value", 10, TimeUnit.SECONDS);
        return Boolean.TRUE.equals(locked);
    }
 
    private void unlock(String key) {
        // 释放锁,删除键
        redisTemplate.delete(key);
    }
 
    @Transactional
    private void doBusinessLogic() {
        // 事务性业务逻辑
    }
}

在这个例子中,tryLock 方法使用了 StringRedisTemplateopsForValue().setIfAbsent() 方法尝试获取锁,该方法在Redis中对应的是 SET key value NX PX milliseconds 命令,其中 NX 表示只在键不存在时设置值,PX 表示设置键的过期时间。

unlock 方法简单地使用了 StringRedisTemplatedelete() 方法释放锁,即删除键。

acquireLock 方法中,我们首先尝试获取锁,如果成功,则执行业务逻辑,在业务逻辑执行完毕后,无论成功还是回滚,都会释放锁。这里假设了业务逻辑在一个独立的方法 doBusinessLogic() 中,并用 @Transactional 注解标记,以确保业务逻辑在事务的上下文中执行。

请注意,这个例子中锁的过期时间设置为10秒,实际使用时应该根据业务场景适当调整锁的超时时间。同时,在高并发情况下,可能需要使用更复杂的算法来确保锁的安全性和效率。

2024-08-28

在使用Redisson提供的可重入锁时,每个Redisson客户端实例都有一个内部的LockWatchdogService服务,它会定时检查并刷新加锁的超时时长。当一个线程尝试获取锁时,如果该线程已经持有该锁,它会自动延长锁的超时时长,而不会因为重入而需要多次解锁。

以下是一个简化的示例代码,展示了如何使用Redisson的可重入锁:




import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
 
public class RedissonLockExample {
 
    public static void main(String[] args) {
        // 配置Redisson客户端
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        RedissonClient redisson = Redisson.create(config);
 
        // 获取锁对象实例
        String lockKey = "anyLockKey";
        RedissonLock lock = redisson.getLock(lockKey);
 
        try {
            // 尝试加锁,最多等待100秒,锁定之后10秒自动解锁
            boolean isLocked = lock.tryLock(100, 10, TimeUnit.SECONDS);
            if (isLocked) {
                // 已加锁,执行业务逻辑
                System.out.println("Lock acquired");
                // 重入锁,再次获取相同的锁不会阻塞
                lock.lock();
                // 再次执行业务逻辑
                System.out.println("Lock re-acquired");
 
                // 重复解锁操作需要平衡,否则可能会导致其他等待该锁的线程无法获取锁
                lock.unlock();
                lock.unlock();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // 如果锁被占用,确保释放锁资源
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
 
        // 关闭Redisson客户端
        redisson.shutdown();
    }
}

在这个示例中,我们创建了一个RedissonClient实例,并获取了一个RedissonLock实例。我们尝试锁定一个资源,并在获得锁之后执行一些业务逻辑。在业务逻辑执行期间,我们可以重复获取同一个锁,而不会阻塞其他等待该锁的线程。最终,我们确保释放了所有的锁资源。