当前位置: 首页>后端>正文

php面试之缓存

缓存那些事

1. 缓存

1.1 缓存特征

  • 命中率:命中率=返回正确结果数/请求缓存次数。命中率越高,表明缓存的使用率越高。
  • 最大元素(或最大空间):缓存中可以存放的最大元素的数量,超过将会触发缓存启动清空策略。
  • 清空策略:当缓存空间被用满时,在稳定服务的同时有效提升命中率

1.2 常见的清空策略

  • FIFO(first in first out):先进先出策略
  • LFU(less frequently used):最少使用策略
  • LRU(least recently used):最近最少使用策略

1.3 缓存介质

  • 内存:最快,但是无持久化
  • 硬盘:持久化
  • 数据库:NoSQL数据库

1.4 缓存分类和应用场景

  1. 本地缓存:本地缓存就是在进程的内存中进行缓存。优点:应用和cache是在同一个进程内部。缺点也是应为缓存跟应用程序耦合
  2. 分布式缓存:分布式缓存一般都具有良好的水平扩展能力,对较大数据量的场景也能应付自如。
  3. 多级缓存:本地缓存存一些频率最高的热点数据,其他的热点数据放在分布式缓存中。

1.5 本地缓存

  • 编程直接实现缓存
  • Ehcache
  • Guava Cache

1.6 分布式缓存

  • memcached缓存
  • Redis缓存

2. memcached与redis优缺点

  1. 性能:都比较高
  2. 操作的便利性
    • memcache数据结构单一
    • redis丰富一些,数据操作方面,redis更好一些,较少的网络IO次数
    • mongodb支持丰富的数据表达,索引,最类似关系型数据库,支持的查询语言非常丰富
  3. 内存空间的大小和数据量的大小
    • redis在2.0版本后增加了自己的VM特性,突破物理内存的限制;可以对key value设置过期时间(类似memcache)
    • memcache可以修改最大可用内存,采用LRU算法
    • mongoDB适合大数据量的存储,依赖操作系统VM做内存管理,吃内存也比较厉害,服务不要和别的服务在一起
  4. 可靠性(持久化)
    • redis支持(快照、AOF):依赖快照进行持久化,aof增强了可靠性的同时,对性能有所影响
    • memcache不支持,通常用在做缓存,提升性能;
    • MongoDB从1.8版本开始采用binlog方式支持持久化的可靠性
  5. 数据一致性(事务支持)
    • Memcache 在并发场景下,用cas保证一致性
    • redis事务支持比较弱,只能保证事务中的每个操作连续执行
    • mongoDB不支持事务
  6. 数据分析
    • mongoDB内置了数据分析的功能(mapreduce),其他不支持
  7. 应用场景
    • redis:数据量较小的更性能操作和运算上
    • memcache:用于在动态系统中减少数据库负载,提升性能;做缓存,提高性能(适合读多写少,对于数据量比较大,可以采用sharding)
    • MongoDB:主要解决海量数据的访问效率问题

3. redis

3.1 reids 有哪些优缺点

优点:

  • 读写性能优异
  • 支持数据持久化,支持AOF和RDB两种持久化方式。
  • 支持事务,Redis的所有操作都是原子性的,同时Redis还支持对几个操作合并后的原子性执行。
  • 数据结构丰富,除了支持string类型的value外还支持hash、set、zset、list等数据结构。
  • 支持主从复制

缺点:

  • 数据库容量受到物理内存的限制,不能做海量数据的高性能读写
  • Redis 不具备自动容错和恢复功能
  • 不支持在线扩容

3.2 reids 数据结构

  1. String:字符类型
  • Set name test
  • Get name
  • setnx name test 不存在则set进去
  • Mset 存入多个值
  • Msetnx
  • Mget
  • Getset 获取并存入新的值
  • Setrange 从第几个字符替换
  • Getrange
  • Append 追加
  • Incr 数值加一
  • Incrby 数值加指定
  • Decr 与incr相反
  • Decrby 与decrby相反
  • Strlen 返回键对应的值得字符长度
  1. Hash 方便存对象 键值对
  • Hset
  • Hsetnx
  • Hget
  • Hmset
  • Hmget
  • Hincrby
  • Hexists
  • Hlen:返回hash表中所有字段的数目
  • Hkeys
  • Hvals
  • Hgetall
  • Hdel
  1. List链表(双向链表)
  • lpush 从头压入
  • rpush 从尾部压入
  • lpop 从链表的头部弹出一个元素
  • rpop 从链表的尾部弹出一个元素
  • Linsert 从某个数据之前或者之后插入数据
  • Lset 通过索引来设置元素的值
  • lrem 删除list表中的数据
  • ltrim 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
  • rpoplpush 从一个链表弹出,在从头部压入到另一个链表
  • lindex 返回一个list小标的索引值
    llen 返回这个链表的元素的长度
  1. set 无序集合
  • sadd 向集合中插入一条数据
  • srem 删除集合中的一个元素
  • smembers 查看集合中的元素
  • spop 从集合随机弹出一个元素,返回键值
  • sdiff 两个集合的差集 返回两个集合不一样的,根据第一个集合为标准
  • sdiffstroe 将两个差集存储到另外一个集合
  1. SortedSet 有序集合

  2. HyperLogLog 做基数统计的算法

  3. Redis 发布订阅

3.3 redis 持久化

持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失

  1. RDB:一定时间内将内存的数据以快照的形式保存到硬盘中
  2. AOF:将redis每次执行的命令写到单独的日志文件中

优缺点是什么?

  • AOF文件比RDB更新频率高,优先使用AOF还原数据。

  • AOF比RDB更安全也更大

  • RDB性能比AOF好

  • 如果两个都配了优先加载AOF

3.4 reids 过期策略

  • 定时过期:每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除
  • 惰性过期:只有当访问一个key时,才会判断该key是否已过期,过期则清除
  • 定期过期:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。

3.5 内存淘汰策略

Redis的内存淘汰策略的选取并不会影响过期的key的处理。内存淘汰策略用于处理内存不足时的需要申请额外空间的数据;过期策略用于处理过期的缓存数据。

3.6 集群

哨兵 + redis 主从

3.7 缓存异常

  1. 缓存雪崩

缓存雪崩是指缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。

解决方案

  • 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。

  • 一般并发量不是特别多的时候,使用最多的解决方案是加锁排队。

  • 给每一个缓存数据增加相应的缓存标记,记录缓存的是否失效,如果缓存标记失效,则更新数据缓存。

  1. 缓存穿透
    缓存穿透是指缓存和数据库中都没有的数据,导致所有的请求都落到数据库上,造成数据库短时间内承受大量请求而崩掉

解决方案

  • 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;

  • 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击

  • 采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定不存在的数据会被这个 bitmap 拦截掉,从而避免了对底层存储系统的查询压力

  1. 缓存击穿

缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。和缓存雪崩不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。

解决方案

  • 设置热点数据永远不过期。

  • 加互斥锁,互斥锁

  1. 缓存预热
    缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统。这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!

解决方案

  • 直接写个缓存刷新页面,上线时手工操作一下;

  • 数据量不大,可以在项目启动的时候自动进行加载;

  • 定时刷新缓存;


https://www.xamrdz.com/backend/3ez1935666.html

相关文章: