5.图灵学院-----阿里/京东/滴滴/美团整理----高频缓存篇

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 5.图灵学院-----阿里/京东/滴滴/美团整理----高频缓存篇

一、为什么使用缓存?


1、高性能

2、高可用


二、什么是缓存穿透?缓存击穿?缓存雪崩? 怎么解决?


1、缓存穿透: 缓存中查不到,数据库中也查不到。

解决方案:

1》 对参数进行合法性校验。

2》将数据库中没有查到结果的数据也写入

到缓存。这时要注意为了防止Redis被无用的Key占满,这一类缓存的有效期要设置

得短一点。

3》 引入布隆过滤器,在访问Redis之前判断数据是否存在。 要注意布隆过滤器存在

一定的误判率,并且,布隆过滤器只能加数据不能减数据。

2、缓存击穿:缓存中没有,数据库中有。一般是出现在存数数据初始化以及key过

期了的情况。他的问题在于,重新写入缓存需要一定的时间,如果是在高并发场景

下,过多的请求就会瞬间写到DB上,给DB造成很大的压力。

解决方案:

1》设置这个热点缓存永不过期。这时要注意在value当中包含一个逻辑上的过期时间,然后另起一个线程,定期重建这些缓存。

2》加载DB的时候,要防止并发。

3、缓存雪崩: 缓存大面积过期,导致请求都被转发到DB。

解决方案:

1》把缓存的时效时间分散开。例如,在原有的统一失效时间基础上,增加一个随机值。

2》对热点数据设置永不过期。


三、如何保证Redis与数据库的数据一致?


当我们对数据进行修改的时候,到底是先删缓存,还是先写数据库?

1、如果先删缓存,再写数据库: 在高并发场景下,当第一个线程删除了缓存,还

没有来得及写数据库,第二个线程来读取数据,会发现缓存中的数据为空,那就会

去读数据库中的数据(旧值,脏数据),读完之后,把读到的结果写入缓存(此时,第

一个线程已经将新的值写到缓存里面了),这样缓存中的值就会被覆盖为修改前的脏

数据。

总结:在这种方式下,通常要求写操作不会太频繁。

解决方案:

1》先操作缓存,但是不删除缓存。将缓存修改为一个特殊值(-999)。客

户端读缓存时,发现是默认值,就休眠一小会,再去查一次Redis。 -》 特殊值对业

务有侵入。 休眠时间,可能会多次重复,对性能有影响。

2》延时双删。 先删除缓存,然后再写数据库,休眠一小会,再次删除缓存。-》 如

果数据写操作很频繁,同样还是会有脏数据的问题。

2、先写数据库,再删缓存: 如果数据库写完了之后,缓存删除失败,数据就会不

一致。

总结: 始终只能保证一定时间内的最终一致性。

解决方案:

1》给缓存设置一个过期时间 问题:过期时间内,缓存数据不会更新。

2》引入MQ,保证原子操作。

解决方案:将热点数据缓存设置为永不过期,但是在value当中写入一个逻辑上的过

期时间,另外起一个后台线程,扫描这些key,对于已逻辑上过期的缓存,进行删

除。


四、如何设计一个分布式锁?如何对锁性能进 行优化?


分布式锁的本质:就是在所有进程都能访问到的一个地方,设置一个锁资源,让这

些进程都来竞争锁资源。数据库、zookeeper, Redis。。通常对于分布式锁,会要

求响应快、性能高、与业务无关。

Redis实现分布式锁:SETNX key value:当key不存在时,就将key设置为value,

并返回1。如果key存在,就返回0。EXPIRE key locktime: 设置key的有效时长。

DEL key: 删除。 GETSET key value: 先GET,再SET,先返回key对应的值,如

果没有就返回空。然后再将key设置成value。

1、最简单的分布式锁: SETNX 加锁, DEL解锁。问题: 如果获取到锁的进程执行

失败,他就永远不会主动解锁,那这个锁就被锁死了。

2、给锁设置过期时长: 问题: SETNX 和EXPIRE并不是原子性的,所以获取到

锁的进程有可能还没有执行EXPIRE指令,就挂了,这时锁还是会被锁死。

3、将锁的内容设置为过期时间(客户端时间+过期时长),SETNX获取锁失败时,拿这

个时间跟当前时间比对,如果是过期的锁,就先删除锁,再重新上锁。 问题: 在

高并发场景下,会产生多个进程同时拿到锁的情况。

4、setNX失败后,获取锁上的时间戳,然后用getset,将自己的过期时间更新上

去,并获取旧值。如果这个旧值,跟之前获得的时间戳 是不一致的,就表示这个锁

已经被其他进程占用了,自己就要放弃竞争锁。

public boolean tryLock(RedisnConnection conn){ long nowTime= System.currnetTimeMillis(); 12

5、上面就形成了一个比较高效的分布式锁。分析一下,上面各种优化的根本问题在

于SETNX和EXPIRE两个指令无法保证原子性。Redis2.6提供了直接执行lua脚本的

方式,通过Lua脚本来保证原子性。redission。


五、Redis如何配置Key的过期时间?他的实 现原理是什么?


redis设置key的过期时间: 1、 EXPIRE 。 2 SETEX

实现原理:

1、定期删除: 每隔一段时间,执行一次删除过期key的操作。

2、懒汉式删除: 当使用get、getset等指令去获取数据时,判断key是否过期。过

期后,就先把key删除,再执行后面的操作。

Redis是将两种方式结合来使用。

懒汉式删除

定期删除:平衡执行频率和执行时长。

long expireTIme = nowTime+1000; if(conn.SETNX(“mykey”,expireTIme)==1){ conn.EXPIRE(“mykey”,1000); return true; }else{long oldVal = conn.get(“mykey”); if(oldVal != null && oldVal < nowTime){ long currentVal = conn.GETSET(“mykey”,expireTime); if(oldVal == curentVal){ conn.EXPIRE(“mykey”,1000); return true; }return false; }return false; } }DEL 3456789101112131415161718192021

定期删除时会遍历每个database(默认16个),检查当前库中指定个数的key(默认是

20个)。随机抽查这些key,如果有过期的,就删除。

程序中有一个全局变量记录到秒到了哪个数据库。


六、海量数据下,如何快速查找一条记录?


1、使用布隆过滤器,快速过滤不存在的记录。

使用Redis的bitmap结构来实现布隆过滤器。

2、在Redis中建立数据缓存。 - 将我们对Redis使用场景的理解尽量表达出来。

以普通字符串的形式来存储,(userId -> user.json)。 以一个hash来存储一条记

录 (userId key-> username field-> , userAge->)。 以一个整的hash来存储所有

的数据,UserInfo-> field就用userId , value就用user.json。一个hash最多能支持

2^32-1(40多个亿)个键值对。

缓存击穿:对不存在的数据也建立key。这些key都是经过布隆过滤器过滤的,所

以一般不会太多。

缓存过期:将热点数据设置成永不过期,定期重建缓存。 使用分布式锁重建缓

存。

3、查询优化。

按槽位分配数据,

自己实现槽位计算,找到记录应该分配在哪台机器上,然后直接去目标机器上

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
11月前
|
缓存 NoSQL 中间件
太卷了!京东、微博最新「Redis缓存高手心法手册」竟被开源了
众所周知,分布式架构被广泛应用于企业级应用开发中,以满足高并发、高可用、高性能、高扩展性等要求。
|
存储 SQL 缓存
阿里面试题:缓存的一些常见的坑,你遇到过哪些,怎么解决的?
在高并发请求时,我们会频繁提到使用缓存技术,最直接的原因是,磁盘IO及网络开销是直接请求内存IO的千百上千倍做个简单计算,如果我们需要某个数据,该数据从数据库磁盘读出来需要0.0045S,经过网络请求传输需要0.0005S,那么每个请求完成最少需要0.005S,该数据服务器每秒最多只能响应200个请求,而如果该数据存于本机内存里,读出来只需要100us,那么每秒能够响应10000个请求。通过将数据存储到离CPU更近的未位置,减少数据传输时间,提高处理效率,这就是缓存的意义。加速读写。因为缓存通常都是全内存的系统,通过缓存的使用可以有效提高用户的访问速度同时优化用户体验。降低后端负载。通过添加缓
|
缓存 人工智能 算法
【高并发】高并发环境下构建缓存服务需要注意哪些问题?我和阿里P9聊了很久!
周末,跟阿里的一个朋友(去年晋升为P9了)聊了很久,聊的内容几乎全是技术,当然了,两个技术男聊得最多的话题当然就是技术了。从基础到架构,从算法到AI,无所不谈。中间又穿插着不少天马行空的想象,虽然现在看起来不太实际,但是随着技术的进步,相信五年、十年之后都会实现的。
128 0
|
缓存 算法
阿里面试真题详解: LFU缓存
阿里面试真题详解: LFU缓存
阿里面试真题详解: LFU缓存
|
SQL 缓存 关系型数据库
阿里双11大促秒杀活动下的缓存技术与高水位限流实现
秒杀最早来自天猫双11各种商品的促销活动中,现在已经有很多业务场景在使用,比如抢红包,抢票等。其特点有三高:瞬时并发高,数据一致性高,热点更新频度高。这样三高的场景下往往给数据库造成极大的压力,大量更新数据库中的同一行,这样必然会产生锁等待,导致数据库的性能急剧下降的问题,很容出现雪崩效应。
2799 1
|
19天前
|
canal 缓存 NoSQL
Redis缓存与数据库如何保证一致性?同步删除+延时双删+异步监听+多重保障方案
根据对一致性的要求程度,提出多种解决方案:同步删除、同步删除+可靠消息、延时双删、异步监听+可靠消息、多重保障方案
Redis缓存与数据库如何保证一致性?同步删除+延时双删+异步监听+多重保障方案
|
2月前
|
缓存 NoSQL Redis
【Azure Redis 缓存】Redission客户端连接Azure:客户端出现 Unable to send PING command over channel
【Azure Redis 缓存】Redission客户端连接Azure:客户端出现 Unable to send PING command over channel
|
2月前
|
缓存 NoSQL Java
Redis深度解析:解锁高性能缓存的终极武器,让你的应用飞起来
【8月更文挑战第29天】本文从基本概念入手,通过实战示例、原理解析和高级使用技巧,全面讲解Redis这一高性能键值对数据库。Redis基于内存存储,支持多种数据结构,如字符串、列表和哈希表等,常用于数据库、缓存及消息队列。文中详细介绍了如何在Spring Boot项目中集成Redis,并展示了其工作原理、缓存实现方法及高级特性,如事务、发布/订阅、Lua脚本和集群等,帮助读者从入门到精通Redis,大幅提升应用性能与可扩展性。
60 0
|
20天前
|
存储 NoSQL Redis
SpringCloud基础7——Redis分布式缓存,RDB,AOF持久化+主从+哨兵+分片集群
Redis持久化、RDB和AOF方案、Redis主从集群、哨兵、分片集群、散列插槽、自动手动故障转移
SpringCloud基础7——Redis分布式缓存,RDB,AOF持久化+主从+哨兵+分片集群
|
3天前
|
存储 缓存 NoSQL
解决Redis缓存击穿问题的技术方法
解决Redis缓存击穿问题的技术方法
16 2
下一篇
无影云桌面