Redis的学习
磁盘基础知识
1.寻址:m/s
2.带宽:G/M
内存
1.寻址:ns
2.带宽:很大
秒>毫秒>微秒>纳秒
内存寻址比硬盘寻址快10万倍
IO buffer
成本问题,
磁盘有磁道和扇区,一扇区512byte,带来成本变大:索引
4K对齐,操作系统无论读多少都是最少4k从磁盘拿
随着文件变大,速度变慢,IO成为瓶颈
数据库
data page 4k
关系型数据库建表:必须给出schema
类型:建表宽度
存:倾向于行级存储
内存维护一个b+树
磁盘:存储数据和索引
表很大的时候,性能下降?
如果有索引,增删改变慢
查询速度
1.如果一个或少量查询,性能依然快,因为where条件走的依然是一个data page
2.当并发量来了,可能不是加载一个data page到内存,受硬盘带宽影响,有可能性能下降(IOPS)
redis默认共有16个库,它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets)
缓存和数据库
1.管道技术
一个请求/相应服务可以实现为,即使客户端没有读取到旧请求的响应,服务端依旧可以处理新请求。通过这种方式,可以完全无需等待服务端应答地发送多条指令给服务端,并最终一次性读取所有应答。管道技术最显著的优势是提高了redis服务的性能。
2.Pub/Sub
订阅,取消订阅和发布实现了发布/订阅消息范式(引自wikipedia),发送者(发布者)不是计划发送消息给特定的接收者(订阅者)。而是发布的消息分到不同的频道,不需要知道什么样的订阅者订阅。订阅者对一个或多个频道感兴趣,只需接收感兴趣的消息,不需要知道什么样的发布者发布的。这种发布者和订阅者的解耦合可以带来更大的扩展性和更加动态的网络拓扑
Redis key过期策略:
1.惰性删除:当读/写一个已经过期的key时,会触发惰性删除策略,直接删除掉这个过期key(无法保证冷数据被及时删掉)
2.定期删除:Redis会定期主动淘汰一批已过期的key(随机抽取一批key检查)
3.内存淘汰机制:当前已用内存超过maxmemory限定时,触发主动清理策略
Redis 有两种持久化的数据的方案 RDB(快照/副本)和AOF(日志)
1.RDB的优点是:恢复的速度相对快 缺点是:不支持拉链只有一个dump.rdb,丢失数据相对多一些时点与时点之间窗口数据容易丢失
2.AOF的优点:数据的完整性和一致性更高,缺点:体积无线变大,恢复速度慢,4.0以前是重写:删除抵消的命令
合并重复的命令最终也是一个纯指令的日志文件,4.0以后是重写:将老的数据RDB到aof文件中将增量的以指令的方式Append到AOF,AOF是一个混合体
利用了RDB的快利用了日志的全量
Redis事务
1.Redis 提供的不是严格的事务,Redis 只保证串行执行命令,并且能保证全部执行,但是执行命令失败时并不会回滚,而是会继续执行下去
Redis的高可用
Redis 支持主从同步,提供 Cluster 集群部署模式,通过 Sentine l哨兵来监控 Redis 主服务器的状态。当主挂掉时,在从节点中根据一定策略选出新主,并调整其他从 slaveof 到新主。
在 Redis 集群中,sentinel 也会进行多实例部署,sentinel 之间通过 Raft 协议来保证自身的高可用。
Redis Cluster 使用分片机制,在内部分为 16384 个 slot 插槽,分布在所有 master 节点上,每个 master 节点负责一部分 slot。数据操作时按 key 做 CRC16 来计算在哪个 slot,由哪个 master 进行处理。数据的冗余是通过 slave 节点来保障。
Redis 哨兵
哨兵的功能有:
1.集群监控:负责监控 Redis master 和 slave 进程是否正常工作。
2.消息通知:如果某个 Redis 实例有故障,那么哨兵负责发送消息作为报警通知给管理员。
3.故障转移:如果 master node 挂掉了,会自动转移到 slave node 上。
4.配置中心:如果故障转移发生了,通知 client 客户端新的 master 地址。
缓存击穿
在高并发的情况下,大量访问这个key,刚好这个key失效了,造成并发访问数据库
解决这个问题的方法如下:
1.针对多个热点 key 同时失效的问题,可以在缓存时使用固定时间加上一个小的随机数,避免大量热点 key 同一时刻失效
缓存雪崩
由于原有缓存失效,新缓存未到期间所有原本应该访问缓存的请求都
去查询数据库了,而对数据库 CPU 和内存造成巨大压力,严重的会造成数据库宕机。从而形成一系列连锁反应,造成整个系统崩溃
解决这个问题的方法如下:
1.一般并发量不是特别多的时候,使用最多的解决方案是加锁排队。
2.给每一个缓存数据增加相应的缓存标记,记录缓存的是否失效,如果缓存标记失效,则更新数据缓存。
3.为 key 设置不同的缓存失效时间。
缓存穿透
缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空(相当于进行了两次无用的查询)。这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中率问题
解决这个问题的方法如下:
1.采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定不存在的数据会被这个 bitmap 拦截掉,从而避免了对底层存储系统的查询压力
Redis分布式锁
1.setnx
2.设置过期时间
3.多线程或者守护线程延长过期时间