常识
磁盘
寻址 ms
带宽 G/M
i/obuffer
扇区 512byte
页 4k(最少)
内存
寻址 ns 快磁盘10w倍
带宽
数据库
b+树 非叶子节点都在内存(疑问?????非叶子加载到内存过程),其他都在磁盘,期间需要反复获取磁盘内容
将数据库中的数据分拆到每个page 左边 (行数据)
索引 右边(列数据)
表很大数据下降,查询速度?
1个或少量 速度不会变化
并发大会受磁盘带宽速度影响
redis
单线程单实例
内存存储系统,
用作数据库,缓存,消息中间件,还可以防止恶意攻击,服务端用户状态存储
支持数据结构:
字符串、散列Hash、列表list、集合set、有序集合zset、范围查询、bitmaps、hyperloglogs和地理空间、索引半径、
Redis Module:像BloomFilter,RedisSearch,Redis-ML
string 数据结构
字符数组
list
双向链表
hash 字典
数组加链表
渐进式rehash
value 具备5中数据类型
扩容条件
set
特殊字典 value 为null
zset
跳跃表
唯一 有序
随机化数据结构
跳表具有如下性质:
(1) 由很多层结构组成
(2) 每一层都是一个有序的链表
(3) 最底层(Level 1)的链表包含所有元素
(4) 如果一个元素出现在 Level i 的链表中,则它在 Level i 之下的链表也都会出现。
(5) 每个节点包含两个指针,一个指向同一链表中的下一个元素,一个指向下面一层的元素
bloom filter 布隆过滤器
当一个元素被加入集合时,通过K个散列函数将这个元素映射成一个位数组中的K个点,把它们置为1。检索时,我们只要看看这些点是不是都是1就(大约)知道集合中有没有它了
- 字符串: set get sppend setrange getrange strlen
set k1 2 nx
set k1 3 xx
nx 只能新建
xx 只能更新
mset k1 2 k3 3
mget k1 k2
getrange k1 1 2 获得索引1-2的值
gerrange k1 1 -1
- 数据 :incr decr incrbyfloat
- bitmap: setbit bitcount bitpos bitop
命令
type key 返回value数据类型
object encoding k2 判断编码类型
keys 阻塞式查找key
scan 非阻塞式 增量式迭代命令
key 是个对象 包含
type ?规避异常
encoding ?
二进制安全?
内置
复制、lua脚本、lru驱动事件、事务、不同级别磁盘持久化
高可用
哨兵、自动分区
计算向数据移动??
重要!内核epoll 系统调用 ?
linux 没有aio
同步多路复用
jvm线程成本1mb
持久化
rdb
指定时间间隔将内存数据 快照 写入磁盘,fork子进程,先将数据写入临时文件,写入成功后替换之前的文件,二进制压缩
优点
- 只包含一个dump.rdb
- 容灾好
- 性能最大化,子进程完成,主进程继续执行,io最大化
- 数据大时比aof启动效率好
缺点
- 数据安全低,时间间隔内无法保证
aof
以日志的形式记录服务器所处理的每一个写、删除操作。以文本记录。
优点
1.数据安全,提供三种同步策略
- 每秒同步
- 修改同步
- 不同步
- 通过append模式写文件,通过redis-check-aof工具解决一直性问题
- rewrite模式,定期对aof文件重写,压缩。
缺点
1.aof文件比rdb大,恢复慢
2. 数据集大启动效率低
3. 运行没有rdb高
键的过期时间删除策略
-
惰性过期
- 访问key时才会判断过期,节省cpu,对内存不好
-
定期过期
- 每隔一段时间,扫描一定数量,可以达到平衡目的
-
定时过期(redis没有)
- 每隔key设置定时器
线程模型
基于Reactor模式(响应)开发了网络时间处理器,叫文件事件处理器,单线程的。采用io多路复用同时监听多个socket。
文件事件处理器结构
- 多个socket
- io多路复用程序??
- 文件事件分派器
- 事件处理器(命令请求处理器、命令回复处理器、连接应答处理器)
单线程 多线程业务场景不同
多线程在多个业务并发执行时效率高
单线程针对业务简单效率高
缓存雪崩、穿透、击穿
首先要明白 redis处理能力是mysql处理能力的10倍以上 以此为基点
雪崩
- 缓存大面积失效,导致请求都到数据库
- redis重启
方案
- 过期时间随机
- 给每一个缓存数据增加相应的标记
- 缓存预热
- 互斥锁
穿透
缓存、数据库都没有
缓存和数据口都没有数据,导致所有请求都到数据库上
方案
- 接口增加校验如用户鉴权,id基础校验
- 从缓存取不到的数据,数据库也没有找到,将key-value写为key-null
- 设置布隆过滤器,将可能存在的数据哈希到一个足够大的bitmap中,一定不存在的会被bitmap拦截
击穿
缓存没有、数据口有
解决方案
设置热点数据永不过期
加互斥锁
redis 事务实现?
内存缓存淘汰机制分为三种
FIFO(First In,First Out)先进先出
优点:是先进先出的数据缓存器,他与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单。
缺点:只能顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址
LFU(Least Freauently Used)
最不经常使用页置换算法,清理掉留给经常使用的使用
LRU(Least Recently Used)喜新厌旧
内存管理的一种页面置换算法,新加入的数据放到链表的头部,当缓存命中(被访问)数据移到链表的头部,当链表满的时候,将链表尾部的数据丢弃。
缓存预热
启动时就把热点数据加载好。这样,用户请求时,直接读取的就是缓存的数据,而无需去读取 DB 重建缓存数据。
面试题
如果有⼤量的key需要设置同⼀时间过期,⼀般需要注意什么?
如果⼤量的key过期时间设置的过于集中,到过期的那个时间点,redis可能会出现短暂的卡顿现象。严
重的话会出现缓存雪崩,我们⼀般需要在时间上加⼀个随机值,使得过期时间分散⼀些。
那你使⽤过Redis分布式锁么,它是什么回事?
redis为什么这么快
官网:redis 性能瓶颈不是cpu运行,是网络带宽和内存
- 基于内存
- io多路复用技术 默认epoll实现
为什么数据库慢
- 关系型 group join 聚合操作慢 redis没有集合操作只针对k v
集群
- 主从 多台多个实例 约束:配置相同(高可用)
- 分片 约束每一天不是完整的数据 聚合操作成本高
解决数据一致性问题
指令
excec 8<> /dev/tcp/www.baidu.com/80
8: channal
<> :输入输出流
exec :shell builtin
echo -e “GET /HTTP/1.0\n” http
cat 0<& 8
linux 一切皆文件
socket 可得到输入 输出流
8:fd
channal?
之前 socket 代表 一个输入 输出有
在jdk1.7之后 channal代表输入输出