Redis整理

Redis 简介

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

  • Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
  • Redis支持数据的备份,即master-slave模式的数据备份。
  • 丰富的数据类型:有五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。
  • Redis的所有操作是原子性的,意思就是要么成功执行要么失败完全不执行。
  • 还有丰富的特性:Redis还支持publish/subscribe, 通知, key 过期等等特性。

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

  • Redis有着更为复杂的数据结构并且提供对他们的原子性操作,这是一个不同于其他数据库的进化路径。Redis的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象。
  • Redis运行在内存中但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是,相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样Redis可以做很多内部复杂性很强的事情。同时,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。

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

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

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

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

RDB原理

  • SAVE:该命令会阻塞当前Redis服务,导致Redis服务不可用,直至RDB持久化进程完毕,所以一般都不采取该方式进行RDB持久化。

  • BGSAVE:当使用该命令进行RDB持久化时,Redis会fork产生一个子进程,由子进程进行RDB持久化操作,父进程接受客户端的操作请求。子进程只会遍历读取内存中的数据,写入磁盘,并不会修改数据,若父进程在子进程读取数据过后进行了数据修改,子进程就会与父进程存在数据不一致的问题。

  • Copy on Write:众所周知Redis是单线程程序[1],文件IO操作不能进行多路复用,于是在BGSAVE进行RDB持久化时Redis采用操作系统的Copy on Write[2]机制进行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层后遇到了:缓存雪崩、缓存击穿、缓存穿透

缓存雪崩原因:

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

  • 数据的key同时失效导致
    解决办法:
    1、给key设置随机时间,避免同时失效;
    2、通过定时任务刷新key的过期时间;

  • redis服务其宕机;
    解决办法:
    1、把热点数据放到不同redis集群节点中

缓存穿透:

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

  • 解决办法:
    1、请求redis的数据不存在,查询数据库也不存在都会将数据存到redis中;
    2、使用互斥分布式锁解决:去redis中请求,不存在,在请求数据库之前添加互斥锁,使第一个请求进入到数据库中查询,使其他请求进入到短暂的睡眠,当第一次请求完成后,将数据粗到redis中,其他请求就可以继续redis中继续查询;
    jvm中的锁解决互斥锁:
    分布锁,解决多个独立个体排队问题



    3、如果是uuid的请求使用布隆过滤器来解决;

隆过滤器:

布隆过滤器过滤大部门非法请求;
过滤器会标识所有数据的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一致性算法来解决当集群中机器发生变化,不会发生大量的数据移动问题;
    比如有三台服务器分别计算服务其位置;
    第一台服务器:hash(ip+服务器编号) % 2^32
    第二台服务器:hash(ip+服务器编号) % 2^32
    第三台服务器:hash(ip+服务器编号) % 2^32

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


  • 当新增一台服务器,根据hash(ip+服务器编号) % 2^32计算出位置,


  • 删除一台服务器
    将1-3之间的数据移动到2就行


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

  • 数据倾斜
    hash算法缺点:带来数据的倾斜;
    存储框架数据倾斜:少量数据存在大量数据,大量数据存在少量数据;

计算框架数据的倾斜:


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


  • 通过经验:
    10台redis服务器一般虚拟100-200个虚拟服务节点;
    5台redis服务其一般虚拟200-400个虚拟服务器;
    总和一般1000-2000个虚拟节点;这样数据才不会倾斜

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

缓存雪崩

缓存穿透

缓存穿透

redis过期键删除策略

  • 定时过期
    三种比较常用;定期过期比较好的这种方式;

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

???????


redis事务实现 保证ACID

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



redis集群方案

哨兵模式

redis Cluster

RedisSharding客户端分片

Redis主从复制的核心原理

  • 全量复制


  • 部分复制


Redis的过期键删除策略

  • 定时过期
    给每个key设置一个过期时间;

CAP理论

BASE理论

负载均衡算法


负载均衡类型

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

不用session:JWT或者TOKEN


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

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


Redis6.0多线程工作模式

Redis核心数据结构

Redis缓存雪崩,穿透、

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

setbit实现


统计单日登录用户



统计两天都登陆的用户


redis应用场景

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

  • redis数据结构 :分布式的数据结构;
    jdk的数据结构不能跨集群的数据结构;
  • redis的set和get的执行过程
    存在全局hash表中,hash的这种算法结构查询/存储效率并比较高;
    hash(key)% 全局hash表size;
    redis底层自己实现的自己的hash算法;
  • redis set时value的存储结构;

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

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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容