使用redis的原因
1.使用磁盘存数据,访问太慢;
2.使用数据库索引,还是较慢;
因此使用redis内存数据库,存放热数据。

缓存穿透
要访问的数据不在redis中,穿透到了数据库去找。

解决方案
为防止黑客多次使用无效字段访问而导致多次缓存穿透,可使用过滤器,来存放有效字段;

然而过滤器的数据也是放在内存,如果数据太多会造成内存紧张,效果适得其反;
因此过滤器采用了布隆算法。

布隆算法
将有效字段通过hash函数求得的二进制数组的方式来代表有效字段。
二进制数组占内存非常少。

通过错误率换取空间
因为不同数进行hash计算后可能得到相同值,所以,可能会把某个无效字段判为有效字段,但反之不可能,因此影响不大。

降低错误率:增加数组长度;增加散列函数。
但也不可太多个散列,极端情况下会出现全为1,导致误判严重

redis相关

假设过滤器采用十位的数组:
如下图,假设 S 集合中有n个元素,利用 k 个哈希函数,将S中的每个元素映射到一个长度为 10 的位(bit)数组中不同的位置上,这些位置均置为1。

如果待检测的元素经过这k个哈希函数的映射后,发现其k个位置上的二进制数不全是1,那这个元素一定不在S中,反之,该元素可能是S中的某一个元素。

redis相关

缓存击穿:
存放在redis的某条数据,超时后仍然为热数据,导致数据库被频繁访问。缓存穿透的一种。

解决方案:
对中小型的服务器一般不需要解决,只是单条数据而已。
大型:分布式锁。(zookeeper)
(普通的synchronized只能用于同一个服务器内)
当某个服务器获得锁取得数据,就会放在redis中,这样其它服务器也可以直接去redis拿了。如果不用锁的话,还是会导致在把数据放到redis的过程中MySQL依然要承受短暂压力。

举例: (注:现实中几乎不用这种方式)
对数据库加锁(value),当服务器们想要访问数据库某条热数据时,必须先抢到锁(insert value)。

为了避免服务器在获得锁之后宕机,又使用了另一个jvm来监测。但如果设置锁超时时间过长,可能会导致效率低下;过短又可能会导致几个服务器同时获得锁。

缓存雪崩:
redis的多条热数据同时失效,导致数据库被频繁访问。

原因:

  1. 有效期一样。
    解决方案: 给每条数据设置随机有效期。
  2. redis挂了。
    解决方案: 使用redis集群。

redis集群: 把redis放在多个服务器。
数据量少时,使用 主从复制。
数据量大时,使用 切片。
常用方法:一致性hash算法。

一致性hash算法:
举例:使用 2^32个节点的hash环。
把热数据通过hash (key) 再求余2^32;
把服务器进行hash (ip+端口)再求余2^32,
分别对应环上的某个节点。
把环上的热数据都放在顺时针前一个的redis里。

这样,不管有多少台服务器redis,动态扩展时,都只要对其中的两个redis进行复制。
redis相关
一般的,在一致性哈希算法中,如果一台服务器不可用,则受影响的数据仅仅是此服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据;如果增加一台服务器,则受影响的数据仅仅是新服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据。

性质:1、平衡性:哈希结果尽可能分布到所有缓冲中去;
2、单调性:有新的缓冲区加入到系统中,那么哈希的结果应能够保证原有已分配的内容可以被映射到
新的缓冲区中去,而不会被映射到旧的缓冲集合中的其他缓冲区。
3、分散性:由于不同终端所见的缓冲范围有可能不同,从而导致哈希的结果不一致,最终的结果是相
同的内容被不同的终端映射到不同的缓冲区中;(要尽量降低分散性)
4、负载:对于一个特定的缓冲区而言,也可能被不同的用户映射为不同的内容;(要降低
5、平滑性:缓存服务器的数目平滑改变和缓存对象的平滑改变是一致的。

若出现数据倾斜,可以使用虚拟节点机制,对每一个服务节点计算多个哈希,每个计算结果位置都放置一个此服务节点,称为虚拟节点。可以知道,虚拟节点越多,数据就能分布更均匀。
实现方式:可以在服务器ip 端口后面加上编号。

相关文章:

  • 2021-10-13
猜你喜欢
  • 2021-11-23
  • 2021-12-03
相关资源
相似解决方案