视频、很大的文件可以转为二进制后,存在string的redis里面。但是注意最大为512M
1.单线程的前提
Redis的网络IO和键值对读写是由一个线程来完成的;
Redis的其他功能,如持久化、异步删除、集群数据同步等,则依赖其他线程来执行;
2.单线程的优劣
单线程可以简化数据结构和算法的实现,并且可以避免线程切换和竞争造成的消耗;
如果某个命令执行的时间过长,会造成其他命令的阻塞;
3.单线程的IO模型
IO多路复用:一个线程可以监听多个文件描述符(socket描述符)
传输媒体的带宽或容量往往会大于传输单一信号的需求,为了有效地利用通信线路,希望一个信道同时传输多路信号,这就是所谓的多路复用技术
将就绪的socket丢到套接字队列里,排队。文件事件分派器去根据socket的不同状态调用不同的事件处理器。
单线程指的是IO多路复用哪里是单线程的。后面还是多线程。
好处:同时有上万个连接接入,而同时激活态只有几百个进入队列,那么分派一个线程池几十个线程就能解决这个问题。
快照的持久化会耗时,还会造成阻塞,适合用来冷备份,例如一天备份一次。不适合用来做实时持久化。要想实时持久化就用AOF
在什么情况下RDB会阻塞?
bgsave命令出发RDB,调父进程来创建一个子进程,通过子进程持久化数据,父进程还要响应正常的命令。即持久化的时候有两个进程在做这个事情。
创建子进程fork函数时,父进程会被阻塞,但是速度很快,阻塞很短。
子进程创建之后,父进程解决阻塞,响应其他命令。子进程读父进程的内存数据,并将其存到RDB文件里。
一边持久化一边改,冲突?父子进程的同时读写是基于写时复制技术,不会产生阻塞
父进程将数据存在内存里,是多页的。子进程持久化时和父进程要修改的页是同一个时,父进程会将该页复制一个副本,再进行修改。
所谓快照就是在fork出子进程时,父进程内存的数据相当于照一张相,这些数据不会动了。
把命令写到缓冲区里,aof有一个同步机制,写道旧AOF文件里,可以用于重启服务时恢复数据。
AOF怎么重写的?
每次命令的追加,文件逐渐增大。到一定大小就要压缩。
通过bgrewriteaof命令重写(先判断是不是AOF重写或者RDB持久化),通知父进程fork一个子进程,子进程去产生新的压缩后的AOF文件。父进程解除阻塞后,继续往aof_buf写,同时记录rewrite_buf在子进程产生文件时追加的命令,最后同步到新AOF文件中。当子进程写好了,通知父进程,父进程再响应命令的时候就不会往rewrite_buf写入,但会把rewrite_buf同步到新AOF文件里,新的文件就会替换旧的文件。
rewrite_buf:记录在重写期间新的命令的,重写完成后将其命令刷到新AOF文件里
创建子进程fork函数时,父进程会被阻塞,但是速度很快,阻塞很短。
当写入数据发现超出maxmemory限制时,则采用指定的策略进行删除:
缓存与数据库的同步
在出现错误的情况下对比:
ps:第一个图的第一步为delete
读到旧数据比不同步好
在不出错的情况下对比:
对比以上发现:先更新数据库,再删缓存更合理
如果项目中放进缓存的数据没有写数据库更新的业务逻辑,那么缓存可以设置一定时间失效,再加载。
客户端查询根本不存在的数据,使得请求直达存储层,导致其负载过大,甚至宕机可能是业务层误将缓存和库中数据删除了,也可能是有人恶意攻击,专门访问库中不存在的数据。
解决方案:
1.缓存空对象:存储层未命中后,仍然将空值存入缓存层,客户端再次访问数据时,缓存层会直接返回空值;
2.布隆过滤器:将数据存入布隆过滤器,访问缓存之前以过滤器拦截,若请求的数据不存在则直接返回空值;
一份热点数据,它的访问量非常大。在其缓存失效的瞬间,大量请求直达存储层,导致服务崩溃。
解决方案:
1.永不过期
热点数据不设置过期时间,所以不会出现.上述问题,这是"物理"上的永不过期;
为每个数据设置逻辑过期时间,当发现该数据逻辑过期时,使用单独的线程重建缓存;
2.加互斥锁
对数据的访问加互斥锁,当一个线程访问该数据时,其他线程只能等待。这个线程访问过后,缓存中的数据将被重建,届时其他线程就可以直接从缓存中取值。
和缓存击穿不一样,缓存击穿是一个数据失效,而缓存雪崩是指整个缓存层redis挂了。
在某一时刻,缓存层无法继续提供服务,导致所有的请求直达存储层,造成数据库宕机。可能是缓存中有大量数据同时过期, 也可能是Redis节点发生故障,导致大量请求无法得到处理。
解决方案:
1.避免数据同时过期
设置过期时间时,附加一一个随机数,避免大量的key同时过期;
2.启用降级和熔断措施
在发生雪崩时,若应用访问的不是核心数据,则直接返回预定义信息/空值/错误信息;在发生雪崩时,
对于访问缓存接口的请求,客户端并不会把请求发给Redis,而是直接返回;
3.构建高可用的缓存服务
采用哨兵或集群模式,部署多个Redis实例,个别节点宕机,依然可以保持服务的整体可用。
生产者向截点发数据,把它存在CommitLog里面。每一个主题有一个ConsumerQueue。他的数据不是放在内存里的,是持久化的不会丢消息。
不是基于内存而是基于磁盘,因为磁盘随机读写性能很差,所以才有了上面的设计,(不管什么主题顺序写,每个队列拿到对应的主题,顺序读)
同步刷盘
只有在消息真正持久化至磁盘后RocketMQ的Broker端才会真正返回给Producer端一个 成功的ACK响应。同步刷盘对MQ消息可靠性来说是一种不错的保障,但是性能上会有较大影响,-般适用于金融业务应用该模式较多。
异步刷盘
能够充分利用OS的PageCache的优势,只要消息写入PageCache即可将成功的ACK返回给Producer端。消息刷盘采用后台异步线程提交的方式进行,降低了读写
延迟,提高了MQ的性能和吞吐量。