# 基础介绍

使用C语言开发的的一个开源的高性能键值对数据库 中文网 (opens new window)
Windows版下载 (opens new window)
Linux版下载 (opens new window)

默认端口号:6379

# 核心文件

  • redis-server.exe:服务器启动命令
  • redis-cli.exe:命令行客户端
  • redis.windows.conf:redis核心配置文件
  • redis-benchmark.exe:性能测试工具
  • redis-check-aof.exe:AOF文件检查工具
  • redis-check-dump.exe:RDB文件检查工具

# 基本特征

  • 数据间没有必然的关联关系
  • 内部采用单线程机制进行工作
  • 高性能,高并发
  • 持久化支持,可进行数据灾难恢复

# 应用场景

  • 作为缓存使用
    • 原始业务功能设计,例如:秒杀、促销活动、排队购票等
    • 高频次数据访问,例如:突发时政、关注焦点、在线人数等
  • 系统功能优化或升级
    • 单服务器升级集群
    • Session、Token管理

# 基本操作

keys * //获取所有的键
type key //获取键对应value的类型
del key //删除指定的key value

# 参数配置

bind  # 绑定redis自身的服务器的ip,不是绑定访问过来的IP地址,默认是127.0.0.1,即只允许本地访问
port  # 指定redis监听端口,默认为6379
requirepass  # 设置连接密码,客户端连接时,需要密码认证
protected-mode yes # 开启保护模式(默认开启),若开启且bind未配置密码也未设置,redis只接受本机连接
timeout  # 设置客户端连接时的超时时间,单位为秒,默认值:0代表禁用,永不关闭

# Windows中设置密码的方法

  • 在redis目录下redis.windows.conf文件找到requirepass,追加一行
# requirepass foobared
requirepass root  # root为设置的密码
  • 设置redis启动时加载配置文件的命令如下:
redis-server.exe redis.windows.conf
  • 输入如下命令即可完成Redis服务化:
redis-server --service-install redis.windows-service.conf --loglevel verbose     
# 或者:
redis-server --service-install redis.windows.conf --loglevel verbose 
  • Redis 常用的操作命令
# 卸载服务
redis-server --service-uninstall
# 开启服务
redis-server --service-start
# 停止服务
redis-server --service-stop

# 数据类型

数据类型指的是存储的数据类型,也就是value部分的类型,key部分永远是字符串

# string 字符串

set key value //存储
get key //获取
del key //删除

mset key1 value1 key2 value2 ……  //存储多个
mget key1 key2 …… //获取多个

setex key seconds value //设置秒
setex key milliseconds value //设置毫秒

# hash 哈希

value为Map类型

hset key field value //存储 hset myhash username lisi
hget key field  //获取一个  hget myhash username
hgetall key //获取全部
hdel key field  //删除 

# list 列表

  • 双向链表linkedlist,支持重复元素
  • 可以添加一个元素到列表的头部(左边)或者尾部(右边)
//存储
lpush key value //将元素加入到列表左边
rpush key value //将元素加入到列表右边

//获取
lrange key start end //范围获取
lrange key 0 -1 //获取所有

//删除
lpop key //删除列表最左边的元素,并将该元素返回
rpop key //删除列表最右边的元素,并将该元素返回

//测试
lpush mylist a
lpush mylist b
rpush mylist c
lrange mylist 0 -1
//输出 bac

# set 集合

不允许重复的元素,无序的

sadd key value  //存储
sadd key value1 value2 …… //存储多个
smembers key //获取所有元素
srem key value //删除

# sortedset 有序集合

  • 不允许重复的元素,且元素有序
  • 每个元素都会关联一个double类型的分数
zadd key score value //存储
zrange key start end //获取
zrange key 0 -1 withscores //获取全部并带着分数
zrem key value  //删除

# 数据持久化

# RDB

默认方式,不需要配置,在一定的时间间隔中,检测key的变化,然后持久化数据

  • 在conf配置文件中:
    • save 900 1 => 900秒后至少有1个key发省改变就持久化一次
    • save 300 10 => 300秒后至少有10key发省改变就持久化一次
    • save 60 10000 => 50秒后至少有10000个key发省改变就持久化一次
  • 如果修改了conf配置文件,不能直接启动redis-server.exe,需按如下方式启动
    D:\编程\Redis\Redis-x64-3.0.504\redis-server.exe redis.windows.conf
    

# AOF

日志记录的方式,可以记录每一条命令的操作。每次操作后持久化数据

  • 在conf配置文件中:
    • appendonly no(关闭) => appendonly yes(开启)
    • appendfsync always => 每次操作都持久化
    • appendfsync everysec => 每隔一秒持久化(默认值)
    • appendfsync no => 不持久化
  • 如果修改了conf配置文件,同样需按如上方式启动

# 布隆过滤器防止缓存穿透

# 缓存穿透

# 是指请求一个不在缓存中的数据,导致请求直接打到后端数据库,进而可能引发数据库压力激增的情况

# 布隆过滤器

# 是一种空间效率高、查询速度快的概率型数据结构,它能够用于判断一个元素是否在一个集合中
# 其基本的设计思想就是通过多个哈希函数将元素映射到一个位数组中
# 所以布隆过滤器能够快速判断一个元素可能存在于集合中
# 但由于其特性,可能会误判(即假阳性),因此就不能完全替代真实的集合

# 布隆过滤器的基本原理

# 位数组:初始化一个位数组(假设大小为m),所有位都设置为0
# 哈希函数:使用k个不同的哈希函数
# 插入元素:将元素通过这k个哈希函数映射到位数组中,将对应的位设为1
# 查询元素:如果k个哈希值对应的位全为1,则认为元素可能存在;如果有任何一个为0,则确定该元素不存在

# 使用布隆过滤器防止缓存穿透

# 在Spring Boot中,可以使用Google的Guava库来实现布隆过滤器,在Guava中提供了一套现成的布隆过滤器
# 我们可以通过这套现成的布隆过滤器来实现。如下所示,先引入相关的配置依赖
  • 集成布隆过滤器
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.0.1-jre</version>
</dependency>
  • 创建布隆过滤器
@Service
public class BloomFilterService {

    private BloomFilter<Integer> bloomFilter;

    @PostConstruct
    public void init() {
        // 初始化布隆过滤器,预计插入100万条数据,错误率0.01%
        bloomFilter = BloomFilter.create(Funnels.integerFunnel(), 1_000_000, 0.01);
    }

    public void put(Integer id) {
        bloomFilter.put(id);
    }

    public boolean mightContain(Integer id) {
        return bloomFilter.mightContain(id);
    }
}
  • 在Controller中使用布隆过滤器,通过过滤器判断请求的数据是否存在
@RestController
public class UserController {

    @Autowired
    private BloomFilterService bloomFilterService;

    @Autowired
    private UserService userService; // 假设有一个UserService类来处理用户数据

    @GetMapping("/user/{id}")
    public User getUser(@PathVariable Integer id) {
        // 先通过布隆过滤器判断
        if (!bloomFilterService.mightContain(id)) {
            return null; // 或者抛出404异常
        }
        
        // 如果可能存在,则查询缓存或数据库
        User user = userService.getUserById(id);
        return user;
    }
}
  • 向布隆过滤器添加数据
// 在进行数据插入操作的时候,我们可以将数据的ID添加到布隆过滤器中
// 如下所示,一般情况下我们可以在数据插入成功之后进行调用
public void saveUser(User user) {
    // 保存用户到数据库
    userRepository.save(user);
    // 将用户ID加入布隆过滤器
    bloomFilterService.put(user.getId());
}