目录
2.3.4.1 大型互联网高并发缓存架构
1、Redis数据失效导致的雪崩
因为缓存失效,从而导致大量请求需要访问数据库。
1、大量请求,导致数据库处理不过来,整个系统依赖数据库的功能全部崩溃。
2、单系统挂掉,其他依赖于该系统的应用也会出现不稳定甚至崩溃。
2、redis数据失效的场景
1、数据淘汰(LRU/LFU)
2、数据过期expire
3、服务重启(宕机/升级)
3、缓存雪崩解决方案
1、对数据库访问限流:信号量控制并发
2、容错降级:返回异常码
3、针对内存不足:采用redis集群方案
3.1、Semaphore信号量限流
J.U.C包重要的并发编程工具类,又称“信号量”,控制多个线程争抢许可。
核心方法:
acquire:获取一个许可,如果没有就等待
release:释放一个许可
典型场景:
代码并发处理限流
测试运行代码本地地址:E:\meWork\study\project\subject-2\subject-2-cache\cache-stampeding\src\test\java\com\study\cache\stampeding\CacheStampedingApplicationTests.java
测试之前需要准备环境:
1、先安装:rebloom
$ git clone git://github.com/RedisLabsModules/rebloom
$ cd rebloom
$ make
#容量100万, 容错率万分之一, 占用空间是4m
然后启动redis:src/redis-server conf/redis.conf --loadmodule /root/rebloom/redisbloom.so INITIAL_SIZE 1000000 ERROR_RATE 0.0001
rebloom安装参考地址:https://blog.csdn.net/zhaoyu_nb/article/details/90408036
2、建表
CREATE TABLE `goods` (
`id` int(11) DEFAULT NULL,
`quantity` varchar(255) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`price` varchar(255) DEFAULT NULL COMMENT '商品'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
3.2、容错降级
提示网络不给力,请确保网络连接正常后再重试
解决缓存击穿思路
4、缓存击穿场景重现
查询必然不存在的数据,请求透过redis,直击数据库。
4.1、解决缓存击穿思路
查询之前先判断目标数据是否存在,不存在的直接忽略。
(将流量拦截于缓存和数据库之前)
4.2、Bloom filter(布隆过滤器)
布隆过滤器是1970年由布隆提出的。
实际上是一个很长的二进制数组和一系列hash函数。
布隆过滤器可以用于检索一个元素是否在一个集合中。
布隆过滤器并非拦截所有请求,意在将缓存击穿控制在一定的量!!!
目的:减少内存占用
方式:不保存所有ID信息,只在内存中做一个标记
优点:内存空间占用少、空间效率和查询时间都比一般的算法要好得多
缺点:不能精准过滤、是有一定的误识别率和删除困难、需要不断维护,带来新的工作
(布隆过滤器判断不存在,100%不存在,判断存在,则可能不存在【hash重复,导致不存在的元素可能会被判断为存在】)
1、二进制数组构建过程:
1、加载符合条件的记录
2、计算每条元素的hash值
3、计算hash值对应二进制数组的位置
4、将对应位置的值改为1
2、查找元素是否存在的过程
1、计算元素的hash值
2、计算hash值对应二进制数组的位置
3、找到数组中对应位置的值,0代表不存在,1代表存在
4.3、自研布隆过滤器
利用redis特性和命令:bitmaps(setbit设置指定位置的值、getbit获取值)
可以理解为这是redis自带的二进制数组特性。
数组构建:加载符合条件的记录,并将每一条记录对应的bitmaps位置设值为1
5、Java应用层-自定义缓存注解
5.1、元注解
Retention:定义注解的生命周期,可选值为(source、class、runtime)
Documented:文档化注解,会被javadoc工具文档化
Inherited:注解是自动继承的,想让一个类和它的子类都包含某个注解,就可以使用它来修饰这个注解
Target:表示可以用来修饰类、接口、注解类型、枚举类型
......
method:可以用来修改时方法
field:可以用来修饰属性(包括枚举常量)
constructor:可以用来修饰构造器
local_variable:可用来修饰局部变量
5.2、注解annotation的应用
1、创建注解:public @interface AnnotationName{}
2、元注解(描述注解的一种方式)
@Retention:定义注解的生命周期【source -> class -> runtime】
@Documented:文档注解,会被javadoc工具文档化
@Inherited:是否让子类继承该注解
@Target:描述注解的应用范围
TYPE:可以用来修饰类、接口、注解类型、枚举类型
Package:可以用来修饰包
parameter:可以用来修饰参数
annotation_type:可以用来修饰注解类型
method:可以用来修饰方法
field:可以用来修饰属性(包括枚举常量)
constructor:可以用来修饰构造器
local_variable:可用来修饰局部变量
具体代码地址:E:\meWork\study\project\subject-2\subject-2-cache\cache-stampeding\src\main\java\com\study\cache\stampeding\annotations\CoustomCacheAspect.java