redis常见问题
1.redis应用场景?
(1)token令牌的生成
通过token替代session,session有个最大的问题是不支持集群。把token存在redis里,因为redis是可以共享使用的。
(2)短信验证码code
验证码有效期只有30分钟或者1小时,使用redis对验证码的code设置有效期。
(3)使用redis去减轻数据库访问的压力
把热点数据(经常被查询到的)做成热点key。热点key要提前预热下(提前把热点的key从数据库放到redis中,否则刚开始访问的用户直接从数据库中查询,速度很慢)。
(4)网页计数器
记录网页的PV量多少。redis是单线程的,可以保证线程安全,保证原子性。
(5)分布式锁
redis中实现分布式锁有两种方案:a. setnx;b.使用框架。
(6)订单30分钟有效期
使用redis的key的有效期和失效的监听。一旦key失效时,会走客户端的一个回调,告诉客户端一个事件通知。
(7)实现注册中心、分布式的配置中心等
2.redis线程是否安全?
redis是线程安全的。redis是单线程的。
3.redis是单线程为什么效率高?
redis数据都存在内存里面的。核心是用到nio的io多路复用机制(ngix),能够很好支持并发,从而保证线程安全。
redis单线程,也就是底层采用一个线程去为维护多个不同客户端的io操作。
但是nio在不同操作系统实现机制不同。在windows中使用select实现轮询的时间复杂度是o(n),而且还存在空轮询的情况,效率很低,其次是默认对轮询的数据有一定的限制,所以吃出上万的tcp连接很难。
所以在linux上采用epoll实现事件驱动回调,不会存在空轮询的情况,只对活跃的连接实现主动回调,这样性能大幅度提升,,而是时间复杂度为o(1)。这就是为什么ngix和redis都能支持很高程度的并发,最终都是linux的io多路复用机制epoll。
(redis官方不支持windows版本,windows里是没有epoll)
io多路复用是nio。服务器端只用一个线程去维护客户端所有连接。请求(tcp连接)通过管道(Channel)到达服务器都会注册到一个选择器(selector)的集合中去,通过一个线程去循环遍历这个集合,判断每个连接是否有数据,有数据就读取。(一个线程去维护所有客户端连接)。—-》这就是io多路复用。(多路:多个连接。复用:用一个线程去维护)
io多路复用有三个核心区域:管道channel、选择器selector和缓冲区buffer。为什么用到buffer:因为字节流传输效率很低,通过缓冲,成块成块的传输,提高效率。
redis使用到io多路复用原则,即redis通过一个选择器去接受客户端的所有请求,一个线程不断循环判断里面是否有数据,有数据就开始读取。
4.redis中如何存放对象?
方法一:存放json
string类型,存json就行,再通过json反序列化对象。好处:?
方法二:存放二进制
不跨语言,只支持java对象。
5.redis是否支持事务机制?事务支持回滚吗?
支持。两种形式:Multi和Watch。
redis中的事务和mysql中事务的区别:redis中的事务默认是没有行锁机制:mysql中一个事务中对某行数据进行操作,在另一个事务中就不能对这行数据进行操作(行锁);而redis多个事务可以对同一个key进行操作,没有行锁机制,很难保证数据的原子性(缺陷)。
上面是Multi的缺陷,通过Watch解决。
watch原理是采用redis的乐观锁机制(版本号)控制。每次set时版本号加1,当提交事务时和set时版本号如果不一致(证明中间有其他事务对这个key修改了),就会提交失败。
watch可以监视一个或多个键,一旦在接下来的一个事务执行之前有一个键值发生了改变,那么事务就不会被执行。注意:是接下来的一个事务,而不是所有事务。
redis中事务不支持回滚,只是支持事务的取消。redis为什么不支持回滚?mysql回滚把行锁给释放掉,redis中没有行锁,就不用回滚了。
6.redis有没有发布订阅?
有。redis发布订阅一般很少用。数据一致性就是通过发布订阅去订阅到数据库的binlog去保持和数据库的数据一致。
7.订单超时30分钟自动取消如何实现?
搞一个token30分钟,当token失效时,会走客户端的回调方法,再检测下订单有没有支付,没有支付就返回超时。
8.redis与数据库如何保持数据一致性?
(1)直接清空redis,重新读取数据库。问题是效率不高。
(2)采用增量binlog的同步方案。在redis和数据库之间有个消息中间件,消息中间件订阅到数据库的binlog文件(订阅的过程),一旦客户端对数据库有增删改操作时,binlog文件就会增加,消息中间件就会订阅过来,消息中间件再把这些增量的binlog发给redis,redis解析binlog文件,然后再去操作。
9.redis中内存满了如何解决?
(1)对内存实现扩容
(2)淘汰策略:把不经常使用的key释放掉。
10.redis宕机后数据是否会丢失?
不会。redis会持久化到硬盘中(最多延迟1秒的数据)。rdb和aof(增量同步,以日志方式写入aof中)。
注意:开启了aof持久化最多丢失1秒的数据。(redis中数据,数据库还有。redis不会当数据库用)
11.redis中支持哪些持久化机制?
rdb和aof。
区别:rdb属于全量同步,把所有数据生成二进制文件,放到硬盘中。好处是效率高,缺陷是有定时性,丢失数据多。aof属于增量同步,表示把每个增删改操作记录到aof日志文件中,aof有三种方式:每秒钟同步一次;每次操作都同步;从不同步(缓冲区满了就os自动同步),默认是每秒钟同步一次。优点是最多只会丢失一秒的数据,缺点是效率低。
12.增量同步与全量同步区别?
增量是对行为同步:每次增删改操作都会同步到日志文件中
全量采用定时同步:每隔多长时间同步一次。
13.redis主从复制网络产生延迟怎么办?
redis 主 同步数据给 从 时产生延迟,问题:会出现脏读或者数据不一致。(redis集群都是内网搭的,也很少存在延迟。服务器跨区域会存在)。redis很难保证强一致性,数据同步时网络存在时间差(集群都有这个问题)。只能人工补偿,或者人工手动把数据迁过来。只能最终一致性的方案实现数据的同步。
14.redis主从同步如果效率很慢怎么解决?
采用多主多从或者树状结构去实现同步。一主多从(哨兵)时,主的同步压力很大,要给其他从发送同步的数据命令,主宕机了就无法写操作。因此要做多主多从(cluster集群),是个树状形式。哨兵是一主多从,是中心化思想集群,而多主多从是去中心化。
15.redis中如何做高可用?哨兵机制的作用?
高可用??主从同步中如果主宕机了,那么就要人为的从从redis中选一个节点出来做主节点,效率低,就引入哨兵机制。哨兵解决的问题就是当主节点宕机情况下,自动的从剩余的节点选出一个新的主节点。哨兵也需要集群部署(有几个redis就有几个哨兵),因为要投票保证公平性。哨兵如何确定主宕机了?配置文件里面配置有几个哨兵确认主宕机之后,才会认为master宕机了,然后从新选。
16.哨兵机制的优缺点?
缺陷:哨兵安装了多个;只能有一个主节点,不能存在多个;这种集群缺陷是数据可能产生冗余(主和从的数据保持一致,非常浪费资源)。因此引入redis的cluster集群
17.redis的cluster集群原理?
cluster集群是分片集群。预先会分配16384个卡槽,会根据算法?对key计算卡槽对应在哪个服务器位置,然后直接做个set操作。优点是:实现快速的扩容和缩容,而且是去中心化的,可以存在多个master节点。