ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

Redis从零到进阶知识总结

2021-04-13 13:59:01  阅读:135  来源: 互联网

标签:AOF 进阶 文件 Redis redis 零到 key RDB


目录

一、Redis是什么

Redis是一个开源的基于内存数据结构存储的作为数据库、缓存和消息代理的组件
Redis提供了例如 string、hashes、lists、sets、sorted sets 等数据结构作为
区间查询、位图、超重对数、空间索引、数据流
Redis包含内置的复制,Lua脚本,LRU驱逐策略,事务和不同级别的持久化机制
并且提供高可用的基于哨兵和自动分区
官方解释:https://redis.io/

二、为什么会有Redis?

随着时代的发展的科技的进步,市面上的应用程序无时无刻不存在的数据存储量大的场景
而如果统一使用关系型数据库将每一次的数据加载都通过IO读取文件磁盘中的数据
将会大大降低系统的承载量与性能,因为IO读取磁盘,而磁盘要进行寻址是ms级别并且会受硬盘带宽影响速度
基于以上场景,非关系型存储应运而生,其中,redis则是作为键值对存储(key-value)最好的代表作
因为redis是基于 in-memory 的方式进行数据存储。而内存的寻址是纳秒(ns)级别的 (s > ms > us > ns )
所以磁盘寻址会比内存寻址上慢了10W倍,并且磁盘的带宽一般都是G/M级别的内存的带宽会比磁盘大很多

三、Redis能帮我们解决什么

一、在数据量大、查询比较频繁的热点数据下,可以通过redis减轻数据库的压力
二、因为redis是内存级别的存储,数据的响应极快,可以提高我们程序的高可用性

四、安装Redis(Linux)

1.下载并解压安装包(可通过redis官网找到下载链接 https://redis.io/)

wget https://download.redis.io/releases/redis-6.2.1.tar.gz
tar -xf redis-6.2.1.tar.gz

2.生成可执行文件程序

进入到解压的redis文件目录中,当中会有一个Makefile文件,执行make编译指令后
这个文件的脚本其实会带着你输入的参数帮你进入到src的目录下去执行真正的Makefile文件
...  make

注意:安装中有可能会报错,是因为脚本执行需要C语言的编译器,需要先安装gcc
...  yum install gcc

安装完gcc后,要对刚刚执行脚本文件生成的一些垃圾文件先进行清空
...  make distclean 

然后再重新执行make命令

2.配置全局变量(可选)

如果需要配置redis的服务每次自动启动,则需要进入到/etc/profile 这个文件下进行配置全局变量
找到最后一行加入自己的配置

...   export REDIS_HOME=你的redis文件地址
...   export PATH=$PATH:$REDIS_HOME/bin

保存后不要忘记让配置生效
... source /etc/profile

3.抽取可执行文件到单独目录(可选)

将make命令生成的几个可执行文件单独输出到你指定的目录,进入到redis的文件目录中执行
... make install PREFIX=你想要输出的文件地址目录

4.使用工具生成多个redis进程(可选)

在redis/utils目录中有一个 install_server.sh 的文件,执行文件后会帮你自动启动一个redis进程
同时会询问你本次redis进程你要
		分配的端口号(默认不填为6379)
		配置文件地址(不指定则帮你分配到/etc/redis/端口号.conf)
		日志地址(不指定则分配到/var/log/redis_端口号.log)
		数据存储地址(不指定则分配到/var/lib/redis/端口号)
		执行redis-server文件的地址(不指定则会找到/usr/local/bin/redis-server)
... ./install_server.sh

所有东西确定好之后按下回车后生成上面相关的操作
日志:
	Copied /tmp/6381.conf => /etc/init.d/redis_6381
	Installing service...
	Successfully added to chkconfig!
	Successfully added to runlevels 345!
	Starting Redis server...
	Installation successful!

从指令日志中我们可以知道redis还会帮我们自动启动这个进程服务的脚本复制到了/etc/init.d/redis_6381

至此,redis安装可以算告一段落


五、Redis五大数据类型

Redis是由Key-Value的数据结构存储,key中有不同的类型和对象信息
Redis中key-value值是二进制安全的,意味着可以用任何二进制序列
key也有对应的类型可以使用 TYPE KEY_NAME 查看key的类型
也可以使用 Object endcoding key 查看的内部编码。每个类型的类型图如下 在这里插入图片描述

一、String(Bit arrays/simply bitmaps)

// 你可以将 String 值当作一系列 bits 处理:可以设置和清除单独的 bits,数出所有设为 1
// 的 bits 的数量,找到最前的被设为 1 或 0 的 bit
// string类型除了一些简单的操作命令之外,还有一些值得需要注意一下 以set k1 v1为例子
1.STRLEN key 
	由于redis是二进制存储的,所以设置进去的v1值是作为二进制序列化的存储 v1: 01110110 00110001
	通过 STRLEN k1 查看值的长度是2,意思是2个字节长度的意思
	
2.BITCOUNT key [start end]
	查看某个key值得start个字节到end字节中有多少个1的存在,以v1为例子
	BITCOUNT k1 0 0 查看key为k1的值中第0个字节到第0个字节中1存在的位数有多少个,输入为5
	
3.BITPOS key bit [start] [end]
	返回字符串中某个第start个字节到第end个字节第一次被设置成0或者1的位置

4.BITOP operation destkey key [key ...]
	对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上
	operation支持 AND(并) 、 OR(或) 、 NOT(非) 、 XOR(异或) 四个参数值
	
string二进制位使用场景
	对电商平台如果要统计每个客户每年的登录天数,如果使用数据库存储则需要最大存储365条数据
	假设平台活跃用户量为1000w人次,那么一年该表的存储量则达到了36.5亿的数据量。如果使用
	redis的二进制位进行存储,利用的二进制0和1的特性,每天登陆则对某个位进行存储1
	那么一个客户最大需要365位存储,每个用户46个字节*1000w用户最终只需要470M	
			 

二、List

在这里插入图片描述

// List值类型是一个按照插入顺序的字符串元素的集合,他们基本上就是链表(双向)
// 而且可以从集合的左边或者右边对元素进行弹出,可以做到类似栈(FILO)和队列(FIFO)的存储效果
// 除了基本的操作之外,有几个需要注意一下的命令如下
1.BLMOVE source destination LEFT|RIGHT LEFT|RIGHT timeout
	从集合中弹出一个元素放到另一个集合中并返回该元素;或者阻塞直到有一个有效元素

2.BLPOP/BRPOP
	移除和获取集合中左/右边的第一个元素或者阻塞指导有一个有效元素	

使用场景:
	某个博主的关注的粉丝、外卖订单的下单顺序等

三、Set

// set是一个不重复且无序的字符串元素的集合
1.SCARD key
	获取某个set中元素的数量

2.SDIFF key [key ...]
	返回一个集合与给定集合的差集的元素

3.SPOP key [count]
	移除和返回一个随机的元素

4.SRANDMEMBER key [count]
	获取一个或多个不重复的随机元素

使用场景:将抽奖的人名字作为元素放入集合中,每次抽奖随机弹出一个或多个中奖人,做到一个人只能中一次奖

四、Hash

// 由field和关联的value组成的map。field和value都是字符串
1.HRANDFIELD key [count [WITHVALUES]]
	获取一个或多个随机属性,加上WITHVALUES会输出filed对应的value

2.HSETNX key field value
	当某个key的field不存在时,才会设置成功

使用场景:
	1.购物车的生成 key:订单号 field:商品属性 
	2.用户登录的信息存储 key:用户的id field:用户属性

五、Sorted Set

sorted set底层实现原理(skip list)

在这里插入图片描述

sorted set底层是基于跳跃表进行实现,根据图解与案例讲解流程如下
1.依次插入前面四个元素的时候会随机造层,当要放入other时
2.根据分值7查找第一层比第一层的最后一个元素大,那么落到L2层
3.L2层依次比较后找到7比8小,则找到L1层orange的位置往前进行比较后选择要插入元素的索引位置

// 类似Sets,但是每个字符串元素都关联到一个叫score浮动数值(floating number value)
// 里面的元素总是通过score进行着排序,所以不同的是,它是可以检索的一系列元素
1.BZPOPMAX/BZPOPMIN key [key ...] timeout
	移除和返回多个sorted sets中最高/低分值的一个或多个元素,或阻塞知道有一个有效的元素

2.ZMSCORE key member [member ...]
	返回某个元素的分值

小结

具体每个类型对应的命令可以通过redis的官网或者客户端通过 helpo @string 等指令进行查看
中文官网地址 http://redis.cn/topics/data-types-intro.html

六、发布/订阅

发送者(发布者)不是计划发送消息给特定的接收者(订阅者)。而是发布的消息分到不同的频道,不需要知道什么样的订阅者订阅。订阅者对一个或多个频道感兴趣,只需接收感兴趣的消息,不需要知道什么样的发布者发布的。这种发布者和订阅者的解耦合可以带来更大的扩展性和更加动态的网络拓扑

1.多个客户端订阅某个channel(通道) SUBSCRIBE myRedis 
2.由发布者对myRedis 管道进行消息的发布 PUBLISH myRedis hello world 
3.多个客户端则会同时收到来自发布者发布的消息

七、管道(Pipelining)

通常情况下一个请求会遵循以下步骤:
客户端向服务端发送一个查询请求,并监听socket返回,通常是以阻塞模式,等待服务端响应
服务端处理命令,并将结果返回给客户端
Client: INCR X
Server: 1
Client: INCR X
Server: 2
Client: INCR X
Server: 3
Client: INCR X
Server: 4

一次请求/响应服务器能实现处理新的请求即使旧的请求还未被响应。
这样就可以将多个命令发送到服务器,而不用等待回复,最后在一个步骤中读取该答复。

这就是管道(pipelining),是一种几十年来广泛使用的技术
例如许多POP3协议已经实现支持这个功能,大大加快了从服务器下载新邮件的过程。

Redis很早就支持管道(pipelining)技术,因此无论你运行的是什么版本
你都可以使用管道(pipelining)操作Redis

八、Redis 事务

Redis中的事务是一个单独的隔离操作:
事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被客户端发送来的命令请求所打断
事务是一个院子操作:事务中的命令要么全部被执行,要么全部都不执行
总的来说只要开启redis事务,下面所执行的命令并不会真正去执行而是存储到了一个队列中
当提交了事务之后会执行队列中的所有命令,如果有一个不成功则全部都会放弃执行

// 开启事务前可以对多个key进行监听,只要在开启事务期间内,其他队监听的key有作操作则本次事务会放弃执行
WATCH k1 k2 

// 开启事务
MULTI

// 执行操作
set k1 v1 
set k2 v2 

// 提交事务/放弃事务
EXEC/DISCARD

九、LRU

一、Maxmemory配置指令

1.当redis被当做缓存来使用,当你新增数据时,让他自动地回收数据是一件很方便的事情
2.LRU是Redis唯一支持的回收方法
3.maxmemory配置指令用于配置Redis存储数据时指定限制的内存大小
4.通过redis.conf可以设置该指令,或者之后使用CONFIG SET命令来进行运行时配置 maxmemory 100mb
5.设置maxmemory为0代表没有内存限制。对于64位的系统这是个默认值,对于32位的系统默认内存限制为3GB。
6.当指定的内存限制大小达到时,需要选择不同的行为,也就是策略。 Redis可以仅仅对命令返回错误,这将使得内存被使用得更多,或者回收一些旧的数据来使得添加数据时可以避免内存限制

二、回收策略

当maxmemory限制达到的时候Redis会使用的行为由Redis的maxmemory-policy配置来进行配置
有以下策略可用:
	noeviction:返回错误当内存限制达到并且客户端尝试执行会让更多内存被使用的命令
	allkeys-lru: 尝试回收最少使用的键(LRU),使得新添加的数据有空间存放
	volatile-lru: 尝试回收最少使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放
	allkeys-random: 回收随机的键使得新添加的数据有空间存放
	olatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键
	volatile-ttl: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放
	如果没有键满足回收的前提条件的话,策略volatile-lru, volatile-random以及volatile-ttl就和noeviction 差不多了
	

十、Redis持久化

Redis持久化提供了两种不同级别的持久化方式:
1:RDB持久化方式能够在指定时间间隔对你的数据进行快照存储
2.AOF持久化方式记录每次对服务器写的操作
当服务器重启的时候会重新执行这些命令来回复原始的数据
AOF命令以redis协议追加保存每次写的操作到文件末尾
Redis还能对AOF文件进行后台重写,使得AOF体积不至于过大

在这里插入图片描述

工作原理

AOF重写和RDB创建快照一样,都巧妙利用了写时复制(copy on write)机制

写时复制:
内核只为新生成的子进程穿件虚拟空间结构,它们来复制于父进程的虚拟空间结构,但是不分配物理内存
它们共享父进程的物理空间,当父子进程中有更改响应段的行为发生时,再为子进程响应的段分配物理空间

RDB:
1.redis调用forks创建子进程,同时拥有父进程和子进程
2.子进程将数据集写入到一个临时RDB文件中
3.当子进程完成对新的RDB文件写入时,Redis用新RDB文件替换原来的RDB文件,并删除旧的RDB文件

AOF:
1.redis执行fork(),同时拥有父进程和子进程
2.子进程开始将新的AOF文件的内容写入到临时文件
3.对于所有新执行的写入命令,父进程一边将它们累积到一个内存缓存中
  一边将这些改动追加到现有的AOF文件的末尾,这样即使在重写的中途发生停机
  现有的AOF文件也是安全的
4.当子进程完成重写工作时,给父进程发送一个信号,父进程在接收到信号之后
  将内存缓存中的所有数据追加到新的AOF文件的末尾
5.Redis院子地用新文件替换旧文件,之后所有命令都会直接追加到新的AOF文件的末尾

RDB

配置

// 打开配置redis配置文件,找到 SNAPSHOTTING 相关文档配置
// redis 会保存DB如果都满足多少秒内修改了多少次的条件,则会出发save指令
save <seconds> <changes>

// RDB存储的文件名
dbfilename dump.rdb

// 文件地址目录
dir /var/lib/redis/6380

总结

优点:
1.非阻塞,速度快,空间小
2.如果存在特定场景,比如关机维护等,可以使用save进行数据的持久化
3.类似于序列化的存储,恢复数据的速度会比较快

缺点:
1.存在时点性问题,一旦某个时间点未出发持久化Redis宕机,则会存在数据丢失量较大
2.不支持拉链,只有一个dump.rdb文件,如果数据较多每次都会全量写入

AOF

AOF文件是一个只进行追加的日志文件,有序地保存了对redis执行的所有以Redis协议的格式保存的写入操作
你可以使用不同的fsync策略:无fsync,每秒fsync,每次写的时候fsync.使用默认的每秒fsync策略
fsync是由后台线程进行处理的,主线程会尽力处理客户端请求),一旦出现故障,你最多丢失1秒的数据.

日志重写

因为aof的运作方式是不断地将命令追加到文件的末尾,随着命令的不断增加AOF的文件体积也会变得越来越大
比如你对某个key不断的设置 1和2的值设置了1w次,那么AOF文件就需要使用1w条记录。
然而实际上这个键的值是为最后一次写入的值,其余的9999条都是多余的
为了处理这种情况,AOD文件进行重建(rebuild)执行BGREWRITERAOF命令,Redis则会生成一个新的文件
这个文件包含重建当前数据集所需的最少命令

配置

// 默认情况下AOF持久化机制是关闭的,需要到配置文件中找到 appendonly 设置成 yes
appendonly no

// 还可以设置写入的策略 appendfsync 默认是每秒写入策略,我们可以使用默认的
# appendfsync always 异步追加写入到日志,缓慢安全的
appendfsync everysec 每秒钟一次
# appendfsync no 不适用异步追加,只要让操作系统在需要的时候刷新数据即可

// 默认追加的文件名
appendfilename "appendonly.aof"

// 将文件基本大小与当前大小进行比较,如果当前大小为大于指定的百分比(auto-aof-rewrite-percentage)
// 重写将会被触发,如果想禁用重写AOF,可以设置百分比为0,默认文件最小尺寸为64m
// 假设基本大小为64m,当前文件大小如果为128m则会触发aof重建机制
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

总结

优点:
1.每次有写入操作都会记录到AOF中,根据默认的异步写入机制,最多丢失的数据为1秒的数据,安全
2.AOF只是对日志文件的追加,所以即使某些原因(磁盘空间已满、写的过程中宕机)未执行完整的写入命令
  也可以使用redis-check-aof工具修复这些问题
3.当aof文件体积过大时,自动地在后台对AOF进行重写。冲写完的AOF文件包含当前数据集的最小指令集合
  并且整个重写是安全的,即使在重写的过程中发生停机,现有的AOF文件也不会丢失

缺点:
1.如果相对于同样的数据集来说,AOF文件的体积要比RDB文件的体积要大
2.根据fsync策略,AOF的速度可能会慢于RDB。在一般情况下,每秒fsync的性能依然非常高
  而关闭fsync可以让AOF的速度和RDB一样快  

持久化选择方案

一般来说, 如果想达到足以媲美 PostgreSQL 的数据安全性, 你应该同时使用两种持久化功能。
如果你非常关心你的数据, 但仍然可以承受数分钟以内的数据丢失, 那么你可以只使用 RDB 持久化。
有很多用户都只使用 AOF 持久化, 但我们并不推荐这种方式: 因为定时生成 RDB 快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快, 除此之外, 使用 RDB 还可以避免之前提到的 AOF 程序的 bug 。
因为以上提到的种种原因, 未来我们可能会将 AOF 和 RDB 整合成单个持久化模型

同时开启AOF与RDB

在Redis2.4版本以前。如果开启AOF则只会对日志指令集的抵消和重复合并
在Redis2.4及以后。如果开启了AOF后那么重写则会将原来的数据以RDB的方法存储到aof文件的头部
再以记录日志的方式持续增长日志
所以:在Redis2.4及以后的版本,AOF是一个混合体。利用的RDB的快和AOF的全量

总结

从上面的笔记总结可以得出几点:
1.Redis是基于内存的可作为缓存/数据库的中间件
2.Redis的持久化方式AOF与RDB的实现原理
3.Redis每种数据类型的特点与使用场景

标签:AOF,进阶,文件,Redis,redis,零到,key,RDB
来源: https://blog.csdn.net/weixin_35570213/article/details/115370442

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有