【RocketMQ】NameServer总结

NameServer是一个注册中心,提供服务注册和服务发现的功能。NameServer可以集群部署,集群中每个节点都是对等的关系(没有像ZooKeeper那样在集群中选举出一个Master节点),节点之间互不通信。
服务注册
Broker启动的时候会向所有的NameServer节点进行注册,注意这里是向集群中所有的NameServer节点注册,而不是只向其中的某些节点注册,因为NameServer每个节点都是对等的,所以Broker需要向每一个节点进行注册,这样每一个节点都会有一份Broker的注册信息。

服务发现
Broker向NameServer注册以后,生产者Producer和消费者Consumer就可以从NameServer中获取所有注册的Broker信息,并从中选取Broker进行消息的发送和消费。

以生产者为例,在NameServer集群部署模式下,生产者会从多个NameServer中随机选取一个进行通信,从中拉取所有Broker的注册信息,并将拉取到的信息进行缓存,生产者知道了Broker的信息后,就可以得知Topic的分布情况,然后选取一个消息队列,与其所在的Broker通信进行消息的发送。如果通信的Nameservre宕机,消费者会轮询选择下一个NameServer。

为什么需要NameServer?

在使用RocketMQ的时候,为了提升性能以及应对高并发的情况,一般都会使用多个Broker进行集群部署,假设没有注册中心,对于Broker来说,如果想获取到集群中所有的Broker信息(生产者和消费者需要通过某个Broker获取整个集群的信息,从而得到Topic的分布情况),每个Broker都需要与其他Broker通信来交换信息,以此来得到集群内所有Broker的信息,在Broker数量比较大的情况下,会造成非常大的通信压力。

为什么不使用zookeeper这样的分布式协调组件?
首先zookeeper的实现复杂,引入zookeeper会增加系统的复杂度,并且zookeeper在CAP中选择了CP,也就是一致性和分区容错性,从而牺牲了可用性,为了保持数据的一致性会在一段时间内会不可用。

而NameServer在实现上简单,RocketMQ的设计者也许认为对于一个消息队列的注册中心来说,一致性与可用性相比,可用性更重要一些,至于一致性可以通过其他方式来解决。

假如选择了CP的ZooKeeper,先不考虑其他原因,在ZooKeeper不可用的时候,如果有消费者或生产者刚好需要从NameServer拉取信息,由于服务不可用,导致生产者和消费者无法进行消息的生产和发送,在高并发或者数据量比较大的情况下,大量的消息无法发送/无法消费影响是极大的,而如果选择AP,即便数据暂时处于不一致的状态,在心跳机制的作用下也可以保证数据的最终一致性,所以RocketMQ选择了自己实现注册中心,简单并且轻量

举个例子,假如集群中有三个Broker(分别为 A、B、C),向三台NameServer进行了注册(也分别为A、B、C),消费者从NameServer中获取到了三个Broker的信息,如果此时BrokerA需要停止服务,分别通知三台NameServer需要下线,从NameServer中剔除该Broker的信息,由于网络或者其他原因,NameServer A和B收到了下线的请求,NameServer C并未收到,此时就处于数据不一致的状态,如果某个消费者是与NameServer C进行通信,会认为Broker还处于可用的状态:

对于这种情况,首先NameServer与Broker之间会有一个心跳机制,NameServer定时检测在某个时间范围内是否收到了Broker发送的心跳请求,如果未收到,会认为该Broker不可用,将其剔除(在下面会讲到),所以对于NameServer来说,尽管数据会暂时处于不一致的状态,但是可以保证过一段时间之后恢复数据的一致性,也就是最终一致性。

对于消费者来说,既然可以从NameServer C中获取到Broker A的信息,那么消费者就认为Broker A可用,如果发送的消息所在的消息队列在Broker A中,就会与Broker A通信进行发送,但实际上Broker A实际上是不可用的,消息会发送失败,所以RocketMQ设计了消息重试机制以及故障延迟机制。

Broker注册

Broker启动后会开启定时向NameServer进行注册(发送心跳包)的任务,发送心跳包的时间间隔可以在配置文件中进行设置,但是最长不能超过10s,也就是说Broker最长10秒钟会向Nameserver发送一次心跳包。

NameServer收到Broker的注册请求(心跳包)后,会判断Broker之前是否已经注册过,如果未注册过将其加入到注册的Broker集合brokerAddrTable中,同时也会记录收到注册请求的时间,将其加入到brokerLiveTable中,里面记录了NameServer收到每个Broker发送心跳包的时间,在进行心跳检测的时候根据这个时间戳来判断是否在规定时间内未收到该Broker发送的心跳包。

读写锁
由于NameServer可能同时收到多个Broker的注册以及生产者或者消费者的拉取请求,为了保证数据的一致性(因为有读写请求同时发生或者写与写请求同时发生),在处理相关请求的时候需要加锁,为了提高性能,使用了ReadWriteLock读写锁,处理注册请求时会先添加写锁,处理拉取请求时添加读锁,这样如果某一时刻都是读的请求可以同时进行,互不影响,如果有写请求,其他请求就需要等锁释放才可以进行往下进行。如果不使用读写锁,直接对所有的请求加锁,会影响性能,实际上读与读之间并不需要加锁。

心跳检测

Nameserver在启动的时候会开启一个用于心跳检测的定时任务(每10s执行一次),定时扫描处于不活跃状态的Broker,如果在规定时间内未收到某个Broker的心跳包,会认为此Broker不可用,需要将其进行剔除。

上面说到brokerLiveTable保存了当前NameServer收到的心跳数据,里面记录了每一个Broker最近进行注册/发送心跳的时间戳,所以只需遍历brokerLiveTable,获取每一个Broker最近一次发送心跳的时间进行判断,如果上一次发送心跳的时间 + 过期时间(120s) 小于 当前时间,也就是超过120s没有收到某个Broker的心跳包,则认为此Broker已下线,将Broker移除

Broker下线

正常下线
当Broker下线的时候会向NameServer发起取消注册的请求,NameServer收到请求后会将Broker剔除。

异常下线

如果Broker异常宕机,或者发送给NameServer的取消注册请求由于某些原因并未发送成功,NameServer可能并未感知到Broker的下线,由于心跳机制定时检测的功能,会在一段时间后发现未收到Broker的心跳请求,主动将Broker剔除。

生产者和消费者

生产者和消费者都会定时从NameServer中更新Broker的注册信息,默认是30s进行一次更新:

public class MQClientInstance {
    private void startScheduledTask() {
         this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {

            @Override
            public void run() {
                try {
                   // 更新路由信息 MQClientInstance.this.updateTopicRouteInfoFromNameServer();
                } catch (Exception e) {
                    log.error("ScheduledTask updateTopicRouteInfoFromNameServer exception", e);
                }
            }
        }, 10, this.clientConfig.getPollNameServerInterval(), TimeUnit.MILLISECONDS);
    }
}

对应的相关源码可参考:

【RocketMQ】【源码】NameServer的启动
【RocketMQ】【源码】Broker服务注册

本文转载于网络 如有侵权请联系删除

相关文章

  • 磁盘未初始化 修复_初始化磁盘是什么意思

    大家好,又见面了,我是你们的朋友全栈君。磁盘没有初始化是因为0号扇区损坏,导致机械硬盘分区表读取不出来,从而机械硬盘出现磁盘没有初始化。工具/软件:极限数据恢复软件步骤1:程序打开后,直接双击需要恢复数据的物理盘。步骤2:等待程序扫描完毕大概需要几分钟到半个小时,稍微耐心等下即可。步骤3:软件扫描到资料后,软件会将扫描到的分区列出来。步骤4:勾上所有需要恢复的资料,右击选择《复制勾选的文件》,程序会将勾上的文件COPY出来。步骤5:最后一步只需要等待软件将文件拷贝完毕就好了。注意事项1:磁盘没有初始化找到出来的数据需要暂时保存到其它盘里。注意事项2:想要恢复磁盘没有初始化需要注意,在数据恢复之前,不要重建新的分区。发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/125326.html原文链接:https://javaforall.cn

  • 腾讯安全联合成立数据安全专委会

    昨天,2021年北京工业互联网数据安全发展论坛暨北京工业互联网技术创新与产业发展联盟数据安全专委会成立大会在京召开。同时,大会发布了由国家工业信息安全发展研究中心联合腾讯安全共同研发的“工业互联网数据安全检测评估系统”。大会由北京市经济和信息化局指导,北京工业互联网技术创新与产业发展联盟、工业信息安全产业发展联盟主办,腾讯云计算(北京)有限责任公司承办。会议聚焦工业互联网数据安全主题,共同探讨数据安全新形势、新技术、新体系等。(大会现场)工业和信息化部网络安全管理局信息安全处三级调研员宋海彬,国家工业信息安全发展研究中心副主任郝志强,保障技术所所长李俊,保障技术所副所长王墨,腾讯安全副总裁黎巍,清华大学大数据研究中心主任助理金涛,以及来自企业、科研院所、高校等150余位代表参加,清华大学大数据系统软件国家工程实验室总工程师、联盟秘书长王晨主持会议。宋海彬表示,我国作为互联网大国,也是数据大国,数据已成为当前数字经济发展的关键要素。工业和信息化部作为工业和电信领域数据安全的监管部门,将加快落实《数据安全法》等法律法规要求,加强顶层设计,持续完善数据安全政策标准体系,组织开展数据安全评估认

  • Browser 对象(一、history)

    history对象包含用户在浏览器窗口中访问过的URLhistory对象是window对象的一部分,也就是说可以window.history进行访问1、history对象的属性(length)console.log(history.length);复制 通过history.length直接返回浏览器历史列表中URL的数量2、history对象的方法back()history.back();复制<ahref="javascript:history.back();">返回上一页</a>复制<inputtype="button"value="返回上一页"onclick="returnBack()"/> <script> functionreturnBack(){ history.back(); } <script>复制通过调用history.back()方法加载当前URL在浏览器历史列表中的前一个URL 3、history对象的方法forward()hi

  • kali破解wifi 攻击(仅供实验,不可用于违法事宜)

    文章目录kaliwifi攻击密码破解方法破解密码主要步骤kaliuser:errol仅供实验,不可用于违法事宜wifi攻击kali网卡选择AP模式:可作为evil无线接入点monitor模式:可以进行抓包密码破解方法1.穷举法:简单来说就是将密码进行逐个推算直到找出真正的密码为止。比如一个四位并且全部由数字组成其密码共有10000种组合,也就是说最多我们会尝试9999次才能找到真正的密码。2.字典法:当然如果破译一个有8位而且有可能拥有大小写字母、数字、以及符号的密码用普通的家用电脑可能会用掉几个月甚至更多的时间去计算,其组合方法可能有几千万亿种组合。这样长的时间显然是不能接受的。其解决办法就是运用字典,所谓“字典”就是给密码锁定某个范围,比如英文单词以及生日的数字组合等,所有的英文单词不过10万个左右这样可以大大缩小密码范围,很大程度上缩短了破译时间破解密码主要步骤Shell1通过aircrack-ng工具,将网卡改为监听模式</

  • 基于 Kubernetes,Helm 及 Jenkins 实现弹性 CI/CD

    让我们在Kubernetes上创建一个CI/CD(持续集成和持续部署)解决方案,使用Jenkins作为构建工具,并使用Traefik作为用于灵活应用程序部署和路由的入口。目标主要目标是在Kubernetes之上提供一种灵活的CI/CD解决方案,并在每个环境中自动部署应用程序,定义主机和路由。为了使此过程易于理解,将详细介绍并描述以下步骤:设置Kubernetes并了解其基本概念;使用Helm安装Traefik,Dashboard和Jenkins;创建Kotlin应用程序以展示如何使用CI/CD;实施Jenkins管道以自动构建和部署应用程序。为了完成上述步骤并验证提出的CI/CD解决方案,提出了具有以下组件的体系结构:Kubernetes:用于容器管理和编排;Traefik:作为访问服务的代理和负载平衡器;Kubernetes仪表板:通过基于Web的界面管理Kubernetes;Jenkins:作为自动化服务器来自动构建和部署应用程序;GitHub:使用Git管理源代码;DockerHub:作为用于使用示例应用程序管理Docker映像的注册表;应用程序说明:出于开发和测试目的的示例应用

  • 使用Supervisor管理进程

    Supervisor(http://supervisord.org)是一个用Python写的进程管理工具,可以很方便的用来启动、重启、关闭进程(不仅仅是Python进程)。除了对单个进程的控制,还可以同时启动、关闭多个进程,比如很不幸的服务器出问题导致所有应用程序都被杀死,此时可以用supervisor同时启动所有应用程序而不是一个一个地敲命令启动。安装Supervisor可以运行在Linux、MacOSX上。如前所述,supervisor是Python编写的,所以安装起来也很方便,可以直接用pip: sudopipinstallsupervisorsupervisord配置Supervisor相当强大,提供了很丰富的功能,不过我们可能只需要用到其中一小部分。安装完成之后,可以编写配置文件,来满足自己的需求。为了方便,我们把配置分成两部分:supervisord(supervisor是一个C/S模型的程序,这是server端,对应的有client端:supervisorctl)和应用程序(即我们要管理的程序)。首先来看supervisord的配置文件。安装完supervisor之后,可

  • Unity3D-关于项目的屏幕适配(看我就够了)

    1、游戏屏幕适配屏幕适配是为了让我们的项目能够跑在各种电子设备上(手机,平板,电脑) 那么了解是适配之前首先要了解两个知识点:1-1、什么是像素?单位面积中构成图像的点的个数。 特点:单位面积内的像素越多,分辨率越高,图像的效果就越好。1-2、什么是分辨率?分辨率可以从显示分辨率与图像分辨率两个方向来分类。 示分辨率(屏幕分辨率)是屏幕图像的精密度,是指显示器所能显示的像素有多少.分辨率的单位有:(dpi点每英寸)、lpi(线每英寸)和ppi(像素每英寸)。 特点: 图像的分辨率越高,所包含的像素就越多,图像就越清晰,印刷的质量也就越好。 同时,它也会增加文件占用的存储空间。1-3、移动设备分辨率–以iphone为例Paste_Image.png2、什么是适配?什么是适配?适应、兼容各种不同的情况游戏开发中,适配的常见种类¤系统适配 针对不同版本的操作系统进行适配,例如Unity3D5.4系统¤屏幕适配 针对不同大小的屏幕尺寸进行适配,例如Iphone5s,iphone7 iPhone的尺寸 3.5inch、4.0inch、4.7inch、5.5inch iPad的尺寸 7.9inch

  • ReadWriteLock 读写锁实现一个缓存

    1.概述关注公众号JavaStorm学习更多干货实际工作中我们会遇到一种并发场景:读多写少,这个时候为了优化性能,我们就会使用缓存。针对读多写少这种并发场景,JavaSDK并发包提供了读写锁——ReentrantReadWriteLock,非常容易使用,并且性能很好。通过本文学会如何写出一个缓存组件,以及锁降级是什么?2.什么是读写锁?读写锁遵循以下三个基本原则:允许多个线程同时读共享变量。只允许一个线程写共享变量。如果有一个线程正在执行写操作,此时禁止读线程读共享变量。读写锁与互斥锁的一个重要区别就是读写锁允许多个线程同时读共享变量,而互斥锁是不允许的,这是读写锁在读多写少场景下性能优于互斥锁的关键。但读写锁的写操作是互斥的,当一个线程在写共享变量的时候,是不允许其他线程执行写操作和读操作。3.ReentrantReadWriteLock3.1ReentrantReadWriteLock快速实现一个缓存工具类。首先声明一个Cache<K,V>,其中泛型V代表缓存的value类型,缓存的数据我们保存在hashMap中,不是线程安全的,这时候我们通过ReentrantRead

  • 数据分析从零开始实战(二)

    上节补充上篇数据分析从零开始实战(一)CSV 逗号分隔值(Comma-SeparatedValues,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。 TSVTSV是Tab-separatedvalues的缩写,即制表符分隔值。 Python的csv模块准确的讲应该叫做dsv模块,因为它实际上是支持范式的分隔符分隔值文件(DSV,delimiter-separatedvalues)的。 delimiter参数值默认为半角逗号,即默认将被处理文件视为CSV。 当delimiter='\t'时,被处理文件就是TSV。零写在前面上一篇文章中带大家了解了数据分析基础,配置好了数据分析的基本环境,以及利用pandas模块读写csv文件,在本文开头,我也补充了csv与tsv的基本介绍与区别,意在更好的让大家理解相关知识点,本文将带大家继续学习文件读取。点击查看第一篇文章:数据分析从零开始实战|基础篇(一)一基本知识概要1.利用pandas读写tsv文件 2.利用pandas读写json文件 二开始动手动脑1.利用pand

  • CCNA学习日记3

    下面把今天学到的重点总结一下,如果有什么错误,欢迎大家纠正!1.路由器密码配置n控制台密码Router(config)#lineconsole0Router(config-line)#loginRouter(config-line)#password123n虚拟终端密码Router(config)#linevty04Router(config-line)#loginRouter(config-line)#password123nAUX密码Router(config)#lineaux0Router(config-line)#loginRouter(config-line)#password123n特权模式明文密码Router(config)#enablepassword123n特权模式加密密码Router(config)#enablesecret123注:如果设置了特权模式明文密码和特权模式加密密码,则以加密密码为准,一般设置特权模式加密密码即可2.路由协议路由协议用于路由器选择路径和管理路由表3.路由协议和被路由协议的区别被路由协议RoutedProtocol(如IP)工作在网络层,而

  • HDFS架构和基本操作学习

    本节我们对HDFS进行深入的学习,包括理解其架构特点,学习一些基本的操作命令HDFS是hadoop实现的一个分布式文件系统。(HadoopDistributedFileSystem)来源于Google的GFS论文。它的设计目标有:非常巨大的分布式文件系统。运行在普通廉价的硬件上,及一般的PC机(相比于小型机,单片机而言的)。易扩展,为用户提供性能不错的文件存储服务。HDFS的架构HDFS架构示意图1.HDFS采用了1个Msater(NameNode)和N个slaves(DataNode)的架构一个HDFS集群包含一个NameNode,主要职责是管理文件系统的元数据信息,控制客户端对文件的访问。一个HDFS集群包含多个DataNode,通常一个节点就是一个DataNode,负责相应节点上文件的存储。NameNode的作用负责客户端请求的响应维护整个文件系统的目录树(例如记录文件的增删改查操作)和负责元数据(文件名称、副本系数,文件和block的映射,DataNode和block的映射等)的管理DataNode的作用存储文件对应的数据块,存储数据是核心作用定期向NameNode发送心跳信息

  • apache配置多站点

    Apache在安装之后默认只是指向一个站点,即127.0.0.1,如果要进行多站点的配置,需要更改一些配置。1.让Apache在启动时能加载虚拟主机模块。 打开Apache安装目录下conf/httpd.conf文件,找到下面两行文字,把最前面的#号去掉,然后保存。 #LoadModulevhost_alias_modulemodules/mod_vhost_alias.so #Includeconf/extra/httpd-vhosts.conf  2.接着找到同一文件中的DocumentRoot和Directory,改为站点目录的上一级目录 例如站点放在D:/apache/www/1和D:/apache/www/2,则改为以下形式 DocumentRoot"D:/apache/www" <Directory"D:/apache/www"> 3.配置完成后即可打开Apache安装目录下/conf/extra/httpd-vhosts.conf文件,在最后添加如下: DocumentRoot是文件放置路径,ServerName是网站域

  • 八种创建等高列布局【出自w3c】

    高度相等列在Web页面设计中永远是一个网页设计师的需求。如果所有列都有相同的背景色,高度相等还是不相等都无关紧要,因为你只要在这些列的父元素中设置一个背景色就可以了。但是,如果一个或多个列需要单独设置自己的背景色,那么它的视觉完整性的设计就显得非常重要了。大家都知道当初Table实现等高列布局是多么的简单,但是我们使用CSS来创建等高列布局并非是那么容易的事情。如果一个设计是固定宽度(非流体的宽度设计),那么实现多列等高效果是相当的容易。最好的技术就是使用DanCederholm的FauxColumns技术。只要制作一张合适的背景图片,在你多列的父元素中进行垂直铺放,从而达到一种假像(假的多列等高布局效果)。但是在流体布局中要用CSS实现多列等高的设计那就不是那么容易的事情,因为我们没有办法在使用背景图片来实现多列等高的假像了,那么是不是就没有办法实现了呢?那当然不是那么回事了,不管是实现固定布局还是流体布局的等多列等高视觉效果,方法还是蛮多的,这些方法体现了CSS的不同技术,也各有千秋,下面我们就一起来探讨Web页面中的多列等高的实现技术。下面要介绍的方法都是让我们的布局如何实现多列

  • Airbnb 的 React Native 历程(四):React Native 落下帷幕

    转载请注明出处。请前往TigaonTech查看原文以及更多有趣的技术文章。原文链接:https://medium.com/airbnb-engineering/sunsetting-react-native-1868ba28e30a我们在这个系列的5篇文章里,讲述了Airbnb使用ReactNative进行移动端开发的历程,以及在放弃ReactNative之后的计划。这是这个系列文章的第4篇。我们当前在哪?ThisisthefourthinaseriesofblogpostsinwhichweoutlineourexperiencewithReactNativeandwhatisnextformobileatAirbnb.Wherearewetoday?尽管很多团队指望于ReactNative,并且也计划在可预见的未来去使用它,我们最终还是没法达成我们起初的目标。除此以外,还存在一些我们无法克服的技术和组织架构上的挑战,这使得我们继续投入ReactNative变得很具挑战。AlthoughmanyteamsreliedonReactNativeandhadplannedonusingi

  • 多线程编程学习笔记系列文章目录

     多线程编程学习笔记-基础(一) 多线程编程学习笔记-基础(二) 多线程编程学习笔记-基础(三)   多线程编程学习笔记——线程同步(一) 多线程编程学习笔记——线程同步(二)  多线程编程学习笔记——线程同步(三) 多线程编程学习笔记——线程池(一) 多线程编程学习笔记——线程池(二) 多线程编程学习笔记——线程池(三)     多线程编程学习笔记——任务并行库(一)  多线程编程学习笔记——任务并行库(二)  多线程编程学习笔记——任务并行库(三) 多线程编程学习笔记——任务并行库(四)  多线程编程学习笔记——async和await(一) 多线程编程学习笔记——async和await(二) 多线程编程学习笔记——async和await(三)   多线程编程学习笔记——使用并发集合(一) 多线程编程学习笔记——使用并发集合(二) 多线程编程学习笔记——使用并发集合(三) 多线程编程学习笔记——使用异步IO  多线程编程学习笔记——编写一个异步的HTTP服务器和客户端 多线程编程学习

  • Grafana 备份恢复教程

    原文链接:https://fuckcloudnative.io/posts/how-to-back-up-all-of-your-grafana-dashboards/ 目前我们k8s集群的Grafana使用ceph作为持久化存储,一但我将Grafana的Deployment删除重建之后,之前的所有数据都会丢失,重建的PV会映射到后端存储的新位置。万幸的是,我真的手欠重建了,还没有提前备份。。。万幸个鬼啊我。 在我历经250分钟重建Dashboard之后,心里久久不能平静,一句MMP差点就要脱口而出。 1.低级方案 再这样下去我真的要变成250了,这怎么能忍,立马打开Google研究了一把Grafana备份的各种骚操作,发现大部分备份方案都是通过shell脚本调用Grafana的API来导出各种配置。备份脚本大部分都集中在这个gist中: https://gist.github.com/crisidev/bd52bdcc7f029be2f295 我挑选出几个比较好用的,大家也可以自行挑选其他的。 导出脚本 #!/bin/bash #Usage: # #export_grafa

  • 腾讯产品快速尝鲜,蓝鲸智云社区版V6.1灰度测试开启

    这周小鲸悄悄推送了社区版V6.1(二进制部署版本,包含基础套餐、监控日志套餐),没过一天就有用户来问6.1的使用问题了。小鲸大吃一鲸,原来你还是爱我的。 ![请添加图片描述](https://img-blog.csdnimg.cn/708b08e3f71e406d8fc560c3281a0cb7.gif)##这次又有什么亮点功能了?|产品|亮点功能||----------------------|------------------------------------------------------------||PaaS平台|1.新增中、英文切换入口,社区版6.1全面支持国际化<br/>||CMDB(配置平台)|1.支持了模型修改所属模型分组<br/>2.新增平台管理功能模块<br/>3.支持定制业务空闲机池<br/>4.支持模板实例跨页全选<br/>5.支持模板克隆<br/>6.支持实例关联关系变更事件监听<br/>7.支持主机“追加”模块能力<br/>8.支持通用模型实例统一高级筛

  • cogs 362. [CEOI2004]锯木厂选址

                    ★★★  输入文件:two.in  输出文件:two.out   简单对比                  时间限制:0.1s  内存限制:32MB 从山顶上到山底下沿着一条直线种植了n棵老树。当地的政府决定把他们砍下来。为了不浪费任何一棵木材,树被砍倒后要运送到锯木厂。木材只能按照一个方向运输:朝山下运。山脚下有一个锯木厂。另外两个锯木厂将新修建在山路上。你必须决定在哪里修建两个锯木厂,使得传输的费用总和最小。假定运输每公斤木材每米需要一分钱。 输入 输入的第一行为一个正整数n——树的个数(2≤n≤20000)。树从山顶到山脚按照1,2……n标号。接下来n行,每行有两个正整数(用空格分开)。第i+1行含有:wi——第i棵树的重量(公斤为单位)和di——第i棵树和第i+1棵树之间的距离,1≤wi≤10000,0≤di≤10000。最后一个数dn,表示第n棵树到山脚的锯木厂的距离。保证所有树运到山脚的锯木厂所需要的费用小于2000000000分。 输出 输出只有一行

  • matplotlib中文显示-微软雅黑

    网上有很多方法,但是基本的是片面的。 参考1https://tracholar.github.io/wiki/python/matplotlib-chinese-font.html 参考2https://www.cnblogs.com/touristlee/p/8805655.html windows下,做到以下三点,可以成功 (1)现在msyh.ttf字体,放到matplot的字体目录,       路径如 D:\Program\Anaconda3\Lib\site-packages\matplotlib\mpl-data         参考1有示例       使用下面代码找路径 importmatplotlib print(matplotlib.matplotlib_fname())复制 (2)修改文件,matplotlibrc     参考1或参考2   (3)删除缓存,很重要!     具体i方式是首先删除C:\Users\你的用户名\.matplotlib把这个.matplotlib文件夹删掉,然后重启应用。     5.直接使用&

  • es8中无法设置主节 出现unknown setting [node.master]

    es8中无法设置主节出现unknownsetting[node.master] 设置node.master:true改为:node.roles:[master] 其中节点的角色有多种选择 master data data_content data_hot data_warm data_cold data_frozen ingest ml remote_cluster_client transform

  • cocos2d-x中常见的场景切换

    本文转载自:http://www.cnblogs.com/linux-ios/archive/2013/04/09/3010779.html复制 复制 boolHelloWorld::init() { ////////////////////////////// //1.superinitfirst if(!CCLayer::init()) { returnfalse; } CCSizesize=CCDirector::sharedDirector()->getWinSize(); CCSprite*sp=CCSprite::create("background1.png"); sp->setPosition(ccp(size.width/2,size.height/2)); addChild(sp); CCLabelTTF*label=CCLabelTTF::create("点击按钮切换","",20); //label->setPosition(ccp(size.width/2,size.height/2)); label->setColor(ccc3(

相关推荐

推荐阅读