Redis(1)-Redis简介与特性详解

随着互联网的高速发展,高并发,大数据量的应用场景越来越普遍,传统的DB数据库已经不能直接的支撑业务的要求了,系统需要那些低延迟高处理速度,能够处理海量的数据流,并且易于大规模集群化管理的数据存储系统。这时候 ,NoSQL型数据库应运而生,它一般具备高性能、可扩展性强、高可用等优点,而Redis便是其中应用最广泛的一种。

Redis是什么?

在redis的官网上我们可以看到下面一段简介:

Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache, and message broker. Redis provides data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes, and streams. Redis has built-in replication, Lua scripting, LRU eviction, transactions, and different levels of on-disk persistence, and provides high availability via Redis Sentinel and automatic partitioning with Redis Cluster.

Redis是一个开源(BSD许可),基于内存运行的数据结构存储系统,可用作数据库、缓存和消息代理。Redis提供诸如字符串(String)、哈希(Hash)、列表(List)、集合(Set)、 有序集合 (sorted set)、位图(Bitmaps)、hyperloglogs、geospatial indexes,和流(streams)等数据结构。Redis具有内置的 复制(replication), LUA脚本(Lua scripting),LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的磁盘持久性 (persistence),并通过Sentinel和自动分区(Cluster)提供高可用性(high availability) 。

简而言之,Redis是一种开源的,运行于内存中的的,基于k-v(键值对)的非关系型数据存储系统。

一.Redis 特点概览

Redis作为目前市场上最受欢迎的NoSQL数据库,有着非常多的优点。下面总体的概括介绍下,Redis的特点:

纯内存操作、读写性能优异: C语言实现,所有数据都加载在内存中,运行速度非常快,数据读速度11万/秒,写数据81000/s。(在笔者所在公司单台redis机器为2C4G的规格,通常计算tps为2万tps/s);

单进程单线程模型 :单线程操作,避免线程上下文切换开销,非阻塞的多路复用IO防止IO等待的开销 ,这也是Reids快的一个原因。

支持数据持久化:基于内存存储的Redis,提供了提供了两种数据持久化策略(RDB 和 AOF),可以方便的实现数据的落盘存储。

操作原子性, 支持事务:所有Redis操作是原子的,同时Redis还支持对几个操作合并后的原子性执行。

非关系型、数据结构丰富: Redis为key-value存储系统 ,支持多种数据结构:列表,集合,有序集合,散列数据类型。

支持主从复制(master-slaver):通过主从复制可以允许多个slave server拥有和master server相同的数据库副本。可读写分离,让master server专用于写数据,slave server用于读数据,一写多读。

实现高可用和分布式:提供了高可用实现Redis Sentinel,它能够保证Redis节点的故障发现和故障自动转移。从3.0版本正式提供了分布式实现Redis Cluster,它是Redis真正的分布式实现,提供了高可用、读写和容量的扩展性。

支持多开发语言:Redis支持多种语言,诸如Lua,Ruby,Python, Twisted Python, PHP, Erlang, Tcl, Perl, ,Java, Scala, Clojure等。

下面将结合这些特点,对Redis的一些常见知识做梳理,帮助读者更快的理解Redis。

1.为什么要使用Redis?

因为Redis够快,读写速度快就意味“高性能”与天生适应“高并发”,而这两个性能正是现代互联网所需要的。

2.Redis为什么这么快?

1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于 HashMap,HashMap 的优势就是查找和操作的时间复杂度都是O(1);

2、数据结构简单,对数据操作也简单,Redis 中的数据结构是专门进行设计的;

3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;

4、使用多路 I/O 复用模型,非阻塞 IO;

3.Redis有哪些数据类型

Redis主要有5种数据类型,包括String,List,Set,Zset,Hash,满足大部分的使用要求

二、持久化相关

3.Redis为什么要持久化?

Redis是纯内存操作的,那么断电停机了要怎么办?因此出现了数据持久化,即把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失。

4. Redis 的持久化机制是什么?各自的优缺点?

Redis 提供两种持久化机制 RDB(默认) 和 AOF 机制:

RDB:是Redis DataBase缩写快照

RDB是Redis默认的持久化方式。按照一定的时间将内存的数据以快照的形式保存到硬盘中,对应产生的数据文件为dump.rdb。通过配置文件中的save参数来定义快照的周期。

在这里插入图片描述

优点:

  • 1、只有一个文件 dump.rdb,方便持久化。
  • 2、容灾性好,一个文件可以保存到安全的磁盘。
  • 3、性能最大化,fork 子进程来完成写操作,让主进程继续处理命令,所以是 IO 最大化。使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 redis 的高性能
  • 4.相对于数据集大时,比 AOF 的启动效率更高。

缺点:

​ 数据安全性低。RDB 是间隔一段时间进行持久化,如果持久化之间 redis 发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候)

  • AOF:持久化

AOF持久化(即Append Only File持久化),则是将Redis执行的每次写命令记录到单独的日志文件中(aof 文件),当重启Redis会重新将持久化的日志中文件恢复数据。

当两种方式同时开启时,数据恢复Redis会优先选择AOF恢复。

在这里插入图片描述

优点:

  • 1、数据安全,aof 持久化可以配置 appendfsync 属性,有 always,每进行一次 命令操作就记录到 aof 文件中一次。
  • 2、通过 append 模式写文件,即使中途服务器宕机,可以通过 redis-check-aof 工具解决数据一致性问题。
  • 3、AOF 机制的 rewrite 模式。AOF 文件没被 rewrite 之前(文件过大时会对命令 进行合并重写),可以删除其中的某些命令(比如误操作的 flushall))

缺点:

  • 1、AOF 文件比 RDB 文件大,且恢复速度慢。
  • 2、数据集大的时候,比 rdb 启动效率低。

总结

  • AOF文件比RDB更新频率高,优先使用AOF还原数据。
  • AOF比RDB更安全也更大
  • RDB性能比AOF好
  • 如果两个都配了优先加载AO

5.如何选择合适的持久化方式?

  • 一般来说, 如果想达到足以媲美PostgreSQL的数据安全性,你应该同时使用两种持久化功能。在这种情况下,当 Redis 重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。
  • 如果你非常关心你的数据, 但仍然可以承受数分钟以内的数据丢失,那么你可以只使用RDB持久化。
  • 有很多用户都只使用AOF持久化,但并不推荐这种方式,因为定时生成RDB快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比AOF恢复的速度要快,除此之外,使用RDB还可以避免AOF程序的bug。
  • 如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式。

三、过期键的删除策略

6. Redis的过期键的删除策略

我们都知道,Redis是key-value数据库,我们可以设置Redis中缓存的key的过期时间。Redis的过期策略就是指当Redis中缓存的key过期了,Redis如何处理。

过期策略通常有以下三种:

  • 定时过期:每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。

  • 惰性过期:只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。

  • 定期过期:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。

    (expires字典会保存所有设置了过期时间的key的过期时间数据,其中,key是指向键空间中的某个键的指针,value是该键的毫秒精度的UNIX时间戳表示的过期时间。键空间是指该Redis集群中保存的所有键。)

Redis中同时使用了惰性过期和定期过期两种过期策略。

扩展:Redis key的过期时间和永久有效分别怎么设置?

EXPIRE和PERSIST命令。

7.Redis的内存空间用完了会怎样?

1.如果达到设置的上限,Redis的写命令会返回错误信息(但是读命令还可以正常返回)。

2.如果配置了内存淘汰机制,当Redis达到内存上限时会冲刷掉旧的内容。

8. Redis的内存淘汰策略有哪些?

Redis的内存淘汰策略是指在Redis的用于缓存的内存不足时,怎么处理需要新写入且需要申请额外空间的数据。

不同于之前的版本,redis5.0为我们提供了八个不同的内存置换策略。很早之前提供了6种。

设置过期时间的键空间选择性移除:

(1)volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。
(2)volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰。
(3)volatile-random:从已设置过期时间的数据集中任意选择数据淘汰。
(4)volatile-lfu:从已设置过期时间的数据集挑选使用频率最低的数据淘汰。

全局的键空间选择性移除

(5)allkeys-lru:从数据集中挑选最近最少使用的数据淘汰
(6)allkeys-lfu:从数据集中挑选使用频率最低的数据淘汰。
(7)allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
(8) no-enviction(驱逐):禁止驱逐数据,这也是默认策略。意思是当内存不足以容纳新入数据时,新写入操作就会报错,请求可以继续进行,线上任务也不能持续进行,
在这里插入图片描述

9.淘汰机制的实现

1、删除失效主键
既然是淘汰,那就需要把这些数据给删除,然后保存新的。Redis 删除失效主键的方法主要有两种:
(1)消极方法(passive way),在主键被访问时如果发现它已经失效,那么就删除它。redis在实现GET、MGET、HGET、LRANGE等所有涉及到读取数据的命令时都会调用 expireIfNeeded,它存在的意义就是在读取数据之前先检查一下它有没有失效,如果失效了就删除它。
(2)积极方法(active way),周期性地探测,发现失效就删除。消极方法的缺点是,如果key 迟迟不被访问,就会占用很多内存空间,所以才有积极方式。
(3)主动删除:当内存超过maxmemory限定时,触发主动清理策略,该策略由启动参数的配置决定
主键具体的失效时间全部都维护在expires这个字典表中:

在这里插入图片描述

四、Redis的应用场景

1.计数器

可以对 String 进行自增自减运算,从而实现计数器功能。Redis 这种内存型数据库的读写性能非常高,很适合存储频繁读写的计数量。利用这一特性可以生成全局唯一性ID。

2.缓存

将热点数据放到内存中,设置内存的最大使用量以及淘汰策略来保证缓存的命中率。

3.分布式锁实现

在分布式场景下,无法使用单机环境下的锁来对多个节点上的进程进行同步。可以使用 Redis 自带的 SETNX 命令实现分布式锁,除此之外,还可以使用官方提供的 RedLock 分布式锁实现。

4.消息队列(发布/订阅功能)

List 是一个双向链表,可以通过 lpush 和 rpop 写入和读取消息。不过最好使用 Kafka、RabbitMQ 等消息中间件。

5.查找表

例如 DNS 记录就很适合使用 Redis 进行存储。查找表和缓存类似,也是利用了 Redis 快速的查找特性。但是查找表的内容不能失效,而缓存的内容可以失效,因为缓存不作为可靠的数据来源。

五、Redis的常见数据类型

Redis主要有5种数据类型,包括String,List,Set,Zset,Hash,满足大部分的使用要求

数据类型 可存储的Value 操作 应用场景
String 字符串、整数、浮点数 对整个字符串或其中部分操作;
对数进行自增、自减操作
键-值 缓存
List 列表 首位压入、弹出元素;
对部分元素进行操作
存储表型数据结构,入文章列表
Hash 包含键值对的无序散列表 添加、获取、移除单个键值对;
获取所有键值对;
检查某键是否存在
结构化对象,如一个实体
Set 无序集合 添加、获取、移除单个元素;
检查元素是否存在;
计算交、并、差集;
从集合中随机获取元素
交集、并集、差集操作
ZSet 有序集合 添加、获取、移除单个元素;
根据分值范围或成员来获取元素
计算一个键的排名
去重、排序

猜你喜欢

转载自blog.csdn.net/weixin_43828467/article/details/112336353