redis

一、redis为什么快

  • 1.基于内存:内存读写效率远高于磁盘读写

  • 2.存储形式:键值对的内存数据库,哈希表结构 O(1)时间复杂度可以获取值

  • 3.单线程:避免上下文切换

  • 4.IO多路复用 :单个线程处理多个客户端链接

  • 5.编码:支持多种数据结构及编码,根据元素数量,有阀值,大于小于阀值的编码不同

  • 6.渐进式ReHash:把一次性大量拷贝(数组移动)的开销,分摊到多次处理请求的过程中

  • 7缓存时间戳:由一个定时任务,每毫秒更新一次缓存,获取时间从缓存中直接拿

二、redis的应用场景

常用基本数据类型(8种)

名称 英文名 作用域
字符串 String 缓存、计数器、分布式session,分布式锁
哈希 hash 存放对象
列表 list 消息队列、文章列表
集合 set 标签、随机数、社交图谱
有序集合 zset 排行榜
Bitmaps Bitmaps 布隆过滤器
HyperLogLog HyperLogLog uv
Geo Geo redis3.2推出 用于存储地理位置信息

1.字符串(string)

  • 命令的时间复杂度
    • del、mset、mget支持多键操作,时间复杂度和键个数相关为 O(n)
    • getrange的 -> O(n)
    • 剩余全是O(1)
  • 缓存:具有支持高并发的特性,加速读写,降低后端压力
  • 计数器:实现快速计数、查询缓存的功能、同时数据可异步落地到其他数据源
  • 分布式会话:(共享session):将用户的session进行集中管理
  • 分布式锁:使用redis setnx来实现分布式锁

2.哈希(Hash)

  • 适用于存储对象,比string开发效率更高

3.列表(list)

用来存储多个有序字符串

  • 消息队列:lpush + brpop 命令组合实现阻塞队列:
    生产环境客户端使用lpush从列表左侧插入元素,多个消费者客户端使用brpop命令阻塞式的”抢“列表尾部的元素,多个客户端保证了消费的负载均衡和高可用性。
  • 文章列表:有序,且支持按照索引范围获取元素

4.集合(set)

  • 标签:同一标签:对于用户体验和增强用户粘性比较重要
  • 随机数:抽奖活动
  • 社交网络:点赞、粉丝数、共同好友、喜好、推送、下拉刷新等
    • sunion命令 : 返回多个set类型的并集
    • sinter命令:返回多个set类型的交集集
    • sdiff命令:返回多个set类型的差集

5.有序集合(zset)

  • 排行榜:多维度:时间、浏览量、获赞数

6.BitMaps(位数组实现):

bitmaps应用场景

  • 几亿用户系统签到
  • 去重登录次数统计
  • 某用户是否在线状态
    命令:setbit、getbit、bitcount
    bitmaps原理:redis内构一个足够长的数组,每个数组只能是0和1两个值,数组下标表示用户id,这个几亿长的大数组就可以通过下标和元素值(0和1)来构建一个记忆系统
  • 布隆过滤器:用于判断一个元素是否在一个集合中

7.HyperLogLog(基于概率有误差)

用于计算一个很大的元素集合的基数,基数是指集合中不同元素的数量。这种结构是用来处理大数据的,因为它会以极小的内存空间(通常每个元素只需要12字节)来计算基数。

  • UV : 统计每个网页每天的uc数据,不精确的去重计数方案,误差0.81%

8.Geo

常用结构命令

  • 1.geoadd:添加地理位置信息
    eg:geoadd cities 13.361389 38.115556 "Palermo"
  • 2.geopos:获取地理位置信息。
    eg:geopos cities "Palermo"
  • 3.geodist:获取两个地理位置的距离。
    eg:geodist cities "Palermo" "Catania" km
  • 4.georadius:根据用户给定的经纬度坐标来获取位于指定范围内的地理位置元素
    eg:georadius cities 15 37 100 km WITHCOORD WITHDIST WITHHASH
  • 5.georadiusbymember:根据位置元素所对应的坐标来获取位于指定范围内的地理位置元素。
    eg:georadiusbymember cities "Palermo" 100 km WITHCOORD WITHDIST WITHHASH
  • 6.geohash:获取一个或多个位置元素的 Geohash 值。
    eg:geohash cities "Palermo" "Catania"

三、为什么redis6.0引入多线程

redis6.0之前

  • redis的瓶颈不是cpu,受制于内存、网络
  • 提高redis性能,pipeline(命令批量)
  • 单线程,维护成本低,不需关注线程安全
  • 惰性rehash减少阻塞

redis6.0引入多线程之后:

本质:多线程任务 分摊到Redis 同步IO中,读写负载。

  • 1、小数据包。数据-》内存 响应时间 100ns 8w-10wQPS(极限)
  • 2、针对大的公司,需要更大的QPS,IO的多线程(内部执行命令还是单线程)
  • 3、为什么不采用分布式架构—很大的缺点。
    服务器数量多,维护成本高。Redis命令 不适用 需要数据分区,无法解决热点数据读写的问题。
    数据倾斜、重新分配、扩容、缩容,更加复杂

4.redis的高级功能

  • 1.慢查询
    快速定位系统中的慢操作,监测发生时间、耗时、命令的详细信息
  • 2.Pipeline:命令批量
  • 3.wathc命令
    确保事务中的key有没有被其他客户端修改过,才执行事务,否则不执行(类似于乐观锁)
  • 4.redis + lua语言实现限流
  • 5.分布式锁:setnx:加锁设置过期时间 + 看门狗续期
  • 6.高并发高可用
    • 1.主从复制
      提供了复制功能,实现了相同数据的多个Redis副本。每个主节点可以对应多个从节点,复制的数据流只能由主节点复制到从节点
    • 主从复制的问题
      • 需要手动晋升子节点,同时需要修改应用方的节点地址。
      • 主节点的写能力收到单机限制
      • 主节点的存储能力收到单机的限制
  • 7 哨兵(redis sentinel)
    主从复制模式下,主节点故障,需要人工将从节点晋升为主节点。
    2,8版本开始提供哨兵架构解决此问题。
    原理是哨兵通过发送命令(ping命令),等待Redis服务器响应,如果在指定时间内,主机Redis无响应,从机则判断主机宕机,选举从机上位,从而监控运行的多个Redis实例
    • 1.心跳机制:每个sentinel每秒一次向主从服务器发送ping命令,获取状态信息,心跳检测
    • 2.判断master节点是否下线(默认30s)
    • 3.基于Raft算法选举领头sentinel
    • 4.故障转移:选择一个slaver节点来作为master
      • 1.选择优先级最高的(replica-priority配置项)越小,优先级越高
      • 2.优先级相同,选择offset(偏移量)最大的,越多同步数据越多
      • 3.如果offset也相同,选择 run id 较小的
        通过以上4个步骤,s实现由Redis Sentinel自动完成故障发现和转移,实现自动高可用

Redis哨兵模式的优缺点

  • 哨兵模式优点:最大的优点就是主从可以自动切换,系统更健壮,可用性更高;
  • 哨兵模式缺点:最大的缺点就是还要多维护一套哨兵模式,实现起来也变的更加复杂增加维护成本;

5.redis的事务

本质:按照顺序串行化执行队列中的每个命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。
顺序性、一次性、排他性 执行一个队列中的一系列命令。

命令 描述
EXEC 执行所有事务块命令
DISCARD 取消事务、放弃执行事务块所有命令
MULTI 标记一个事务块,开启事务
UNWATCH 取消watch命令对所有key的监视
WATCH 监视key,如果在事务执行前,该key被其他命令改动,事务将被打断
代码实例:
        //构建redis连接
        Jedis jedis = jedisPool.getResource();
        //标记一个事务块,开启事务
        Transaction transaction = jedis.multi();
        try {
            transaction.set("name1","江先进");
//            int n = 10/0;
            transaction.set("name2","张硕");
            //执行事务
            transaction.exec();
        }catch (Exception e){
            //取消事务
            transaction.discard();
            e.printStackTrace();
        }


redis提供了简单的事务功能,将一组需要一起执行的命令放到 multi 和exec两个命令之间。multi命令代表事务开始,exec命令代表事务结束,另外discard命令是回滚
回滚机制上,redis只能对基本语法错误进行判断,运行时错误无法回滚

6.redis的过期策略及内存淘汰机制

6.1:redis过期删除策略:默认定期删除+惰性删除

6.1.1定时删除

在设置某个key 的过期时间同时,我们创建一个定时器,让定时器在该过期时间到来时,立即执行对其进行删除的操作
优点:定时删除对内存是最友好的,能够保存内存的key一旦过期就能立即从内存中删除。
缺点:对CPU最不友好,在过期键比较多的时候,删除过期键会占用一部分 CPU 时间,对服务器的响应时间和吞吐量造成影响。

6.1.2:定期删除

每隔一段时间,我们就对一些key进行检查,删除里面过期的key。Redis默认每隔100ms就随机抽取部分设置了过期时间的key,检测这些key是否过期,如果过期了就将其删除

这里有两点需要注意下:

默认的每隔100ms是在Redis的配置文件redis.conf中有一个属性"hz"默认为10,表示1s执行10次定期删除,即每隔100ms执行一次,可以修改这个配置的值来设置默认的间隔时间。

随机抽取部分,而不是全部key。因为如果Redis里面有大量key都设置了过期时间,全部都去检测一遍的话CPU负载就会很高,会浪费大量的时间在检测上面,甚至直接导致redis挂掉。所有只会抽取一部分而不会全部检查。
优点:可以通过限制删除操作执行的时长和频率来减少删除操作对 CPU 的影响。另外定期删除,也能有效释放过期键占用的内存。
缺点:难以确定删除操作执行的时长和频率。如果执行的太频繁,定期删除策略变得和定时删除策略一样,对CPU不友好。如果执行的太少,那又和惰性删除一样了,过期键长时间占用的内存没有及时释放的话,当我们再次获取这个过期的key时,依然会返回这个key的值,就相当于这个过期时间是无效的了。

6.1.3:惰性删除

设置该key 过期时间后,我们不去管它,当需要该key时,我们在检查其是否过期,如果过期,我们就删掉它,反之返回该key。
优点:对 CPU友好,我们只会在使用该键时才会进行过期检查,对于很多用不到的key不用浪费时间进行过期检查。
缺点:对内存不友好,如果一个键已经过期,但是一直没有使用,那么该键就会一直存在内存中,如果数据库中有很多这种使用不到的过期键,这些键便永远不会被删除,内存永远不会释放,从而造成内存泄漏。所以redis还引入了另一种内存淘汰机制。

6.2:内存淘汰机制

6.2.1:如何配置内存淘汰机制

在redis.conf中:

  • 配置 maxmemory 设置redis的最大内存空间,通常设置为物理内存的四分之三
  • 配置maxmemory-policy noeviction,设置淘汰策略,默认为 noeviction

6.2.2:内存淘汰的方式:

noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。(默认选项,一般不会选用)
allkeys-lru:当内存不足以容纳新写入数据时,在整个键空间中,移除最近最少使用的key。(这个是最常用的)
allkeys-lfu:当内存不足以容纳新写入数据时,在整个键空间中,移除最不经常(最少)使用的key。
allkeys-random:当内存不足以容纳新写入数据时,在整个键空间中,随机移除某个key。
volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。
volatile-lfu:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最不经常(最少)使用的key。
volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。
volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。

6.2.3:常用的淘汰算法

FIFO算法(First in first out:先进先出)

基于队列的先进先出原则,最先进入的数据会被最先淘汰掉。这是最简单、最公平的一种思想
(1)实现:维护一个FIFO队列,按照时间顺序将各数据(已分配页面)链接起来组成队列,并将置换指针指向队列的队首。再进行置换时,只需把置换指针所指的数据(页面)顺次换出,并把新加入的数据插到队尾即可。
(2)缺点:这种算法有个很严重的缺点,就是会导致缺页率增加。缺页率指的是判断一个页面置换算法优劣的指标。随着分配页面的增加,被置换的内存页面往往是被频繁访问的,因此FIFO算法会使一些页面频繁地被替换和重新申请内存,从而导致缺页率增加。由于缺页率会随着分配页面的增加而增加,使得redis的开销也逐渐增加,所以这种算法已经不再使用。

LRU算法(Least recently used:最近最少使用)

LRU算法是一种常见的缓存算法,它的思想是:最近最少使用的会被优先淘汰。如果一个数据在最近一段时间没有被访问到,那么可以认为在将来它被访问的可能性也很小。因此,当空间满时,最久没有访问的数据最先被淘汰掉。
(1)实现:最简单的实现方法是用数组+时间戳的方式,不过这样做效率较低。因此,我们可以用双向链表(LinkedList)+ 哈希表(HashMap)实现(链表用来表示位置,哈希表用来存储和查找),在Java里有对应的数据结构LinkedHashMap。

(2)缺点:它在需要淘汰时,只是随机选取有限的key进行对比,排除掉访问时间最久的元素,也就意味着它不能选择整个候选元素的最优解,只是局部最优。默认随机选取的key的数目为5,在配置文件redis.conf 中由maxmemory_samples属性的值决定,采样数量越大越接近于标准LRU算法,但也会带来性能的消耗。在Redis 3.0以后增加了LRU淘汰池,进一步提高了与标准LRU算法效果的相似度。淘汰池即维护的一个数组,数组大小等于抽样数量 maxmemory_samples,在每一次淘汰时,新随机抽取的key和淘汰池中的key进行合并,然后淘汰掉最旧的key,将剩余较旧的前面5个key放入淘汰池中待下一次循环使用。假如maxmemory_samples=5,随机抽取5个元素,淘汰池中还有5个元素,相当于变相的maxmemory_samples=10了,所以进一步提高了与LRU算法的相似度。

LFU算法(Least frequently used:最不常使用)

LFU算法的思想是:如果一个数据在最近一段时间很少被访问到,那么可以认为在将来它被访问的可能性也很小。因此,当空间满时,最小频率访问的数据最先被淘汰。
实现:如果只为每个key维护了一个计数器,每次key被访问的时候,计数器增大,计数器越大,则认为访问越频繁。

这样还是远远不够的,还会存在两个问题:
(1)因为可能存在在开始一个小时内,某个key1有100万的访问量,但是在之后的一个小时内,这个key1的访问量为0了,而在这第二个小时内另外有个key2的访问量达到了20万,虽然这20万不如前面那个key1开始那个小时的100万访问量大,但是在第二个小时内这key2的访问量远大于key1的访问量,所以在第二个小时内key1依然会优先于key2被淘汰掉。
(2)当新加入的key,由于没有被访问过,所以初始的计数器为0,如果这时候触发淘汰机制的话,就会把最先添加到key最先淘汰掉。
所以在LFU算法中维护了这个24bit的字段,不过被分成了16 bits与8 bits两部分。第一部分:高16 bits用来记录计数器的上次缩减时间,时间戳,单位精确到分钟。第二部分:低8 bits用来记录计数器的当前数值,这个数值反映了访问频率,而不是次数。

在redis.conf配置文件中还有2个属性可以调整LFU算法的执行参数:lfu-log-factor、lfu-decay-time。其中lfu-log-factor用来调整计数器counter的增长速度,lfu-log-factor越大,counter增长的越慢。lfu-decay-time是一个以分钟为单位的数值,用来调整counter的缩减速度。

LRU与LFU的选择

需要根据业务权衡到底是选择 淘汰最近最少使用(LRU) 还是选择 最不经常使用(LFU)

总的来说,无论是 LRU LFU TTL 还是Random 都是几近算法来实现的,在可靠性和性能上做了一定的平衡。还是应该在业务中主动删除没有价值的数据,或者更新某些key的过期时间等来提高Redis的性能和空间,不能过分依赖于淘汰策略。

Redis的内存淘汰策略的选取并不会影响过期的key的处理。内存淘汰策略用于处理内存不足时的需要申请额外空间的数据;过期策略用于处理过期的缓存数据

7.缓存穿透、缓存击穿、缓存雪崩

1.缓存穿透:数据库和redis都不存在

解决方案

  • 1.参数校验,屏蔽非法参数
  • 2.数据库查询为空,可缓存一个空值或默认值
    1. 使用布隆过滤器快速判断数据是否存在

2.缓存击穿:单个key没有或过期,同一时间查询这同一条数据并发量过多

解决

  • 热点数据用不过期,或者通过异步线程在每次热点数据快要过期时,进行续期
  • 使用互斥锁,避免大量请求同时查询数据库
  • 熔断、降级、防止系统崩溃
  • 还可以考虑对重要的热点数据进行多级缓存

3.缓存雪崩:同一时间,缓存大面积失效

原因

1.redis失效、宕机(故障)

  • 搭建Redis集群,主从架构
  • RDB持久化、IOF持久化
  • 加入缓存组件:EHCache,搭建多级缓存(容易高并发的数据存入)
  • 加入限流组件:hystrix,超过一定流量后,增加请求限制(保护数据处理层)

2、Redis大量key的ttl过期
ttl(过期时间)岔开,增加随机值,避免同一时间全部失效。

  • 热点数据永不过期,或者通过异步线程在每次热点数据快要过期时,进行续期
  • 数据的过期时间不要全一致,设为一定范围内的随机时间
  • 并发量不高,可加入队列或者锁,限制同一时间访问数据库的阈值
  • 分布式部署,将热点数据打散分不到多个节点
  • 如果是缓存中间件宕机了,需要尽可能保证其高可用性,可以搭建redis集群,提前做好报警机制

8.什么是bigkey,会有什么影响

key对应的value所占内存空间较大

比如字符串类型:单个value值特别大,一般认为超过10kb就是bigkey,和具体的ops相关

非字符串类型:哈希、列表、集合、有序集合,体现在元素个数过多

危害

  • 内存空间不均匀
  • 超时堵塞:单线程操作bigkey比较耗时
  • 网络拥塞:每次获取bigkey产生的网络流量较大

例如:一个bigkey为1MB,每秒访问为1000,则每秒产生1000MB的流量,普通千兆网(按照字节算是128MB/s)的服务器是灭顶之灾,而且服务器通常会采用单机多实例的方式来部署,可能会对其他实例造成影响。

解决方案:value拆分

redis如何解决key冲突

  • 1.业务隔离
  • 2.key的设计:业务模块+系统名称+关键(id),针对用户可以加入(userid)
  • 3.分布式锁:多客户端并发写入key
  • 4.时间戳:key拼接时间戳,根据时间戳保证多个客户端的业务执行顺序

redis怎么提高命中率

  • 1、提前加载
  • 2、增加缓存的存储空间,增加缓存的数据
  • 3、调整缓存的存储类型
    例:对象通过Hash存储,而不用String。
    根据业务做适当调整。
  • 4、调整缓存的存储类型
    • 定时任务更新
    • MySQL通过检测binlog,将消息推送到Redis,更新缓存
    • 通过Mq,业务更新修改数据时,通过MQ发送消息,消费更新缓存

redis持久化方式有哪些方式,有什么区别?

持久化:将数据写入磁盘,,避免因进程退出而造成 的数据丢失,下次重启时通过持久化文件恢复数据。

RDB(快照)

通过快照(内存中数据在某一时刻的状态记录)的方式实现持久化,根据快照的触发条件,将内存的快照写入磁盘,以二进制的压缩文件进行存储。
缺点:每隔一段时间触发持久化,数据安全性低

AOF(独立日志)

以独立日志的方式记录每次写的命令,重启时重新执行aof文件中的命令恢复数据
AOF重写机制:AOF文件的大小达到某个阈值时,会将其中指令进行压缩。(如果有对于某个key多次的变更指令,则仅保留最新的数据指令)。
*优化
因为AOF重写过程中需要读取当前内存中所有键值数据,性能较低,redis将其放在一个后台子线程中完成。
为了避免重写过程中出现数据变动,主进程的数据变更需要追加到AOF重写缓冲区中,等到AOF重写完成后,再把AOF重写换乘区里面的内容追加到新的AOF文件中。
缺点:AOF文件可能过大,性能较差

如果执行bgrewriteaof命令,将内存中已有的数据以二进制格式存放在AOF文件中(模拟RDB),后续命令亦然采用AOF追加方式。

生产环境中一般采用两种持久化机制混合使用。

将内存中数据快照存储在AOF文件中(模拟RDB),后续再以AOF追加方式。

如果仅作为缓存使用,可以承受几分钟数据丢失,可以使用RDB,对主程序性能影响最小
redis持久化

如何保证缓存与数据库双写一致性:

1.新增数据类

新增数据时,数据会直接写入数据库,不用对缓存做任何操作;此时缓存没有新增数据,而数据库中是最新值。

2.更新缓存类

1.先删除缓存,后更新db

  • 先淘汰缓存-》再写数据库—〉休眠1秒,再次淘汰缓存
    延迟双删可以有效避免缓存不一致问题
    以下是伪代码实现延迟双删
redis.delkey(x)
db.update(x)
Thread.sleep(n)
redis.delkey(x)

3.读取binlog日志:

异步删除,更新缓存

  • 可以使用canal将binlog日志采集发送mq队列中
  • 通过ack机制确认处理这条更新消息,删除缓存,保证数据一致性

redis集群方案

redis常见性能问题和解决方案

1、持久化 性能问题
早期仅支持全量复制->部分复制(一台机器性能开销过大)

因此开始配置主从 :主节点不再做持久化而是交给从节点来做

2、数据比较重要,开启AOF。策略最好配置每秒同步。
3、主从复制 流畅,建议同一个局域网内操作,负责网络开销过大
4、尽量避免主库压力过大,增加从库
5、主从复制 尽量不要使用网状结构、线性结构

什么情况下可能会导致redis阻塞

  • 客户端阻塞:命令执行时间过长: keys* Hgetall smembers 时间复杂度O(N)
  • BigKey删除:需要释放大量占用内存 zset(100万的元素 删除大概需要2s)
  • 清空库:flushdb
  • AOF日志同步写,记录AOF日志
  • 从库 加载RDB文件
  • redis尽量部署独立的服务器中

线上redis响应慢处理思路:

  • 1、紧急处理方案,扩容
  • 2、生产环境查看Redis内存使用率,分析一定时间段内key数量变化
    分析是否是大量数据未设置过期时间,或者是因为新版本迭代引起
  • 3、清除bigkey,优化生成bigkey的代码块,调整未设置过期时间的代码块
  • 4、根据业务场景调整淘汰策略

如何保证redis高可用:

主从模式:

  • 部署多台redis服务器,主从复制保证数据副本一致,主库通过rdb文件发送从库实现复制
  • 主从采用读写分离,主库写操作,从库读操作
  • 主库宕机,手动切换从库称为主库,通知应用方更新主节点地址

哨兵模式

作用

  • 监控:周期性ping主从库,检测是否挂了,标记下线状态
  • 自动选主切换:多个从库按照一定规则选作主库
  • 通知:选出主库,把主库信息发送给其他从库及应用方,重新建立连接

由一个或多个哨兵实例组成哨兵系统,监控其他Redis节点的同时,哨兵实例之间也互相监控。

哨兵之间通过发布订阅机制组成集群。一主多从

缺点:无法实现在线扩容,并发压力受限于单个服务器的资源配置。

26.3 Redis Cluster
哨兵模式解决了自动切换主从的问题,但是没有解决在线扩容的问题。

本质:Redis Cluster实现了Redis的分布式存储,每个节点存储不同的数据,实现数据分片。

引入Slot槽实现数据分片,每个节点分配一个Slot区间,当我们存取Key的时候,Redis根据key计算得到Slot值,找到对应的节点进行读写。多主多从。

布隆过滤器

布隆过滤器可以应对缓存穿透问题
数据结构:一个很长的二进制向量和一组Hash映射函数组成。

作用:检索一个元素是否在一个集合中,空间查询效率比一般的算法要好的多。

缺点:有一定误识别率和删除困难。

原理:集合A中有n个元素,利用K个哈希散列函数,将A中每个元素映射到一个长度为a位的数组B中不同位置上。这些位置上的二进制数均设置为1。经过这个K个哈希散列函数映射后,发现其k个位置上的二进制数全部为1,这个元素很可能属于集合A。

目标 一种高效的空间节约型数据结构,特别适用于那些需要快速判断某个元素是否可能属于一个大规模集合,同时能够容忍一定误判率的场景。

采用由N个独立哈希函数生成的位(bit)序列来表示哈希区域。初始状态下,所有哈希位均置为0。
对于给定元素,通过N个哈希函数计算出各自的寻址位(如“a1、a2、a3…aN”),并将这些位对应的0值置为1。
  具体操作步骤如下:
定义一个长度为N bits的哈希空间,并初始化所有位为0。
选取d个不同的哈希函数,每个函数将给定元素映射到[0, N-1]范围内,并将相应位置的0置为1。
对待查询元素,同样使用d个哈希函数计算其映射位置,记为“a1、a2、a3…ad”。
遍历这d个位置在哈希空间中的值,若全部为1,则表明该元素可能存在于哈希空间中;
若至少有一个为0,则断定该元素肯定不在哈希空间中。

应用场景:

  • 缓存穿透防护:(在缓存层前部署布隆过滤器)
  • 消息去重:
    布隆过滤器可用于检查消息的唯一标识符(如消息ID)是否已处理。消费者在接收消息后,先将消息ID提交给布隆过滤器检查。若判断为未处理,则进行消费并将其添加至布隆过滤器;若判断为已处理,则直接丢弃。即使出现少量误判(将新消息判断为已处理),通常可通过其他机制(如消息确认回执)进行修正,而整体上显著降低了重复消息的处理负担。
  • URL爬虫去重:利用布隆过滤器记录已访问过的URL
  • 垃圾邮件过滤:
  • 大数据预处理:
    处理大规模数据集时,布隆过滤器可应用于数据清洗阶段,快速剔除明显不属于目标集合的数据。例如,在数据导入、数据分析或数据挖掘任务启动前,通过布隆过滤器筛查出可能存在的重复记录、无关项或已知异常值,从而减少后续处理所需的计算资源
  • 推荐系统:
    在推荐系统中,布隆过滤器有助于快速判断用户是否可能对某些商品或内容感兴趣。比如,根据用户的浏览历史构建一个已看过商品的布隆过滤器,当生成推荐列表时,先过滤掉用户已知的或已浏览过的商品,从而提升推荐的新鲜度和效率

Redis的理解

  • 本质:基于Key-Value存储结构的非关系型数据库
  • 数据类型:提供5种基本数据类型,String、set、zset、list、Map。
  • 性能:基于内存存储,并且在数据结构上做了大量优化,IO性能较好。
  • 作用:作为应用与数据库之间的分布式缓存组件。
  • 高可用:提供了主从复制、哨兵、以及集群方式实现高可用,集群中通过hash槽的方式实现了数据分片,进一步提升了性能。

原文链接:https://blog.csdn.net/Zyw907155124/article/details/129830935

posted @   Skyvswfq  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示