缓存服务器梳理(二)

1.为什么要用缓存

内存在整个计算机系统来说也就是一个缓存,CPU操作内存速度很快;因为操作数据的时候,先从硬盘中取出数据放到内存中,然后CPU操作数据

缓存:提升访问效率,将一些频繁访问地放在缓存里面



常见的缓存:


Ehcache:继承在应用服务器里面内,很好集成,方便简易;容量小


Mem cache:存储类型很单一,就是字符串


Redis:存储类型丰富,性能非常高,可靠性高

Redis持久化

有两种方式:一种是快照,一种是AOF

快照(一般不会用):持久化到磁盘

我们在redis.conf文件中可以找到对应的配置

900 1:900s以内,有一个key改变就把一个Key放磁盘里面
300 10:300s以内,有10个key发生改变,会持久化到磁盘

以此类推

优点:

会把所有的数据持久化到磁盘

缺点:

效率低,影响性能和数据的浪费
如果要禁用的话直接把save禁止掉


AOF(append only file)

只是把改变的添加到某一个磁盘里面,当下次Redis启动的时候就加载这些改动的部分

 
 
把No改为Yes就可以启用AOF模式

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进行统一的存放,并在请求前做拦截,这样避免请求穿透到后端数据库。这种方式实现起来相对复杂,比较适合命中不高,但是更新不频繁的数据。

原文地址:https://www.cnblogs.com/chengxuyonghu/p/13685056.html