# redis-lean **Repository Path**: interview_44/redis-lean ## Basic Information - **Project Name**: redis-lean - **Description**: redis学习,复习 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-02-22 - **Last Updated**: 2023-02-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # redis-lean #### 介绍 为啥使用redis ![](./picture/1.png) #### 软件架构 ![](./picture/运行原理.png) 首先,redis 服务端进程初始化的时候,会将 server socket 的 AE_READABLE 事件与连接应答处理器关联。 客户端 socket01 向 redis 进程的 server socket 请求建立连接,此时 server socket 会产生一个 AE_READABLE 事件,IO 多路复用程序监听到 server socket 产生的事件后,将该 socket 压入队列中。文件事件分派器从队列中获取 socket,交给连接应答处理器。连接应答处理器会创建一个能与客户端通信的 socket01,并将该 socket01 的 AE_READABLE 事件与命令请求处理器关联。 假设此时客户端发送了一个 set key value 请求,此时 redis 中的 socket01 会产生 AE_READABLE 事件,IO 多路复用程序将 socket01 压入队列,此时事件分派器从队列中获取到 socket01 产生的 AE_READABLE 事件,由于前面 socket01 的 AE_READABLE 事件已经与命令请求处理器关联,因此事件分派器将事件交给命令请求处理器来处理。命令请求处理器读取 socket01 的 key value 并在自己内存中完成 key value 的设置。操作完成后,它会将 socket01 的 AE_WRITABLE 事件与命令回复处理器关联。 如果此时客户端准备好接收返回结果了,那么 redis 中的 socket01 会产生一个 AE_WRITABLE 事件,同样压入队列中,事件分派器找到相关联的命令回复处理器,由命令回复处理器对 socket01 输入本次操作的一个结果,比如 ok,之后解除 socket01 的 AE_WRITABLE 事件与命令回复处理器的关联。 为啥 redis 单线程模型也能效率这么高? 1、基于io多路复用监听器,监听客户端请求,事件监听模式。 2、文件分派器,纯内存操作。 核心是基于非阻塞的 IO 多路复用机制。 C 语言实现,一般来说,C 语言实现的程序“距离”操作系统更近,执行速度相对会更快。 单线程反而避免了多线程的频繁上下文切换问题,预防了多线程可能产生的竞争问题。 ### 数据类型 #### string: set college szu #### hash:对象set值 hset person name bingo hset person age 20 hset person id 1 hget person name #### list list 是有序列表,这个可以玩儿出很多花样。 比如可以通过 list 存储一些列表型的数据结构,类似粉丝列表、文章的评论列表之类的东西。 比如可以通过 lrange 命令,读取某个闭区间内的元素,可以基于 list 实现分页查询,这个是很棒的一个功能,基于 redis 实现简单的高性能分页,可以做类似微博那种下拉不断分页的东西,性能高,就一页一页走。 0开始位置,-1结束位置,结束位置为-1时,表示列表的最后一个位置,即查看所有。 lrange mylist 0 -1 比如可以搞个简单的消息队列,从 list 头怼进去,从 list 尾巴那里弄出来。 lpush mylist 1 lpush mylist 2 lpush mylist 3 4 5 rpop mylist #### set set 是无序集合,自动去重。 直接基于 set 将系统里需要去重的数据扔进去,自动就给去重了,如果你需要对一些数据进行快速的全局去重,你当然也可以基于 jvm 内存里的 HashSet 进行去重,但是如果你的某个系统部署在多台机器上呢?得基于 redis 进行全局的 set 去重。 可以基于 set 玩儿交集、并集、差集的操作,比如交集吧,可以把两个人的粉丝列表整一个交集,看看俩人的共同好友是谁?对吧。 把两个大 V 的粉丝都放在两个 set 中,对两个 set 做交集。 sadd mySet 1 #### sorted set sorted set 是排序的 set,去重但可以排序,写进去的时候给一个分数,自动根据分数排序。 zadd board 85 zhangsan ### redis过期策略 定期删除 + 惰性删除 #### 定期删除 定期删除,指的是 redis 默认是每隔 100ms 就随机抽取一些设置了过期时间的 key,检查其是否过期,如果过期就删除。 #### 惰性删除 在你获取某个 key 的时候,redis 会检查一下 ,这个 key 如果设置了过期时间那么是否过期了?如果过期了此时就会删除,不会给你返回任何东西。 但是实际上这还是有问题的,如果定期删除漏掉了很多过期 key,然后你也没及时去查,也就没走惰性删除,此时会怎么样?如果大量过期 key 堆积在内存里,导致 redis 内存块耗尽了,咋整? 答案是:走内存淘汰机制。 #### 内存淘汰机制 allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(这个是最常用的)。 ### redis replication ![](./picture/高可用.png) ### redis cluster ![](./picture/5-cluster.drawio.png) ### redis 持久化机制 ![](./picture/4、redis存储机制.drawio.png) redis支持两种备份同时开启。 #### AOF:以写日志模式,写到os cache,在写到AOF文件。 rewrite操作一条一条数据写入,恢复的时候等于做内存回放,比较慢。 #### rdb:定时把redis的数据写为一个rbd文件。 定期,全量生成一个文件。恢复的时候,直接加入内存中即可,比较快。特别适合做冷备。 不适合做第一备份方案,应为rdb会丢失数据比较多。 ### 缓存,雪崩 ![](./picture/6-雪崩、穿透.drawio.png) ### 并发竞争 ![](./picture/7-并发竞争.drawio.png)