•   缓存概况

缓存的特征

       随着用户数和访问量越来越大,为缓解服务器的压力才引用缓存。

       命中率(命中率=返回正确结果数/请求缓存次数)越高,表明缓存的使用率越高。

       最大元素(或最大空间)代表缓存中可以存放的最大元素的数量,一旦缓存中元素数量超过这个值

(或者缓存数据所占空间超过其最大支持空间),那么将会触发缓存启动清空策略。

       常见的缓存清空策略:

FIFO(first in first out):先进先出策略。

                LFU(less frequently used):最少使用策略。

                LRU(least recently used):最近最少使用策略。

根据过期时间判断,清理过期时间最长的元素或快要过期的元素 等等。

单机版缓存

解决本地缓存数据的实时性问题,目前大量使用的是结合ZooKeeper的自动发现机制来实时抓取更新数据,

比如美团点评内部的基础配置组件MtConfig。

                     

redis集群命中率不高 redis命中率_缓存

分布式缓存

         单机版缓存节点主要会有以下两个问题:

               (1)请求量超过单端口可承受极限。

               (2)数据容量超过单实例内存容量。

        所以从单机版扩展为分布式缓存,每个实例上只缓存数据总量的一部分数据。客户端在请求的时候,

需要决定从哪个节点中获取数据(hash)。客户端根据请求的key,取模后选择对应的缓存节点;但是缺点

在于每加、减一个节点,hash方式全部改变,整体命中率会下降的非常快,造成的震荡很大,如图:

                                              

redis集群命中率不高 redis命中率_数据_02

     利用一致性hash可以在加减节点时,很好的减小震荡。

        一致性hash:实现思路是为系统中每个节点分配一个token,范围一般在0~2^32,这些token构成一个

哈希环(防止集群中某个缓存服务器摘除的时候,以前存储在这台机器上的key找不到顺时针距离它最近的

一个节点)。数据读写执行节点查找操作时,先根据key计算hash值,然后顺时针找到第一个大于该哈希值

的token对应的节点。

                                         

redis集群命中率不高 redis命中率_数据_03

引入主从缓

存结构,即加入备份节点(先获取Master数据,当Master返回空或者无法取到数据的时候,访问Slave节点)。

分布式缓存常见问题

       (1)缓存数据集中过期

设定一个缓存过期时间时,如果某时刻并发很高,可能会同时生成很多缓存数据,并且过期时间都一样,

过期时间到后,造成缓存数据集体失效。

                解决方案:将缓存失效时间分散开,可以在原有失效时间基础上增加一个随机值,比如随机几分钟,

让缓存数据重复率就会降低。

       (2)缓存穿透

                查询一个根本不存在的数据,缓存层和存储层都不会命中,如果存储层查不到数据则不写入缓存

会使存储层负载加大宕掉。如果发现大量存储层空命中,可能就是出现缓存穿透问题。

                解决方案:a. 缓存空对象

                                 

redis集群命中率不高 redis命中率_缓存_04

                              b.使用布隆过滤器拦截(了解还不是很详细)

                                 在访问缓存层和存储层之前,将存在的key用布隆过滤器提前保存起来,做第一层拦截。

       (3)缓存雪崩

由于缓存层承载大量请求能有效的保护存储层,但是如果缓存层由于某些原因整体不能提供服务

缓存层crash),于是所有请求都会达到存储层,存储层的调用量会暴增,造成存储层也会挂掉。

                解决方案:提高缓存层服务高可用性(似乎想当于白说,意思就是通过技术手段让缓存层尽量不crash)。

       (4)缓存层并发

在高并发场景下,同时多个请求去从数据库获取数据,对后端数据库造成极大的冲击,甚至导致 “雪崩”

现象。此外,当某个key被更新时,同时也可能被获取,会导致一致性问题。

               解决方案:直白点讲,加锁,这样在缓存更新或者过期的情况下,先尝试获取到锁,当更新或者从数据

库获取完成后再释放锁,在此期间其他请求只能牺牲时间来等待。

  • Redis缓存

      Redis 由C语言开发,可做缓存又可作注册中心。

      所有的数据都是字符串。

      命令不区分大小写,而key区分大小写。

      Redis是单线程的。

      Redis中不适合保存内容大的数据。

      五种数据类型:

                       

redis集群命中率不高 redis命中率_redis集群命中率不高_05

   Redis的持久化方案

           这种高级的key-value数据库,所有数据都是保存在内存中,如果没有配置持久化,Redis重启后数据就

会全部丢失。于是需要开启Redis的持久化功能,将数据保存到磁盘上,当redis重启后,可以从磁盘中恢复数据。

           Redis提供两种方式进行持久化:

                    Rdb快照持久化:将Reids在内存中的数据库记录定时dump到磁盘,是默认支持的持久化方案。

                    AOF(append only file)持久化:将Redis的操作日志以追加的方式写入文件,数据库恢复时把之

前所有的操作命令执行一遍即可。

                   两种持久化方案同时开启使用AOF文件来恢复数据库。

   Redis集群介绍

                             

redis集群命中率不高 redis命中率_Redis_06

所有的Redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。

                      (2)各个主节点之间采用投票容错机制,当节点接收到其他节点发来的信息时, 它会记下那些

                               被其他节点标记为失效的节点,这被称为失效报告(Failure Report)。当集群中超过半数

                               的节点检测该节点失效时,该Fail节点是通过才生效。

                      (3)客户端与Redis节点直连,不需要中间Proxy层。客户端不需要连接集群所有节点,连接集群

                               中任何一个可用节点即可。

                      (4)Redis 集群中内置了 16384 【0—16383】个哈希槽,当需要在 Redis 集群中放置一个

                               key-value 时,Redis 先对 key 使用 Crc16 算法算出一个结果,然后把结果对 16384 求余数

                               这样每个 key 都会对应一个编号在 0-16383之间的哈希槽,Redis 会根据节点数量大致均等的

                               将哈希槽映射到不同的节点。

           集群中至少应有三个节点,要保证集群高可用,则需要每个主节点有一个备份节点,所以至少需要6台服务器。 

           如果只是需要做热备份或读写分离,那么使用主从模式即可;

           如果需要做故障转移,那么需要使用哨兵模式。