1:redis 数据类型有哪些?
String (字符串):是key,value结构存储,value是String类型;特点是单个value默认大小为512M,可以改配置文件
项目中的使用:用户登录的验证码存储,JWT令牌的存储(令牌有些情况是需要存的:JWT令牌是用来安全传输的,但是它比较长,在网络传输中是比较消耗资源的,所以一般会根据JWT生成JTI(令牌短标识相当于UUID),将JTI存储到用户的请求中,在redis里存 JTI -JWT,就可以通过JTI拿到JWT再去校验JWT的真伪(传输效率会较快)
List(队列类型) :队列它是栈内存空间,出栈后内存里就没了;list可以做MQ;一般做一些请求排队(电商平台做秒杀活动,10点秒杀5台手机,并发过高可能会导致出现超卖,值出现负数,-10就是被抢了15台,解决方法(预扣减库存):使用redis的list作一个队列,在这个队列里存放5个对象,被取出一台后就少一台)
项目中的使用:队列,文章精准发布的立即消费队列(消费的时候取出来就没了,可以保证线程安全问题,还可以保证顺序性,所以可以代替MQ做队列(比MQ快),但是有MQ了就没必要)
Set(无序集合):不可重复,无序
项目中的使用:特点是去重(点赞,收藏)
Zset(有序集合):有一个score分值,可以用来排序
项目中的使用:排行榜,热点文章排行榜(一周内的热点文章存储)
hash(Map:可以存储 大key 小key value结构,就是大key,value里存储的是Map
项目中的使用:可以存储对象,购物车(大key:谁的购物车;小key:商品id;value:商品对象)点赞,收藏啥都能存
2:redis在项目中的作用?
1.作为存储缓存,降低数据库访问压力(访问量较高的(首页菜单,首页文章)需要一定的效率,并发量很大)
用redis做缓存怎么保证数据不丢失?(缓存数据丢失会导致所有请求全部走数据库)(缓存击穿)
1:用分布式锁来保证只有一个请求进去,查完后保存一份到redis缓存就可以解决
2:做持久化防止缓存数据丢失,给它存到硬盘里去,会影响性能(性能和安全不可兼得)
2.分布式环境下代替Session数据共享
多个服务器不能共享Session,可以用Redis替代Session,就可以共享(做集群的时候多个服务器之间数据的共享)
3.借助redis的特性incrment 自增保证幂等性
短时间多个相同请求只成功一个;increment自增操作默认是+1,设置increment阈值>1就不进去这样只能一个成功
4.借助redis特性SetNX 来实现分布式锁 (Redissession)
SetNX获得锁,delKey释放锁
3:redis常见问题?
1.缓存穿透:用户得恶意访问不存在的key 导致一直访问数据库(缓存没有访问数据库)。布隆过滤器,设置 null值(就算没有查到这个值,也给它设置一个null值,下次相同的查询就走缓存null)。
2.缓存雪崩 : 很多缓存数据突然同时失效(一般设置缓存都是统一时间设置) ,大量请求直接走数据库。
(错开缓存时间,缓存的生命时长用一个随机值错开)(缓存预热:不设置缓存时间,开机直接把缓存存入redis) ,多级缓存(一级缓存数据丢了,走二级缓存,再把数据放一级缓存,二级也没有才访问数据库,多了一层屏障,缓存越多和数据库的一直性会越差)
3.缓存击穿 : 热点数据突然失效。加锁(只让一个进去,这方法好),列队(排队)
4:redis的数据都是存在内存中的,如果存满了会怎么办呢?(还能存进去吗?)
能;如果redis 存满的话,会根据淘汰策略,淘汰一部分数据,让你存新的数据。
淘汰策略:里面好像有个lru算法,移除ttl短的数据(具有更早过期时间的key)
5:Redis是单进程单线程的?
是的,为什么是单线程的效率还那么高?
底层使用是一个IO多路复用器(它可以同时有多个连接,谁有访问就立即执行)
在redis4.0后引入了多线程,增删改都是用多线程
6:什么是Redis持久化?
(项目中没有遇到过,可以通过持久化来解决)
把数据永久性存储在硬盘,防止redis数据丢失就是持久化,两种方式:
默认开启RDB (快照,每隔一段时间进行一次全量备份,恢复速 度快,但是会丢失数据(因为是一段时间备份一次,还没有备份的时候服务器宕机,内存清空了,中间这段时间的数据就会丢失)),
AOF(日志,每次操作,都会记录对应的日志,恢复速度慢,硬盘占用空间, 备份数据全,不会出现丢失)。
7:一般选择哪种方式作为持久化呢?
使用RDB(做一段时间的全量备份) + AOF(做部分的日志记录)
8:项目中Redis使用单体还是集群?
redis一般都会做集群,redis是基于内存,对数据量的存储要求很高,(但是开发环境是单体,线上可能是集群)
使用哨兵的作用:(高可用方案,可以理解为读写分离,主从复制),(1)监控主数据库和从数据库是 否正常运行。(2)主数据库出现故障时自动将从数据库转换为主数据库。
哨兵高可用方案,主从数据库的数据存储必须一致,防止redis单点故障。单是不能达到扩容的效果
扩容需要用redis的cluster:
用那个看需求,是要高可用还是大容量
生产环境中的 redis 是怎么部署的?
最小节点的高可用集群:
我们公司redis存储数据还不是很大(大概10G左右),我们采用主 从加哨兵模式保证redis服务的高可用(对高可用需求高)。整个集群1个主redis,1个从redis,3个哨兵(至少要3个哨兵才 能保证高可用,否则无法选举leader,无法实现主从切换)。可允许一台哨兵或redis实例挂掉。每台机 器配置:16G 内存+ 4 核 CPU + 1T 磁盘。
redis分布式锁中的问题?
1.如何防止其他线程释放了别人的锁(给锁添加一个唯一标识,知道唯一标识 一样才能释放)2.防止获得锁的任务执行中出现异常不释放锁导致死锁(给锁设置生命时长)3.防止业 务的执行时间大于锁的生命时长(使用守护子线程进行锁续期) 4.如果保证redis多个指令执行的原子性 (Lua脚本)
redis怎么存储超10亿级用户?(要的是扩容性)
官方redis 集群方案,redis-cluster ,最小三主三从 ,16384hash槽(用 来分布式存储数据)。
redis缓存不一致解决方案?
为什么会出现缓存不一致:
并发修改会出现的问题:线程A对mysql里的数据做修改,在它修改成功后,将数据同步到redis之中这个过程中,线程B拿到执行权,对mysql做了另外的修改,它同步到redis中了,此时A才同步成功,这个时候mysql里的数据就和redis里的不一致了
解决:用锁的话会降低性能,就违背了用redis的初衷了
延时双删
做修改的时候删除缓存,然后过3秒再删一次,这样并发时间肯定就过了
弊端:性能不好,频繁的增删改,就会频繁的删除缓存,就需要频繁查
标准的解决方案:阿里的cannal
让redis里数据修改的顺序和mysql数据修改的顺序一致就可以保证他们两个数据一致
mysql里的有一个binlog日志它会记录所有提交的sql,
cannal将自己伪装成mysql的从级,mysql就会将自己的binglog日志主动发送给cannal(主从同步),它会解析binglog日志然后来修改redis,这样binglog里记录的顺序就是redis修改的顺序就,就是数据库的执行顺序