redis

Redis整理

2021-03-26  本文已影响0人  奇点一氪

Redis 简介

Redis 是完全开源免费的,遵守BSD协议,是性能极高的nosql数据库,Redis读的速度能达到110000次/s,写的速度能达到81000次/s 。

Redis与其他key-value存储有什么不同?

Redis内存数据如何保存到磁盘

Redis的所有数据都存在内存之中,防止数据丢失;

Redis持久化有两种方式,分别是RDB(又称快照)与AOF。

对于两种方式各有优缺点,具体如下:
RDB:将内存中所有数据以二进制数据方式存到硬盘中,同步慢,数据较小。
AOF:追加操作指令到原来的aof文件中,同步较快,数据量随时间增加文件而增大。

RDB原理

单独使用RDB持久化,存在日志文件丢失风险

AOF原理

AOF日志存储的是,Redis执行的顺序写指令。当开启AOF持久化时,Redis会先执行数据的写指令,再将指令写入AOF日志中。

fsync:实际情况中,AOF机制会先将Redis写指令写入内存缓冲区中,再根据配置情况,定时调用fsync将缓冲区文件写入AOF日志中。我们可以根据实际情况设置fsync频率:

always:每次修改,立即提交磁盘。该方式数据完整性良好,但是IO开销大,影响效率.
everysec: 每秒同步一次到磁盘。该方式只会丢失一秒内的数据,
no: 从不同步到磁盘。

Redis4.0

从Redis4.0开始,Redis开始支持混合持久化。即将RDB与AOF结合使用,RDB负责定时全量持久化数据,AOF负责记录最后一次RDB后的增量日志。使得Redis的数据恢复在恢复效率与数据完整性之间取得一个完美的平衡点。

Redis线程模型、单线程快的原因

1.

2.单线程快的原因
内存操作
核心是基于非阻塞的io多路复用机制
单线程避免多线程的上下文切换带来的性能问题;

1.使用场景

面试流程
1.redis是什么,基于内内存的;k/v类型的nosql数据库,工作线程是单线程的 worker,
iothreads
连接很多 ; epoll
5中类型;本地方法;计算数据移动,io优化
集群
分片
主从
持久化;
整体模型
串行/并行那个更优

线程模型:worker 单线程

秒杀;串行;


单个线程

多个线程:io是多线程的,工作线程是单线程的

工作线程是一个,满足redis单线程的


你的项目中如何运用的redis

1.并发
2.性能
3.分布式锁、

b/s:单一架构当访问量非常大的时候,tomcat访问数据库会达到瓶颈,引入redis-nosql数据库;(是为了解决什么问题?)提高性能,解决并发量;
介绍redis :redis基于内存,(redis特性,速度方面)
redis用来干什么;

使用redis做缓存层有没有遇到什么问题?

在引入redis层后遇到了:缓存雪崩、缓存击穿、缓存穿透

缓存雪崩原因:

后果:产生的雪崩导致服务卡顿,乃至服务宕机;

缓存穿透:

非法请求,查询不存在的数据,直接穿过redis访问数据库;例如:每次请求id为uuid的请求,redis中不存在,直接查询数据库;

隆过滤器:

布隆过滤器过滤大部门非法请求;
过滤器会标识所有数据的id,但是布隆过滤器会存在错误率,请求进来经过布隆过滤器,判断id是否存在,存在可能查询不到数据;因为经过布隆算法,将id经过hash算法存到布隆过滤器中;但是当redis去布隆过滤器中查询,布隆过滤器中不存在,那就真的不存在,所以会存在错误率;

二进制数组;
可以设置错误率;错误率越小,hash函数越多,存到过滤器中的数据量越多,导致的计算时间越长;
误判率大,hash函数少,存到过滤器中的数据量越少,计算按时间越短;


缓存击穿:

web请求队一个热点数据进行大量访问,当key失效了,大量请求会进入到数据;导致服务卡顿,宕机;

你知道redis集群中hash一致性算法原理机器作用

hash一致性算法;

如何保证数据均匀的存在这两台redis服务器中
redis 是key:value数据库
对key进行hash取模算法:
hash(key) %2 == 0 ?redis1:redis2


在计算数据存储在那个位置
hash(key) % 2^32 = value
根据value数据库顺时针查找数据库;


hash一致性算法思路是:解决小范围数据的移动,不至于全盘数据调整;对于集群的拓展,容错效率都非常高;

计算框架数据的倾斜:


解决数据倾斜问题;使用虚拟节点;
redis服务器虚拟成2个节点


-------------------------------------------------------------------------

缓存雪崩

缓存穿透

缓存穿透

redis过期键删除策略

Redis线程模型,单线程为什么那么快

???????


redis事务实现 保证ACID

与mysql都是相同;保证
原子性:
一致性:
持久性:
隔离性:
mysql有回滚机制,redis没有回滚机制
事务开始之前监控key,



redis集群方案

哨兵模式

redis Cluster

RedisSharding客户端分片

Redis主从复制的核心原理

Redis的过期键删除策略

CAP理论

BASE理论

负载均衡算法


负载均衡类型

分布式架构下,Session共享有什么方案

不用session:JWT或者TOKEN


高并发场景下秒杀下超卖bug

通过redisson 获取锁对象,对产品的key进行加锁,加完锁,然后对锁进行30/3的时间进行续命,保证锁不失效;操作哇按后进行释放锁;


Redis6.0多线程工作模式

Redis核心数据结构

Redis缓存雪崩,穿透、

如何实现千万级用户日活统计

setbit实现


统计单日登录用户



统计两天都登陆的用户


redis应用场景

redis核心数据结构和底层原理

incr: 存储的时候对value转成int类型,转成功就可以自增,不能转就不能自增;

操作类型

String


在分库分表的情况下id怎么生成,使用redis的incr生成id;
批量生成id在edis中生成100个,程序中自增++,当程序中++到100了就调用redis的incryby生成100个;优化生成效率;


hash结构

对象缓存



应用:京东的购物车


List 数据结构


使用:


redis的list类型的:消息流应用
当消息来了往自己的消息列表中粗怒一条数据,不用每次都查询寻数据库;提高性能;


set数据结构


set应用:


集合操作:


zset有序集合

zset应用:比如:热搜


redis数据结构

zset数据存储结构:

压缩列表和跳表的切换阈值;阈值:128个元素切换:


这个地方说说集合特点
链表特点,源码;
集合特点,源码;

数组插入:



链表插入:


redis数据结构

JAVA缓存热点数据,使用redis缓存数据,保证热点数据的缓存用法与原理

通过redis本身的设置过期时间来实现缓存热点数据



1、缓存每命中一次,就重新给该数据设置过期时间
2、那么经常命中的缓存始终不会过期,不会被删除,而非热点数据过期时间一到那么就会被删除掉,保证了redis中始终存在的是热点数据。
【原理】
1、原理其实就是Java中延时阻塞队列DelayQueue的原理
2、当对redis中缓存数据设置过期时间,相当于将缓存数据放入redis中维护的延时阻塞队列DelayQueue。
3、DelayQueue会对放入的缓存数据根据过期时间进行排序,时间短的在前面,时间长的在队列后面。
4、会使用一个或者多个线程循环查询DelayQueue,一旦能从DelayQueue获取元素了就说明该缓存数据到期了,就可以取出来并且删除掉了。
5、当有多个线程都同时查询DelayQueue的时候,只有一个线程能够争取到头元素,其它线程将被阻塞。当头元素被取走以后,会唤醒所有阻塞线程,线程竞争头元素,竞争到头元素的线程会查询头元素的剩余delay时间,并且标记头元素已经被该线程占有,再根据delay时间wait自己,最后获取头元素后唤醒其它阻塞线程。

Redis I/O 多路复用模块

“I/O 多路复用模块”会监听多个 FD ,当这些FD产生,accept,read,write 或 close 的文件事件。会向“文件事件分发器(dispatcher)”传送事件。

文件事件分发器(dispatcher)在收到事件之后,会根据事件的类型将事件分发给对应的 handler。

我们顺着图,从上到下的逐一讲解 Redis 是怎么实现这个 Reactor 模型的。

I/O 多路复用模块

Redis 的 I/O 多路复用模块,其实是封装了操作系统提供的 select,epoll,avport 和 kqueue 这些基础函数。向上层提供了一个统一的接口,屏蔽了底层实现的细节。

一般而言 Redis 都是部署到 Linux 系统上,所以我们就看看使用 Redis 是怎么利用 linux 提供的 epoll 实现I/O 多路复用。

首先看看 epoll 提供的三个方法:

/*
 * 创建一个epoll的句柄,size用来告诉内核这个监听的数目一共有多大
 */
int epoll_create(int size);

/*
 * 可以理解为,增删改 fd 需要监听的事件
 * epfd 是 epoll_create() 创建的句柄。
 * op 表示 增删改
 * epoll_event 表示需要监听的事件,Redis 只用到了可读,可写,错误,挂断 四个状态
 */
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

/*
 * 可以理解为查询符合条件的事件
 * epfd 是 epoll_create() 创建的句柄。
 * epoll_event 用来存放从内核得到事件的集合
 * maxevents 获取的最大事件数
 * timeout 等待超时时间
 */
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

再看 Redis 对文件事件,封装epoll向上提供的接口:

/*
 * 事件状态
 */
typedef struct aeApiState {

 // epoll_event 实例描述符
 int epfd;

 // 事件槽
 struct epoll_event *events;

} aeApiState;

/*
 * 创建一个新的 epoll 
 */
static int aeApiCreate(aeEventLoop *eventLoop)
/*
 * 调整事件槽的大小
 */
static int aeApiResize(aeEventLoop *eventLoop, int setsize)
/*
 * 释放 epoll 实例和事件槽
 */
static void aeApiFree(aeEventLoop *eventLoop)
/*
 * 关联给定事件到 fd
 */
static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask)
/*
 * 从 fd 中删除给定事件
 */
static void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int mask)
/*
 * 获取可执行事件
 */
static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp)

https://www.jb51.net/article/137486.htm

缓存预热

系统冷启动
当系统上线时,缓存内还没有数据,如果直接提供给用户使用,每个请求都会穿过缓存去访问底层数据库,如果并发大的话,很有可能在上线当天就会宕机,这种情况就叫“系统冷启动”,因此我们需要在上线前先将数据库内的热点数据缓存至Redis内再提供出去使用,这种操作就成为"缓存预热"。

解决方案
提前给redis中嵌入部分数据,再提供服务。 这宛如一句feihua,但是却也是行之有效的好办法。
那如何实施?

肯定不可能将所有数据都写入redis,因为数据量太大了,第一耗费的时间太长了,第二redis根本就容纳不下所有的数据。

所以,就.需要更具当天的具体访问情况,统计出频率较高的热数据。

然后将访问频率较高的热数据写入到redis,如果说热数据也比较多,我们也得多个服务并行的读取数据去写,并行的分布式的缓存预热。

然后将嵌入的热数据的redis对外提供服务,这样就不至于冷启动,直接让数据库崩溃了。

缓存更新

缓存服务(Redis)和数据服务(底层数据库)是相互独立且异构的系统,在更新缓存或更新数据的时候无法做到原子性的同时更新两边的数据,因此在并发读写或第二步操作异常时会遇到各种数据不一致的问题。如何解决并发场景下更新操作的双写一致是缓存系统的一个重要知识点。

即数据一致性,在开头的那篇博客里已经讲得挺详尽了。

那就再提一嘴,延时双删,这里就不展开了,挺多的。

上一篇 下一篇

猜你喜欢

热点阅读