redis核心问题

redis线程,高并发下的缓存穿透、击穿、血崩、缓存淘汰策略、持久化机制,redis的分布式锁

01.说一下在你项目中的redis的应用场景

1,5大value类型 :根据我的redis课有场景的介绍

2,基本上就是缓存~!

3,为的是服务无状态,延申思考,看你的项目有哪些数据结构或对象,再单机里需要单机锁,在多机需要分布式锁,抽出来放入redis中;

4,无锁化

02.redis是单线程还是多线程

1, 无论什么版本,工作线程就是一个

2, 6.x高版本出现了IO多线程

3,使用上来说,没有变化


4, [去学一下系统IO课],你要真正的理解面向IO模型编程的时候,有内核的事,从内核把数据搬运到程序里这是第一步,然后,搬运回来的数据做的计算是第二步,netty

5,单线程,满足redis的串行原子,只不过IO多线程后,把输入/输出放到更多的线程里去并行,好处如下: 1,执行时间短,更快; 2,更好的压榨系统及硬件的资源(网卡能够高效的使用);

*,客户端被读取的顺序不能被保障
哪个顺序是可以被保障的: 在一个连接里,socket里

6.x以前

6.x以前

缓存不严谨,尽量去分片

6.x以后

 6.x以后

03.redis存在线程安全的问题么

重复2中的单线程串行

redis可以保障内部串行

外界使用的时候要保障,业务上要自行保障顺序~!

04.遇到过缓存穿透么

image-20210309132305485

05.遇到过缓存击穿么

image-20210309133256790

06.如何避免缓存雪崩

以上问题,核心就是避免DB无效/重复请求,结合图去理解

涉及一些架构思想上的提升

image-20210309133911287 image-20210309134226303 image-20210309134154406

07.缓存课后解答

  1. 如果查询的key缓存也没有DB也没有,访问的量又比较大会怎么样?

  2. 6.x多线程IO模式下,是怎么保证事务的?
    事务有queue的

08.redis是怎么删除过期key的(缓存时如何回收的)

1,后台在轮询,分段分批的删除那些过期的key

2,请求的时候判断是否已经过期了

尽量的把内存无用空间回收回来

09.缓存是如何淘汰的

0,内存空间不足的情况下:

1,淘汰机制里有不允许淘汰

2,lru/lfu/random/TTL

3,全空间

4,设置过期的key的

10.如何进行缓存预热

1,提前把数据塞入redis,(你知道那些是热数据么?肯定不知道,会造成上线很多数据没有缓存命中)

2,开发逻辑上也要规避差集(你没缓存的),会造成击穿,穿透,雪崩,实施4,5,6中的锁方案

3,一劳永逸,未来也不怕了

*结合4,5,

10.如何进行缓存预热

1,提前把数据塞入redis,(你知道那些是热数据么?肯定不知道,会造成上线很多数据没有缓存命中)

2,开发逻辑上也要规避差集(你没缓存的),会造成击穿,穿透,雪崩,实施4,5,6中的锁方案

3,一劳永逸,未来也不怕了

*结合4,5,

12.简述一下主从不一致的问题?

1,redis的确默认时弱一致性,异步的同步

2,锁不能用主从(单实例/分片集群/redlock)==>redisson

3,在配置中提供了必须有多少个client连接能同步,你可以配置同步因子,趋向于强一致性

4,wait 2 0 小心

5,34点就有点违背

13.描述一下持久化原理

当前线程阻塞服务

异步后台进程完成持久

fork + cow

14.描述一下redis持久化方式?

1,RDB,AOF;主从同步也算持久化

2,高版本;开启AOF,AOF时可以通过执行日志得到全部内存数据的方式,但是追求性能

2.1,体积变大,重复无效指令 重写,后台用线程把内存的kv生成指令写个新的aof

2.2,4.x 新

15.Redis也打不住了,万级流量回答到DB上,该怎么处理?

见456

16.redis中的事务三条指令是什么,第三条指令到达后执行失败了,怎么处理

image-20210308195931941

17.为什么使用setnx(redis实现分布式锁的指令)

1,好东西,原子 (不存在的情况下完成创建)

1,如果要做分布式锁,就要用set k v nx ex (不存在,过期时间,避免死锁)

redis时间复杂度

String类型

命令 时间复杂度
set 0(1)
get 0(1)
del 0(k),k是键的个数
mset 0(k),k是键的个数
mget 0(k),k是键的个数
incr 0(1)
decr 0(1)
incryby 0(1)
decryby 0(1)
incrybyfloat 0(1)
append 0(1)
strlen 0(1)
setrange 0(n),n为更改字符串长度
getrange 0(n),n为获取字符串长度

Hash类型

命令 时间复杂度
hset 0(1)
hget 0(1)
hdel 0(k),k是键的个数
hlen O(1)
hgetall 0(k),k是field的个数
hmget 0(k),k是field的个数
hmset 0(k),k是field的个数
hexists O(1)
hkeys 0(k),k是field的个数
hvals 0(k),k是field的个数
hsetnx O(1)
hincrby O(1)
hincrbyfloat O(1)
hstrlen O(1)

List列表

命令 时间复杂度
rpush 0(k),k是field的个数
lpush 0(k),k是field的个数
linsert 0(n),n是插入位置距离表头或表尾的距离
lrange O(s+n),s是start的偏移量,n是start到end的范围
lindex O(n),n是索引的偏移量
llen O(1)
lpop O(1)
rpop O(1)
lrem O(n),n是列表的长度
ltrim O(n),n是要裁剪的元素总数
lset O(n),n是索引的偏移量
blpop O(1)

Set集合

命令 时间复杂度
sadd O(k),k为元素个数
srem O(k),k为元素个数
scard O(1)
sismember O(1)
srandmember O(count)
spop O(1)
smembers O(n),n为元素总数
sinter O(m*k),k为多个集合中元素较少的个数,m是键个数
suinon O(k),k为多个集合元素个数和
sdiff O(k),k为多个集合元素个数和

Zset有序集合

命令 时间复杂度
zadd O(k*log(n)),k为添加 成员个数,n为当前成员个数
zcard O(1)
zscore O(1)
zrankzrevrank O(log(n)),n为当前成员个数
zrem O(k*log(n)),k为删除成员个数,n为当前成员个数
zincrby O(log(n)),n为当前成员个数
zrangezrevrange O(log(n)+k),k为要获取成员个数,n为当前成员个数
zrangebyscorezrevrangebyscore O(log(n)+k),k为要获取成员个数,n为当前成员个数
zcount O(log(n)+k),k为要获取成员个数,n为当前成员个数
zremrangebyrank O(log(n)+k),k为要删除成员个数,n为当前成员个数
zremrangebyscore O(log(n)+k),k为要删除成员个数,n为当前成员个数
zinterstore O(nk) + O(mlog(m)),n是成员数最小的有序集合的成员个数,k是有序集合的个数,m是结果集中成员个数
zunionstore O(n) + O(m*log(m)),n是所有有序集合成员个数和,m是结果集中成员个数