Redis相关概念

0e56340b9eca46e8834101bb36b5838e.jpg1. 什么是Redis?它主要用来什么的?

 

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

 

与MySQL数据库不同的是,Redis的数据是存在内存中的。它的读写速度非常快,每秒可以处理超过10万次读写操作。因此redis被广泛应用于缓存,另外,Redis也经常用来做分布式锁。除此之外,Redis支持事务、持久化、LUA 脚本、LRU 驱动事件、多种集群方案

 

 

 

说说Redis的基本数据结构类型

大多数小伙伴都知道,Redis有以下这五种基本类型:

 

String(字符串)

Hash(哈希)

List(列表)

Set(集合)

zset(有序集合)

它还有三种特殊的数据结构类型

 

Geospatial

Hyperloglog

Bitmap

2.1 Redis 的五种基本数据类型

 

 

 

 

String(字符串)

 

简介:String是Redis最基础的数据结构类型,它是二进制安全的,可以存储图片或者序列化的对象,值最大存储为512M

简单使用举例: set key value、get key等

应用场景:共享session、分布式锁,计数器、限流。

内部编码有3种,int(8字节长整型)/embstr(小于等于39字节字符串)/raw(大于39个字节字符串)

C语言的字符串是char[]实现的,而Redis使用SDS(simple dynamic string) 封装,sds源码如下:

 

struct sdshdr{ unsigned int len; // 标记buf的长度 unsigned int free; //标记buf中未使用的元素个数 char buf[]; // 存放元素的坑 }

 

 

Hash(哈希)

 

简介:在Redis中,哈希类型是指v(值)本身又是一个键值对(k-v)结构

简单使用举例:hset key field value 、hget key field

内部编码:ziplist(压缩列表) 、hashtable(哈希表)

应用场景:缓存用户信息等。

注意点:如果开发使用hgetall,哈希元素比较多的话,可能导致Redis阻塞,可以使用hscan。而如果只是获取部分field,建议使用hmget。

 

 

 

 

 

 

 

 

List(列表)

 

简介:列表(list)类型是用来存储多个有序的字符串,一个列表最多可以存储2^32-1个元素。

简单实用举例:lpush key value [value ...] 、lrange key start end

内部编码:ziplist(压缩列表)、linkedlist(链表)

应用场景:消息队列,文章列表,

一图看懂list类型的插入与弹出:

 

 

 

 

 

 

 

 

list应用场景参考以下:

 

lpush+lpop=Stack(栈)

lpush+rpop=Queue(队列)

lpsh+ltrim=Capped Collection(有限集合)

lpush+brpop=Message Queue(消息队列)

 Set(集合)

 

 

 

 

简介:集合(set)类型也是用来保存多个的字符串元素,但是不允许重复元素

简单使用举例:sadd key element [element ...]、smembers key

内部编码:intset(整数集合)、hashtable(哈希表)

注意点:smembers和lrange、hgetall都属于比较重的命令,如果元素过多存在阻塞Redis的可能性,可以使用sscan来完成。

应用场景:用户标签,生成随机数抽奖、社交需求。

有序集合(zset)

 

简介:已排序的字符串集合,同时元素不能重复

简单格式举例:zadd key score member [score member ...],zrank key member

底层内部编码:ziplist(压缩列表)、skiplist(跳跃表)

应用场景:排行榜,社交需求(如用户点赞)。

 

2.2 Redis 的三种特殊数据类型

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

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

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

 

 

3.Redis为什么这么快

3.1 基于内存存储实现

我们都知道内存读写是比在磁盘快很多的,Redis基于内存存储实现的数据库,相对于数据存在磁盘的MySQL数据库,省去磁盘I/O的消耗。

 

3.2 高效的数据结构

我们知道,Mysql索引为了提高效率,选择了B+树的数据结构。其实合理的数据结构,就是可以让你的应用/程序更快。先看下Redis的数据结构&内部编码图:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

字符串长度处理: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 多路复用

 

多路I/O复用技术可以让单个线程高效的处理多个连接请求,而Redis使用用epoll作为I/O多路复用技术的实现。并且,Redis自身的事件处理模型将epoll中的连接、读写、关闭都转换为事件,不在网络I/O上浪费过多的时间。

 

 

 

什么是I/O多路复用?

 

1

2

3

4

I/O :网络 I/O

多路 :多个网络连接

复用:复用同一个线程。

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

单线程模型

 

Redis是单线程模型的,而单线程避免了CPU不必要的上下文切换和竞争锁的消耗。也正因为是单线程,如果某个命令执行过长(如hgetall命令),会造成阻塞。Redis是面向快速执行场景的数据库。,所以要慎用如smembers和lrange、hgetall等命令。

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

 

3.5 虚拟内存机制

Redis直接自己构建了VM机制 ,不会像一般的系统会调用系统函数处理,会浪费一定的时间去移动和请求。

 

Redis的虚拟内存机制是啥呢?

 

虚拟内存机制就是暂时把不经常访问的数据(冷数据)从内存交换到磁盘中,从而腾出宝贵的内存空间用于其它需要访问的数据(热数据)。通过VM功能可以实现冷热数据分离,使热数据仍在内存中、冷数据保存到磁盘。这样就可以避免因为内存不足而造成访问速度下降的问题。

 

4. 什么是缓存击穿、缓存穿透、缓存雪崩?

4.1 缓存穿透问题

先来看一个常见的缓存使用方式:读请求来了,先查下缓存,缓存有值命中,就直接返回;缓存没命中,就去查数据库,然后把数据库的值更新到缓存,再返回。

 

 

 

 

 

 

 

 

读取缓存

 

缓存穿透:指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,进而给数据库带来压力。

 

1

通俗点说,读请求访问时,缓存和数据库都没有某个值,这样就会导致每次对这个值的查询请求都会穿透到数据库,这就是缓存穿透。

缓存穿透一般都是这几种情况产生的: 

 

业务不合理的设计,比如大多数用户都没开守护,但是你的每个请求都去缓存,查询某个userid查询有没有守护。

业务/运维/开发失误的操作,比如缓存和数据库的数据都被误删除了。

黑客非法请求攻击,比如黑客故意捏造大量非法请求,以读取不存在的业务数据

如何避免缓存穿透呢? 一般有三种方法。

 

1.如果是非法请求,我们在API入口,对参数进行校验,过滤非法值。

2.如果查询数据库为空,我们可以给缓存设置个空值,或者默认值。但是如有有写请求进来的话,需要更新缓存哈,以保证缓存一致性,同时,最后给缓存设置适当的过期时间。(业务上比较常用,简单有效)

3.使用布隆过滤器快速判断数据是否存在。即一个查询请求过来时,先通过布隆过滤器判断值是否存在,存在才继续往下查。

 

1

布隆过滤器原理:它由初始值为0的位图数组和N个哈希函数组成。一个对一个key进行N个hash算法获取N个值,在比特数组中将这N个值散列后设定为1,然后查的时候如果特定的这几个位置都为1,那么布隆过滤器判断该key存在。

4.2 缓存雪奔问题

缓存雪奔: 指缓存中数据大批量到过期时间,而查询数据量巨大,请求都直接访问数据库,引起数据库压力过大甚至down机。

 

缓存雪奔一般是由于大量数据同时过期造成的,对于这个原因,可通过均匀设置过期时间解决,即让过期时间相对离散一点。如采用一个较大固定值+一个较小的随机值,5小时+0到1800秒酱紫。

Redis 故障宕机也可能引起缓存雪奔。这就需要构造Redis高可用集群啦。

 

4.3 缓存击穿问题

缓存击穿: 指热点key在某个时间点过期的时候,而恰好在这个时间点对这个Key有大量的并发请求过来,从而大量的请求打到db。

 

缓存击穿看着有点像,其实它两区别是,缓存雪奔是指数据库压力过大甚至down机,缓存击穿只是大量并发请求到了DB数据库层面。可以认为击穿是缓存雪奔的一个子集吧。有些文章认为它俩区别,是区别在于击穿针对某一热点key缓存,雪奔则是很多key。

 

解决方案就有两种:

 

1.使用互斥锁方案。缓存失效时,不是立即去加载db数据,而是先使用某些带成功返回的原子操作命令,如(Redis的setnx)去操作,成功的时候,再去加载db数据库数据和设置缓存。否则就去重试获取缓存。

2. “永不过期”,是指没有设置过期时间,但是热点数据快要过期时,异步线程去更新和设置过期时间。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/94554.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入探讨 Presto 中的缓存

【squids.cn】 全网zui低价RDS,免费的迁移工具DBMotion、数据库备份工具DBTwin、SQL开发工具等 Presto是一种流行的开源分布式SQL引擎,使组织能够在多个数据源上大规模运行交互式分析查询。缓存是一种典型的提高 Presto 查询性能的优化技术。它为 Prest…

阿里云新账户什么意思?老用户、产品首购详细说明

阿里云新账户、老账号、产品首购和同人账号什么意思?阿里云账号分为云新账户、老账户、产品首购、同人账号和同一用户,阿里云官方推出的活动很多是限制账号类型的,常见的如阿里云新用户,什么是阿里云新用户?是指从未在…

408计网应用层总结

网络应用模型 ■客户/服务器模型(C/S):客户是服务请求方,服务器是服务提供方 ■P2P模型:各主机都是客户,也都是服务器(任意一对计算机成称为对等方) 注: 1.客户…

Overloud TH-U Complete for Mac:演绎您的音乐世界

Overloud TH-U Complete for Mac是一款功能强大的吉他谱曲软件,可以让您在Mac电脑上轻松进行吉他模拟、录音和混音等操作,创作属于自己的音乐作品。 Overloud TH-U Complete for Mac提供了丰富的吉他模拟和音效库,涵盖了多种吉他放大器、箱体…

计算机考研 | 2016年 | 计算机组成原理真题

文章目录 【计算机组成原理2016年真题44题-9分】【第一步:信息提取】【第二步:具体解答】 【计算机组成原理2016年真题45题-14分】【第一步:信息提取】【第二步:具体解答】 【计算机组成原理2016年真题44题-9分】 假定CPU主频为5…

Docker项目部署

目录 一、前端项目部署 1、上传文件 2、开启容器 3、测试 二、后端项目部署 1、打包java项目 2、将jar包和Dockerfile文件长传到Linux系统 3、构建镜像 4、开启容器 5、测试 三、DockerCompose快速部署 基本语法 一、前端项目部署 1、上传文件 里面包括页面和配置文…

秋招校招,什么是群面?

时间已经来到十月份,我们也迎来了秋季招聘的高峰期。一般来说,企业为了提高面试的速度,一般都会让我们进行群面。可是,很多人不懂得“群面”的意思,由此导致自己在面试环节丢分。今天,就跟着小编一起来了解…

阿里云关系型数据库有哪些?RDS云数据库汇总

阿里云RDS关系型数据库大全,关系型数据库包括MySQL版、PolarDB、PostgreSQL、SQL Server和MariaDB等,NoSQL数据库如Redis、Tair、Lindorm和MongoDB,阿里云百科分享阿里云RDS关系型数据库大全: 目录 阿里云RDS关系型数据库大全 …

QT实现TCP服务器客户端的实现

ser: widget.cpp: #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//实例化一个服务器server new QTcpServer(this);// 此时&#xf…

嵌入式软件架构中抽象层设计方法

大家好,今天分享一篇嵌入式软件架构设计相关的文章。 软件架构这东西,众说纷纭,各有观点。什么是软件架构,我们能在网上找到无数种定义。 比如,我们可以这样定义:软件架构是软件系统的基本结构&#xff0c…

g(x)=abx形式的函数最小二乘法计算方法

设函数,利用最小二乘法求解系数a和b: 设,,有 用最小二乘法求解和后,可得和: ,

【网络安全---ICMP报文分析】Wireshark教程----Wireshark 分析ICMP报文数据试验

一,试验环境搭建 1-1 试验环境示例图 1-2 环境准备 两台kali主机(虚拟机) kali2022 192.168.220.129/24 kali2022 192.168.220.3/27 1-2-1 网关配置: 编辑-------- 虚拟网路编辑器 更改设置进来以后 ,先选择N…

(Note)机器学习面试题

机器学习 1.两位同事从上海出发前往深圳出差,他们在不同时间出发,搭乘的交通工具也不同,能准确描述两者“上海到深圳”距离差别的是: A.欧式距离 B.余弦距离 C.曼哈顿距离 D.切比雪夫距离 S:D 1. 欧几里得距离 计算公式&#x…

【单片机】13-实时时钟DS1302

1.RTC的简介 1.什么是实时时钟(RTC) (rtc for real time clock) (1)时间点和时间段的概念区分 (2)单片机为什么需要时间点【一定的时间点干什么事情】 (3)RTC如何存在于…

国庆假期day5

作业:请写出七层模型及每一层的功能,请绘制三次握手四次挥手的流程图 1.OSI七层模型: 应用层--------提供函 表示层--------表密缩 会话层--------会话 传输层--------进程的接收和发送 网络层--------寻主机 数据链路层----相邻节点的可靠传…

Ubuntu22.04 交叉编译gcc9.5 for arm

一、准备 环境:ubuntu22.04为刚刚安装,未安装gcc等包 vi ~/.bashrc输入 export PATH$PATH:/opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin 保存,reboot 安装: sudo apt install cmake sudo apt install gawk sudo apt instal…

[BJDCTF2020]Mark loves cat

先用dirsearch扫一下,访问一下没有什么 需要设置线程 dirsearch -u http://8996e81f-a75c-4180-b0ad-226d97ba61b2.node4.buuoj.cn:81/ --timeout2 -t 1 -x 400,403,404,500,503,429使用githack python2 GitHack.py http://8996e81f-a75c-4180-b0ad-226d97ba61b2.…

详解Linux的系统调用fork()函数

在Linux系统中,fork()是一个非常重要的系统调用,它的作用是创建一个新的进程。具体来说,fork()函数会在当前进程的地址空间中复制一份子进程,并且这个子进程几乎完全与父进程相同,包括进程代码、数据、堆栈以及打开的文…

【Java 进阶篇】JDBC 数据库连接池详解

数据库连接池是数据库连接的管理和复用工具,它可以有效地降低数据库连接和断开连接的开销,提高了数据库访问的性能和效率。在 Java 中,JDBC 数据库连接池是一个常见的实现方式,本文将详细介绍 JDBC 数据库连接池的使用和原理。 1…

算法强训:第三十四天

文章目录 收件人列表养兔子一、收件人列表OJ链接 本题思路:先接收到一个数字,代表接下来是多少组数据 ,逐个接收每个名字,如果名字中没有,或者 则直接输出,否则在改名字前后拼接"\""再输出,除最后一个名字外,每个名字之后都有一个", " ,该组用例…