从零单排学Redis【白银】(一)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 Tair(兼容Redis),内存型 2GB
简介: 笔记

前言

只有光头才能变强

今天继续来学习Redis,上一篇从零单排学Redis【青铜】已经将Redis常用的数据结构过了一遍了。如果还没看的同学可以先去看一遍再回来~

这篇主要讲的内容有:

  • Redis服务器的数据库
  • Redis对过期键的处理
  • Redis持久化策略(RDB和AOF)

本文力求简单讲清每个知识点,希望大家看完能有所收获


一、Redis服务器中的数据库


我们应该都用过MySQL,MySQL我们可以在里边创建好几个库:

30.png

                                              MySQL创建几个数据库

同样地,Redis服务器中也有数据库这么一个概念。如果不指定具体的数量,默认会有16个数据库。

31.jpg                                 通过SELECT命令可以切换到0~15的数据库

上面的命令我们也可以发现:当切换到15号数据库,存进15号库的数据,再切换到0号数据库时,是获取不到的!

  • 这说明,数据库与数据库之间的数据是隔离的。


1.1Redis数据库的原理


Redis服务器用redisServer结构体来表示,其中redisDb是一个数组,用来保存所有的数据库,dbnum代表数据库的数量(这个可以配置,默认是16)

struct redisServer{  
    //redisDb数组,表示服务器中所有的数据库
    redisDb *db;  
    //服务器中数据库的数量
    int dbnum;  
};

我们知道Redis是C/S结构,Redis客户端通过redisClient结构体来表示:

typedef struct redisClient{  
    //客户端当前所选数据库
    redisDb *db;  
}redisClient;

Redis客户端连接Redis服务端时的示例图:

32.jpg                                Redis客户端连接Redis服务端时的示例图

Redis中对每个数据库用redisDb结构体来表示:

typedef struct redisDb { 
    int id;         // 数据库ID标识
    dict *dict;     // 键空间,存放着所有的键值对              
    dict *expires;  // 过期哈希表,保存着键的过期时间                          
    dict *watched_keys; // 被watch命令监控的key和相应client    
    long long avg_ttl;  // 数据库内所有键的平均TTL(生存时间)     
} redisDb;

从代码上我们可以发现最重要的应该是dict *dict,它用来存放着所有的键值对。对于dict数据结构(哈希表)我们在上一篇也已经详细说了。一般我们将存储所有键值对的dict称为键空间

键空间示意图:

33.jpg                                              键空间示意图

Redis的数据库就是使用字典(哈希表)来作为底层实现的,对数据库的增删改查都是构建在字典(哈希表)的操作之上的

例如:

redis > GET message
"hello world"

34.jpg                                              查找键的示意图


1.2键的过期时间


Redis是基于内存,内存是比较昂贵的,容量肯定比不上硬盘的。就我们现在一台普通的机子,可能就8G内存,但硬盘随随便便都1T了。

因为我们的内存是有限的。所以我们会干掉不常用的数据,保留常用的数据。这就需要我们设置一下键的过期(生存)时间了。

  • 设置键的生存时间可以通过EXPIRE或者PEXPIRE命令。
  • 设置键的过期时间可以通过EXPIREAT或者PEXPIREAT命令。

其实EXPIREPEXPIREEXPIREAT这三个命令都是通过PEXPIREAT命令来实现的。

我们在redisDb结构体中还发现了dict *expires;属性,存放所有键过期的时间。

举个例子基本就可以理解了:

redis > PEXPIREAT message 1391234400000
(integer) 1

设置了message键的过期时间为1391234400000

35.jpg                                    新增一个过期时间的键

既然有设置过期(生存)时间的命令,那肯定也有移除过期时间,查看剩余生存时间的命令了:

  • PERSIST(移除过期时间)
  • TTL(Time To Live)返回剩余生存时间,以秒为单位
  • PTTL以毫秒为单位返回键的剩余生存时间


1.2.1过期策略


上面我们已经能够了解到:过期键是保存在哈希表中了。那这些过期键到了过期的时间,就会立马被删除掉吗??

要回答上面的问题,需要我们了解一下删除策略的知识,删除策略可分为三种

  • 定时删除(对内存友好,对CPU不友好)
  • 到时间点上就把所有过期的键删除了。
  • 惰性删除(对CPU极度友好,对内存极度不友好)
  • 每次从键空间取键的时候,判断一下该键是否过期了,如果过期了就删除。
  • 定期删除(折中)
  • 每隔一段时间去删除过期键,限制删除的执行时长和频率。

Redis采用的是惰性删除+定期删除两种策略,所以说,在Redis里边如果过期键到了过期的时间了,未必被立马删除的!


1.2.2内存淘汰机制


如果定期删除漏掉了很多过期key,也没及时去查(没走惰性删除),大量过期key堆积在内存里,导致redis内存块耗尽了,咋整?

我们可以设置内存最大使用量,当内存使用量超出时,会施行数据淘汰策略

Redis的内存淘汰机制有以下几种:

36.jpg                                        内存淘汰机制

一般场景:

使用 Redis 缓存数据时,为了提高缓存命中率,需要保证缓存数据都是热点数据。可以将内存最大使用量设置为热点数据占用的内存量,然后启用allkeys-lru淘汰策略,将最近最少使用的数据淘汰


二、Redis持久化


Redis是基于内存的,如果不想办法将数据保存在硬盘上,一旦Redis重启(退出/故障),内存的数据将会全部丢失。

  • 我们肯定不想Redis里头的数据由于某些故障全部丢失(导致所有请求都走MySQL),即便发生了故障也希望可以将Redis原有的数据恢复过来,这就是持久化的作用。

Redis提供了两种不同的持久化方法来讲数据存储到硬盘里边:

  • RDB(基于快照),将某一时刻的所有数据保存到一个RDB文件中。
  • AOF(append-only-file),当Redis服务器执行写命令的时候,将执行的写命令保存到AOF文件中。


2.1RDB(快照持久化)


RDB持久化可以手动执行,也可以根据服务器配置定期执行。RDB持久化所生成的RDB文件是一个经过压缩的二进制文件,Redis可以通过这个文件还原数据库的数据。

37.jpg                                             RDB文件还原数据

有两个命令可以生成RDB文件:

  • SAVE阻塞Redis服务器进程,服务器不能接收任何请求,直到RDB文件创建完毕为止。
  • BGSAVE创建出一个子进程,由子进程来负责创建RDB文件,服务器进程可以继续接收请求。

Redis服务器在启动的时候,如果发现有RDB文件,就会自动载入RDB文件(不需要人工干预)

  • 服务器在载入RDB文件期间,会处于阻塞状态,直到载入工作完成。

除了手动调用SAVE或者BGSAVE命令生成RDB文件之外,我们可以使用配置的方式来定期执行:

在默认的配置下,如果以下的条件被触发,就会执行BGSAVE命令

save 900 1              #在900秒(15分钟)之后,至少有1个key发生变化,
    save 300 10            #在300秒(5分钟)之后,至少有10个key发生变化
    save 60 10000        #在60秒(1分钟)之后,至少有10000个key发生变化

原理大概就是这样子的(结合上面的配置来看):

struct redisServer{
    // 修改计数器
    long long dirty;
    // 上一次执行保存的时间
    time_t lastsave;
    // 参数的配置
    struct saveparam *saveparams;
};

遍历参数数组,判断修改次数和时间是否符合,如果符合则调用besave()来生成RDB文件

38.jpg                                               Redis服务器的状态

总结:通过手动调用SAVE或者BGSAVE命令或者配置条件触发,将数据库某一时刻的数据快照,生成RDB文件实现持久化。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
缓存 NoSQL Redis
|
NoSQL 关系型数据库 MySQL
从零单排学Redis【白银】
Redis持久化、数据库、对过期键的处理
1186 0
|
1月前
|
存储 缓存 NoSQL
数据的存储--Redis缓存存储(一)
数据的存储--Redis缓存存储(一)
|
1月前
|
存储 缓存 NoSQL
数据的存储--Redis缓存存储(二)
数据的存储--Redis缓存存储(二)
数据的存储--Redis缓存存储(二)
|
1月前
|
消息中间件 缓存 NoSQL
Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。
【10月更文挑战第4天】Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。随着数据增长,有时需要将 Redis 数据导出以进行分析、备份或迁移。本文详细介绍几种导出方法:1)使用 Redis 命令与重定向;2)利用 Redis 的 RDB 和 AOF 持久化功能;3)借助第三方工具如 `redis-dump`。每种方法均附有示例代码,帮助你轻松完成数据导出任务。无论数据量大小,总有一款适合你。
68 6
|
1月前
|
缓存 NoSQL 关系型数据库
redis和缓存及相关问题和解决办法 什么是缓存预热、缓存穿透、缓存雪崩、缓存击穿
本文深入探讨了Redis缓存的相关知识,包括缓存的概念、使用场景、可能出现的问题(缓存预热、缓存穿透、缓存雪崩、缓存击穿)及其解决方案。
159 0
redis和缓存及相关问题和解决办法 什么是缓存预热、缓存穿透、缓存雪崩、缓存击穿
|
8天前
|
缓存 NoSQL Redis
Redis 缓存使用的实践
《Redis缓存最佳实践指南》涵盖缓存更新策略、缓存击穿防护、大key处理和性能优化。包括Cache Aside Pattern、Write Through、分布式锁、大key拆分和批量操作等技术,帮助你在项目中高效使用Redis缓存。
66 22
|
7天前
|
缓存 NoSQL 中间件
redis高并发缓存中间件总结!
本文档详细介绍了高并发缓存中间件Redis的原理、高级操作及其在电商架构中的应用。通过阿里云的角度,分析了Redis与架构的关系,并展示了无Redis和使用Redis缓存的架构图。文档还涵盖了Redis的基本特性、应用场景、安装部署步骤、配置文件详解、启动和关闭方法、systemctl管理脚本的生成以及日志警告处理等内容。适合初学者和有一定经验的技术人员参考学习。
64 7
|
12天前
|
存储 缓存 监控
利用 Redis 缓存特性避免缓存穿透的策略与方法
【10月更文挑战第23天】通过以上对利用 Redis 缓存特性避免缓存穿透的详细阐述,我们对这一策略有了更深入的理解。在实际应用中,我们需要根据具体情况灵活运用这些方法,并结合其他技术手段,共同保障系统的稳定和高效运行。同时,要不断关注 Redis 缓存特性的发展和变化,及时调整策略,以应对不断出现的新挑战。
44 10
|
12天前
|
缓存 监控 NoSQL
Redis 缓存穿透的检测方法与分析
【10月更文挑战第23天】通过以上对 Redis 缓存穿透检测方法的深入探讨,我们对如何及时发现和处理这一问题有了更全面的认识。在实际应用中,我们需要综合运用多种检测手段,并结合业务场景和实际情况进行分析,以确保能够准确、及时地检测到缓存穿透现象,并采取有效的措施加以解决。同时,要不断优化和改进检测方法,提高检测的准确性和效率,为系统的稳定运行提供有力保障。
42 5