跳转至

Redis 避免惡意重複下載

Vagrantfile

  config.vm.network "forwarded_port", guest: 6379, host: 6379 # redis

docker-compose.yml

version: '3.8'

services:
   redis:
    image: redis:latest
    container_name: redis-server
    ports:
      - "6379:6379" # 將 Redis 的默認端口暴露給主機
    volumes:
      - redis_data:/data # 持久化存儲
      - ./redis/redis.conf:/usr/local/etc/redis/redis.conf
    restart: always
    command: redis-server /usr/local/etc/redis/redis.conf

volumes:
  redis_data:

Redis CLI 測試連接

建議完全停止并删除当前运行的容器再重新启动容器,不然文件可能會映射不到

後端有用到redis就會一直報這個錯(error) ERR AUTH called without any password configured for the default user. Are you sure your configuration is correct?

vagrant@ubuntu-bionic:~$ cd redis

vagrant@ubuntu-bionic:~/redis$ sudo nano redis.conf
vagrant@ubuntu-bionic:~/redis$ cat redis.conf
requirepass redis_password

# 在容器内直接运行 redis-cli 命令,与容器内的 Redis 实例交互
vagrant@ubuntu-bionic:~$ sudo docker exec -it redis-server redis-cli
vagrant@ubuntu-bionic:~$ sudo docker exec -it redis-server redis-cli  -h 127.0.0.1 -p 6379
127.0.0.1:6379> SADD myset "value1" "value2"
(integer) 2

# 確認密碼
127.0.0.1:6379> auth redis_password
(error) ERR AUTH <password> called without any password configured for the default user. Are you sure your configuration is correct?
127.0.0.1:6379> exit

# 进入 Redis 容器,确认 redis.conf 文件是否已经映射
vagrant@ubuntu-bionic:~$ sudo docker exec -it redis-server sh
# cat /usr/local/etc/redis/redis.conf
cat: /usr/local/etc/redis/redis.conf: No such file or directory

# 停止并删除当前运行的容器
vagrant@ubuntu-bionic:~$ sudo docker compose down

# 重新启动容器
vagrant@ubuntu-bionic:~$ docker-compose up -d redis

# 顯然 完全停止并删除当前运行的容器再重新启动容器 才有效 
# 进入 Redis 容器,确认 redis.conf 文件是否已经映射
vagrant@ubuntu-bionic:~$ sudo docker exec -it redis-server sh
# cat /usr/local/etc/redis/redis.conf
requirepass redis_password

Nacos 配置中心

spring:
  redis:
    host: 192.168.33.11
    port: 6379
    password: yourpassword
    lettuce:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0

backend

[org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory]: Factory method 'redisConnectionFactory' threw exception; nested exception is java.lang.NoClassDefFoundError: org/apache/commons/pool2/impl/GenericObjectPoolConfig

這個錯誤表明 Spring Boot 應用在使用 Redis 時缺少依賴 Apache Commons Pool2,該庫用於連接池的管理,LettuceConnectionFactory 需要它來配置 Redis 的連接池

在 Maven 中添加 Apache Commons Pool2 的依賴,這通常是 Redis 使用 Lettuce 客戶端時必需的。

    <redis.version>2.6.2</redis.version>
    <commons-pool2.version>2.11.1</commons-pool2.version>
</properties>

<dependencies>
    <!-- Spring Boot Redis Starter -->
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
        <version>${redis.version}</version>
      </dependency>

      <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-pool2</artifactId>
        <version>${commons-pool2.version}</version>
      </dependency>

</dependencies>
package com.feddoubt.YT1.service.redis;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
public class DownloadLimiter {

    private static final long DUPLICATE_REQUEST_INTERVAL_MS = TimeUnit.SECONDS.toMillis(30); // 30秒

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public boolean tryDownload(String requestHash) {
        long now = System.currentTimeMillis();
        // 尝试获取请求时间,同时设置新的TTL为30秒
        Boolean isSet = stringRedisTemplate.opsForValue().setIfAbsent(requestHash, String.valueOf(now),
                DUPLICATE_REQUEST_INTERVAL_MS, TimeUnit.MILLISECONDS);

        // 如果 Redis 中已存在相同键(且未过期),则请求重复
        if (!isSet) {
            return false;
        }

        // 如果键不存在,则记录请求并允许通过
        return true;
    }
}