一 ,为什么用缓存
缓存在性能方面存取速度快,在弹指一瞬间就要执行某步操作,当遇到那些 执行比较慢,或频繁变动的sql就可以考虑放入缓存
在并发方面,我们缓存可以数据库一个缓冲时间,不然太多请求容易让数据挂掉
二,redis有什么缺点
这个还真说不出个一二三,不过缓存常见的问题还是可以说说的
缓存雪崩:
这个就是缓存大面失效,这时候会大量请求mysql,就会导致mysql挂掉
解决方式,
1、redis惊群处理,我们设置过期时间时,可以再加一个时间为更新缓存时间,当 当前时间大于更新缓存时间时,就查询数据库从新生成缓存
2、一致性哈希,例如有10台服务器,每天都有大量请求,当我们在查询数据时就会以id%10取余,比如说 9%10=9,然后就把这个请求分配到对应的第九台服务器,那么这时第九台服务器压力过大,崩了怎么办,我们会这台服务器的缓存转移到另外一台,比如说第五台,那么第五台就要承担自身与第九台服务器的压力,本来一台服务器的压力都扛不住,何况是两台
这个时候我们就需要动用轮盘算法去分担各台的压力,轮盘算法我不会,但大致思路我懂,
如上图 。左边的B \ A 节点互换 |
当A挂掉后,1A的缓存存入B 4A缓存存入c,
3、双缓存
我们有两个缓存,缓存a和缓存b,a的失效时间是半小时,b没失效时间,平时就a来读写数据,当a崩掉后,我们就用b缓存,通过缓存预热脚本去更新缓存a,然后重启一个线程去更新缓存a与缓存b的内容
缓存穿透:
这个就是,黑客发送大量请求,去调用一个存在的key这样就会大量调用数据库
解决方式:
第一方式比较low就是设置空值
第二个是 互斥锁,这是什么东东,我也不知道
三、单线程的redis为什么这么快
1,纯内存操作,你说快不快,然后通过异步写入磁盘,不过有个盲点,内容满了就写不进去了
2,采用io多路复用机制
常见的socket请求处理有两种
并发处理
采用多线程,每一个io流都会有一个线程去处理
个人理解就是数据量不是特别大时,存取速度会比较快
但是数据量特大的时候,就有很大的鸡肋了,大量的线程处与等待的状态,占用cpu,线程的排列也很耗费时间
io多路复用
大数据,大处理占用很大优势,由于是单线程就比较节省资源,只需要对io进行一个排列,就能管理多个io流
四、redis的数据类型
string
这个没什么好说的
hash
没用过,不过用户信息的唯一性应该是没问题的
list
这个可以做消息队列,秒杀的是防止库存超卖,往队列里提前生成库存
set
用的也少,全局去重这个功能还是没问题的
sorted set
因为多了个权重参数score,做排行榜还是可以的
五,redis过期策略与淘汰机制
对redis了解比较深的应该知道,redis过期后,读取不到数据,但还在内存里,这样就会导致内存占用过高,以及内存用完后就无法写入了
这个时候我们可以
1、定期删除,用一个定时器监视key,过期后就删了,但是这样做太浪费cpu了
2、定期删除+惰性删除,redis每100ms做一个检查,检查一部分,把过期的删掉,然后每次请求中,查看是否设置过期时间,如果设置了,看看是否过期,过期了就删
那么这个我们就要想象了,定期删除+惰性删除也是删除一部分数据,那么还遇到内存过高的情况怎么办
在redis.conf中有一行配置:
maxmemory-policy volatile-lru
其中有一个参数allkeys-lre:这个就是当内存过高时,在key中,移除最少用到的key