高并发之缓存

为何缓存?

目前磁盘IO和网络IO相对于内存IO的大幅度性能劣势,通过将高频使用的数据存储在离近CPU的位置,以减少传输时间,提高处理效率。

系统缓存:

  • CPU在从内存里读取数据的时候,会额外的读许多数据到内存里;
  • 各个输入输出之间用buffer保存一批数据统一发送和接收。

软件设计缓存:

  • web服务将静态资源提前部署到CDN;
  • 数据库缓存查询,一级缓存,二级缓存;

内存数据库(redis)把大量数据存在内存而非硬盘;

缓存Tips:

缓存穿透

收到了一个请求,但是该请求缓存里没有,只能去数据库里查询,然后放进缓存。这里面有两个风险,一个是同时有好多请求访问同一个数据,然后业务系统把这些请求全发到了数据库;第二个是有人恶意构造一个逻辑上不存在的数据,然后大量发送这个请求,这样每次请求都会被发送到数据库,可能导致数据挂掉。

解决方案:

  • 事先做校验,对恶意数据直接过滤掉,不要发到数据库层;
  • 缓存空结果,就是对查询不存在的数据仍然记录一条该数据不存在在缓存里,这样能有效的减少查询数据库的次数。

那么非恶意访问呢?这个要结合缓存击穿来讲

缓存击穿

对于热点数据,当数据失效,所有请求都死去数据库请求更新缓存,数据库被压垮。

解决方案:

  1. 全局锁,就是所有访问某个数据的请求都共享一个锁,获得锁的那个才有资格去访问数据库,其他线程必须等待。但是现在的业务都是分布式的,本地锁没法控制其他服务器也等待,所以要用到全局锁,比如用redis的setnx实现全局锁。
  2. 对即将过期的数据主动刷新,比如起一个线程轮询数据,比如把所有数据划分为不同的缓存区间,定期分区间刷新数据等等。

我们给所有的数据设置了同样的过期时间,然后在某一个历史性时刻,整个缓存的数据全部过期了,然后瞬间所有的请求都被打到了数据库,数据库就崩了。

解决思路要么是分治,划分更小的缓存区间,按区间过期;要么是给每个key的过期时间加个随机值,避免同时过期,达到错峰刷新缓存的目的。

 

posted on 2018-10-23 10:56  samuel1  阅读(199)  评论(0编辑  收藏  举报

导航