关于redis:认识Redis不只是缓存还有这些厉害的功能

53次阅读

共计 4984 个字符,预计需要花费 13 分钟才能阅读完成。

在当今数据驱动的世界中,疾速存取信息成为了技术倒退的要害。而在泛滥存储解决方案中,Redis 以其独特的魅力和弱小的性能,成为了开发者们的宠儿。明天,就让咱们一起来认识一下 Redis。

一、Redis 是什么,能够用来干什么?

Redis,英文全称是 Remote Dictionary Server(近程字典服务),是一个开源的应用 ANSI C 语言编写、反对网络、可基于内存亦可长久化的日志型、Key-Value 数据库,并提供多种语言的 API。

与 MySQL 数据库不同的是,Redis 的数据是存在内存中的。它的读写速度十分快,每秒能够解决超过 10 万次读写操作。因而 redis 被广泛应用于缓存,另外,Redis 也常常用来做分布式锁、计数器、排行榜等。

Redis 的常见利用

1. 缓存

这是 Redis 利用最宽泛中央,根本所有的 Web 利用都会应用 Redis 作为缓存,来升高数据源压力,进步响应速度。

2. 计数器

Redis 人造反对计数性能,而且计数性能十分好,能够用来记录浏览量、点赞量等等。

3. 排行榜

Redis 提供了列表和有序汇合数据结构,正当地应用这些数据结构能够很不便地构建各种排行榜零碎。

4. 社交网络

赞 / 踩、粉丝、独特好友 / 爱好、推送、下拉刷新。

5. 音讯队列

Redis 提供了公布订阅性能和阻塞队列的性能,能够满足个别音讯队列性能。

6. 分布式锁

分布式环境下,利用 Redis 实现分布式锁,也是 Redis 常见的利用。

7. 位操作

用于数据量上亿的场景下,例如几亿用户零碎的签到,去重登录次数统计,某用户是否在线状态等等。这里要用到位操作——应用 setbit、getbit、bitcount 命令。

原理是:redis 内构建一个足够长的数组,每个数组元素只能是 0 和 1 两个值,而后这个数组的下标 index 用来示意用户 id(必须是数字哈),那么很显然,这个几亿长的大数组就能通过下标和元素值(0 和 1)来构建一个记忆系统。

二、Redis 有哪些数据结构类型?

Redis 有五种根本类型和三种非凡的数据结构类型,上面咱们别离来看一些都有哪些类型。

2.1 Redis 的五种根本数据结构

string
字符串最根底的数据结构。字符串类型的值理论能够是字符串(简略的字符串、简单的字符串(例如 JSON、XML))、数字(整数、浮点数),甚至是二进制(图片、音频、视频),然而值最大不能超过 512MB。

字符串次要有以下几个典型应用场景:

  • 缓存性能
  • 计数
  • 共享 Session
  • 限速

hash
哈希类型是指键值自身又是一个键值对构造。

哈希次要有以下典型利用场景:

  • 缓存用户信息
  • 缓存对象

list
列表(list)类型是用来存储多个有序的字符串。列表是一种比拟灵便的数据结构,它能够充当栈和队列的角色。

列表次要有以下几种应用场景:

  • 音讯队列
  • 文章列表

set
汇合(set)类型也是用来保留多个的字符串元素,但和列表类型不一 样的是,汇合中不容许有反复元素,并且汇合中的元素是无序的。

汇合次要有如下应用场景:

  • 标签(tag)
  • 独特关注

sorted set
有序汇合中的元素能够排序。然而它和列表应用索引下标作为排序根据不同的是,它给每个元素设置一个权重(score)作为排序的根据。

有序汇合次要利用场景:

  • 用户点赞统计
  • 用户排序

2.2 Redis 的三种非凡数据类型

Geo: Redis3.2 推出的,地理位置定位,用于存储地理位置信息,并对存储的信息进行操作。

HyperLogLog: 用来做基数统计算法的数据结构,如统计网站的 UV。

Bitmaps: 用一个比特位来映射某个元素的状态,在 Redis 中,它的底层是基于字符串类型实现的,能够把 bitmaps 成作一个以比特位为单位的数组。

三、Redis 为什么这么快?

3.1 基于内存存储实现

咱们都晓得内存读写是比在磁盘快很多的,Redis 基于内存存储实现的数据库,绝对于数据存在磁盘的 MySQL 数据库,省去磁盘 I / O 的耗费。

3.2 高效的数据结构

咱们晓得,Mysql 索引为了提高效率,抉择了 B + 树的数据结构。其实正当的数据结构,就是能够让你的利用 / 程序更快。先看下 Redis 的数据结构 & 外部编码图:

SDS 简略动静字符串

字符串长度解决:Redis 获取字符串长度,工夫复杂度为 O(1),而 C 语言中,须要从头开始遍历,复杂度为 O(n);

空间预调配: 字符串批改越频繁的话,内存调配越频繁,就会耗费性能,而 SDS 批改和空间裁减,会额定调配未应用的空间,缩小性能损耗。

惰性空间开释: SDS 缩短时,不是回收多余的内存空间,而是 free 记录下多余的空间,后续有变更,间接应用 free 中记录的空间,缩小调配。

二进制平安: Redis 能够存储一些二进制数据,在 C 语言中字符串遇到’\0’会完结,而 SDS 中标记字符串完结的是 len 属性。

字典

Redis 作为 K-V 型内存数据库,所有的键值就是用字典来存储。字典就是哈希表,比方 HashMap,通过 key 就能够间接获取到对应的 value。而哈希表的个性,在 O(1)工夫复杂度就能够取得对应的值。

跳跃表

跳跃表是 Redis 特有的数据结构,就是在链表的根底上,减少多级索引晋升查找效率。

跳跃表反对均匀 O(logN), 最坏 O(N)复杂度的节点查找,还能够通过程序性操作批量解决节点。

3.3 正当的数据编码

Redis 反对多种数据数据类型,每种根本类型,可能对多种数据结构。什么时候, 应用什么样数据结构,应用什么样编码,是 redis 设计者总结优化的后果。

String: 如果存储数字的话,是用 int 类型的编码; 如果存储非数字,小于等于 39 字节的字符串,是 embstr;大于 39 个字节,则是 raw 编码。

List: 如果列表的元素个数小于 512 个,列表每个元素的值都小于 64 字节(默认),应用 ziplist 编码,否则应用 linkedlist 编码。

Hash: 哈希类型元素个数小于 512 个,所有值小于 64 字节的话,应用 ziplist 编码, 否则应用 hashtable 编码。

Set: 如果汇合中的元素都是整数且元素个数小于 512 个,应用 intset 编码,否则应用 hashtable 编码。

Zset: 当有序汇合的元素个数小于 128 个,每个元素的值小于 64 字节时,应用 ziplist 编码,否则应用 skiplist(跳跃表)编码。

3.4 正当的线程模型

I/O 多路复用

多路 I / O 复用技术能够让单个线程高效的解决多个连贯申请,而 Redis 应用用 epoll 作为 I / O 多路复用技术的实现。并且,Redis 本身的事件处理模型将 epoll 中的连贯、读写、敞开都转换为事件,不在网络 I / O 上节约过多的工夫。

什么是 I / O 多路复用?

  • I/O:网络 I/O
  • 多路:多个网络连接
  • 复用:复用同一个线程。

IO 多路复用其实就是一种同步 IO 模型,它实现了一个线程能够监督多个文件句柄;一旦某个文件句柄就绪,就可能告诉应用程序进行相应的读写操作;而没有文件句柄就绪时, 就会阻塞应用程序,交出 cpu。

单线程模型

Redis 是单线程模型的,而单线程防止了 CPU 不必要的上下文切换和竞争锁的耗费。也正因为是单线程,如果某个命令执行过长(如 hgetall 命令),会造成阻塞。

Redis 是面向疾速执行场景的数据库,所以要慎用如 smembers 和 lrange、hgetall 等命令。

Redis 6.0 引入了多线程提速,它的执行命令操作内存的依然是个单线程。

3.5 虚拟内存机制

Redis 间接本人构建了 VM 机制,不会像个别的零碎会调用零碎函数解决,会节约肯定的工夫去挪动和申请。

Redis 的虚拟内存机制是什么?

虚拟内存机制就是临时把不常常拜访的数据 (冷数据) 从内存替换到磁盘中,从而腾出贵重的内存空间用于其它须要拜访的数据(热数据)。通过 VM 性能能够实现冷热数据拆散,使热数据仍在内存中、冷数据保留到磁盘。这样就能够防止因为内存不足而造成访问速度降落的问题。

你还在苦恼找不到真正收费的编程学习平台吗? 能够试试【云端源想】!课程视频、知识库、微实战、云实验室、一对一征询……你想要的全副学习资源这里都有,重点是当初还是收费的!点这里即可查看!

四、什么是热 Key 问题,如何解决?

在 Redis 中,咱们把拜访频率高的 key,称为热点 key。

如果某一热点 key 的申请到服务器主机时,因为申请量特地大,可能会导致主机资源有余,甚至宕机,从而影响失常的服务。

而热点 Key 是怎么产生的呢?次要起因有两个:

  • 用户生产的数据远大于生产的数据,如秒杀、热点新闻等读多写少的场景。
  • 申请分片集中,超过单 Redi 服务器的性能,比方固定名称 key,Hash 落入同一台服务器,霎时访问量极大,超过机器瓶颈,产生热点 Key 问题。

那么在日常开发中,如何辨认到热点 key 呢?

凭教训判断哪些是热 Key;

  • 客户端统计上报;
  • 服务代理层上报。

如何解决热 key 问题?

  • Redis 集群扩容:减少分片正本,平衡读流量;
  • 将热 key 扩散到不同的服务器中;
  • 应用二级缓存,即 JVM 本地缓存, 缩小 Redis 的读申请。

五、Redis 过期策略和内存淘汰策略

5.1Redis 过期策略

咱们在 set key 的时候,能够给它设置一个过期工夫,比方 expire key 60。指定这 key60s 后过期,60s 后,redis 是如何解决的?
咱们先来介绍几种过期策略:
定时过期
每个设置过期工夫的 key 都须要创立一个定时器,到过期工夫就会立刻对 key 进行革除。该策略能够立刻革除过期的数据,对内存很敌对;然而会占用大量的 CPU 资源去解决过期的数据,从而影响缓存的响应工夫和吞吐量。

惰性过期
只有当拜访一个 key 时,才会判断该 key 是否已过期,过期则革除。该策略能够最大化地节俭 CPU 资源,却对内存十分不敌对。极其状况可能呈现大量的过期 key 没有再次被拜访,从而不会被革除,占用大量内存。

定期过期
每隔肯定的工夫,会扫描肯定数量的数据库的 expires 字典中肯定数量的 key,并革除其中已过期的 key。

该策略是前两者的一个折中计划。通过调整定时扫描的工夫距离和每次扫描的限定耗时,能够在不同状况下使得 CPU 和内存资源达到最优的均衡成果。

expires 字典会保留所有设置了过期工夫的 key 的过期工夫数据,其中:

  • key 是指向键空间中的某个键的指针。
  • value 是该键的毫秒精度的 UNIX 工夫戳示意的过期工夫。
  • 键空间是指该 Redis 集群中保留的所有键。

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

假如 Redis 以后寄存 30 万个 key,并且都设置了过期工夫,如果你每隔 100ms 就去查看这全副的 key,CPU 负载会特地高,最初可能会挂掉。因而,redis 采取的是定期过期,每隔 100ms 就随机抽取肯定数量的 key 来检查和删除的。

然而呢,最初可能会有很多曾经过期的 key 没被删除。这时候,redis 采纳惰性删除。在你获取某个 key 的时候,redis 会检查一下,这个 key 如果设置了过期工夫并且曾经过期了,此时就会删除。

如果定期删除漏掉了很多过期的 key,而后也没走惰性删除。就会有很多过期 key 积在内存内存,间接会导致内存爆的。或者有些时候,业务量大起来了,redis 的 key 被大量应用,内存间接不够了,运维小哥哥也遗记加大内存了。

难道 redis 间接这样挂掉?不会的!Redis 用 8 种内存淘汰策略爱护本人~

5.2 Redis 内存淘汰策略

volatile-lru: 当内存不足以包容新写入数据时,从设置了过期工夫的 key 中应用 LRU(最近起码应用)算法进行淘汰。

allkeys-lru: 当内存不足以包容新写入数据时,从所有 key 中应用 LRU(最近起码应用)算法进行淘汰。

volatile-lfu: 4.0 版本新增,当内存不足以包容新写入数据时,在过期的 key 中,应用 LFU 算法进行删除 key。

allkeys-lfu: 4.0 版本新增,当内存不足以包容新写入数据时,从所有 key 中应用 LFU 算法进行淘汰。

volatile-random: 当内存不足以包容新写入数据时,从设置了过期工夫的 key 中,随机淘汰数据。

allkeys-random:当内存不足以包容新写入数据时,从所有 key 中随机淘汰数据。

volatile-ttl: 当内存不足以包容新写入数据时,在设置了过期工夫的 key 中,依据过期工夫进行淘汰,越早过期的优先被淘汰。

noeviction: 默认策略,当内存不足以包容新写入数据时,新写入操作会报错。

正文完
 0