缓存服务器梳理(二)
1.为什么要用缓存
内存在整个计算机系统来说也就是一个缓存,CPU操作内存速度很快;因为操作数据的时候,先从硬盘中取出数据放到内存中,然后CPU操作数据
缓存:提升访问效率,将一些频繁访问地放在缓存里面
常见的缓存:
Ehcache:继承在应用服务器里面内,很好集成,方便简易;容量小
Mem cache:存储类型很单一,就是字符串
Redis:存储类型丰富,性能非常高,可靠性高
Redis持久化
有两种方式:一种是快照,一种是AOF
快照(一般不会用):持久化到磁盘
我们在redis.conf文件中可以找到对应的配置
300 10:300s以内,有10个key发生改变,会持久化到磁盘
以此类推
优点:
会把所有的数据持久化到磁盘
缺点:
效率低,影响性能和数据的浪费
如果要禁用的话直接把save禁止掉
AOF(append only file)
只是把改变的添加到某一个磁盘里面,当下次Redis启动的时候就加载这些改动的部分
AOF也有三种模式,一般我们会用第二种模式
- appendfsync always:只要添加一条就放到磁盘里面,效率低(一般不用)
- appendfsync everysec:每秒中有多少改变都写到磁盘(就算Redis挂了,有些数据丢失,影响不会那么大)
- appendfsync no:多久同步一次,不是我们控制的,完全依赖于操作系统,Redis(一般不用)
AOF和快照模式的比较
存储结构:
内容是redis通讯协议(RESP )格式的命令文本存储。
比较:
1、aof文件比rdb更新频率高,优先使用aof还原数据。
2、aof比rdb更安全也更大
3、快照性能比aof好
4、如果两个都配了优先加载AOF。
Redis内存
Redis是一个内存数据库
Redis的容量依赖于内存的大小
Redis可以自己设定内存大小
如果我们自己设了内存大小的话,同时要设置内存策略;
Redis默认使用的是LRU算法
LRU算法:
长时间不用的数据(key),会从Redis中删除
Redis集群出现之前如果实现高可用:
主从复制,主服务器要什么改变都复制到从服务器
缺点:
数据量会非常大,每一个从服务器数据量和主服务器一样
3.0以后Redis有了集群的解决方案。
Redis Cluster分区实现原理
槽(slot)概念
Redis Cluster中有一个16384长度的槽的概念,他们的编号为0、1、2、3……16382、16383。这个槽是一个虚拟的槽,并不是真正存在的。正常工作的时候,Redis Cluster中的每个Master节点都会负责一部分的槽,当有某个key被映射到某个Master负责的槽,那么这个Master负责为这个key提供服务,至于哪个Master节点负责哪个槽,这是可以由用户指定的,也可以在初始化的时候自动生成(redis-trib.rb脚本)。
这里值得一提的是,在Redis Cluster中,只有Master才拥有槽的所有权,如果是某个Master的slave,这个slave只负责槽的使用,但是没有所有权。
这张图的意思是:比如我们有一个客户端请求了某个key发现不在某个节点上,该节点会找到这个key所在的节点,然后返回给客户端,让客户端重新发起请求。
Redis的线程模型
Redis是单线程,单进程的程序。一个指令来了,先放进队列里面,先进先出;为什么单线程还这么快,因为是运行在内存里面,CPU操作内存速度是非常快的
缓存穿透问题
缓存穿透在有些地方也称为“击穿”。很多朋友对缓存穿透的理解是:由于缓存故障或者缓存过期导致大量请求穿透到后端数据库服务器,从而对数据库造成巨大冲击。
这其实是一种误解。真正的缓存穿透应该是这样的:
在高并发场景下,如果某一个key被高并发访问,没有被命中,出于对容错性考虑,会尝试去从后端数据库中获取,从而导致了大量请求达到数据库,而当该key对应的数据本身就是空的情况下,这就导致数据库中并发的去执行了很多不必要的查询操作,从而导致巨大冲击和压力。
可以通过下面的几种常用方式来避免缓存传统问题:
(1)缓存空对象
对查询结果为空的对象也进行缓存,如果是集合,可以缓存一个空的集合(非null),如果是缓存单个对象,可以通过字段标识来区分。这样避免请求穿透到后端数据库。
同时,也需要保证缓存数据的时效性。这种方式实现起来成本较低,比较适合命中不高,但可能被频繁更新的数据。
(2)单独过滤处理
对所有可能对应数据为空的key进行统一的存放,并在请求前做拦截,这样避免请求穿透到后端数据库。这种方式实现起来相对复杂,比较适合命中不高,但是更新不频繁的数据。