一,redis的数据类型 string Hash List Set zset,string的存储结构是什么?
String:数据结构是简单动态字符串(simple dynamic string),简称sds;sds的结构如下: "nihao" 单词最终是这样存储的
free记录的是当前可用的空间,len记录的当前数据的长度,buf记录的是当前的数据,它是一个字符数据结构,因为是用C写的所以后面有"\0"。
这种结构的优点:
防止数据溢出:假如不是这种sds结构存储,redis是用C写的,所以我们每次存储数据的时候先申请空间,再存储数据。如果空间不够,但是存入的数据较大就会溢出到相邻的空间里面,就好比我们先挖坑,再放水,如果有一个坑水放多了就会溢出到相邻的坑里面。sds每次更新数据都会提前把坑大小给挖好,直接放数据就行。
减少修改数据时造成的数据空间被重复分配:sds是动态分配内存的,每次根据我们存入的数据大小分配空间,但实际上分配的空间总比要存入的空间多一点,这个其实是预分配空间,多出来的空间就记录在free里面,如果字符串内容变小,空间不会被回收,只会被记录在free里面,下次用的时候不用重新申请空间,直接用就ok,这叫惰性回收
Hash是属于hash结构,常用命令 hset 和 hget。
list是属于双向链表结构,常用命令 lpush 插入一个或多个值到列表头部 和 lpop 移除并获取列表第一个值。
set常用命令:sadd 增加一个或多个数据,spop移除并随机获取一个值。
zset常用命令:zadd,增加一个或者多个有序数据 zrange获取分数区间内的数据。
二,redis能做什么,使用的时候注意什么?
三,保存数据时先保存db还是先保存redis?先保存db后保存redis会有什么问题?
肯定先保存db,后保存redis,因为后保存redis异常可以回滚db。
利用事务回滚db其实也是会有问题的,比如保存redis的时候网络一直超时,那么就会出现堵塞的情况。 解决办法:单独起一个线程,去保存redis,如果redis保存失败了就进行重试直到成功。
db保存失败,redis保存成功了,就在catch块再删除一次redis,直到删除成功。其实上面说的情况是极端情况出现的问题,也可以用canal订阅myslq的binlog日志,数据一旦有变动就可以拿到数据放到redis中,这种方式是最保险的。
四,什么是缓存穿透 雪崩 击穿?
缓存穿透:我们一般是先查询redis,没有查询数据去db查询,db返回数据就把数据放进redis,返回空就不放,这样就会导致查询实际是越过了redis,直接去db查询,导致db压力过大。 解决办法:如果db返回空就把redis的值设置为一个默认值,比如空字符串,然后 给它设置一个很短的失效时间,我一般设置30秒。
缓存雪崩:大面积的redis key集中失效,导致数据库压力突然升高。解决办法:key的失效时间尽量分散,热点key的过期时间设置久一点。
缓存击穿:某一个热点key,持续性接受大的流量请求,突然这个key失效了,就会击中db。就像结界被打破了一样。解决办法:这种场景出现的情况比较少,一般热点数据都是可以预知的,所以提前做了准备,比如缓存失效时间设置的时间久一点,甚至加了二级缓存。