Redis学习笔记

bitmap 位图:

可以用于记录某个用户的每天的登录情况,

668141e2f9314b3da01aa38e1cc2aa0d.png

布隆过滤器:

类似于hashset,用于判断某个数据是否存在于集合中,本质上是一个很长的二进制数据(类似bitmap)和一系列的随机映射函数。

a.插入

当有数据插入时,先通过k个映射函数将变量变成k个值,然后再把bitmap上对应的点位设置为1。

查询数据时,如果有任何一个点的值为0,则该数据一定不存在;全为1,则数据可能存在。

b.误判率:

布隆过滤器的误判是指多个输入经过哈希之后在相同的bit位置1了,这样就无法判断究竟是哪个输入产生的,因此误判的根源在于相同的 bit 位被多次映射且置 1。

这种情况也造成了布隆过滤器的删除问题,因为布隆过滤器的每一个 bit 并不是独占的,很有可能多个元素共享了某一位。如果我们直接删除这一位的话,会影响其他的元素。

c.特点:

如果查询的元素中,有某个点位是0,则数据一定不存在;全是1则可能存在

只能插入元素,但是不能删除元素,因为删除元素会增加误判率

d.优点:

1、可以表示数据全集,其他任何数据结构都不行

2、不存储元素,对数据保密性高的场合有优势

3、k 为哈希函数个数,m 为布隆过滤器长度,n 为插入的元素个数,p 为误报率

空间复杂度是O(m),时间复杂度是O(k),插入、查询的时间复杂度都是O(k)

e.缺点:

数据量越大,误差率越大。如果想保持误差率在低范围,则要加大数组长度,即占用空间更大

应用场景:

  • 网页爬虫对 URL 去重,避免爬取相同的 URL 地址;
  • 反垃圾邮件,从数十亿个垃圾邮件列表中判断某邮箱是否垃圾邮箱;
  • 解决缓存穿透问题,但查询的数据不存在于数据库中,则直接返回,减少数据库不必要的查询。具体过程如下:

当客户端查询时,先通过布隆过滤器查看缓存中是否存在该数据,如果不存在,则直接返回。如果布隆过滤器中显示缓存可能存在,则从缓存中读取数据,如果缓存也不存在,就从数据库中读取。

字符串String:

记录普通的字符串,一个字符串最大可512M

列表list:

链表,插入删除复杂度为O(1),查询为O(n),一个列表最多可以存储2^32 - 1 个元素, 当列表中存储的元素较少时,Redis 会使用一块连续的内存来存储这些元素,这个连续的结构被称为 ziplist(压缩列表),而当数据量较大时,Redis 列表就会是用 quicklist(快速链表)存储元素。quicklist 的结构图如下:

20230724024159.png?origin_url=https%3A%2F%2Fnote.youdao.com%2Fyws%2Fres%2F181%2FWEBRESOURCEb0a12b06d329ee42410611d97b87fabe&pos_id=V1eGfWbI

Hash:

适合存储对象,如命令:

hmset user:1004 12580:nums 5 12580:info {json字符串}

用户1004 购买了12580这个商品,数量为5; 后面是12580的信息

当存储的数据量较少的时,hash 采用 ziplist 作为底层存储结构(底层是key value key value ... 这样的数组):

  • 哈希对象保存的所有键值对(键和值)的字符串长度总和小于 64 个字节。
  • 哈希对象保存的键值对数量要小于 512 个。

当无法满足上述条件时,hash 就会采用第二种方式来存储数据,也就是 dict(字典结构),该结构类似于 Java 的 HashMap

Set:

内部数据不重复, 哈希映射表实现的,所以它的添加、删除、查找操作的时间复杂度为 O(1),可以用类似数学方法对集合进行数据操作

a.情况如下使用 intset (整形数组) :

  • 集合内保存的所有成员都是整数值;
  • 集合内保存的成员数量不超过 512 个。

b.其他情况用hash table

Order Set(ZSet):压缩列表

和set的区别是可以排序,所以当需要用到不重复需要排序的列表时可以使用,如主播的礼物榜

底层是 zipList(压缩列表)和 skipList(跳跃列表)

以下条件时使用压缩列表:

  • 成员的数量小于128 个;
  • 每个 member (成员)的字符串长度都小于 64 个字节

20230724024159.png?origin_url=https%3A%2F%2Fnote.youdao.com%2Fyws%2Fres%2F232%2FWEBRESOURCE3202d4154582b9c32228f9d8fad3885f&pos_id=OEYF2igX

HyperLoglog:

适用于海量数据的计算、统计,其特点是占用空间小,计算速度快,每个 HyperLogLog key 只占用 12 KB 内存,所以理论上可以存储大约2^64个值

最典型的应用场景就是统计网站用户月活量,或者网站页面的 UV(网站独立访客)数据等

pfadd pfcount pfmerge

Reids持久化:

一、RDB:

1、手动策略:

又称快照(snapshot)模式(所谓“快照”就是将内存数据以二进制文件的形式保存起来),将数据保存在dump.rdb文件中,保存的命令为save,bgsave

save会阻塞当前程序,不建议使用;bgsave是通过调用fork()函数来保存;以上两种都是手动保存

20230724024159.png?origin_url=https%3A%2F%2Fnote.youdao.com%2Fyws%2Fres%2F253%2FWEBRESOURCE88748b91cb0158a563de79f1559ea380&pos_id=bbIK7rjR

2、自动策略

在redis配置文件中有

save 900 1 表示在 900 秒内,至少更新了 1 条数据,Redis 自动触发 BGSAVE 命令,将数据保存到硬盘。

save 300 10 表示在 300 秒内,至少更新了 10 条数据,Redis 自动触 BGSAVE 命令,将数据保存到硬盘

save 60 10000 表示 60 秒内,至少更新了 10000 条数据,Redis 自动触发 BGSAVE 命令,将数据保存到硬盘。

只要上述三个条件任意满足一个,服务器就会自动执行 BGSAVE命令。可以根据实际情况自己调整触发策略。

3、优劣势

20230724024159.png?origin_url=https%3A%2F%2Fnote.youdao.com%2Fyws%2Fres%2F271%2FWEBRESOURCE266de5f6d69cd7dc2ee70f58392d3544&pos_id=wX8b5Qaz

二、AOF

日志模式,记录redis服务器已经执行过的命令(只记录对数据库有修改的命令),默认是不开启,需要修改配置文件 appendonly no 为 yes,然后重启服务器,AOF包含写入机制和重写机制

1、写入机制:

每执行一条修改命令,redis 服务器先进行相应的校验,如果没问题的话就追加到AOF文件中,然后再执行命令,保证遇到宕机之后,数据不会丢失(为了提升效率,会先将命令写入缓存区,等缓存区满了才真正将内容写进文件)

2、重写机制:

redis在执行过程中,aof文件会越来越大,需要对命令进行整理,减少文件的内存大小,可以 通过 BGREWRITEAOF 命令手动执行重新机制,重新生成新的aof文件;该文件有以下特点:

  • 数据库数据和原本文件记录的数据库数据完全一致
  • 文件体积更小
  • 重写期间,服务器不会阻塞,可以正常执行客户端命令

自动触发功能:

20230724024159.png?origin_url=https%3A%2F%2Fnote.youdao.com%2Fyws%2Fres%2F318%2FWEBRESOURCEbf9903ee31423d03f948bbc4e2f87843&pos_id=ABjCernC

3、配置策略

aof是先将命令写进内存,如果宕机则会丢失,造成数据丢失风险;因此aof提供了3种执行策略:

always 每执行一条命令,就调用一次fsync()函数,将缓冲区的数据写入硬盘

Everysec(默认):服务器每一秒调用一次 fsync 函数,将缓冲区里面的命令写入到硬盘。这种模式下,服务器出现故障,最多只丢失一秒钟内的执行的命令数据,通常都使用它作为 AOF 配置策略;

No:服务器不主动调用 fsync 函数,由操作系统决定何时将缓冲区里面的命令写入到硬盘。这种模式下,服务器遭遇意外停机时,丢失命令的数量是不确定的,所以这种策略,不确定性较大,不安全。

三、AOF和RDB对比

20230724024159.png?origin_url=https%3A%2F%2Fnote.youdao.com%2Fyws%2Fres%2F331%2FWEBRESOURCEf55235e35afb54143c546cd9243ed19b&pos_id=s0flWE4i

Redis分布式锁:

分布式锁:相当于某个客户端在 redis 服务端占一个坑(设置某个数据),当其他客户端访问的时候,需要等先前的客户端释放锁才能设置,否则只能读取

常用命令:

setnx key val

expire key timeout

del key

说明:如果某个key不存在,则给他设置val,并返回1,否则返回0;然后通过expire设置自动过期时间删除key,避免造成死锁 ,或者手动用del删除key;

但是这样操作,当在setnx命令之后服务器宕机,会导致死锁;

解决方法:

使用set 命令,格式如下

SET key value [expiration EX seconds|PX milliseconds] [NX|XX]

  • EX second:设置键的过期时间为 second 秒。 SET key value EX second 效果等同于 SETEX key second value 。
  • PX millisecond:设置键的过期时间为毫秒。SET key value PX millisecond 效果等同于 PSETEX key millisecondvalue 。
  • NX:只在键不存在时,才对键进行设置操作。 SET key value NX 效果等同于 SETNX key value 。
  • XX:只在键已经存在时,才对键进行设置操作。

Redis缓存问题

为了减轻后台数据库的压力,一般会先将数据读取出来后,缓存到redis中,但用户查询的时候,如果redis中存在则直接返回,否则读取数据库信息,然后返再将数据缓存到redis中并返回给用户

1、缓存穿透:

当用户查询某个数据时,Redis中不存在,即缓存没有命中,此时就会去数据库中查询,结果数据库中也不存在,于是数据库返回空对象,此次查询失败。如果有大量类似的请求,会造成数据库压力过大而奔溃

解决办法:

缓存空对象:当数据库返回空对象时,将该空对象缓存到redis中,并设置一个过期时间,但是占用redis的缓存空间

使用布隆过滤器进行缓存预热:当系统启动时,先将相关数据加载到redis缓存系统中,避免用户请求时再去加载数据

2、缓存击穿:

用户查询的数据,缓存中不存在,然而数据库中存在(一般是因为缓存中的该数据过期了)。单同时有大量的请求到达,要访问某热点数据,结果因Redis中缓存查询不到,导致去查询数据库,造成数据库压力过大崩溃。

解决方法:

1.设置热点数据不会过期。

2.采用分布式锁:

上锁:当某个数据在缓存中查询不到时,先通过分布式锁进行加锁,第一个获取锁的进程访问数据库进行查询,并将结果缓存到redis中,然后解锁

解锁:当其他进程发现锁被占用时,先进入等待状态,直至解锁,然后直接从缓存中读取数据

3、缓存雪崩:

当系统中有大量的key同时过期,而此时服务器访问量非常大,导致数据库压力暴增崩溃。

雪崩是指同时有很多个key过期,而击穿是只有一个key过期。

解决办法:

设置热点数据永不过期

为key设置随机过期时间,避免key集中过期

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值