Redis 入门

redis 简介
为什么要用 redis /为什么要用缓存
为什么要用 redis 而不用 map/guava 做缓存?
redis 和 memcached 的区别
redis 常见数据结构以及使用场景分析
redis 设置过期时间
redis 内存淘汰机制
redis 持久化机制(怎么保证 redis 挂掉之后再重启数据可以进行恢复)
缓存雪崩和缓存穿透问题解决方案
如何解决 Redis 的并发竞争 Key 问题
如何保证缓存与数据库双写时的数据一致性?

什么是radis? radis是一个数据存在内存中的数据库,从外也经常用来做分布式锁,其提供了多种数据类型来支持不同的业务场景。

为什么要用radis?
主要从 高性能和高并发来看待问题。
因为radis数据存在内存内 所以访问的话会相比于在硬盘里会快很多。

为什么要用radis做缓存 而不用map/guava做缓存?
缓存分为本地缓存和分布式缓存。
以java为例,使用自带的map或者guava实现的是本地缓存,最主要的特点是轻量以及快速,生命周期随着 jvm 的销毁而结束,并且在多实例的情况下,每个实例都需要各自保存一份缓存,缓存不具有一致性。
使用 redis 或 memcached 之类的称为分布式缓存,在多实例的情况下,各实例共用一份缓存数据,缓存具有一致性。缺点是需要保持 redis 或 memcached服务的高可用,整个程序架构上较为复杂。

那么同样是分布式缓存,redis和memcached有什么不同呢?

  1. redis支持更丰富的数据类型(支持更复杂的应用场景):Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。memcache支持简单的数据类型,String。
  2. Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用,而Memecache把数据全部存在内存之中。
  3. 集群模式:memcached没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据;但是redis目前是原生支持cluster模式的,redis官方就是支持redis cluster集群模式的,比memcached来说要更好。
  4. Memcached是多线程,非阻塞IO复用的网络模型;Redis使用单线程的多路 IO 复用模型。
    在这里插入图片描述

redis常见的数据结构以及使用场景分析
String
Hash
List(用double linkedlist实现 可以基于此实现简单的高性能分页)
Set
Sorted Set(与set相比 sorted set增加了一个权重参数score 使得集合中的元素能够按照score进行有序排序)

redis设置过期时间:
因为radis储存在内存中的数据都是热门数据 而热门数据都是需要经常被更新的 所以我们要对储存在redis数据库中的值设置一个过期时间。(一般项目中的token或者一些登录信息 尤其是短信验证码 都是有时间限制的)
因此 我们setkey的时候 都可以给一个expire time.可如果你设置一个一批key只能存活一小时 那么一小时之后 这批key是如何被删除的?
两种删除方式:定期删除或者是Lazy删除
定期删除就是每隔100ms随机抽取一些key 检查其是否过期 过期就删除 至于为什么要随机 因为redis key非常多。
而lazy删除则是当系统查看那个key的时候 发现过期 这时才会给删除掉。
但是上述两过期key删除方式带来的问题很多 可能会导致大量过期key堆积在内存里 导致redis内存块耗尽了 怎么办?这就引申出了redis内存淘汰机制。

redis内存淘汰机制:
(即 如何保证redis数据都是热点数据?)
通过提供六种数据淘汰策略:(3+2+1)
volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰(least recent use)
volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰(expire time approaching)
volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰(randomly choose)
allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key(这个是最常用的).(没设置过期时间 但是内存不够 选择LRU淘汰)
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
no-enviction:禁止驱逐数据,也就是说当内存不足以容纳新写入数据时,新写入操作会报错。这个应该没人使用吧!(内存满 禁止写入)

Radis持久化机制

因为radis在内存中 关机或重启会消失 因此我们需要在关机或重启使将内存数据写入硬盘中。redis有两种持久化方式:snapshotting and append-only file
snapshotting:
Redis可以通过创建快照来获得存储在内存里面的数据在某个时间点上的副本。Redis创建快照之后,可以对快照进行备份,可以将快照复制到其他服务器从而创建具有相同数据的服务器副本(Redis主从结构,主要用来提高Redis性能),还可以将快照留在原地以便重启服务器的时候使用。
快照持久化是Redis默认采用的持久化方式,在redis.conf配置文件中默认有此下配置:


save 900 1              #在900(15分钟)之后,如果至少有1个key发生变化,Redis就会自动触发BGSAVE命令创建快照。

save 300 10            #在300(5分钟)之后,如果至少有10个key发生变化,Redis就会自动触发BGSAVE命令创建快照。

save 60 10000        #在60(1分钟)之后,如果至少有10000个key发生变化,Redis就会自动触发BGSAVE命令创建快照。
//可以看出 key变动越剧烈 说明越重要 因此我们需要尽快保存下来

append-only file
与快照持久化相比,AOF持久化 的实时性更好,因此已成为主流的持久化方案。默认情况下Redis没有开启AOF(append only file)方式的持久化,可以通过appendonly参数开启:
appendonly yes
开启AOF持久化后每执行一条会更改Redis中的数据的命令,Redis就会将该命令写入硬盘中的AOF文件。AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的,默认的文件名是appendonly.aof。
在Redis的配置文件中存在三种不同的 AOF 持久化方式,它们分别是:

appendfsync always     #每次有数据修改发生时都会写入AOF文件,这样会严重降低Redis的速度
appendfsync everysec  #每秒钟同步一次,显示地将多个写命令同步到硬盘
appendfsync no      #让操作系统决定何时进行同步

经常选择的是第二种

什么是radis的缓存雪崩和缓存穿透问题:
缓存雪崩:
问题:缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。
解决方法:
事前:尽量保证整个 redis 集群的高可用性,发现机器宕机尽快补上。选择合适的内存淘汰策略。
事中:本地ehcache缓存 + hystrix限流&降级,避免MySQL崩掉
事后:利用 redis 持久化机制保存的数据尽快恢复缓存
在这里插入图片描述
缓存穿透:
一般指照成缓存雪崩的恶意攻击。黑客故意去请求缓存中不存在的数据 导致所有请求都落在数据库上。
解决办法: 有很多种方法可以有效地解决缓存穿透问题,最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。另外也有一个更为简单粗暴的方法(我们采用的就是这种),如果一个查询返回的数据为空(不管是数 据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。

解决redis的并发竞争key的问题
多个系统同时对一个key进行操作
解决方案:没有看懂

如何保证缓存与数据库双写时的一致性?
这个也不太清楚 最好从头看一下redis

posted @ 2020-04-04 00:21  EvanMeetTheWorld  阅读(43)  评论(0)    收藏  举报