Redis详解和学习(一)

为什么要引入(使用)Redis?

在一开始学习Redis时,或许我们会有这么一个疑问?都是数据库,为什么我们不用Mysql,SQLServer,还要弄个Redis,偏偏面试,实际应用中还很常见,这是为什么?

1.速度快,因为Redis是基于内存的,我们知道,内存的读写速度肯定快于磁盘的读写,那么,当我们对读写速度有一定要求时,便需要使用到Redis

2.用作缓存,既然Redis的处理速度快,那么我们就可以利用它的这个特点,当多个请求同时要求读写数据库时,用Redis做个缓存,以防数据将数据库打崩

3.使用key-value键值对存储,在二元组情形下十分适用(在这也留个讨论题,Redis为什么要使用键值对存储?)

4.其高可用和持久化的特性。(后面会详细阐述)

好像mysql中有个存储引擎为MEMORY也是基于内存,那为什么不用呢?

是的,mysql中也有基于内存的存储引擎Memory的使用。且两者的性能也差不多,但它有以下缺点:

1.memory 存储引擎表只有一个独立的磁盘文件,扩展名为.frm memory 存储引擎只存放表定义不存放数据。当我们重启电脑或者因为宕机电脑出故障时,会导致创建的表的数据全部丢失!!!只保留了表结构。

2.Memory不支持行锁只支持表锁,那么在高并发的条件下,其性能便显而易见

Redis的基本数据类型

(一)、五种基本数据类型(指的是value,key的类型只有string)

1.String:
String 类型是 Redis 中最常使用的类型,内部的实现是通过 SDS(Simple Dynamic String )来存储的。SDS 类似于 Java 中的 ArrayList,可以通过预分配冗余空间的方式来减少内存的频繁分配。这是最简单的类型,就是普通的 set 和 get,做简单的 KV 缓存。
SDS源码如下:

struct sdshdr{
     //记录buf数组中已使用字节的数量
     //等于 SDS 保存字符串的长度
     int len;
     //记录 buf 数组中未使用字节的数量
     int free;
     //字节数组,用于保存字符串
     char buf[];
}

String的实际应用场景比较广泛的有:
缓存功能:String字符串是最常用的数据类型,不仅仅是Redis,各个语言都是最基本类型,因此,利用Redis作为缓存,配合其它数据库作为存储层,利用Redis支持高并发的特点,可以大大加快系统的读写速度、以及降低后端数据库的压力。

计数器:许多系统都会使用Redis作为系统的实时计数器,可以快速实现计数和查询的功能。而且最终的数据结果可以按照特定的时间落地到数据库或者其它存储介质当中进行永久保存。

共享用户Session:用户重新刷新一次界面,可能需要访问一下数据进行重新登录,或者访问页面缓存Cookie,但是可以利用Redis将用户的Session集中管理,在这种模式只需要保证Redis的高可用,每次用户Session的更新和获取都可以快速完成。大大提高效率。

2.Hash:
这个是类似 Map 的一种结构,(数组+链表)这个一般就是可以将结构化的数据,比如一个对象(前提是这个对象没嵌套其他的对象)给缓存在 Redis 里,然后每次读写缓存的时候,可以就操作 Hash 里的某个字段。

3.List:
List 是有序列表。双向链表,(按照插入顺序排序)可以应用于消息队列,分页查询等

4.Set:
Set 是无序集合,会自动去重的那种。
如果你需要对一些数据进行快速的全局去重,你当然也可以基于 JVM 内存里的 HashSet 进行去重,但是如果你的某个系统部署在多台机器上呢?得基于Redis进行全局的 Set 去重。Set还可以应用于交集,并集的求解

5.Sorted Set:
Sorted set 是排序的 Set,去重但可以排序,写进去的时候给一个分数,自动根据分数排序。

有序集合的使用场景与集合类似,但是set集合不是自动有序的,而Sorted set可以利用分数进行成员间的排序,而且是插入时就排序好。所以当你需要一个有序且不重复的集合列表时,就可以选择Sorted set数据结构作为选择方案。

排行榜:有序集合经典使用场景。例如视频网站需要对用户上传的视频做排行榜,榜单维护可能是多方面:按照时间、按照播放量、按照获得的赞数等。

用Sorted Sets来做带权重的队列,比如普通消息的score为1,重要消息的score为2,然后工作线程可以选择按score的倒序来获取工作任务。让重要的任务优先执行。

(二)、高级用法:(详讲见后续更新)

Bitmap :
位图是支持按 bit 位来存储信息,可以用来实现布隆过滤器(BloomFilter);
具体介绍查看这篇博客:Bitmap和Bloom Filiter(布隆过滤器)

HyperLogLog:
供不精确的去重计数功能,比较适合用来做大规模数据的去重统计,例如统计 UV;

Geospatial:
可以用来保存地理位置,并作位置距离计算或者根据半径计算位置等。有没有想过用Redis来实现附近的人?或者计算最优地图路径?

pub/sub:
功能是订阅发布功能,可以用作简单的消息队列。

Pipeline:
可以批量执行一组指令,一次性返回全部结果,可以减少频繁的请求应答。

Lua:
Redis 支持提交 Lua 脚本来执行一系列的功能。

RDB全量持久化

先前我们说到,MEMORY和Redis都是将数据保存在内存中,那为什么Redis的数据在关机后不会丢失?这就依赖于Redis中的RDB和AOP。

RDB:是Redis用来进行持久化的一种方式,是把当前内存中的数据集快照写入磁盘,也就是 Snapshot 快照(数据库中所有键值对数据)。恢复时是将快照文件直接读到内存里。(所以速度很快)其文件保存在dump.rdb(默认)

触发RDB持久化的方式

自动化:
1.根据redis.conf配置里的SAVE m n定时触发
默认配置:

save 900 1:表示900 秒内如果至少有 1 个 key 的值变化,则保存
save 300 10:表示300 秒内如果至少有 10 个 key 的值变化,则保存
save 60 10000:表示60 秒内如果至少有 10000 个 key 的值变化,则保存

2.主从复制时,主节点自动触发

3.执行Debug Reload

4.执行Shutdown且没有开启AOF持久化

手动
手动触发
1、save
该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止。
显然该命令对于内存比较大的实例会造成长时间阻塞,这是致命的缺陷,为了解决此问题,Redis提供了第二种方式。
在这里插入图片描述

2、bgsave
执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。具体操作是Redis进程执行fork操作创建子进程,会先将数据写入临时文件,等持久化结束,再用临时文件更换上一次持久化好的文件。RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短。

基本上 Redis 内部所有的RDB操作都是采用 bgsave 命令。
在这里插入图片描述

RDB总结:

①、优势
1.RDB是一个非常紧凑(compact)的文件,它保存了redis 在某个时间点上的数据集。这种文件非常适合用于进行备份和灾难恢复。

2.生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。

3.RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。

②、劣势
1、RDB方式数据没办法做到实时持久化/秒级持久化。因为bgsave每次运行都要执行fork操作创建子进程,属于重量级操作,如果不采用压缩算法(内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑),频繁执行成本过高(影响性能)

2、RDB文件使用特定二进制格式保存,Redis版本演进过程中有多个格式的RDB版本,存在老版本Redis服务无法兼容新版RDB格式的问题(版本不兼容)

3、在一定间隔时间做一次备份,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改(数据有丢失)

AOF(append-only file)增量持久化

保存的是指令,每条写指令都保存,所以更大。而且恢复是通过恢复指令恢复数据,所以速度更慢。全量备份总是耗时的,有时候我们提供一种更加高效的方式AOF,工作机制很简单,redis会将每一个收到的写命令都通过write函数追加到文件中。通俗的理解就是日志记录。

1、持久化原理
在这里插入图片描述
每当有一个写命令过来时,就直接保存在我们的AOF文件中。

2、文件重写原理
AOF的方式也同时带来了另一个问题。持久化文件会变的越来越大。为了压缩aof的持久化文件。redis提供了bgrewriteaof命令。将内存中的数据以命令的方式保存到临时文件中,同时会fork出一条新进程来将文件重写。
在这里插入图片描述
重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似。(比如set a 1;set a 123只会保存set a 123)

AOF三种触发机制
在这里插入图片描述

AOF总结

优点
(1)AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据。

(2)AOF日志文件没有任何磁盘寻址的开销,写入性能非常高,文件不容易破损。

(3)AOF日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。

(4)AOF日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。比如某人不小心用flushall命令清空了所有数据,只要这个时候后台rewrite还没有发生,那么就可以立即拷贝AOF文件,将最后一条flushall命令给删了,然后再将该AOF文件放回去,就可以通过恢复机制,自动恢复所有数据

缺点
(1)对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大

(2)AOF开启后,支持的写QPS会比RDB支持的写QPS低,因为AOF一般会配置成每秒fsync一次日志文件,当然,每秒一次fsync,性能也还是很高的

选择:
在这里插入图片描述
后续会对Redis的锁,主从复制,哨兵机制进行介绍,请持续关注!

觉得不错的话点赞加关注,再看不迷路


版权声明:本文为weixin_43896829原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。