七、Redis & Kafka


Github地址

CSDN地址

七、Redis

参考这个

7.0 Redis介绍

 Redis(Remote Dictionary Server远程字典服务),是一款高性能的(key/value)分布式内存数据库,基于内存运行并支持持久化的NoSQL数据库。因为数据都在内存中,运行速度快。redis支持丰富的数据类型并且支持事务,事务中的所有命令会被序列化、按顺序执行,在执行的过程中不hi被其他客户端发送来的命令打断。

redis支持的数据类型及应用场景

redis支持五种常见的数据类型作为其value,redis的key都是字符串类型

类型说明应用场景
stringvalue最大可为512M做计数功能的缓存
list字符串列表,按照插入顺序排序,底层是一个链表,可实现一个简单的消息队列做redis分页功能
set字符串类型的无序集合全局去重
sorted set是一个字符串类型的有序集合,给每一个元素一个固定的分数score来保持顺序用来做排行榜或进行范围查找
hash键值对集合存放一些特定结构的信息

三种特殊的数据类型,BitMap、Geo和HyperLogLog

redis底层的数据结构包括:简单动态字符串,链表,字典,跳表,整数集合以及压缩列表。

redis相比memcached的优势
  • memcached所有值均是简单字符串,redis作为替代者,支持更为丰富的数据类型。
  • redis的速度比memcached快很多,并且redis支持数据的持久化
  • redis支持数据的备份,即master-slave模式的数据备份
  • 使用底层模型不同,它们之间底层实现方式以及客户端之间通信的应用协议不一样,redis构建了自己的VM管理机制
  • value大小不同,redis最大支持512MB,而memcached仅1MB
redis配置文件

配置文件redis.windows.conf,分模块配置,常用如下:

  • NETWORK:该模块可以配置一些redis服务器地址,端口以及超时时间等
  • GENERAL:该模块可以对日志文件的路径和日志级别等进行配置
  • SNAPSHOTTING:redis持久化配置信息等
  • REPLICATION:redis集群配置等信息
  • MEMORY MANAGEMENT:内存管理,包括数据过期删除策略信息的设置
  • APPEND ONLY MODE:日志持久化方式信息设置
redis单线程?

 redis是单线程的,redis的单线程是指网络请求模块使用了一个线程,所以不考虑并发安全性。但是对于依赖多个操作符合操作来说,还是需要锁,而且大部分情况是分布式锁。

  1. 单线程的redis为什么执行速度这么快?
    ①基于内存实现,完全内存计算
    ②单线程操作,避免了线程上下文切换操作
    多路I/O复用的线程模型,实现了一个线程监控多个IO流,及时响应请求
    ④redis对外部的依赖比较少,属于轻量级内存数据库

扩展1. 多路I/O复用的线程模型
 redis支持多路I/O复用的系统调用有select,pselect,poll。epoll等函数。I多路I/O复用的通过一种机制,一个进程可以监视多个描述符,一旦某个描述符读就绪或写就绪,其能通知应用程序进行相应的读写操作。
 多路IO复用机制与多进程和多线程技术相比系统开销小,系统不必创建进程/线程,也不必维护这些进程/线程从而大大减小了系统的开销。

redis常见函数

(1)select函数

  • 会修改传入的参数数组(不太好)
  • 最大监听数1024个
  • 如果任何一个socket(I/O stream)出现了数据,select没有返回具体是哪个返回了数据,需采用轮询方式遍历获取
  • 线程不安全(当你在一个线程中已经监听该socket,另一个线程想要将该socket关闭,则结果会不可预知)

(2)poll函数

  • 不修改传入参数数组
  • 无1024限制(链表实现)
  • 依旧线程不安全

(3)epoll函数

  • 不仅返回socket组里面数据,还可确定哪个socket有数据
  • 线程安全
缓存雪崩、缓存击穿、缓存穿透、数据库和缓存的双写一致性问题
  1. 缓存一致性
SUCCESSFAILEDQUESTION
更新数据库成功更新缓存失败数据不一致
更新缓存成功更新数据库失败数据不一致
更新数据库成功淘汰缓存失败数据不一致
淘汰缓存成功更新数据库失败查询缓存miss

解决办法:

详细介绍双写、失效

双删延时的解决办法: 先删除缓存数据,然后再更新数据库数据,最后再隔固定的时间再次删除缓存。

双写模式: 先写数据库,再写缓存

更新数据库产生的binlog订阅(使用canal): 将有变化的key记录下来,并且尝试去不断的去删除缓存(如果上次删除缓存失败)

  1. 缓存击穿问题

eg. redis中存储的是热点数据,当高并发请求访问redis热点数据的时候,如果redis中数据过期了,会造成缓存击穿,请求都打在了数据库上。

解决方法: 使用互斥锁,只让一个请求去load DB,成功之后重新写缓存,其余请求没有获取到互斥锁,可以尝试重新获取缓存中的数据。

  1. 缓存穿透问题

eg. 大量的请求的key在缓存中根本不存在,导致请求直接到了数据库上,大量请求导致数据库异常。

解决办法:

①最基本的做好参数校验,一些不合法的参数请求直接抛出异常返回给客户端

②缓存无效key

③使用有效的机制(比如布隆过滤器)来拦截不合法的key值等。

  1. 缓存的雪崩现象

eg. 缓存同一时间大面积失效,这个时候又来一波(或后面的)请求到数据库上,导致数据库短时间内承受大量请求而崩掉。

解决方法:

①事前:尽量保证真个redis集群的高可用性,发现机器宕机尽快补上。选择合适的内存淘汰策略

②事中:本地缓存 + hystrix限流&降级,避免MySQL崩掉

③利用redis持久化机制保存的数据尽快恢复缓存

redis的持久化方式

八、Kafka

7.0 Kafka 的设计是什么样的

Kafka 将消息以 topic 为单位进行归纳
将向 Kafka topic 发布消息的程序成为 producers.
将预订 topics 并消费消息的程序成为 consumer.
Kafka 以集群的方式运行,可以由一个或多个服务组成,每个服务叫做一个 broker.
producers 通过网络将消息发送到 Kafka 集群,集群向消费者提供消息

7.1 Kafka 如何保证高可用?

Kafka 的基本架构组成是:由多个 broker 组成一个集群,每个 broker 是一个节点;当创建一个 topic 时,这个 topic 会被划分为多个 partition ,每个 partition 可以存在
于不同的 broker 上,每个 partition 只存放一部分数据。这就是天然的分布式消息队列,就是说一个 topic 的数据,是分散放在多个机器上的,每个机器就放一部分数据。
写数据的时候,生产者只将数据写入 leader 节点, leader 会将数据写入本地磁盘,接着其他 follower 会主动从 leader 来拉取数据, follower 同步好数据了,就会发送 ack给 leader , leader 收到所有 follower 的 ack 之后,就会返回写成功的消息给生产者

消费数据的时候,消费者只会从 leader 节点去读取消息,但是只有当一个消息已经被所有follower 都同步成功返回 ack 的时候,这个消息才会被消费者读到。

7.2 kafka 为什么那么快?

Cache Filesystem Cache PageCache缓存
顺序写 :由于现代的操作系统提供了预读和写技术,磁盘的顺序写大多数情况下比随机写内存还要快。
Zero-copy :零拷技术减少拷贝次数
Batching of Messages :批量量处理。合并小的请求,然后以流的方式进行交互,直顶网络上限。
Pull 拉模式 :使用拉模式进行消息的获取消费,与消费端处理能力相符。

7.3 Kafka如何保证消息不丢失
  1. 消费者异常导致的消息丢失
    消费者可能导致数据丢失的情况是:消费者获取到了这条消息后,还未处理, Kafka 就自动提交了 offset ,这时 Kafka 就认为消费者已经处理完这条消息,其实消费者才刚准备处理这条消息,这时如果消费者宕机,那这条消息就丢失了。
    消费者引起消息丢失的主要原因就是消息还未处理完 Kafka 会自动提交了 offset ,那么只要关闭自动提交 offset ,消费者在处理完之后手动提交 offset ,就可以保证消息不会丢失。但是此时需要注意重复消费问题,比如消费者刚处理完,还没提交 offset ,这时自己宕机了,此时这条消息肯定会被重复消费一次,这就需要消费者根据实际情况保证幂等性。

  2. 生产者数据传输导致的消息丢失
    对于生产者数据传输导致的数据丢失主常见情况是生产者发送消息给 Kafka ,由于网络等原因导致消息丢失,对于这种情况也是通过在 producer 端设置 acks=all 来处理,这个参数是要求 leader 接收到消息后,需要等到所有的 follower 都同步到了消息之后,才认为本次写成功了。如果没满足这个条件,生产者会自动不断的重试。

  3. Kafka 导致的消息丢失
    Kafka 导致的数据丢失一个常见的场景就是 Kafka 某个 broker 宕机,而这个节点正好是某个 partition 的 leader 节点,这时需要重新重新选举该 partition 的 leader 。如果该 partition 的 leader 在宕机时刚好还有些数据没有同步到 follower ,此时 leader挂了,在选举某个 follower 成 leader 之后,就会丢失一部分数据。

7.4 Kafka 如何保证消息的顺序性
  1. 如何保证消息在 Kafka 中顺序性
    对于 Kafka ,如果我们创建了一个 topic ,默认有三个 partition 。生产者在写数据的时候,可以指定一个 key ,比如在订单 topic 中我们可以指定订单 id 作为 key ,那么相同订单 id 的数据,一定会被分发到同一个 partition 中去,而且这个 partition 中的数据一定是有顺序的。消费者从 partition 中取出来数据的时候,也一定是有顺序的。通过制定 key 的方式首先可以保证在 kafka 内部消息是有序的。
  2. 如何保证消费者处理消费的顺序性
    对于某个 topic 的一个 partition ,只能被同组内部的一个 consumer 消费,如果这个consumer 内部还是单线程处理,那么其实只要保证消息在 MQ 内部是有顺序的就可以保证消费也是有顺序的。但是单线程吞吐量太低,在处理大量 MQ 消息时,我们一般会开启多线程消费机制,预先设置 N 个内存 Queue ,具有相同 key 的数据都放到同一个内存 Queue 中;然后开启 N 个线程,每个线程分别消费一个内存 Queue 的数据即可,这样就能保证顺序
    性。
7.5 为什么Kafka不支持读写分离
  • 数据一致性问题。数据从主节点转到从节点必然会有一个延时的时间窗口,这个时间窗口会导致主从节点之间的数据不一致。某一时刻,在主节点和从节点中 A 数据的值都为 X, 之后将主节点中 A 的值修改为 Y,那么在这个变更通知到从节点之前,应用读取从节点中的 A 数据的值并不为最新的 Y,由此便产生了数据不一致的问题。
  • 延时问题。类似 Redis 这种组件,数据从写入主节点到同步至从节点中的过程需要经历 网络→主节点内存→网络→从节点内存 这几个阶段,整个过程会耗费一定的时间。而在Kafka 中,主从同步会比 Redis 更加耗时,它需要经历 网络→主节点内存→主节点磁盘→网络→从节点内存→从节点磁盘 这几个阶段。对延时敏感的应用而言,主写从读的功能并不太适用。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yexiaomola

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值