1.redis实现分布式锁
2.redis实现唯一id
3.redis怎么解决hash冲突的
4.操作redis的客户端实现
- Jedis
- Jedis是Redis的Java实现的客户端,其API提供了比较全面的Redis命令的支持
- Jedis中的方法调用是比较底层的暴露的Redis的API
- Jedis使用阻塞的I/O,且其方法调用都是同步的,程序流需要等到sockets处理完I/O才能执行,不支持异步。Jedis客户端实例不是线程安全的,所以需要通过连接池来使用Jedis
- 因为使用的是阻塞I/O,而磁盘I/O是机械动作,相较于cpu的效率是低很多的,所以Jedis的效率也是较低的,现在一般不在使用
- RedisTemplate
- RedisTemplate是SpringDataRedis中对JedisApi的高度封装
- SpringDataRedis相对于Jedis来说可以方便地更换Redis的Java客户端,比Jedis多了自动管理连接池的特性,方便与其他Spring框架进行搭配使用如:SpringCache
- Redisson
- Redisson实现了分布式和可扩展的Java数据结构,和Jedis相比,功能较为简单,不支持字符串操作,不支持排序、事务、管道、分区等Redis特性
- Redisson使用非阻塞的I/O和基于Netty框架的事件驱动的通信层,其方法调用是异步的。Redisson的API是线程安全的,所以可以操作单个Redisson连接来完成各种操作。
- 主要用在分布式项目中,提供一些常用方法
- 集成springboot使用方法
4.Redis是单进程单线程的为什么还能处理高并发
- 性能极高 – Redis 读的速度是 110000 次 /s, 写的速度是 81000 次 /s 。
5.Redis过期键删除策略
6.Redis内存淘汰机制
- 当内存不足以容纳新写入数据,redis的内存淘汰机制就派上用场了
- 采用定是删除+惰性删除没其他问题了吗,不是的,如果定是删除没有删除的key。并且你也没有即时去请求key,也就是说惰性删除没生效,这样,redis的内存会越来越高,那么就应该采取内存淘汰机制。
- 在redis.conf中有一行maxmemory-policy noeviction该配置就是配置内存淘汰机制
- Redis提供了下面几种淘汰策略供用户选择,其中默认的策略为noeviction策略:
noeviction:当内存使用达到阈值的时候,所有引起申请内存的命令会报错。
allkeys-lru:在主键空间中,优先移除最近未使用的key。(常用方法)
volatile-lru:在设置了过期时间的键空间中,优先移除最近未使用的key。
allkeys-random:在主键空间中,随机移除某个key。
volatile-random:在设置了过期时间的键空间中,随机移除某个key。
volatile-ttl:在设置了过期时间的键空间中,具有更早过期时间的key优先移除。
- 这里补充一下主键空间和设置了过期时间的键空间,举个例子,假设我们有一批键存储在Redis中,则有那么一个哈希表用于存储这批键及其值,如果这批键中有一部分设置了过期时间,那么这批键还会被存储到另外一个哈希表中,这个哈希表中的值对应的是键被设置的过期时间。设置了过期时间的键空间为主键空间的子集。
7.Redis持久化机制
8.Redis事务
- redis 事务一次可以执行多条命令,服务器在执行命令期间,不会去执行其他客户端的命令请求
- 事务中的多条命令被一次性发送给服务器,而不是一条一条地发送,这种方式被称为流水线,它可以减少客户端与服务器之间的网络通信次数从而提升性能
- Redis 最简单的事务实现方式是使用 MULTI 和 EXEC 命令将事务操作包围起来
- 批量操作在发送 EXEC 命令前被放入队列缓存。
- 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余命令依然被执行。也就是说 Redis 事务不保证原子性
- 在事务执行过程中,其他客户端提交的命令请求不会插入到事务执行命令序列中
- 事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。
- 总结:单条Redis 命令的执行是原子性的(也就是要么成功要么失败),但是多条Redis命令打包形成事务一起去执行,其中一条redis命令失败是不会影响事务中其他的redis命令的(也就是事务中的redis命令不保证原子性),但是redis的事务可以保证不被其他的redis命令影响
9.Redis事务命令
- MULTI 标记一个事务块的开始(开启事务)
- EXEC 执行所有事务块内的命令。(提交事务)
- DISCARD 取消事务,放弃执行事务块内的所有命令
10.Redis集群方案什么情况下会导致整个集群不可用?
有A,B,C三个节点的集群,在没有配置主从复制模型的情况下,如果节点B失败了,那么整个集群中就会缺少5501-11000这个范围的槽而不可用,所以如果配置redis集群模式一般都会再配置主从复制保证系统性能和高可用性,配置了主从复制之后一般再配置redis的哨兵模式就会保证当有主节点挂掉之后集群可以自动选举出新的master不用人工进行失败转移。
10.Redis的主从复制(读写分离容灾恢复)
- 和MySQL主从复制的原因一样,Redis虽然读取写入的速度都特别快,但是也会产生读压力特别大的情况。为了分担读压力,Redis支持主从复制,Redis的主从结构可以采用一主多从或者级联结构
- 主对于数据可读可写。从默认是只读不写的(当然也可以配置)
- Redis主从复制可以根据是否是全量分为全量同步和增量同步。
- 全量同步:Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份
- 增量同步:Redis增量复制是指Slave初始化后开始正常工作时主服务器发生的写操作同步到从服务器的过程。
增量复制的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令 - 同步策略:主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。当然,如果有需要,slave 在任何时候都可以发起全量同步。redis 策略是,无论如何,首先会尝试进行增量同步,如不成功,要求从机进行全量同步。
- 详细介绍
11.Redis的哨兵模式
redis哨兵
- 什么是哨兵,哨兵一般就是在redis服务器上增加一个配置sentinel.conf的文件,然后配置上需要监控的redis服务器即可
- 主从结构只能保证数据有备份,但是如果主挂掉了,怎么办,整个服务就不可用了(因为从服务器默认是只读不写的)
- 解决方案就是哨兵模式:他可以作为一个第三方,监控着我们主节点的状态,当发现主挂掉后,就会从这个挂掉的主的从服务器中进行选举,推选出一个新主,同时其他slave也切换成这个新主的slave,如果原来的主重启成功了也不会再次成为主了,而是作为slave挂到新主上
- 因为哨兵模式需要选举数量过半,所以一个slave肯定是不够的,所以最少是两个
- 哨兵模式判断master挂掉的依据
- sdown是主观宕机,就一个哨兵如果自己觉得一个master宕机了,那么就是主观宕机
- odown是客观宕机,如果quorum(法定人数)数量的哨兵都觉得一个master宕机了,那么就是客观宕机
11.slave->master选举算法
如果一个master被odown了,而且majority的哨兵都允许了准备切换,那么某个哨兵就会执行准备切换的操作,此时要选举一个slave成为master,则会考虑slave的一下几种条件
- salve跟master断开连接的时长(如果一个slave跟一个master断开连接的时间太长,【已经超过了一个down-after-millieconds的10倍】那么这个slave就被认为不适合选举为master)
- 按照slave的优先级进行排序,slave的pripority越低,优先级就越高(这个是在配置文件中配置的默认都是100)
- 如果优先级slave priority相同,那么看replica offset(复制位移),那个slave复制了越多的数据,offset越靠后,优先级就越高
- 如果上面条件都相同,那么选择一个run id比较小的那个salve
- 最后应该还有一个eacoph这个条件,具体是什么自行百度吧
12.redis的主从复制与哨兵模式的作用:
- redis通过主从复制来实现高可用,但是发生故障时需要人工进行主从切换,效率低下。
- 哨兵机制实现了redis主从的自动切换,提高了redis集群的可用性,提高了redis集群的故障转移效率。
13.redis数据丢失问题
- redis的主从复制可能会丢失数据,因为假如当客户端往master写了2000条数据时,slave在异步复制数据时只复制了1500条数据时,master宕机了,那么就会有500条的数据丢失。
- redis出现脑裂(出现了两个大脑)时可能会丢失数据,脑裂产生的原因是因为网络分区,当master因为网络问题与slave断开了连接,这是slave以为master宕机了,哨兵模式会从新对slave进行选举,后面网络恢复了之后就会出现两个master,这个时候之前master上的数据就不会往slave同步,导致数据丢失
- 解决办法:可以通过两个参数来减少数据丢失的量,但并不能100%保证一点也不丢失
- 通过配置redis的 min-slaves-to-write 和min-slaves-max-log 两个参数来降低数据丢失的量
- 上面两个参数是指:当slave复制master的数据成功时会响应一个ack给master,当响应master的时间太长时,可能就认为master故障或者宕机了,这时就直接拒绝客户端的事物请求
14.问题:如果把redis-slave默认是只读不写的,如果配置成可读可写的,那么是不是就不需要再配置哨兵模式检测master挂了自动把salve选举成master了?
猜想把salve配成可读可写模式能否代替哨兵模式:
- 假如说你的redis只是一主一从,这样把slave配置成可读可写,那么即使master挂了之后也不会影响redis架构,从这层理解是没问题的。
- 但是如果你的redis配置的是一主多从,这样即使你把所有的salve都配置成可读可写的,那么当master挂了,在往一个salve写数据的时候,其他salve不会数据备份了
15.缓存穿透、缓存雪崩
- 缓存穿透:指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据,导致数据库压力过大甚至崩溃
- 解决方案:
- 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
- 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击
- 缓存雪崩:指缓存中数据大批量到过期时间(或者是redis宕机),而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库
- 解决方案:
- 设置热点数据(经常查询的数据)永远不过期。
- 缓存数据的过期时间设置不同,防止同一时间大量数据过期现象发生
- 如果缓存数据库是分布式部署,将热点数据均匀分布在不同的缓存数据库中