Redis

1.为什么要用Redis作缓存

高性能
因为如果是用户第一次访问某些数据,那么这些数据就会从硬盘上读取,读取的速度比较缓慢。
这时redis可以把读取的数据存到缓存中,那么下次读取数据的时候就可以直接从缓存中获取。
操作缓存就是直接操作内存,所以速度快。

高并发
直接操作缓存的承载能力是远远大于直接访问数据库的,所以设置缓存可以把部分数据存到缓存,那么部分的请求会直接访问缓存,不用经过数据库

2.为什么用redis而不用map/guava做缓存?

缓存分为本地缓存和分布式缓存。map和guava是本地缓存,快速且轻量级,但是其生命周期会随着jvm的销毁而结束。并且在多实例的情况下,每个实例都会有自己的缓存,缓存不具有一致性

但是对于redis等分布式缓存,多个实例共享一份缓存数据,缓存具有一致性。 缺点是,为了保持redis的高可用性,结构上比较复杂

3.redis的线程模型

redis是单线程模型。
这是因为redis中使用的文件事件处理器 file event handler是单线程,所以redis才算是单线程模型
文件事件处理器包含四个部分
1.IO多路复用
2.多个socket
3.文件事件分配器
4.事件处理器

执行过程: 由于是多个socket,那么会并发产生不同的操作,而IO多路复用会将产生的多个操作放进队列中,然后文件事件分派器从队列中取出一个事件,交给事件处理器处理。

4.redis和memecached的区别

  1. redis的数据类型丰富,而memecached只有单一的k-v类型
  2. redis支持数据的持久化,而memecached是把数据全部放在内存
  3. memecached没有原生的集群模式,只能后期自己往集群分片写入数据;但是redis原生支持集群模式

redis数据类型

1.String

字符串类型 就是简单的key-value,value可以是String 也可以是数字类型

2.Hash

可以在val中存储多个key-val的数据,类似于对象的属性。
所以hash 类型主要用于存储对象

3.List

链表,底层是一个双向链表,支持反向查找和遍历
(lpush lpop rpush rpop lrange)
lrange命令是指从某个元素开始读取多少个元素,所以可以基于list的lrange实现分页

4.Set

主要方法:sadd spop smembers sunion
set的主要特点就是不能存重复的元素,而且set还提供 smember方法可以用于判断元素是不是在集合内。可以用set实现交集、并集、差集的操作

5.Zset

有序集合,相比Set多了一个score权重参数。可以按照score进行排序

redis设置过期时间

在set key的 时候可以设置一个expire time 用于指定key 的过期时间。

在expiretime到时的时候,redis怎么具体删除的呢?:定期删除+惰性删除
定期删除:redis默认的是每隔100ms就从库中随机抽取key,检查是否过期,过期了则删除。完全随机的机制避免了遍历redis中所有的key
惰性删除:定期删除会导致一部分过期的key没被删除。但是redis是不会主动删除的,只有当系统主动去检查过期的key的时候,才能删除过期的key。

redis的内存淘汰机制

上面说的定期删除+惰性删除不能将全部过期的key删除,那么就会导致一个问题:大量过期的key存在于内存中,导致redis内存耗尽。所以redis的内存淘汰机制用于解决redis内存耗尽的问题

  1. volatile-lru:从设置过期时间的数据集中区最少使用的数据进行淘汰
  2. volatile-ttl:从设置过期时间的数据集中找 将要过期的数据淘汰
  3. volatile-random:从设置过期时间的数据集中 随机找数据淘汰
  4. allkeys-lru:从数据集中找是用最少的数据淘汰
  5. allkeys-random:从数据集中随机找数据淘汰
  6. no-eviction:禁止淘汰数据,也就是说内存满了后,再插入数据会失败

4.0版本后新增
7. volatile-lfu:从设置过期时间的数据集中找 最不经常使用的 淘汰
8. allkeys-lfu:全数据集中找最不经常使用的key淘汰

redis的持久化机制

redis持久化为的是解决重启后数据恢复。
持久化指的是将内存中的数据保存到硬盘中,这样可以帮助重启、或机器故障后恢复数据
两种方式 快照(RDB)和 只追加文件(AOF)

RDB

RDB:周期性的对redis中数据进行持久化,意思是每个一段时间就会生成redis内存的一份完整的快照。生成的新的快照会覆盖老的快照。
redis持久化默认采取的就是快照方式。
怎么配置RDB?
在redis.conf文件中 写入 save 900 1 代表 900秒后 如果至少有1个key发生变化,就执行快照
关于冷备
RDB适合做冷备份: 将每次的快照上传至云服务器中,可以实现冷备份
缺点:丢失数据多。
AOF也可以做冷备,但是只有一个文件,并需要每隔一段时间就copy一次

AOF

AOF实时性更好
redis默认不开启AOF,可以通过代码

appendonly yes

开启
在redis中,每执行一条更改redis数据的命令,redis就会将命令写入硬盘中的AOF文件,当AOF文件中的命令越来越多时,就会rewrite一个新的AOF文件,把旧的删除,并且根据LRU内存淘汰机制,删除不需要的key

rewrite触发机制:上一次的AOF文件大小为现在的一半,或者现在AOF文件大于64M

appendfsync always 每次数据修改都会更新AOF
appendfsync everysec 每秒更新
appednfsync no 操作系统决定何时更新

AOF优点:

  1. 数据丢失少
  2. 没有磁盘寻址的开销,写入性能高(因为写入的时候会先交给OS cache,然后再写入硬盘)
  3. 对误删可以紧急修复。在rewrite前,拷贝AOF文件,并将误删命令删除,就可以恢复数据了

AOF缺点:
1 AOF文件比RDB文件大
2 做数据恢复比较慢,做冷备份,定期的备份不方便

Redis4.0以后对于持久化的优化

4.0以后开始支持RDB和AOF混合持久化
好处是能结合AOF和RDB的共同优点,快速加载的痛死避免丢失过多的数据

缺点是 保存在AOF中的RDB部分是压缩的,可读性差

Redis的事务处理

Redis的事务在开启的时候,会将命令一条一条的插入到一个队列中,然后这些命令不会被真的执行,EXEC提交后,会统一执行队列中的命令
MULTI:可以用于开启事务
EXEC:用于提交事务
DISCARD:放弃事务,事务中所有的命令取消
WATCH:监控一个或多个key,如果在事务执行期间,这些key被修改,那么事务执行失败,然后需要重新获取数据(类似乐观锁)
UNWATCH:取消对key的监控

什么是缓存雪崩

就是由于缓存同一时间大面积的失效,导致大量的请求直接访问到数据库,从而导致数据库崩溃
怎么解决缓存雪崩?

  1. 事前:保证redis多集群的高可用性
  2. 事中:设置本地缓存ehcache+hystrix限流组件,并降级,避免mysql崩溃
  3. 事后,利用redis持久化机制,尽快恢复

什么是缓存穿透

就是大量请求不在缓存中,直接访问数据库,请求根本没有经过缓存这一层

怎么解决缓存穿透?

  1. 缓存无效的key:如果请求的key数据库和redis都没有,那么可以让redis缓存这个key,并设置过期时间
set key value EX 1000

这个方法只能解决key变化不大的请求,对于大量且变换的key,这种方法就不可行。

  1. 布隆过滤器
    先将所有可能存在的key都存入布隆过滤器中,这时,当访问的请求不存在布隆过滤器中,就会过滤掉该请求;存在的话,请求会到达redis,再到达数据库。

如何解决redis并发竞争key的问题

多个系统同时操作一个key,就会导致key被并发竞争。
通过分布式锁来防止这种情况
1 .数据库
2. Meecache 的 add命令
3. redis 的setnx
4. zookeeper的临时节点
zookeeper实现方式:当给方法加锁的时候,zookeeper会在对应的方法的对应的指定节点生成一个唯一的瞬时的有序节点。随后可以判断有序节点的最小节点是否获取了锁。当锁释放的时候,需要将瞬时节点删除。

如何解决redis缓存和数据库双写一致性的问题

由于请求redis和数据库的先后顺序不一致,会导致请求在更新数据库中数据的时候,出现redis双写不一致
解决方法:如果要求缓存和数据库中数据必须完全一致,那么久需要将读请求和写请求串行化,放到一个队列中,同时执行,这样就保障了双写一致,但是这样就会导致吞吐量大大降低

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值