答案就是熟悉的redis
笔者的需求背景是这样的,公司有两个java服务,一个负责前台业务,也就是用户端的业务;一个负责后台业务,也就是管理端的业务。两个服务都只用到了mysql和redis,算是比较简单的业务服务。前台业务部署在两台服务器上,并且需要支持d性扩张;后台业务部署在一台服务器上。此时有一个刷新本地缓存的功能,需要在管理后台服务发起,两个用户前台服务执行。
第一版,采用了直接请求的方案。管理后台服务会直接调用前台服务的内网IP,通过>不存在任何直接的冲突,不过它们也不能完全兼容。Yncsrver主要是分布式服务器管理系统,它能够让用户通过多台服务器节点来提供服务。而rocketmg是一款用于服务器集群管理的工具,它能够帮助用户将多台服务器或集群分配到多个不同的应用中,并能够将任务调度、延迟任务、安全等功能统一管理。总而言之,它们可以共存且相互补充,但是要看具体的业务需求而定。
Apache RocketMQ作为阿里开源的一款高性能、高吞吐量的分布式消息中间件。
支持Broker和Consumer端消息过滤,支持发布订阅模型和点对点,支持拉pull和推push两种消息模式,单一队列百万消息、亿级消息堆积,支持单master节点,多master节点,多master多slave节点,任意一点都是高可用,水平拓展,Producer、Consumer、队列都可以分布式,消息失败重试机制、支持特定level的定时消息,新版本底层采用Netty,43x支持分布式事务,适合金融类业务,高可用性跟踪和审计功能。
Producer :消息生产者
Producer Group :消息生产者组,发送同类消息的一个消息生产组
Consumer :消费者
Consumer Group :消费同类消息的多个实例
Tag :标签,子主题(二级分类)对topic的进一步细化,用于区分同一个主题下的不同业务的消息
Topic :主题, 如订单类消息,queue是消息的物理管理单位,而topic是逻辑管理单位。一个topic下可以有多个queue,
默认自动创建是4个,手动创建是8个
Message :消息,每个message必须指定一个topic
Broker :MQ程序,接收生产的消息,提供给消费者消费的程序
Name Server :给生产和消费者提供路由信息,提供轻量级的服务发现、路由、元数据信息,可以多个部署,互相独立(比zookeeper更轻量)
Offset : 偏移量,可以理解为消息进度
commit log : 消息存储会写在Commit log文件里面
1、添加maven依赖
2、新建jms包,JMSConfig类,设置配置常量
3、新建生产者PayProducer
4、新建PayController
这个时候,启动应用,访问api/sync路径,会报没有这个topic异常
需要去管控台手工创建topic,或者将SpringBoot依赖的RocketMQ版本与服务端RocketMQ的版本改成一样的,也可以。例如我的pomxml文件中,依赖的版本是430,而服务器上部署的RocketMQ版本是440,就不会自动创建topic。
创建topic之后,再次访问访问api/sync路径,会报下面异常
在conf/brokerconf文件中添加如下配置
然后指定配置文件启动Broker,返回上一级,然后重启Broker
或者使用守护进程方式启动Broker
再次访问api/sync,返回成功
RocketMQ管控台也可查询此消息
新建PayConsumer
访问: >
说起零拷贝之前,先来了解下服务器中文件数据通过网络传输到客户端的流程。作为应用服务器,其中会有很多从磁盘中读取数据,然后应用程序对加载到内存中的数据进行处理,然后通过网卡发送给客户端,传统数据处理通过以下两个函数实现:
在这个过程中,数据流转的大致过程如下:
可以见到,在这个过程中发生了2次cpu copy和2次DMA copy,以及发生了数次cpu状态切换。 这个 *** 作对于应用服务器来说很频繁,因此带来的开销也是非常大。
因此所谓的零拷贝就是,让其中的2次cpu拷贝省略掉,因为这两次cpu拷贝的数据其实已经在内存中,没有必要再让cpu参与进来进行数据的拷贝,浪费cpu。在大量文件读写的时候,这个优化带来的收益还是比较可观的。
零拷贝的实现方式有两种:
mmap通过虚拟内存映射,让多个虚拟地址指向同一个物理内存地址,用户空间的虚拟地址和内核空间的虚拟地址指向同一个物理内存地址,这样用户空间和内核空间共享同一个内存数据。这样DMA引擎从磁盘上加载的数据不需要在内核空间和用户空间进行复制,减少了一次cpu拷贝。
sendfile通过系统调用,并且规定了in_fd文件描述符必须是可以mmap的,sendfile只能将文件数据发送到socket中,sendfile减少了一次cpu状态的切换
无论是mmap结合write方式还是sendfile方式都只是减少了一次cpu拷贝,而后DMA引擎还具有了收集功能,可以在内核缓存区发送到socket缓冲区的时候避免掉cpu复制,只是将缓冲区地址和数据长度发送给socket缓冲区,然后DMA引擎通过收集功能直接读取收集数据发送到网卡中。这里依赖DMA引擎的收集功能省略掉了最后一次cpu拷贝,到此才是真正的零拷贝。
所谓的零拷贝就是避免数据在内核空间缓存区和用户空间缓缓冲区之间的复制,避免掉2次cpu复制,释放cpu。
在RocketMq中采用的是mmap()结合write()方式来实现零拷贝。
在java中还可以通过FileChanneltransferTo()来实现数据从文件描述符传输到socket中,它的底层是通过sendfile系统调用来实现。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)