1、布隆过滤器
1)构造
构造主要包括以下三个步骤:
选择k个哈希函数、将待检索字符串分别做Hash映射、每个映射的值对应的bit数组置为“1”
2)检索
将待检索的字符串通过k个哈希函数映射;
查看映射的整数对应的位置是否1,如果都为1,说明待检索字符串是存在的。
3)效果
如果要检索的字符串(原本不存在)映射后数组每个位置恰好都为1,那就出现了误判!
对于一个拥有最优k值且误判率在1%的布隆过滤器,每个元素只需要9.6bits(与元素的大小无关)。若给每个元素增加4.8bits左右,误判率将会减少十倍。
布隆过滤器的应用:
1)网页爬虫对URL的去重
避免爬取相同的URL地址。
2)缓存击穿
将已存在的缓存放到布隆中,当黑客访问不存在的缓存时迅速返回避免缓存及DB挂掉。
3)HTTP缓存服务器
当本地局域网中的PC发起一条HTTP请求时,缓存服务器会先查看一下这个URL是否已经存在于缓存之中,如果存在的话就没有必要去原始的服务器拉取数据了(为了简单起见,我们假设数据没有发生变化),这样既能节省流量,还能加快访问速度,以提高用户体验。
4)黑/白名单
类似反垃圾邮件。
总结:布隆过滤器用于判断一个元素是否在一个集合中,不会有假负例(将在集合中的元素误判不在集合中),但会有一定的误识率(将不在集合中的元素误判为在集合中)。
2、redis有哪些数据类型,分别用于什么场景
1)string(SDS int,raw或者是embstr)
介绍 :string 数据结构是简单的 key-value 类型。虽然 Redis 是用 C 语言写的,但是 Redis 并没有使用 C 的字符串表示,而是自己构建了一种 简单动态字符串(simple dynamic string,SDS)。相比于 C 的原生字符串,Redis 的 SDS 不光可以保存文本数据还可以保存二进制数据,并且获取字符串长度复杂度为 O(1)(C 字符串为 O(N)),除此之外,Redis 的 SDS API 是安全的,不会造成缓冲区溢出。
常用命令: set,get,strlen,exists,decr,incr,setex 等等。
应用场景: 一般常用在需要计数的场景,比如用户的访问次数、热点文章的点赞转发数量等等。
2)list(早期版本中,列表对象使用的编码是ziplist或linkedlist,现在使用的是快速列表(quicklist))
介绍 :list 即是 链表。链表是一种非常常见的数据结构,特点是易于数据元素的插入和删除并且可以灵活调整链表长度,但是链表的随机访问困难。许多高级编程语言都内置了链表的实现比如 Java 中的 LinkedList,但是 C 语言并没有实现链表,所以 Redis 实现了自己的链表数据结构。Redis 的 list 的实现为一个 双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销。
常用命令: rpush,lpop,lpush,rpop,lrange,llen 等。
应用场景: 发布与订阅或者说消息队列、慢查询。
3)set(intset、字典 不满足intset使用条件的情况下都使用字典(拉链法),使用字典时把value设置为null)
介绍 : set 类似于 Java 中的 HashSet 。Redis 中的 set 类型是一种无序集合,集合中的元素没有先后顺序。当你需要存储一个列表数据,又不希望出现重复数据时,set 是一个很好的选择,并且 set 提供了判断某个成员是否在一个 set 集合内的重要接口,这个也是 list 所不能提供的。可以基于 set 轻易实现交集、并集、差集的操作。比如:你可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis 可以非常方便的实现如共同关注、共同粉丝、共同喜好等功能。这个过程也就是求交集的过程。
常用命令: sadd,spop,smembers,sismember,scard,sinterstore,sunion 等。
应用场景: 需要存放的数据不能重复以及需要获取多个数据源交集和并集等场景
4)hash(ziplist或者hashtable(字典))
介绍 :hash 是一个 string 类型的 field 和 value 的映射表,特别适合用于存储对象,后续操作的时候,你可以直接仅仅修改这个对象中的某个字段的值。 比如我们可以 hash 数据结构来存储用户信息,商品信息等等。
常用命令: hset,hmset,hexists,hget,hgetall,hkeys,hvals 等。
应用场景: 系统中对象数据的存储。
5)sortedset(数据少时用ziplist,数据多用skiplist skiplist底层是zset结构,包含一个字典和一个跳跃表,字典用来根据数据查score,跳表用来根据score查找数据(查找效率高))
介绍: 和 set 相比,sorted set 增加了一个权重参数 score,使得集合中的元素能够按 score 进行有序排列,还可以通过 score 的范围来获取元素的列表
常用命令: zadd,zcard,zscore,zrange,zrevrange,zrem 等。
应用场景: 需要对数据根据某个权重进行排序的场景。比如在直播系统中,实时排行信息包含直播间在线用户列表,各种礼物排行榜,弹幕消息(可以理解为按消息维度的消息排行榜)等信息。
6)bitmap
介绍: bitmap 存储的是连续的二进制数字(0 和 1),通过 bitmap, 只需要一个 bit 位来表示某个元素对应的值或者状态,key 就是对应元素本身 。我们知道 8 个 bit 可以组成一个 byte,所以 bitmap 本身会极大的节省储存空间。
常用命令: setbit 、getbit 、bitcount、bitop
应用场景: 适合需要保存状态信息(比如是否签到、是否登录...)并需要进一步对这些信息进行分析的场景。比如用户签到情况、活跃用户情况、用户行为统计(比如是否点赞过某个视频)。
3、redis底层数据结构-7种
https://blog.csdn.net/weixin_41519463/article/details/109208476
SDS
优点:
1)获取字符串长度的复杂度为O(1)。
2)杜绝缓存区溢出。因为其API会进行空间扩展,扩展之后未使用字节数量free和已使用字节数量len一样
3)减少字符串修改时的内存重分配次数,因为有free(预分配),所有在最坏的情况下就是修改n次,重分配n次。
链表
字典
跳跃表
跳跃表是一种有序的数据结构,通过每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。这种数据结构可以在小于等于O(n)的情况下找到相应的数据,插入删除的性能优于平衡树,范围查找的性能优于平衡树
1)由很多层组成
2)每一层都是一个有序的链表
3)最底层的链表包含了所有的元素;
4)如果一个元素出现在某一层的链表中,那么在该层之下的链表也全都会出现(上一层的元素是当前层的元素的子集);
5)链表中的每个节点都包含两个指针,一个指向同一层的下一个链表节点,另一个指向下一层的同一个链表节点;
skipList详解
intset
只有当数据全是整数值,而且数量少于512个时,才使用intset,intset是一个由整数组成的有序集合,可以保存类型为int16_t、int32_t 或者int64_t 的整数值,并且保证集合中不会出现重复元素,可以进行二分查找。
压缩列表ziplist
压缩列表(ziplist)是Redis为了节省内存而开发的,是由一系列特殊编码的连续内存块组成的顺序型数据结构,一个压缩列表可以包含任意多个节点(entry),每个节点可以保存一个字节数组或者一个整数值。
快速列表quicklist
(1)由于使用链表的附加空间相对太高以及内存碎片化等缺点,Redis后续版本对列表数据结构进行改造,使用quicklist代替了ziplist和linkedlist。
(2)快速列表有quicklistNode和quicklist结构组成
quicklist实际上是ziplist和linkedlist的混合体,它将linkedlist按段进行切分,每一段使用ziplist进行紧凑存储,多个ziplist之间使用双向指针进行串接。
4、redis到底是不是单线程
5、分布式锁常见实现方式有哪些、redis怎么实现分布式锁
ZK、mysql、redis
1)从实现的复杂性角度(从高到低)zookeeper >= redis> 数据库
数据库实现的分布式锁易于理解和实现,且不会给项目引入其他依赖。zookeeper和redis需要考虑的情况更多,实现相对较为复杂,但是都有现成的分布式锁框架curator和redision,用起来代码反而可能会更简洁。
2)从性能角度(从高到低)redis>zookeeper > 数据库
redis数据存在内存,速度很快;zookeeper虽然数据也存在内存中,但是本身维护节点的一致性。需要耗费一些性能;数据库则只有索引在内存中,数据存于磁盘,性能较差。
3)从可靠性角度(从高到低)zookeeper > redis > 数据库
zookeeper天生设计定位就是分布式协调,强一致性,可靠性较高;redis分布式锁需要较多额外手段去保证可靠性;数据库则较难满足复杂场景的需求。
mysql实现分布式锁
Redis实现分布式锁的核心就是:
SET key value NX EX timeOut (setnx 不是原子性,会有问题)
NX:只有这个key不存才的时候才会进行操作,即 if not exists; EX:设置key的过期时间为秒,具体时间由第5个参数决定 timeOut:设置过期时间保证不会出现死锁【避免宕机死锁】
Redis分布式说最大的缺点就是宕机导致多个客户端加锁,导致脏数据,不过这种几率还是很小的。
Redis 是不支持 roll back 的,因而不满足原子性的(而且不满足持久性)。
6、redis的过期删除策略和淘汰策略
7、Redis的持久化和扩容机制
8、redis为啥这么快
9、如何解决Redis和数据库,数据不一致问题
1)延时双删,具体如何实现?
2)订阅binlog
10、redis实现延迟队列
11、redis集群数量、槽数量
由于其他设计折衷,Redis集群不可能扩展到超过1000个节点
为什么redis集群的最大槽数是16384个?
在redis节点发送心跳包时需要把所有的槽放到这个心跳包里,以便让节点知道当前集群信息,16384=16k,在发送心跳包时使用char进行bitmap压缩后是2k(2 * 8 (8 bit) * 1024(1k) = 16K),也就是说使用2k的空间创建了16k的槽数。
3种集群模式:主从复制、哨兵模式、集群模式
集群模式详解