掌握之分布式-4.缓存

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了掌握之分布式-4.缓存相关的知识,希望对你有一定的参考价值。

掌握高并发、高可用架构

第三章 分布式

本章介绍分布式架构的底层技术。主要说明面试过程中可能被问到的技术点。

第四节 缓存

缓存穿透 缓存学雪崩 Redis Memcached Guava

1. 缓存使用中的几个问题
  • 缓存穿透:查询缓存和数据库中一定不存在的数据时,每次查询都是直接到数据库的,这种现象称为缓存穿透

    此时,如果有大量的请求时,会对数据库造成直接冲击,甚至会导致崩溃

    1. 缓存空数据
    2. 使用BloomFilter(布隆过滤器),即缓存数据库中所有存在的Key
  • 缓存雪崩:缓存服务器宕机了,那么所有查询直接落在数据库,对数据库造成巨大压力

    1. 使用缓存集群,增大可用性
    2. 本地缓存
    3. 使用Hystrix(熔断器),它通过熔断、降级、限流三个手段来降低雪崩造成的损失
    4. 持久化机制
  • 热点数据集中失效:本身大批量数据同时失效对Redis服务器也会造成影响,可能会出现慢的情形;再者失效期间,所有的用户请求都会落到数据库上,也会对数据库造成巨大的压力

    1. 使用互斥锁,当发现缓存失效后,第一个请求加锁,然后去查询数据库,把数据存入缓存,这个操作只有一次,其他的请求都是阻塞的,查询执行完成后释放锁,此时已经有了缓存数据,也不会对数据库造成压力了
    2. 对热点数据设置不同的失效时间,加上时间戳
2. Redis的数据结构
  • string

    Redis的最基本的数据结构,可以包含任意数据。一个key对应一个string的value。string类型是二进制安全的。每个string的value最大可以512M
    支持的方法:set、get、mset、mget、setex、setnx

  • list

    列表,一个简单的字符串列表,按照插入的顺序排序,可以向头部(左边)或尾部(右边)添加数据,底层是链表
    支持的方法:lpush、lpushx、lpop、lrange、lset、lindex、llen、rpush、rpop

  • set

    string的无序集合
    支持的方法:sadd、scard、sdiff、sinter、sunion、sismember、smembers

  • zset(sorted set)

    sorted set有序集合,也是string的集合,但是有序的
    支持的方法:zadd、zcard

  • hash

    hash是一个键值对集合,是一个string类型的key(这里叫做field)和value的映射表,key相当于hash的名字,类似于Java中的Map<String, Map<String, String>>
    支持的方法:hset、hget、hdel、hexists、hkeys、hlen、hgetall

    3. Redis适合的场景
    • 会话缓存(Session Cache)
    • 全页缓存(FPC)
    • 队列,利用list数据结构
    • 排行榜/计时器,利用zset
    • 发布/订阅系统
    4. Redis处理并发竞争问题

    Redis采用单进程单线程模式,本身没有锁的概念,其对于多个客户端访问不存在并发的问题

    通过jedis客户端进行并发访问时会出现连接超时、数据转换错误、阻塞等,通过以下方式解决:

    • 客户端与Redis通信时,可以对连接进行池化,每个对Redis的读写操作均采用synchronized
    • 服务器端可以使用setnx
    5. Redis设置过期时间
    • 在set key的时候,可以指定expire time,也就是过期时间
    • Jedis有单独的expire方法

    redis通过定期删除惰性删除来删除过期的key

    • 定期删除,Redis每隔100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除。因为数据量巨大,遍历全部key不现实,太耗CPU,所以是随机的
    • 惰性删除,发起查看key时,会查看key是否过期,如果过期则删除

    只靠这两种机制还是删除不完全的,此时就需要内存淘汰机制了

    6. Redis内存淘汰机制(如何保证热点)
    • volatile-lru:从已设置过期时间的数据集合(server.db[i].expires)挑选最近最少使用的数据淘汰
    • volatile-ttl:从已设置过期时间的数据集合中挑选将要过期的数据淘汰
    • volatile-random:从已设置过期时间的数据集合中随机挑选数据删除
    • allkeys-lru:在键空间中挑选最少使用的数据淘汰(这种策略最常用)
    • allkeys-random:从数据集(server.db[i].dict)中随机淘汰
    • no-eviction:禁止淘汰数据,当写入数据时报错处理

    4.0新增

    • volatile-lfu:从已设置过期时间的集合中挑选最不常用的数据淘汰
    • allkeys-lfu:在键空间中挑选最不常用的数据淘汰
    7. Redis的持久化策略

    支持两种持久化策略:一种是快照(snapshotting,RDB),另一种是只追加文件(append-only file,AOF)

    • 快照持久化(RDB),通过创建快照来存储在内存里的数据在某个时间点的副本;创建快照之后,可以对快照进行备份,可以将快照复制到其他服务器,还可以留在本地

    是默认的持久化方式。在redis.conf中有以下配置

    save 900 1 #在900秒(15分钟)之后,如果至少有1个key发生变化,就会触发BFSAVE创建快照
    save 300 10 #在300秒(5分钟)之后,如果至少有10个key发生变化,就会触发BFSAVE创建快照
    save 60 10000 #在60秒(1分钟)之后,如果至少有10000个key发生变化,就会触发BFSAVE创建快照
    • AOF(append-only file),AOF的实时性更好,默认没有开启,通过以下设置进行开启
    appendonly yes

    开启AOF后,每执行一条更改数据的命令,Redis就将该命令写入硬盘中的AOF文件

    在redis.conf中有三种不同的AOF配置

    appendfsync always #每次更改数据都会写入AOF文件,这会严重降低Redis的性能
    appendfsync everysec #每秒同步一次,将多个命令同步到磁盘
    appendfsync no #由操作系统决定何时同步
    8. Redis事务

    通过MULTIEXECWATCH等命令来实现事务功能

    9. Redis的分布式锁

    通过setnx实现

    10. Redis与Memcached的区别
    • Redis支持丰富的数据结构,Memcached仅支持字符串
    • Redis支持持久化,Memcached不支持
    • Redis支持主从、哨兵、Cluster的集群模式,Memcached没有
    • Redis是单线程多路IO复用模型,Memcached是多线程非阻塞IO复用模型
    11. Redis的集群
    • 主从模式

    主数据库(master)和从数据库(slave)

    • 主数据库进行读写操作,当数据发生变化时会自动同步到从数据库
    • 从数据库是只读的
    • 一个master对应多个slave,一个slave只能有一个master

    • 哨兵模式

    哨兵的作用是监控Redis系统的运行情况

    • 监控主从是否正常运行
    • master出现故障时,自动将slave转换为master
    • 多哨兵之间也会互相监控
    • 多个哨兵监控一个master

    • 集群模式

    只要将每个节点的cluster-enable配置打开即可,每个集群最少三个节点

Memecached

选择Memcached的理由:简单

本地缓存:Ehcache、Guava
Redis和Memcached的区别
  1. Redis支持的数据结构更丰富
  2. Redis支持持久化,Memcached不支持
  3. Memcached没有原生的集群模式,而Redis有主从、哨兵、集群
  4. Memcached是多线程、非阻塞IO复用的网络模型,Redis是单线程多路IO复用的网络模型

以上是关于掌握之分布式-4.缓存的主要内容,如果未能解决你的问题,请参考以下文章

Redis——缓存穿透缓存击穿缓存雪崩分布式锁

Python 分布式缓存之Reids数据类型操作

缓存技术4之进程内缓存

缓存技术5之分布式缓存

十分钟彻底掌握缓存击穿缓存穿透缓存雪崩

分布式框架深入理解分布式之缓存击穿