首页 > 数据库 >二、Redis架构

二、Redis架构

时间:2023-11-19 22:11:36浏览次数:34  
标签:AOF 127.0 架构 0.1 Redis k1 key 7000

一、持久化机制

 

client redis[内存] -----> 内存数据- 数据持久化-->磁盘

 

Redis官方提供了两种不同的持久化方法来将内存的数据存储到硬盘里面分别是:

 

  • 快照(Snapshot)

  • AOF (Append Only File) 只追加日志文件

1、快照

①特点:这种方式可以将某一时刻的所有数据都写入硬盘中,当然这也是redis的默认开启持久化方式,保存的文件是以.rdb形式结尾的文件因此这种方式也称之为RDB方式。

官方说法叫快照持久化

默认情况下,redis服务在哪个目录下启动,哪个目录就是工作目录,后面的rdb持久化或者AOF持久化,产生的文件都存在于redis的当前工作目录下。在哪里启动就会读取哪里的快照文件

 

 

 

 

                                                Redis两种持久化方式

 1.1、快照生成方式

  • 客户端方式: BGSAVE 和 SAVE指令

  • 服务器配置自动触发

# 1.客户端方式之BGSAVE
- a.客户端可以使用BGSAVE命令来创建一个快照,当接收到客户端的BGSAVE命令时,redis会调用fork¹来创建一个子进程,然后子进程负责将快照写入磁盘中,而父进程则继续处理命令请求。

`名词解释: fork当一个进程创建子进程的时候,底层的操作系统会创建该进程的一个副本,在类似于unix系统中创建子进程的操作会进行优化:在刚开始的时候,父子进程共享相同内存,直到父进程或子进程对内存进行了写之后,对被写入的内存的共享才会结束服务`

 

 

# 2.客户端方式之SAVE

  • 注意: SAVE命令并不常用,使用SAVE命令在快照创建完毕之前,redis处于阻塞状态,无法对外服务

- b.客户端还可以使用SAVE命令来创建一个快照,接收到SAVE命令的redis服务器在快照创建完毕之前将不再响应任何其他的命令

 

 

# 3.服务器配置方式之满足配置自动触发
- 如果用户在redis.conf中设置了save配置选项,redis会在save选项条件满足之后自动触发一次BGSAVE命令,如果设置多个save配置选项,当任意一个save配置选项条件满足,redis也会触发一次BGSAVE命令

 

# 4.服务器接收客户端shutdown指令
- 当redis通过shutdown指令接收到关闭服务器的请求时,会执行一个save命令,阻塞所有的客户端,不再执行客户端执行发送的任何命令,并且在save命令执行完毕之后关闭服务器

1.2.配置生成快照名称和位置

#1.修改生成快照名称
- dbfilename dump.rdb

# 2.修改生成位置
- dir ./

 2  AOF 只追加日志文件

2.1.特点

这种方式可以将所有客户端执行的写命令记录到日志文件中,AOF持久化会将被执行的写命令写到AOF的文件末尾,

以此来记录数据发生的变化,因此只要redis从头到尾执行一次AOF文件所包含的所有写命令,就可以恢复AOF文件的记录的数据集.

2.2.开启AOF持久化

在redis的默认配置中AOF持久化机制是没有开启的,需要在配置中开启

# 1.开启AOF持久化
- a.修改 appendonly yes 开启持久化
- b.修改 appendfilename "appendonly.aof" 指定生成文件名称

 

 

 

 

 

2.3 日志追加频率

# 1.always 【谨慎使用】
- 说明: 每个redis写命令都要同步写入硬盘,严重降低redis速度
- 解释: 如果用户使用了always选项,那么每个redis写命令都会被写入硬盘,从而将发生系统崩溃时出现的数据丢失减到最少;遗憾的是,因为这种同步策略需要对硬盘进行大量的写入操作,所以redis处理命令的速度会受到硬盘性能的限制;
- 注意: 转盘式硬盘在这种频率下200左右个命令/s ; 固态硬盘(SSD) 几百万个命令/s;
- 警告: 使用SSD用户请谨慎使用always选项,这种模式不断写入少量数据的做法有可能会引发严重的`写入放大`问题,导致将固态硬盘的寿命从原来的几年降低为几个月。

# 2.everysec 【推荐默认】
- 说明: 每秒执行一次同步显式的将多个写命令同步到磁盘
- 解释: 为了兼顾数据安全和写入性能,用户可以考虑使用everysec选项,让redis每秒一次的频率对AOF文件进行同步;redis每秒同步一次AOF文件时性能和不使用任何持久化特性时的性能相差无几,而通过每秒同步一次AOF文件,redis可以保证,即使系统崩溃,用户最多丢失一秒之内产生的数据。 

# 3.no    【不推荐】
- 说明: 由操作系统决定何时同步 
- 解释:最后使用no选项,将完全由操作系统决定什么时候同步AOF日志文件,这个选项不会对redis性能带来影响但是系统崩溃时,会丢失不定数量的数据,甚至丢失全部数据,另外如果用户硬盘处理写入操作不够快的话,当缓冲区被等待写入硬盘数据填满时,redis会处于阻塞状态,并导致redis的处理命令请求的速度变慢。

 

 

2.4  修改同步频率

# 1.修改日志同步频率
- 修改appendfsync everysec|always|no 指定

 

 

 

 

 

3 AOF文件的重写(面试必问)

3.1 AOF带来的问题

AOF的方式也同时带来了另一个问题。持久化文件会变的越来越大。例如我们调用incr test命令100次,文件中必须保存全部的100条命令,其实有99条都是多余的。因为要恢复数据库的状态其实文件中保存一条set test 100就够了。为了压缩aof的持久化文件Redis提供了AOF重写(ReWriter)机制。

3.2. AOF重写

用来在一定程度上减小AOF文件的体积,并且还能保证数据不丢失

3.3. 触发重写方式

# 1.客户端方式触发重写
- 执行BGREWRITEAOF命令  不会阻塞redis的服务

# 2.服务器配置方式自动触发
- 配置redis.conf中的auto-aof-rewrite-percentage选项 参加下图↓↓↓
- 如果设置auto-aof-rewrite-percentage值为100和auto-aof-rewrite-min-size 64mb,并且启用的AOF持久化时,那么当AOF文件体积大于64M,并且AOF文件的体积比上一次重写之后体积大了至少一倍(100%)时,会自动触发,如果重写过于频繁,用户可以考虑将auto-aof-rewrite-percentage设置为更大

 

 

3.4. 重写原理

从 Redis 7.0.0 开始,Redis 使用了多部分 AOF 机制。也就是将原来的单个AOF文件拆分为基础文件(最多一个)和增量文件(可能不止一个)。

基本文件表示重写AOF 时存在的数据的初始(RDB 或 AOF 格式)快照。增量文件包含自创建最后一个基本 AOF 文件用来来的增量更改。所有这些文件都放在一个单独的目录中,并由清单文件跟踪。

从 Redis 7.0.0 开始,在调度 AOF 重写时,Redis 父进程会打开一个新的增量 AOF 文件继续写入。子进程执行重写逻辑并生成新的基础 AOF。

Redis 将使用一个临时清单文件来跟踪新生成的基础文件和增量文件。当它们准备好后,Redis 会执行原子替换操作,使这个临时清单文件生效。

为了避免在 AOF 重写重复失败和重试的情况下创建大量增量文件的问题,Redis 引入了 AOF 重写限制机制,以确保失败的 AOF 重写以越来越慢的速度重试。

 

日志重写

注意:重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,替换原有的文件这点和快照有点类似。

# 重写流程
- 1. redis调用fork ,现在有父子两个进程 子进程根据内存中的数据库快照,往临时文件中写入重建数据库状态的命令
- 2. 父进程继续处理client请求,除了把写命令写入到原来的aof文件中。同时把收到的写命令缓存起来。这样就能保证如果子进程重写失败的话并不会出问题。
- 3. 当子进程把快照内容写入已命令方式写到临时文件中后,子进程发信号通知父进程。然后父进程把缓存的写命令也写入到临时文件。
- 4. 现在父进程可以使用临时文件替换老的aof文件,并重命名,后面收到的写命令也开始往新的aof文件中追加。

 

 

 

 

4 持久化总结

两种持久化方案既可以同时使用(aof),又可以单独使用,在某种情况下也可以都不使用,具体使用那种持久化方案取决于用户的数据和应用决定。

无论使用AOF还是快照机制持久化,将数据持久化到硬盘都是有必要的,除了持久化外,用户还应该对持久化的文件进行备份(最好备份在多个不同地方)。

 

 

2、位图

零存零取,整存零取,整存整取

1.bitmap介绍

位图不是真正的数据类型,它是定义在字符串类型中,一个字符串类型的值最多能存储512M字节的内容

位上限:2^(9(512)+10(1024)+10(1024)+3(8b=1B))=2^32b

2.setbit 设置某一位上的值

语法:SETBIT key offset value (offset位偏移量,从0开始)

127.0.0.1:7000> flushall
OK
127.0.0.1:7000> setbit k1 1 1
0
127.0.0.1:7000> get k1
@
127.0.0.1:7000> setbit k1 7 1
0
127.0.0.1:7000> get k1
A
127.0.0.1:7000> setbit k1 7 2
ERR bit is not an integer or out of range

 

 

127.0.0.1:7000> setbit k1 9 1
0

127.0.0.1:7000> get k1
A@

 

 

3.getbit 获取某一位上的值

语法:GETBIT key offset

127.0.0.1:7000> getbit k1 7
1
127.0.0.1:7000> getbit k1 8
0
127.0.0.1:7000> getbit k1 1
1

 

4.bitpos返回指定值0或者1在指定区间上首次出现的下标

语法:BITPOS key bit [start] [end](字节索引,0表示第一个字节)

 

summary: Find first bit set or clear in a string

since: 2.8.7

group: string

不指定查找范围,表示从全部内容中查找:BITPOS key bit

127.0.0.1:7000> keys *
k1
127.0.0.1:7000> bitpos k1 1
1
127.0.0.1:7000> setbit k1 1 0
1
127.0.0.1:7000> bitpos k1 1
7
127.0.0.1:7000> setbit k1 7 0
1
127.0.0.1:7000> bitpos k1 1
9

 

 

 

指定查找范围:

BITPOS key bit start :从start+1个字节开始查找,直到尾部 BITPOS key bit start end:从start+1字节开始到end+1字节之间查找

然后将数据还原:

 

127.0.0.1:7000> setbit k1 1 1
0
127.0.0.1:7000> setbit k1 7 1
0

查找演示:

127.0.0.1:7000> bitpos k1 1 0 0
1 #在第一个字节中查找1首次出现的下标
127.0.0.1:7000> bitpos k1 1 0
1 #从第一个字节到值得最后一个字节查找1首次出现的下标
127.0.0.1:7000> setbit k1 1 0
1 #将指定下标的值改为0
127.0.0.1:7000> bitpos k1 1 0 0
7 #
127.0.0.1:7000> bitpos k1 1 0
7
127.0.0.1:7000> setbit k1 7 0
1
127.0.0.1:7000> bitpos k1 1 0 0
-1  #在第一个字节中没有找到1,则返回-1
127.0.0.1:7000> bitpos k1 1 0
9  #从第一个字节到值得最后一个字节查找
127.0.0.1:7000> bitpos k1 1 0 1
9 #在第1和第2个字节总找1首次出现的位置
127.0.0.1:7000> bitpos k1 1 0 2
9 #在第1到第3个字节查找1首次出现的位置,但数据总共2(小于end对应的3)个字节,不会抛错。

 

 

5.bitop位操作

语法:BITOP operation destkey key [key ...]

summary: Perform bitwise operations between strings

since: 2.6.0

group: string

对一个或多个保存二进制位的字符串 key 进行位操作,并将结果保存到 destkey 上。operation 可以是 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种

BITOP AND destkey key [key ...] ,对一个或多个 key 求逻与,并将结果保存到 destkey

BITOP OR destkey key [key ...] ,对一个或多个 key 求逻辑或,并将结果保存到 destkey

BITOP XOR destkey key [key ...] ,对一个或多个 key 求逻辑异或,并将结果保存到 destkey

BITOP NOT destkey key ,对给定 key 求逻辑非,并将结果保存到 destkey

除了 NOT 操作之外,其他操作都可以接受一个或多个 key 作为输入,当 BITOP 处理不同长度的字符串时,较短的那个字符串所缺少的部分会被看作 0,空的 key 也被看作是包含 0 的字符串序列

BITOP AND destkey key [key ...]演示:

127.0.0.1:7000> flushall
OK
127.0.0.1:7000> keys *
(empty list or set)
127.0.0.1:7000> setbit k1 1 1
(integer) 0
127.0.0.1:7000> setbit k2 7 1
(integer) 0
127.0.0.1:7000> bitop and k3 k1 k2
(integer) 1
127.0.0.1:7000> get k3
"\x00"

 

BITOP OR destkey key [key ...]演示

127.0.0.1:7000> bitop or k4 k1 k2
(integer) 1
127.0.0.1:7000> get k4
"A"

BITOP XOR destkey key [key ...]

127.0.0.1:7000> bitop xor k5 k1 k2
(integer) 1
127.0.0.1:7000> get k5
"A"

 

 

 

127.0.0.1:7000> bitop not k6 k1
(integer) 1
127.0.0.1:7000> get k6
"\xbf"

 

 

 

 

 

6.bitcount

统计指定位区间上值为1的个数

  1. BITCOUNT key [start] [end] start end 字节的索引 正方向

从左向右从0开始,注意官方start、end是位,测试后是字节

127.0.0.1:7000> get k1
"@"
127.0.0.1:7000> bitcount k1
(integer) 1
127.0.0.1:7000> setbit k1 7 1
(integer) 0
127.0.0.1:7000> bitcount k1
(integer) 2
127.0.0.1:7000> setbit k1 9 1
(integer) 0
127.0.0.1:7000> bitcount k1
(integer) 3 #统计全部的1的总数
127.0.0.1:7000> bitcount k1 0 0
(integer) 2 #统计第一个字节中1出现的总数
127.0.0.1:7000> bitcount k1 0 1
(integer) 3 #统计第0+1到第1+1字节中1出现的总数
  1. BITCOUNT key [start] [end] start end 字节的索引 负方向

从右向左从-1开始,注意官方start、end是位,测试后是字节

127.0.0.1:7000>BITCOUNT k1  0  -1 #等同于BITCOUNT k1
 (integer) 3

 

最常用的就是 BITCOUNT k1

7.Redis的二进制位

127.0.0.1:7000> set k7 ab
OK
127.0.0.1:7000> get k7
"ab"
127.0.0.1:7000> bitcount k7
(integer) 6
127.0.0.1:7000> bitcount k7 0 0
(integer) 3
127.0.0.1:7000> bitcount k7 1 1
(integer) 3

 

 

127.0.0.1:7000> set k8 中
OK
127.0.0.1:7000> bitcount k8
(integer) 13
127.0.0.1:7000> get k8
"\xe4\xb8\xad"

 

8.Bitmap应用场景

网站用户签到的天数统计

用户ID为key,天作为offset,上线置为1 366> 000000000000000

366 /8=46Byte ID为18的用户,今年的第1天签到、第30天签到

127.0.0.1:7000[2]> setbit u18 1 1
(integer) 0
127.0.0.1:7000[2]> setbit u18 30 1
(integer) 0
127.0.0.1:7000[2]> bitcount u18 #统计id为18的用户签到总次数
(integer) 2
127.0.0.1:7000[2]> keys u*
1) "u18"

 

按天统计网站活跃用户

天作为key,用户ID为offset,上线置为1

求一段时间内活跃用户数 5000 0000 / 8366= 6.3MB=366 (五千万活跃用户1年才产生2GB左右的数据)

127.0.0.1:7000>SETBIT 20190601 5  1    #0000 0100
127.0.0.1:7000>SETBIT 20190602 7  1    #0000 0001 
127.0.0.1:7000>SETBIT 20190603 7  1    #0000 0001
求6月1日到6月10日的活跃用户数
127.0.0.1:7000>BITOP OR users 20190601 20190602 20190603 ... 20190610
127.0.0.1:7000>BITCOUNT users    #目标key为users
结果为2

 

用户在线状态、在线人数统计

127.0.0.1:7000> SETBIT online 5  1 #0000 0100 上线为1
(integer) 0
127.0.0.1:7000> SETBIT online 7  1 #0000 0101
(integer) 0
127.0.0.1:7000> bitcount online #当前在线人数
(integer) 2 
127.0.0.1:7000> SETBIT online 7  0
(integer) 1
127.0.0.1:7000> bitcount online #当前在线人数
(integer) 1

 

 

 

3. java操作Redis

3.1 环境准备

1. 引入依赖

<!--引入jedis连接依赖-->
<dependency>
  <groupId>redis.clients</groupId>
  <artifactId>jedis</artifactId>
  <version>4.3.2</version>
</dependency>

 

2.创建jedis对象

 public static void main(String[] args) {
   //1.创建jedis对象
   Jedis jedis = new Jedis("192.168.40.110", 7000);//1.redis服务必须关闭防火墙  2.redis服务必须开启远程连接
   jedis.select(0);//选择操作的库默认0号库
   //2.执行相关操作
   //....
   //3.释放资源
   jedis.close();
 }

 

3.2 操作key相关API

    //测试与key相关的操作
    @Test
    public void testKey(){
        jedis.set("name","xiaohu");
        jedis.set("age","18");
        jedis.set("age1","19");
        jedis.set("age2","20");
        jedis.set("age3","21");
        //删除一个键
        long l = jedis.del("age1");
        if(l==1){
            System.out.println("成功删除age1键");
        }
        //删除多个键
        long l2 = jedis.del("age2", "age3");
        if(l2>1){
            System.out.println("成功删除多个键");
        }
​
        //判断是否存在
        boolean name = jedis.exists("age1");
        if(name==true){
            System.out.println("键存在");
        }
​
        jedis.expire("age",10L);
​
​
    }

 

     

 

标签:AOF,127.0,架构,0.1,Redis,k1,key,7000
From: https://www.cnblogs.com/SIKE231310/p/17839606.html

相关文章

  • Redis主从有几种常见的拓扑结构?
    Redis的复制拓扑结构可以支持单层或多层复制关系,根据拓扑复杂性可以分为以下三种:一主一从、一主多从、树状主从结构。1.一主一从结构一主一从结构是最简单的复制拓扑结构,用于主节点出现宕机时从节点提供故障转移支持。2.一主多从结构一主多从结构(又称为星形拓扑结构)使得应用端可......
  • 从 Mysql 架构上如何查询 sql 的执行过程?
    MySQL是一种流行的关系型数据库管理系统(RDBMS),由瑞典MySQLAB公司开发,目前属于甲骨文公司(Oracle)旗下。MySQL是基于SQL语言的一个开源数据库,可以用于存储、管理、检索数据。它支持大量的并发用户连接,并且提供了灵活的数据类型和索引机制。MySQL有多个版本,包括社区版和商业版,提供了不......
  • Redis7 纯缓存模式
    1、同时关闭RDB+AOF2、禁用rdbsave""禁用rdb持久化模式,我们仍然可以使用save、bgsave生成rdb文件3、禁用aofappendonlyno禁用aof持久化模式下,我们仍然可以使用命令bgrewriteaof生成aof文件......
  • 9、Redis复制(replica)【面试重点】
    一、是什么二、能干嘛三、怎么玩1、权限细节2、基本操作命令四、案例演示1、架构说明2、小口诀3、修改配置文件细节操作4、常用3招4.1一主二仆4.1.1方案1:配置文件固定写死(1)从机配置replicaof及masterauth(2)先启动master后启动两......
  • Canal+Kafka实现MySQL与Redis数据同步(二)
    Canal+Kafka实现MySQL与Redis数据同步(二)创建MQ消费者进行同步在application.yml配置文件加上kafka的配置信息:spring:kafka:#Kafka服务地址bootstrap-servers:127.0.0.1:9092consumer:#指定一个默认的组名group-id:consumer-group1......
  • Redis缓存雪崩、击穿、穿透解释及解决方法,缓存预热,布隆过滤器 ,互斥锁
    Redis缓存雪崩、击穿、穿透解释及解决方法,缓存预热,布隆过滤器,互斥锁......
  • 在Linux环境安装redis步骤,且设置开机自动启动redis
    原创/朱季谦最近一直在学习redis相关知识,看了很多理论知识后,觉得还是要多动手操作,就如王阳明说的知行合一那样,因此,便决定在linux环境安装了redis,过程捣鼓了一番,也遇到了一些波折,但最后还是成功安装完成,顺便把步骤流程记录了下来,分享给有需要的小伙伴。1.首先,我在linux的/usr/local/......
  • x86架构平台安装模拟arm架构系统
    最近工作中需要给ARM架构的服务器安装Python的Conda开发环境,而且服务器不能连接外网。手动安装有些繁琐,最方便的方式是在另一台相同配置的机器上安装好,然后将环境整体打包上传到服务器。但是我手头的电脑都是x86架构,在不购买云服务器的情况下,怎样才能弄一台ARM的机器呢......
  • 8、Redis发布订阅(了解即可)
    一、是什么二、能干嘛三、常用命令(1)(2)(3)(4)(5)(6)四、案例演示1、当堂演示2、小总结pub/sub缺点......
  • 7、Redis管道
    问题由来一、是什么二、案例演示三、小总结1、pipeline与原生批量命令对比2、pipeline与事务对比3、使用pipeline注意事项......