栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

分布式缓存

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

分布式缓存

1. 前奏

缓存如何使用,缓存使用不当 会造成什么后果?

        用缓存的好处:高性能(多用户多次查库,相同内容,查库会耗时,缓存节省时间),高并发(不撞库,并发量就上来了)

        可能遇到的问题::1. 缓存与数据库双写不一致  2. 缓存雪崩  3.  缓存穿透 4. 缓存的并发竞争

2. redis 的线程模型(redis 是 单线程 NIO 异步模型)

        redis 和 memcache 的区别?

        redis 为什么是单线程的还能支持高并发?(非阻塞的IO多路复用)

        为什么单线程的redis 的效率 比 多线程的memcache 高的多?

2.1 redis 和memcache的区别

        1. redis的数据结构 比 memcache 较多

2.2 redis的线程模型

        redis 基于 reactor 模式开发的网络事件处理器,这个处理器叫做 文件事件处理器,file event handler。这个文件事件处理器是单线程的,redis 才叫做 单线程模型,采用 IO 多路复用机制同时监听多个socket, 根据socket 上的事件来选择对应的事件处理器来处理这个事件。

        如果被监听的socket准备好执行 accept、read、write、close 等操作的时候,跟操作对应的事件就会产生,这时文件事件处理器就会调用之前关联好的事件处理器来处理这个事件。

        文件事件处理器是单线程模式运行,但是通过IO 多路复用机制监听多个socket,可以实现高性能的网络通信模型,又可以和内部其他单线程进行对接,保证了redis 内部的线程模型的简单性。

        多个socket 可能会并发产生不同的操作,每个操作对应不同的文件事件,但是IO 多路复用程序会监听多个socket,会将多个socket 放入到一个队列中进行排队,每次从队列中取出一个socket 交给事件分派器,事件分派器将socket 分给相应的 事件处理器。

 3. 哪些数据类型,哪些场景下用哪种类型合适?

        String、hash(Map) 、list、set、sortSet

        String:

                最基本的类型,简单的KV 操作

        hash:
                类似于Map, 可以将 对象(没有嵌套其他对象的) 放在 redis 里,每次读写的时候就可以操作其中的某个字段了。

        list:

                有序列表,例如,可以通过list 存储一些列表型的数据结构,类似粉丝列表,文章的评论列表之类的,,,,例如  可以通过 lrange命令,从某个元素开始读取多少个元素,可以基于list 实现分页查询,通过redis实现简单的高性能分页,可以做  像微博那种,通过下拉来不断更新的操作,性能高,就一页一页的走。

                还能搞个简单的消息队列,就用list 实现了。

        set:

                无序列表,自动去重,直接基于set 将需要去重的数据直接仍在 set 集合中,就自动去重了。。。。。。。。可以基于set 玩 交集 并集 差集,,,例如,交集,可以把两个人的好友列表进行交集,看两个人的共同好友都有谁。

        sortSet:

                有序的set, 可以去重,也能排序。。写进去的时候给一个分数,可以根据这个分数进行排序,这种就有很多种用法了。。最大 的特点是 分数可以自定义排序规则。。。例如想利用时间进行排序的时候,可以把时间做为 分数。。。

                排行榜: 将每个用户及对应的分数写进去         进行排序,接着可以获取前 100 名,还能查看具体某个用户 在 排行榜上的排名。。

4. 过期策略

        既然是缓存,数据随时会丢

        可以给 每个 key 设置过期时间(比如设置了过期时间是 1小时,那一小时以后 redis是如何删除 这个 数据的??) 有两个策略: 定时删除 和 惰性删除。。。

        定期删除: 比如  每隔  100ms , redis 会随机抽取一些设置了 过期时间的key, 检查其是否过期,如果过期了,则删除。。注意,不是每隔 100ms 就把所有设置了过期时间的key 都拿出来检测,那样就会造成性能崩溃。。。。。。问题是:定期删除可能会导致很多的key 到期了 并 没有被删掉,这可咋整呢???于是就

        惰性删除了: 即,在你获取某个key的时候,redis 就会顺便检测一下这个key 是否设置了过期时间了,是否过期了,如果过期了,顺手就删除了,不会返回任何东西。。。

        通过以上两种策略的配合,过期是key 就一定会被删除。

        但是还是会有问题: 如果定期删除的key , 还是会漏掉一部分已经过期的key。  然后也没有去查,也没有走惰性删除,这个key 还是会一直留在内存中,导致redis 内存耗尽。。。那可怎么办呢?还有大量的没有设置过期时间的key  ,快把redis 撑坏了 ??? 答案是: 走  内存淘汰机制。。

        内存淘汰机制(如果内存被吃的太慢了,还是要内存淘汰机制,有如下几个策略:)

                1. 内存满了,新写入的操作直接报错,一般没人这么用,太恶心了。。

                2. LRU, 移除最近最少使用的key (最常用的)

                3. 随机移除key

                4. 在设置了过期时间的key 中 移除 最近最少使用的kay

                5. 在 设置了 过期时间的key 中,有更早过期时间的key 优先删除

        手写一个LRU???

5. 高并发、高可用        5.1 redis的高并发和整体系统高并发的关系

        要搞高并发,不可避免的要吧底层的缓存搞的很好。

        如果用mysql的话,如果做到高并发,也是通过一系列复杂的分库分表,比如订单系统,对事务要求比较高的场景,QPS 达到几万已经算是高的了。

        如果要 做 比如 商品详情页,真正的超高并发,QPS 上十万甚至百万的。

        光有redis 是不够的,但是redis 是整个大型缓存架构中,支撑高并发的架构里非常重要的一个环节。。。首先,底层的缓存中间件,缓存系统,必须能够支撑的起 高并发,其次,再经过良好的整体的 缓存架构设计(多级缓存架构,热点缓存)

        redis 无法承载 高并发的瓶颈在哪里?????

                单机, 单机redis 能承载的QPS 大概在几万不等,这个和业务操作有关,redis 提供了很多复杂的操作,比如lua脚本。。。

        redis 如何能够支撑10万+的并发??

                答: 单机的QPS 几乎不太可能超过10万+,除非特殊情况,机器性能特别好,配置特别高,运维做的也特别好,而且整体操作也并不是太复杂。。

                一般通过 读写分离,一般缓存都是用来支撑高并发的,写请求比较少,读请求比较多,可能写请求也就一秒一两千,几千,读请求可以的达到每秒 20万之多(写在 master上,读在slave 上,而且,随着业务的增加,salve 可以做到水平扩展) 读多写少用缓存,读少写多用异步

5.2 redis的replication 基础

        master写成功了就直接返回 client 成功的消息,然后再异步的吧数据写到 slave node上

        replication 的核心机制:

                1. 采用异步的方式将数据复制到 slave 节点上,从 2.8 开始 salve 会周期性的确认自己复制的数量

                2. 一个master node 可以配置多个salve

                3. salve node 也可以连接其他的 salve node

                4. slave node 在复制的时候不会 block master的工作

                5, salave在复制的时候也不会block 自己的工作,他会用旧数据进行服务,但是当复制完成时,会删除旧数据,记载新的数据集,此时会暂停对外服务?

                6. slave 可以用来水平扩容,做读写分离,扩容的slave 可以增加读的吞吐量。

        master持久化对于主从架构的安全保障和意义??

                如果采用了主从架构,要开启master的持久化功能,不建议用slave node 作为 master node 的数据热备,因为那样的话,如果你关掉master 的持久化,可能在master重启的时候 ,master会认为 数据是空的,然后经过一复制到slave的操作,slave node 的数据也丢了(100% 的数据丢失)。。master 节点必须要做持久化,不然重启没数据,salve也会被同步成没数据的状态,系统就废了!!!!另外一点,,master的各种备份方案,要不要做,怎么做,万一本地的文件丢失了呢?从备份中 挑选一份rdb 去恢复,这样才能保证master启动的时候是有数据的,

即使采用了后续讲解的高可用机制,slave 可以自动接管master,但是也可能 sentinal 没有检测到 master node 失败,master 就自动重启了,还是可能导致slave node 数据清空故障

 5.3 redis replication 细节

         1. 主从架构的核心原理

                当启动一个slave的时候,它会发送一个 PSYNC 的命令给 master node,

                如果这是 salve 重新连接 master,那么 master 会仅仅复制部分缺失的数据给 slave; 否则,如果是第一次连接,那么会触发一次full resynchronization, 开始 full resynchronization 的时候,master会启动一个后台线程,开始生成一份 RDB 快照文件,同时还会将从客户端收到的所有写命令缓存在内存中,RDB文件生成完毕,master会将这个RDB 发送给 slave,slave先接收到磁盘,然后再从磁盘加载到内存,,,而后,master会将内存中的缓存的写命令发送给slave,slave也会同步这些数据。。。。。slave如果跟master 有网络故障,断开连接,会自动重连,master如果发现多个slave node都在重连,仅仅会启动一个 RDB save,用一份数据服务所有的slave。

        2. 主从复制的断点续传

                传输过程中网络断了,再连上可以从原来断开的地方接着传,

                master会在内存中保存一个 backlog,master 和slave 都会保存一个 replication offset,和对应的node id,如果没有找到 offset,就会执行一个全复制。

        3. 无磁盘化复制

                master 会直接在内存中创建 RDB,然后发送给slave,不会在本地落地磁盘,(cinfog文件设置变量)

        4. 过期key处理

                slave 不会处理过期key,只会等待master过期key ,如果master 过期一个key ,或者通过LRU淘汰一个key,那么会模拟一条del操作发送给 slave。

5.4 replication 再细 5.5 redis高可用

        redis  failover(主从切换)

        哨兵 + redis 集群

        数据丢失问题:

                1. master 是异步写数据,在master 挂掉时,还有数据没同步

                2. 脑裂,网络问题,导致的 master 和其他 slave 连接不上,但是和 client 可以连上,,但是client 端还没有将 host 切换至新的master上,而持续将数据写到旧的master,当旧master恢复时,会作为 slave 挂到新的master下,所有数据丢失。

        解决数据丢失:

                设置两个参数: min-slave  1(master下最少的slave数量)      和    min-   10  (最长延时时间)

                1. 异步问题,slave 同master数据同步的延时时间超过10秒 就拒绝一切写请求,即便master 宕机,也损失 10秒的数据,可控

                2. 脑裂问题: 同 1,必须有至少一个slave 供 同步,超过10秒 拒绝写请求

                拒绝了怎么办??

                        上游的client 请求降级,将请求写入本地磁盘,或者  将请求灌入 kafka,每隔10秒将数据取出来,尝试重新写入master。

5.6 如何保证redis 挂掉之后数据的恢复

 5.6 redis cluster 集群模式的原理

        不同的数据分发到不同的 redis master上。

        redis 如何保证 高并发,高可用,读写分离,还能 横向扩展。 在生产环境上,如果用 cluster,那么,读写都是在master 上,(不是 写在master 读在 slave 上了)。

        单 redis master 容量的瓶颈问题:

         横向扩容:支撑海量数据

         redis 的 集群架构 (redis cluster)(多master+读写分类+高可用)

        支持 多个 master node,每个master 下 挂多个 slave,可以读写分离,

        我们只要基于 redis cluster 去搭建 redis 集群即可,不需要再手动去搭建   replciation复制 + 主从架构 + 哨兵集群 + 高可用。。。

        什么时候用 用 单机+replication ? 什么时候用 redis cluster??

         用 redis cluster 的数据分布算法。。(从 hash 算法 -> 一致性hash 算法 -> redis 自己的 hash slot 算法)决定了 数据是如何分布到 不同的master节点上的。。

        

最老土的hash,只要有个master 宕机,所有的消息都错位了!
一致性hash,瓶颈:缓存热点问题

        缓存热点问题是 一致性hash算法的瓶颈(即 数据 负载均衡的问题)于是引出了    虚拟节点的 概念

一致性hash 算法的虚拟节点 解决 数据 负载均衡的问题

 

 

        

                

        

        

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/349598.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号