分布式缓存redis(基础+线程模型+过期策略) - 大总结1

分布式缓存 - 大总结

灵魂拷问一:在项目中如何使用缓存的?

第一种场景,需要缓存要查询用户的历史订单,请求接口剧多,如果实时去请求的话,接口超时。
第二种场景,分布式缓存锁,用户参加了a活动就不能参加b活动,防止并发,所以要用到分布式缓存锁。

灵魂拷问二:为啥要使用缓存呢?

(1) 高性能
多个用户请求同一份数据,每一份查询都耗时很久。
在这里插入图片描述
可以把这份数据放在缓存里,这样第一次查询从数据库查,其余时候就可以从缓存查啦,大大提升效率哈。提升查询性能,优化用户体验。
在这里插入图片描述
(2) 高并发
在高峰期内,有特别多的用户访问系统,每秒请求量很大,直击数据库的时候,可能会导致宕机,可以利用缓存解决这个问题。大部分请求走缓存,小部分请求走数据库。

为什么数据库支持不了高并发,而缓存可以呢?
缓存是走内存的哈,内存天然就有这个优势,但是数据库一般建议并发请求不要超过2000/s。

灵魂拷问三:用了缓存之后 是不是会有一些什么不良后果?

(1)、缓存跟数据库数据不一致
(2)、缓存雪崩
(3)、缓存穿透
(4)、缓存并发竞争

灵魂拷问四:redis和memcached有什么区别?

(1)、redis支持服务器端的数据操作,redis比memcached,拥有更多的数据结构,并支持更丰富的数据操作。在memcached中,需要将数据拿到客户端,进行类似的修改,修改完成之后在set回去,但是redis有直接的set/get,方便很多。
(2)、内存使用效率相比,使用简单的key-value来存储的话,memcached的内存利用率较高,但如果redis使用hash结构来做key-value存储,则redis的内存利用率会高于memcached。
(3)、性能对比,由于redis只适用于单核,而memcached适用于多核,所以平均每一个核上redis在存储小数据时性能更高,但是在100k以上的数据中,memcached性能要高于redis。
(4)、集群模式:memcached没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据,但是redis目前是原生支持cluster模式的。
1 4是重点哈。

灵魂拷问五:redis的线程模型是什么?

redis基于reactor模式开发了网络事件处理器,这个处理器叫做文件事件处理器,这个文件事件处理器是单线程的,所以redis才叫做单线程的模型,采用IO多路复用的机制同时监听多个socket,根据socket上的事件来选择对应的事件处理器来处理这个事件。
IO多路复用+文件事件分配器+事件处理器
(1)、文件事件处理器

灵魂拷问六:为什么单线程的redis比多线程的memcached快得多?为什么redis是单线程的,还可以支持高并发?

(1)、纯内存操作,事件处理器处理快的原因就是因为是纯内存操作的,很快的。
(2)、非阻塞的IO多路复用机制,IO多路复用只负责监听socket,压队列,也很快。
(3)、单线程反而避免了多线程的频繁上下文切换问题。

灵魂拷问七:redis都有哪些数据类型?分别在哪些场景下使用比较合适?

(0)、key
(1)、string(key-value)
普通的kv操作。
(2)、hash
类似于map,把整个对象缓存到redis。后续操作可以仅仅修改这个对象的某个字段的值。
(3)、list
有序列表,且可重复。基于redis的lrange命令实现分页查询。
(4)、set
无序集合,去重列表。系统部署在多台机器上,基于redis进行全局的set去重。
(5)、sort set
有序集合,去重。排行榜。

灵魂拷问八:redis的过期策略?手写LRU?

redis主要是靠内存来进行高性能,高并发的读写操作的。
辣么,如果超过内存的话,会干掉一些数据,保留一些数据,保留的方案可能是常用的保存,不常用的丢掉。
所以,可以针对数据设置过期时间,但是呢,这个过期时间并不是说到了时间就会被删除,很有可能出现,数据过期,从redis中查不到,但还是占有内存的情况。

那么,redis是怎么对过期的key进行删除的?
定期删除 + 惰性删除
定期删除:redis每隔100ms,都随机抽取一些设置了过期时间的key,检查是否过期,如果过期,则进行删除。
惰性删除:获取key的时候,redis会检查key,如果过期了,则会删除该key。
如果定期删除漏掉了很多key,也没触发惰性删除,此时会有大量无用的key堆积在内存里,应该怎么办呢?
内存淘汰机制

内存淘汰机制:如果redis内存占用过多,则会有一些淘汰机制。
(1)、noneviction:当内存不够时,继续写入会报错。
(2)、allkeys-lru:当内存不足时,删除最近最少使用的key。
(3)、allkeys-andom:当内存不足时,随即移除某些key。
(4)、volatile-lru:当内存不足时,在设置了过期时间的key里,移除最近最少使用的key。
(5)、volatile-andom:当内存不足时,在设置了过期时间的key里,随即移除某些key。
(6)、volatile-ttl:当内存不足时,在设置了过期时间的key里,移除马上要过期的key。

手写LRU编码:

package exercise_0504;

import java.util.LinkedHashMap;
import java.util.Map;

public class LRU<K,V> extends LinkedHashMap<K,V> {
    private final int CACHE_SIZE; //最多能缓存多少数据

    public LRU(int cacheSize){
        super((int)Math.ceil(cacheSize/0.75) + 1,0.75f,true);
        // 设置hashmap的初始大小
        // 第一个参数 总个数/负载因子 + 1
        // 第二个参数 负载因子 官方建议 0.75
        // 第三个参数 true表示按照访问顺序排序,最近访问的在前,最老访问的在后。
        CACHE_SIZE = cacheSize;
    }

    @Override
    public boolean removeEldestEntry(Map.Entry eldest){
        return size() > CACHE_SIZE; // 当map中的数据量大于指定的缓存个数的时候,会自动删除最老的数据。
    }
}

灵魂拷问九:redis遇到的坑

研发在使用redis的时候,未设置过期时间,但是DBA对相应实例设置的淘汰策略是volatile-lru,导致redis的内存在某个时间被打满,造成的后果是影响了1个半小时的交易量和开户,损失大大的。

我们公司的redis实例的淘汰策略可能是
allkeys-lru:对所有的键都采用LRU淘汰,不需要过期时间。
volatile-lru:仅对设置了过期时间的键采取LRU淘汰。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值