Redis【2】—— Redis特性 与 数据类型

本文详细介绍了Redis的内存存储特性、编程接口、可扩展性和持久化策略,以及其作为数据库、缓存、会话存储和消息队列的不同应用场景,还探讨了数据类型和内部编码优化,如ziplist和跳表的使用。
摘要由CSDN通过智能技术生成

二、Redis 的基本介绍

(一)关于 Redis

简单来说 Redis 是一个在内存中存储数据的中间件。

1. 特性

(1)在内存中存储数据

使用键值对的方式存储数据,其中**key**都是**string****value****都是则可以是不同数据结构的数据。**与 MySQL相比,Redis这种以“键值对”的方式组织数据的方式,称为:非关系型数据库。

(2)可编程

可以直接通过简单的 交互式命令 操作,也可以通过 **Lua****脚本 **进行操作。

(3)可扩展

Redis提供了一组API,可以通过 CC++Rust 语言编写的动态链接库(可以理解为:函数库。在 **windows**上是**.ddl** 文件,在**Linux**上是 **.so** 文件),在原有的功能基础上再进行扩展。

(4)持久化

明明Redis是在内存中存储数据,那么进程退出 或者 系统重启,都会导致数据的丢失,那怎么能说持久化呢?其实,这里的持久化是指:**Redis**也会把数据存储在硬盘上,也就说:硬盘上备份了Redis的数据。重启的**Redis**只需要加载硬盘中的备份数据即可,这样Redis的内存就能恢复到重启前的状态。

(5)多集群

一个 Redis存储的数据是有限的,为了尽可能多地使用到 Redis的特性,就需要引入多台主机,**Redis**部署到多个节点上。这样每个 Redis 都能存储一部分数据。能够被部署在多台机器上的Redis也就拥有了多集群的特点。

(6)高可用

Redis支持“主从”结构,从节点就相当于主节点的备份。

(7)快速高效 *

为什么Redis会快呢?主要是一下四点原因:

  • 访问硬件上看,第一点也是Redis特性的第一点,**Redis**数据存储在内存中,访问内存的速度 比 访问硬盘和数据库的速度快得多。
  • 业务角度上看,Redis核心功能的逻辑简单,大部分是操作内存的数据结构。相比起MySQL还有聚合函数,链表查询等…Redis的应用场景比较简单。
  • 网络角度上看,Redis使用了 **IO多路复用 **的方式(epoll),使用了一个线程管理多个 socket,即:同时去买三份小吃,哪一份完成就先响应哪一份,注意
  • 实现模型上看,Redis使用的是 **单线程 模型。**这减少了不必要的线程竞争开销。这里多解释一下,多线程能提高效率是有场景要求的,即 CPU密集性任务 的场景。此时,多个线程才能够充分利用 CPU的多核资源

2. 应用场景

(1)把 Redis当数据库

这里指的是把 Redis当作全量数据库,也就是说 这些数据并不能丢失,而且这部分被存储的数据不仅多,而且需要快速被搜索到。想要这样使用Redis就需要不少的硬件资源,而这只能发挥公司的“钞”能力了。

(2)把RedisCachingsession

当作缓存(Caching)的话,其实就是把热点数据提出来存储到**Redis**,也就是所谓的**冷热分离。**此时的Redis存储部分数据,当Redis重启之后,数据依然可以从MySQL中读取回来。

当作会话(Session)的意思其实是:使用**Redis**存储会话信息,所有的服务器最终统一地到 **Redis**中获取会话信息即可。这样就不需要负载均衡器 根据 **userID** 做会话保持
image.png

(3)把Redis当消息队列

消息队列是一种在应用程序之间传递消息的通信模式。它允许发送者(生产者)将消息发送到一个队列中,然后接收者(消费者)可以从队列中获取并处理这些消息。消息队列实现了异步通信机制,提供了解耦和缓冲的功能,使得不同的应用程序或服务可以在时间和空间上解耦,以便更高效地进行通信。

1)消息队列通常由以下组件构成:

  • 消息:要传递的数据或信息。
  • 队列:存储消息的容器,通常是先进先出(FIFO)的数据结构。
  • 生产者:将消息发送到队列的应用程序或服务。
  • 消费者:从队列中获取消息并进行处理的应用程序或服务。
  • 中间件:支持消息传递的中间软件,负责管理和维护队列,确保消息的可靠传递和处理。

2)消息队列的优点包括:

  • 异步处理:生产者和消费者之间解耦,不需要即时响应,可以自由选择处理消息的时间和顺序。
  • 削峰填谷:通过缓冲消息,消费者可以按照自身处理能力来消化消息,避免了系统因突发高峰而崩溃。
  • 可伸缩性:可以根据需求增加或减少生产者和消费者的数量,以适应系统的负载变化。
  • 系统解耦:不同的应用程序或服务之间通过消息队列进行通信,解耦了彼此之间的依赖关系,提高了系统的灵活性和可维护性。
  • 可靠性:消息队列通常会提供持久化机制来确保消息的可靠传递,防止消息丢失。

消息队列在分布式系统、微服务架构、任务调度等场景下具有广泛的应用。一些常见的消息队列实现包括 RabbitMQ、Apache Kafka、ActiveMQ 等。但是,如果不想使用消息队列的功能,又不想引入过多的中间件,可以考虑只用Redis做消息队列。

(二)基本指令

redis-server /etc/redis/redis.conf # 启动Redis
redis-cli # 进入客户端
set key1 value1
get key1
get key2 # 不存在返回nil

image.png

# 匹配模式
# ? 一个字符
# * 多个字符
# [xxxx] 出现什么匹配什么
# [^xxx] 出现什么排除什么
# [a-z] 出现范围(一位字符)

注意在生产环境上不要随便使用 keys * ,原因很简单:我们能够清晰地感受到这个操作的时间复杂度是 O(n),而Redis是一个单线程服务器,且生产环境上的key是很多的,那么这个操作执行的时间就很长,整Redis服务器就会被阻塞住,无法给其他客户端提供服务!此时,其余的Redis操作就会超时。
image.png

exists key1 key2 ...
# 时间复杂度是 O(N) ,N 是 key 的个数

image.png
注意下方的两种写法,上方那种优于下方的写法!因为**Redis****是一个 客户端-服务器 结构的程序,客户端和服务器之间通过网络来进行通信!**第二种分开写的方法相当于有两次网络请求,两次的开销必然是大于一次的。
image.png

keys * # 先查看一下 keys 有多少
del hllo 
del hallo hello hzllo # 返回的是个数

image.png
删除数据是否危险还是要看场景!在把Redis当作缓存的场景下,Redis存储的是热点数据(全量数据是存储在MySQL中的),如果只是删除一两条,那其实影响不大,因为热点数据也很有可能会更新,实在不行就放过几条去读MySQL。但如果一下子删除太多,就容易把系统搞挂。因为Redis是在帮MySQL分担压力的,如果分担不了那压力自然就给到MySQL了,大量的请求很可能就把 MySQL冲击跨了。

set k v
get k
expire k 5 # 单位是秒,pexpire 单位是毫秒
ttl k # 当被删除之后返回的结果就是 -2;如果没有关联过期时间返回结果就是 -1;pttl 单位是毫秒

这个功能还是非常有用的,常见的场景比如:验证码,优惠券过期 等。
那么这个过期删除策略是怎么样的呢?主要有两个:定期删除 + 惰性删除。
所谓惰性删除就是:如果key已经过期,但是并没有请求来查询,那么这个key就暂时不会被删除,直到被请求访问的时候Redis才会删除key,同时返回一个nil。但是这样并不靠谱的。**因此还需要结合“定时删除”。**不过,当有很多key时,全部过滤一遍成本可能会很高,占用的时间可能会边长,占用时间一旦过长,就很可能出现跟上方keys *一样的情况!因此,定期删除只是抽取一部分**key**已经检查
注意:Redis并没有使用定时删除的策略。就算采用也不必未每一个key设置一个定时器,未引入的原因很可能是因为Redis最初是单线程的设计模式,如果使用定时器,势必要引入多线程,这与设计的初衷相悖。
但是上方两种策略依旧不能让人满意,因此**Redis**还有内存淘汰机制
image.png
image.png
image.png

# 常见数据类型有以下几种:
# none、string、list、set、zset、hash、stream
keys *
type key1

lpush key2 111 222 333
type key2

sadd key3 111 222 333
type key3

hset key4 k1 v1 k2 v2
type key4

image.png

三、数据类型 与 编码方式

(一)数据类型

image.png

上方只是常用的Redis数据类型,Redis还有其他的若干种数据类型,但适用的场景可能没这么广。这里还需要说明的是:**Redis****底层在实现上述数据结构时,会在源码层面针对上述实现进行特定优化,以 节省时间、节省空间。**也就是说:Redis会承诺相关的操作时间复杂度不变,但背后实现的细节并不一定是所见的标准数据类型,在特定场景下,会采用其他数据类型实现。

(二)内部编码

image.png

为什么hash要压缩为ziplist
因为在Redis中的key很多,对于的valuehash的也很多,但是每个hash不是很大的情况下压缩成ziplist就会比较节省空间,整个的空间占用率就会下降 且 查询速度并没有降下来。

跳表是什么?
跳表也是链表,只不过每个节点上有多个指针域。根据设置的特殊规则,使用跳表查询元素的时间复杂度是O(logN)

keys *
type key1
object encoding key1 # error 注意'object' 需要大写
OBJECT encoding key1

image.png

  • 21
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值