常见的数据类型及应用场景详解:https://blog.csdn.net/qq_43030934/article/details/131213135
当调用api访问数据库时,假如此过程需要2秒,如果每次请求都要访问数据库,那将对服务器造成巨大的压力,如果将此sql的查询结果存到Redis中,再次请求时,直接从Redis中取得,而不是访问数据库,效率将得到巨大的提升,Redis可以定时去更新数据(比如1分钟)。
如果电脑重启,写入内存的数据是不是就失效了呢,这时Redis还提供了持久化的功能。
redis提供了两种持久化的方式,分别是RDB(Redis DataBase)和AOF(Append Only File)。
AOF,则是换了一个角度来实现持久化,那就是将redis执行过的所有写指令记录下来,在下次redis重新启动时,只要把这些写指令从前到后再重复执行一遍,就可以实现数据恢复了。
优点:
缺点:
RDB,简而言之,就是在不同的时间点,将redis存储的数据生成快照并存储到磁盘等介质上;
缺点:
其实RDB和AOF两种方式也可以同时使用,在这种情况下,如果redis重启的话,则会优先采用AOF方式来进行数据恢复,这是因为AOF方式的数据恢复完整度更高。
如果你没有数据持久化的需求,也完全可以关闭RDB和AOF方式,这样的话,redis将变成一个纯内存数据库,就像memcache一样。
Sentinel可以管理多个Redis服务器,它提供了监控、提醒以及自动的故障转移功能;
复制则是让Redis服务器可以配备备份的服务器;
Redis也是通过这两个功能保证Redis的高可用;
单台服务器资源总是有上限的,CPU和IO资源可以通过主从复制,进行读写分离,把一部分CPU和IO的压力转移到从服务器上,但是内存资源怎么办,主从模式只是数据的备份,并不能扩充内存;
现在我们可以横向扩展,让每台服务器只负责一部分任务,然后将这些服务器构成一个整体,对外界来说,这一组服务器就像是集群一样。
1、Redis相比memecache,拥有更多的数据结构和支持更丰富的数据操作。
2、内存使用率对比,Redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于memecache。
3、性能对比:Redis只使用单核,memecache使用多核。
4、Redis支持磁盘持久化,memecache不支持。
Redis可以将一些很久没用到的value通过swap方法交换到磁盘。
5、Redis支持分布式集群,memecache不支持。
缓存穿透说简单点就是大量请求的 key 根本不存在于缓存中,导致请求直接到了数据库上,根本没有经过缓存这一层。
解决方案:
1.最基本的就是做好参数校验,一些不合法的参数请求直接抛出异常信息返回给客户端。 比如查询的数据库 id 不能小于 0、传入的邮箱格式不对的时候直接返回错误消息给客户端等等。
2.对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对应的数据insert之后清理缓存。
3.对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该Bitmap过滤。
缓存击穿问题也叫热点Key问题,就是缓存在某个时间点过期的时候,恰好在这个时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。
解决方案:
缓存击穿和缓存雪崩的区别在于缓存击穿针对某一key缓存,缓存雪崩是很多key。
优点:没有额外的内存消耗,保证一致性,实现简单
缺点:线程需要等待,性能受影响,可能有死锁风险实时调整,监控哪些数据是热门数据,实时的调整key的过期时长针对热点Key设置缓存永不失效
实时调整,监控哪些数据是热门数据,实时的调整key的过期时长
针对热点Key设置缓存永不失效
当缓存服务器重启或者大量缓存集中在某一时间段失效,这样在失效的时候,会给后端系统带来很大的压力,导致系统崩溃。
解决方案:
针对热点缓存失效的情况:
数据如果为较为复杂的数据时,进行缓存的更新操作就会变得异常复杂,因此一般推荐选择淘汰缓存,而不是更新缓存。
假如先更新数据库,再淘汰缓存,如果淘汰缓存失败,那么后面的请求都会得到脏数据,直至缓存过期。
假如先淘汰缓存再更新数据库,如果更新数据库失败,只会产生一次缓存穿透,相比较而言,后者对业务则没有本质上的影响。
如下场景:同时有一个请求A进行更新操作,另一个请求B进行查询操作。
1.请求A进行写操作,删除缓存
2.请求B查询发现缓存不存在
3.请求B去数据库查询得到旧值
4.请求B将旧值写入缓存
5.请求A将新值写入数据库
次数便出现了数据不一致问题。采用延时双删策略得以解决。
redis_conn.delete('img_%s' % uuid)
db.update(data);
time.sleep(100)
redis_conn.delete('img_%s' % uuid)
转化为中文描述就是
1.先淘汰缓存
2.再写数据库(这两步和原来一样)
3.休眠1秒,再次淘汰缓存
这么做,可以将0.1秒内所造成的缓存脏数据,再次删除。这个时间设定可根据俄业务场景进行一个调节。
两个请求,一个请求A进行更新操作,另一个请求B进行查询操作。
1.请求A进行写操作,删除缓存
2.请求A将数据写入数据库了,
3.请求B查询缓存发现,缓存没有值
4.请求B去从库查询,这时,还没有完成主从同步,因此查询到的是旧值
5.请求B将旧值写入缓存
6.数据库完成主从同步,从库变为新值
依旧采用延时双删策略解决此问题。
此外还有两种解决方案:
1.更新数据库数据;
2.缓存因为种种问题删除失败
3.将需要删除的key发送至消息队列
4.自己消费消息,获得需要删除的key
5.继续重试删除操作,直到成功
1.更新数据库数据
2.数据库会将操作信息写入binlog日志当中
3.订阅程序提取出所需要的数据以及key
4.另起一段非业务代码,获得该信息
5.尝试删除缓存操作,发现删除失败
6.将这些信息发送至消息队列
7.重新从消息队列中获得该数据,重试操作。
以上就是缓存机制及使用场景的介绍,希望对你有所帮助!