IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> redis--重要知识点扫盲 -> 正文阅读

[大数据]redis--重要知识点扫盲

1、简介

(1)redis优点:
基于内存,读写速度快;支持丰富的数据类型;支持持久化;过期策略;性能高;
(2)Redis缺点:
数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。
(3)redis适用场景:
会话缓存(Session Cache):持久化;全页缓存(FPC);队列; 排行榜/计数器; 发布/订阅

(4)网络模型:单线程的多路 IO 复用模型,6.0后引入多线程
1.单线程编程容易并且更容易维护;
2.Redis 的性能瓶颈不在 CPU ,主要在内存和网络;
3.多线程就会存在死锁、线程上下文切换等问题,甚至会影响性能。
引入多线程主要是为了提高网络 IO 读写性能

2、缓存

(1)缓存处理流程
1.如果用户请求的数据在缓存中就直接返回。
2.缓存中不存在的话就看数据库中是否存在。
3.数据库中存在的话就更新缓存中的数据。
4.数据库中不存在的话就返回空数据。

(2)为什么用缓存?
高性能,读取速度快;高并发,每秒执行的查询数是mysql的10-30倍;

(3)缓存穿透:
缓存穿透说简单点就是大量请求的 key 根本不存在于缓存中,导致请求直接到了数据库上,根本没有经过缓存这一层。
解决方法:
1.首先做好参数校验,一些不合法的参数请求直接抛出异常信息返回给客户端。比如查询的数据库 id 不能小于 0、传入的邮箱格式不对的时候直接返回错误消息给客户端等等。
2.缓存无效 key :如果缓存和数据库都查不到某个 key 的数据就写一个到 Redis 中去并设置过期时间,但不能从根本上解决
3.布隆过滤器:把所有可能存在的请求的值都存放在布隆过滤器中,当用户请求过来,先判断用户发来的请求的值是否存在于布隆过滤器中。不存在的话,直接返回请求参数错误信息给客户端,存在的话才会走下面的流程。

(4)缓存雪崩:
缓存在同一时间大面积的失效,后面的请求都直接落到了数据库上,造成数据库短时间内承受大量请求。
解决办法:
针对 Redis 服务不可用的情况:
1.采用 Redis 集群,避免单机出现问题整个缓存服务都没办法使用。
2.限流,避免同时处理大量的请求。
针对热点缓存失效的情况:
1.设置不同的失效时间比如随机设置缓存的失效时间。
2.缓存永不失效。

3、数据结构

string(key-value)
list
hash
set
sorted set
bitmap

4、重要概念:

(1)为什么需要给缓存数据设置过期时间?
防止内存溢出,缓解内存的消耗;某些数据只需在某一时间段存在,如验证码1min/token1天内
设置命令为expire,取消命令persist。

(2)过期数据的删除策略:
1.惰性删除 :只会在取出 key 的时候才对数据进行过期检查。这样对 CPU 最友好,但是可能会造成太多过期 key 没有被删除。
2.定期删除 :每隔一段时间抽取一批 key 执行删除过期 key 操作。并且,Redis 底层会通过限制删除操作执行的时长和频率来减少删除操作对 CPU 时间的影响。
定期删除对内存更加友好,惰性删除对 CPU 更加友好。两者各有千秋,所以 Redis 采用的是 定期删除+惰性/懒汉式删除 。
3.定时删除:在设置键的过期时间的同时,创建一个定时器 timer。让定时器在键的过期时间来临时,立即执行对键的删除操作。

仅仅通过给key设置过期时间还是有问题的。因为定期删除和惰性删除还是可能漏掉了很多过期key的情况。这样就导致大量过期key堆积在内存里,然后就 Out of memory 了。
解决方式:Redis 内存淘汰机制

(3)Redis 内存淘汰机制/回收策略/淘汰策略:
Redis 提供 6 种数据淘汰策略:
1.volatile-lru(least recently used):从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
2.volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
3.volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
4.allkeys-lru(least recently used):当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(这个是最常用的)
5.allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
6.no-eviction:禁止驱逐数据
4.0后新增:
7.volatile-lfu(least frequently used):从已设置过期时间的数据集(server.db[i].expires)中挑选最不经常使用的数据淘汰
8.allkeys-lfu(least frequently used):当内存不足以容纳新写入数据时,在键空间中,移除最不经常使用的 key

如果数据呈现幂律分布,也就是一部分数据访问频率高,一部分数据访问频率低,则使用 allkeys-lru
如果数据呈现平等分布,也就是所有的数据访问频率都相同,则使用 allkeys-random

(4)如何保证redis缓存与数据库数据的一致性?
1.缓存过期时间变短(不推荐,治标不治本) :这样的话缓存就会从数据库中加载数据。但这种解决办法对于先操作缓存后操作数据库的场景不适用。
2.增加 cache 更新重试机制(常用):
如果 cache 服务当前不可用导致缓存删除失败的话,我们就隔一段时间进行重试,重试次数可以自己定。如果多次重试还是失败的话,我们可以把当前更新失
败的 key 存入队列中,等缓存服务可用之后,再将缓存中对应的 key 删除即可。

5、Redis 持久化机制

怎么保证 Redis 挂掉之后再重启数据可以进行恢复?
一般是把内存数据存在硬盘中或是把数据备份到一个远程位置
redis支持两种持久化方式:
(1)快照(snapshotting)持久化(RDB):默认方式
快照留到原地使重启服务器时使用;也可复制到其他服务器使用
配置:
save 900 1 #在900秒(15分钟)之后,如果至少有1个key发生变化,Redis就会自动触发 BGSAVE命令创建快照。
save 300 10 #在300秒(5分钟)之后,如果至少有10个key发生变化,Redis就会自动触发 BGSAVE命令创建快照。
save 60 10000 #在60秒(1分钟)之后,如果至少有10000个key发生变化,Redis就会自动触发 BGSAVE命令创建快照。Copy to clipboardErrorCopied

(2)AOF(append-only file)持久化:实时性更好
每执行一条会数据更改的命令,Redis 就会将该命令写入硬盘中的 AOF文件。
AOF 文件的保存位置和 RDB 文件的位置相同,都是通过 dir 参数设置的,默认的文件名是appendonly.aof。
开启方法:appendonly yesCopy to clipboardErrorCopied
配置:
appendfsync always #每次有数据修改发生时都会写入AOF文件,这样会严重降低Redis的速度
appendfsync everysec #每秒钟同步一次,显示地将多个写命令同步到硬盘(建议)
appendfsync no #让操作系统决定何时进行同步Copy to clipboardErrorCopied

拓展:混合持久化
Redis 4.0 开始支持 RDB 和 AOF 的混合持久化(默认关闭,可以通过配置项 aof-use-rdb-preamble 开启)。
如果把混合持久化打开,AOF 重写的时候就直接把 RDB 的内容写到 AOF 文件开头。
这样做的好处是可以结合 RDB 和 AOF 的优点, 快速加载同时避免丢失过多的数据。
当然缺点也是有的, AOF 里面的 RDB部分是压缩格式不再是 AOF 格式,可读性较差。

补充内容:AOF 重写
AOF 重写可以产生一个新的 AOF 文件,这个新的 AOF 文件和原有的 AOF 文件所保存的数据库状态一样,但体积更小。
通过读取数据库中的键值对来实现的,程序无须对现有 AOF文件进行任何读入、分析或者写入操作。
在执行 BGREWRITEAOF 命令时,Redis 服务器会维护一个 AOF 重写缓冲区,该缓冲区会在子进程创建新 AOF 文件期间,记录服务器执行的所有写命令。
当子进程完成创建新 AOF 文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新 AOF 文件的末尾,使得新旧两个 AOF 文件所保存的数据库状态一致。
最后,服务器用新的 AOF 文件替换旧的 AOF 文件,以此来完成 AOF 文件重写操作。

6、redis事务

事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。

Redis 可以通过 MULTI , EXEC , DISCARD 和 WATCH 等命令来实现事务(transaction)功能。
1.开始事务( MULTI )。
2.命令入队(批量操作 Redis 的命令,先进先出(FIFO)的顺序执行)。
3.执行事务( EXEC )。
DISCARD 取消一个事务,它会清空事务队列中保存的所有命令。
WATCH 命令用于监听指定的键

事务的四大特性:
redis的事务与关系型数据库的事务不同,关系型数据库的事务具有四大特性,redis不具有原子性和持久性:
1.原子性(Atomicity): 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
2. 隔离性(Isolation): 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
3. 持久性(Durability): 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
4. 一致性(Consistency): 执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的;

Redis 事务:提供了一种将多个命令请求打包的功能。然后,再按顺序执行打包的所有命令,并且不会被中途打断。

WATCH命令和基于CAS的乐观锁?

7、性能问题

(1)redis的并发竞争问题如何解决?

(2)redis常见性能问题和解决方案
11.1 Master最好不要写内存快照:
Master写内存快照,save命令调度rdbSave函数,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务
11.2 Master AOF持久化,如果不重写AOF文件,这个持久化方式对性能的影响是最小的,但是AOF文件会不断增大,AOF文件过大会影响Master重启的恢复速度。
Master最好不要做任何持久化工作,包括内存快照和AOF日志文件,特别是不要启用内存快照做持久化,如果数据比较关键,某个Slave开启AOF备份数据,策略为每秒同步一次。
11.3 Master调用BGREWRITEAOF重写AOF文件,AOF在重写的时候会占大量的CPU和内存资源,导致服务load过高,出现短暂服务暂停现象。
11.4 Redis主从复制的性能问题,为了主从复制的速度和连接的稳定性,Slave和Master最好在同一个局域网内

Master 最好不要写内存快照,如果 Master 写内存快照,save 命令调度 rdbSave函数,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务。
如果数据比较重要,某个 Slave 开启 AOF 备份数据,策略设置为每秒同步一。
为了主从复制的速度和连接的稳定性,Master 和 Slave 最好在同一个局域网。
尽量避免在压力很大的主库上增加从。
主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1<- Slave2 <-Slave3……这样的结构方便解决单点故障问题,实现 Slave 对 Master 的替换。如果 Master 挂了,
可以立刻启用 Slave1 做 Master,其他不变。

(3)Redis 如何做内存优化?
尽可能使用散列表(hashes),散列表(是说散列表里面存储的数少)使用的内存非常小,所以你应该尽可能的将你的数据模型抽象到一个散列表里面。
比如你的 Web 系统中有一个用户对象,不要为这个用户的名称,姓氏,邮箱,密码设置单独的 key,而是应该把这个用户的所有信息存储到一张散列表里面。

(4)如何降低 Redis 的内存使用情况呢?
如果你使用的是 32 位的 Redis 实例,可以好好利用 Hash,list,sorted set,set等集合类型数据,因为通常情况下很多小的 Key-Value 可以用更紧凑的方式存放到一起。

(5)Redis 的内存用完了会发生什么?
如果达到设置的上限,Redis 的写命令会返回错误信息(但是读命令还可以正常返回。)或者你可以将Redis 当缓存来使用配置淘汰机制,当 Redis 达到内存上限时会冲刷掉旧的内容。

8、分布式锁

先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。
如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?
可以同时把setnx和expire合成一条指令来用

9、异步队列

一般使用list结构作为队列,rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会再重试。
如果对方追问可不可以不用sleep呢?list还有个指令叫blpop,在没有消息的时候,它会阻塞住直到消息到来。
如果对方追问能不能生产一次消费多次呢?使用pub/sub主题订阅者模式,可以实现1:N的消息队列。
如果对方追问pub/sub有什么缺点?在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如rabbitmq等。
如果对方追问redis如何实现延时队列?使用sortedset,拿时间戳作为score,消息内容作为key调用zadd来生产消息,消费者用zrangebyscore指令获取N秒之前的数据轮询进行处理。

10、同步机制

Redis可以使用主从同步,从从同步。第一次同步时,主节点做一次bgsave,并同时将后续修改操作记
录到内存buffer,待完成后将rdb文件全量同步到复制节点,复制节点接受完成后将rdb镜像加载到内
存。加载完成后,再通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。

11、架构/redis集群

Redis Sentinal着眼于高可用,在master宕机时会自动将slave提升为master,继续提供服务。
Redis Cluster着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。

参考文章:
https://mp.weixin.qq.com/s/ZruUzCtcFC72Ej3-0PFn3A
https://blog.csdn.net/Design407/article/details/103242874

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-07-03 10:53:18  更:2022-07-03 10:53:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/7 18:23:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码