《RabbitMQ实战指南》读书笔记
第一章 RabbitMQ简介
- 消息队列中间件:利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系统的集成。分为点对点和发布订阅的传递模式。
- 消息中间件的作用:解耦、冗余(存储)、扩展性、削峰、可恢复性、顺序保证、缓冲、异步通信。
- RabbitMQ的特点:
- 可靠性:持久化、传输确认及发布确认等;
- 灵活的路由:消息进入队列之前,通过交换器来路由消息;
- 扩展性:多个节点可组成集群;
- 高可用性:队列可在集群的机器上设置镜像;
- 多种协议:支持AMQP、STOMP、MQTT等多种消息中间件协议;
- 多语言客户端;管理界面;插件机制。
第二章 RabbitMQ入门
- 概念介绍:
- Producer:生产者;
- Consumer:消费者;
- Broker:消息中间件的服务节点。
- Queue:队列,用于存储消息,多个消费者可以订阅同一个队列,之后轮询处理。Exchange:交换器,生产者将消息发送到Exchange,由交换器将消息路由到一个或者多个队列中。
- RoutingKey:路由键,生产者将消息发给交换器时指定RoutingKey,用来指定这个消息的路由规则,而RoutingKey与BindingKey联合使用才能生效。
- Binding:绑定,将交换器与队列关联起来,就能正确的将消息路由到队列了
- 交换器类型
- fanout:把所有发送到该交换器的消息路由到所有与该交换器绑定的队列中。
- direct:把消息路由到那些BingdingKey和RoutingKey完全匹配的队列中
- topic:把消息路由到BingdingKey和RoutingKey符合特殊匹配规则的队列中。其中 * 用于匹配一个单词,# 用于匹配多个单词
- headers:根据发送的消息内容中的headers属性进行匹配,在绑定队列和交换器时指定一组键值对。但其性能差,用途少
- 一个Connection可对应多个Channel,(类似于NIO)即TCP连接复用
- AQMP协议包含三层
- ModuleLayer:最高层,定义了供客户端调用的命令
- SessionLayer:中间层,将客户端的命令发送给服务器。
- TransportLayer:最底层,传输二进制数据流,提供帧的处理,信道复用、错误检测和数据表示等
第三章 客户端开发向导
- 创建Connection:Connection可以用来创建多个Channel实例,但多线程间共享Channel实例是非线程安全的。
- Channel和Connection中有isOpen方法可以用来检测是否处于开启状态,但该方法的返回值依赖于shutdownCause,有可能会产生竞争。
- 交换器的API:
作用 | 方法名 | 备注 |
---|---|---|
定义交换器 | exchangeDeclare() | * exchange:交换器的名称;type:交换器类型,例如:fanout、direct、topic;durable:是否持久化;autoDelete:是否自动删除;internal:是否内置,若是内置交换器,客户端程序无法直接发送消息到这个交换器中,只能通过交换器路由到交换器的方式;argument:其它结构化参数,如alternate-exchange |
非等待的交换器 | exchangeDeclareNoWait() | 设置了一个nowait()参数,不需要服务器返回,若声明完一个交换器后,实际服务器还并未完成交换器的创建,此时客户端紧接着使用该交换器,必然会发生异常,所以不建议使用该方法。 |
检测相应的交换器是否存在 | exchangeDeclarePassive(String name) | 若交换器不存在则抛异常:404 channel exception,同时channel会被关闭。 |
删除交换器 | exchangeDelete(String exchange,boolean ifUnused) | 若ifUnused设置为true,则只有在此交换器没有被使用的情况下才会被删除。 |
- 队列的API
作用 | 方法名 | 参数 | 备注 |
---|---|---|---|
声明一个队列 | queueDeclare(String queue …) | queue:队列的名称;durable:是否持久化;exclusive:是否排他;autoDelete:是否自动删除,前提:至少有一个消费者连接到这个队列,之后所有与这个队列连接的消费者都断开时,才会自动删除;argument:其它参数 | 若一个队列被声明为排他队列,该队列仅对首次声明它的连接可见,并在连接断开时自动删除。排他队列基于连接可见,同一个连接的不同信道可以同时访问同一连接创建的排他队列;即使该队列是持久化的,一旦连接关闭或客户端退出,该排他队列都会被自动删除,这种队列适用于一个客户端同时发送和读取消息的应用场景。 |
声明队列 | queueDeclare() | 无参方法 | 默认创建一个由RabbitMQ命名的、排他的、自动删除的、非持久化的队列。生产者和消费者都能够使用queueDeclare声明一个队列,但如果消费者在同一个信道上订阅了另一个队列,就无法再声明队列了,必须先取消订阅,然后将信道置为传输模式后,才能声明队列。 |
绑定队列 | queueBind() | queue:队列名称;exchange:交换器名称;routingKey:用来绑定队列和交换器的路由键;argument:其它参数 | |
与交换器绑定 | exchangeBind() | 将交换器与队列绑定,也可将交换器与交换器绑定。 |
- 消息的拉与推
作用 | 方法名 | 参数 | 备注 |
---|---|---|---|
发送消息(推) | channel.basicPublish() | exchange:交换器名称;routingKey:路由键;props:消息的基本属性集,例如:contentType、headers、priority等;byte[] body 消息体;mandatory;immediate | 先显示的设置autoAck为false,接收到消息后再进行显示ack操作,可防止消息不必要的丢失。 |
消费消息(推) | basicConsume() | queue:队列的名称;autoAck:是否自动确认,推荐false;consumerTag:消费者标签,用来区分多个消费者;noLocal:设置为true则表示不能将同一个Connection中生产者发送的消息传送给这个Connection中的消费者;exclusive:是否排他;arguments:其它参数;callback:设置消费者的回调函数,用来处理RabbitMQ推送的消息。 | |
拉 | basicGet() | 返回值是GetRespone | |
拒绝消息 | basicReject() | deliverTag:消息编号;requeue参数若为false,则RabbitMQ立即把消息从队列中移除。 | |
批量拒绝消息 | channel.basicNack() | ||
请求重发未确认的消息 | basicRecover() | requeue | 默认requeue是true,即未被确认的消息会重新加入到队列中,即同一条消息可能会分配给不同的消费者。 |
关闭连接 | channel.close() | 或使用addShutdownListener(),removeShutdownListener()方法 |
- 消息确认机制:通过autoAck参数实现,当值为false时,队列中的消息分为等待投递给消费者的消息和已经投递给消费者的消息,RabbitMQ不会对消息设置过期时间,若消费该消息的消费者连接断开就重新投递给消费者。因为RabbitMQ允许消费者消费一条消息很久。
第四章 RabbitMQ进阶
- mandatory与immediate参数
- mandatory参数:当值为true时,交换器无法根据自身的类型和路由键找到一个符合条件的队列,就会调用Basic.Return命令将消息返回给生产者,生产者可调用channel.addReturnListener添加监听器获取没有被正确路由的消息。若为false,则消息直接被丢弃。
- immedate参数:当值为true时,若交换器在消息路由到队列时发现队列上并不存在任何消费者,该消息不会存入队列,当与路由键匹配的所有队列中都没有消费者时,会调用Basic.Return返回给生产者。但在RabbitMQ3.0之后不支持该参数,因为会影响镜像队列的性能,增加了代码复杂性,建议采用TTL和DLX的方法替代。
- 备份交换器:可在调用channel.exchangeDeclare()方法时添加alternate-exchange参数实现,也可通过策略的方式实现,但参数优先级更高。备份交换器建议设置为fanout类型。若与mandatory参数同时使用,则mandatory参数无效。
- 过期时间(TTL):对消息和队列设置TTL。设置消息的TTL的两种方式
- 队列中所有消息过期时间相同:
- 通过队列属性channel.queueDeclare的x-message-ttl设置,若将TTL设置为0,则表示若消息不能直接投递到消费者就会被立刻丢弃,可部分替代immediate参数的功能(返回消息的功能可用死信队列实现)
- 通过channel.queueDeclare方法中的x-expires参数设置,该参数可控制队列被自动删除前处于未使用状态,即队列上没有任何的消费者,队列也没有被重新声明,在过期时间段内也未调用过Basic.Get命令
- 对消息进行单独设置:在channel.basicPublish方法加入expiration参数,每条消息的TTL可以不同)。如果同时使用则取较小值。
- 死信队列(DLX):当消息在一个队列中变为死信之后,它能被重新发送到另一个交换器中。通过在channel.queueDeclare方法设置x-dead-letter-exchange参数添加DLX。
- 消息变为死信的情况:
- 消息被拒绝,并且设置requeue参数为false;
- 消息过期;
- 队列达到最大长度。
- 延迟队列:存储对应的延迟消息,即当消息被发送以后,并不想让消费者立刻拿到消息,而是等待特定时间后才拿到这个消息进行消费。RabbitMQ本身没有直接支持延迟队列的功能,可通过DLX和TTL实现,
- 优先级队列:具有高优先级的队列具有高的优先权从而具备优先被消费的特权。可通过设置队列的x-max-priority参数实现。默认最低0。
- RPC实现:在请求消息中发送一个回调队列用来接收响应的消息。BasicProperties类常用的两个属性:replyTo用来设置一个回调队列,correlationId用来关联请求和调用RPC之后的回复。
- 持久化:分为交换器、队列、消息的持久化durable参数。为了确保消息不丢失,可将消费队列的autoACK参数设置为false,引入镜像队列机制等。
- 生产者确认的解决方式:事务机制或发送方确认机制。
- 事务机制:channel.txSelect、channel.txCommit、channel.txRollback,会降低消息吞吐量。
- 发送方确认机制:生产者调用channel.confirmSelect方法将信道设置为confirm模式,调用channel.waitForConfirm方法等待服务端确认。也可使用批量confirm或异步confirm的方法。
- 注:事务与confirm机制互斥,若都开启会报错。两种确认机制能保证消息正确的发送至交换器,但若此交换器没有匹配的队列,消息就会丢失,所以可配置mandatory参数或alternate参数来提高消息的可靠性。
- 消费端要点介绍:消息分发、消息顺序性、弃用QueueingConsumer
- 消息分发的方式:轮询或channel.basicQoS方法允许限制信道上的消费者所能保持的最大未确认消息的数量。但对拉模式的消费方式无效。
- 消息顺序性:若发生异常事务回滚、延迟队列、设置了优先级的消息不能保证顺序消费,若要保证消息的顺序性,需要业务保证,比如在消息内加入全局有序标识。
- 弃用QueueingConsumer:有内存溢出的问题、非事件驱动。同步递归调用会产生死锁、会拖累同一个Connection下的所有信息,使其性能降低。
- 消息传输保障:RabbitMQ支持最多一次和最少一次层级。
第五章 Rabbit管理
- rabbitmqctl常用命令
作用 | 命令 | 备注 |
---|---|---|
创建一个新的vhost | rabbitmqctl add_vhost {vhost} | |
列出当前vhost的信息 | rabbitmqctl list_vhosts {name} {tracing} | |
删除vhost | rabbitmqctl delete_vhost {vhost} | |
授予权限 | rabbitmqctl set_permissions {-p vhost} {user} {conf} {write} {read} | |
创建用户 | rabbitmqctl add_user {username} {password} | |
更改密码 | rabbitmqctl change_password {username} {newpassword} | |
删除用户 | rabbitmqctl delete_user {username} | |
列出所有的用户 | rabbitmqctl list_users | |
停止RabbitMQ应用 | rabbitmqctl stop {pid_file} | |
启动RabbitMQ(不会生成pid_file文件) | rabbit-server -detach | |
将节点加入集群中 | rabbitmqctl join_cluster {cluster_node} {—ram} | –ram表示内存型节点 |
显示集群的状态 | rabbitmqctl cluster_status | |
更新集群信息 | rabbitmqctl update_cluster_nodes {clusternode} | |
确保节点可以启动 | rabbitmqctl force_boot | |
设置集群名称 | rabbitmqctl set_cluster_name {name} | |
查看所有队列 | rabbitmqctl list_queues {-p vhost} {queueinfoitem} | |
返回交换器的信息 | rabbitmqctl list_exchanges {-p vhost} {exchangeinfoitem} | |
列举消费者信息 | rabbitmqctl list_consumers {-p vhost} | |
显示Broker状态 | rabbitmqctl status |
- 多租户与权限,vhost:每一个RabbitMQ服务器都能创建虚拟的消息服务器。每一个vhost本质上是一个独立的小型RabbitMQ服务器,拥有自己独立的队列、交换器、绑定关系和自己独立的权限等,vhost之间是绝对隔离的。RabbitMQ默认创建的vhost为/。
- 管理方式:
- Web端管理:默认地址localhost:15672,用户名密码:guest/guest
- HTTP API接口管理:可通过curl命令调用接口完成队列的创建:
curl -i -u root:root123 -H “content-type:application/json” -XPUT -d ‘{“auto_delete”:false, “durable”:true, “node”:”rabbit@node2”}’ http://127.0.0.1:15672/api/queue/%2F/queue,其中%2F表示默认的vhost,即/,
第六章 RabbitMQ配置
- 环境变量:可在rabbit-env.conf环境变量的定义文件中设置,但shell环境优先。
- 配置文件:RabbitMQ在启动时会打印相关信息,其中config file(s)是目前配置文件所在的路径
- 运行时参数和策略:
- vhost级别的参数对应的命令有三种:set_parameter、list_parameter、clear_parameter
- global级别对应的命令有:set_global_parameter name value、list_global_parameter、clear_global_parameter name
第七章 RabbitMQ运维
- 集群搭建:配置各个节点的hosts文件;编辑RabbitMQ的cookie文件(相当于密钥令牌),以确保各个节点的cookie文件使用的是同一个值;配置集群,通过rabbitmqctl、rabbitmq.config配置文件或rabbitmq-autocluster插件配置。
- 集群节点的类型:分为内存节点或磁盘节点,加入节点时–ram参数指定为内存节点。可使用rabbitmqctl change_cluster_node_type {disc, ram}命令切换节点的类型。但在集群中至少有一个磁盘节点。
- 查看服务日志:开启、关闭RabbitMQ、创建集群都会输出日志。
- 单节点故障恢复:故障可分为硬件故障、网络异常、进程异常等。
- 集群迁移:RabbitMQ集群迁移包括元数据重建、数据迁移、及客户端的切换
- 元数据重建:在新的集群中创建原集群的队列、交换器;绑定关系、vhost、用户和权限等数据信息。可通过web管理界面的高效方式重建。
- 数据迁移:先从原集群中将数据消费出来,存入一个缓存区中,另一个线程读取缓存区中的消息再发布到新的集群中。
- 自动化迁移:将集群资源的使用分为三个部分:客户端、集群、ZooKeeper配置管理。
- 集群监控:通过HTTP API接口或客户端监控。
第八章 跨越集群的界限
- 分布式部署的方式:集群、Federation和Shovel。
- Federation插件的设计目标:是RabbitMQ在不同的Broker节点之间进行消息传递而无须建立集群。Federation插件可让多个交换器或者队列进行联邦。
- 联邦交换器:
北京的clientB向广州的exchangeA发消息,会有一定的延迟,尤其是开启了publisher confirm或事务机制。可通过Federation link插件解决,该插件会在broker1上建立一个同名的交换器exchangeA,同时建立一个内部的交换器exchangeA->broker3B,并通过路由键rkA将这两个交换器绑定,还会建立一个队列federation:exchangeA->broker3B与交换器exchangeA->broker3B绑定,对外部来说这条federation link建立在broker1的exchangeA与broker3的exchangeA之间。之后,北京的ClientB可以连接到broker1并向exchangeA发送消息,而消息会通过Federation link转发到broker3的交换器exchangeA中。最终消息会存入与exchangeA绑定的队列queueA中。经过Federation link转发的消息会带有特殊的headers属性标记。
- 联邦队列:可在多个broker节点或集群之间为单个队列提供负载均衡的功能。
queue1和queue2原来在broker2中,由于某种需求将其配置为federated queue并将broker1作为upstream,Federation插件会在broker1上创建同名的队列queue1和queue2,与broker2中的两个队列分别建立两条单向独立的Federation link。当有消费者ClientA连接broker2消费,但queue1无消息堆积或被消费完了,则会通过Federation link拉取broker1中queue1中的消息,然后存储到本地,之后再被ClientA消费。消费者既可以消费broker2中的队列又可以消费broker1中的队列,这种分布式队列的部署可以提高单个队列的容量。与federated exchange不同,一条消息可以在联邦队列间转发无限次。
- Federation的使用,需要配置一个或多个upstream(可通过federation management插件来完成),每个upstream均定义了到其它节点的Federation link,还需要定义匹配交换器或队列的一种/多种策略。Federation upstream的信息全部保存在RabbitMQ的Mnesia数据库中,包括用户信息、权限信息、队列信息等
- Federation的3种级别配置
- Upstreams:每个upstream用于定义与其他Broker建立连接的信息。
- Upstream sets:每个upstream set用于对一系列使用Federation功能的upstream进行分组。
- Policies:每一个Policy会选定一组交换器、队列或全选,作用于一个单独的upstream或upstream set之上。
- Shovel:能够可靠、持续地从一个Broker中的队列拉取数据并转发至另一个Broker中的交换器
- Shovel的优点:松耦合、支持广域网、高度定制。
queue1和exchange2之间配置一个Shovel link,一条消息从Client发送到exchange1,最终会存储在queue2中。通常使用Shovel时配置队列作为源端,交换器作为目的端。
- Shovel的部署方式:静态与动态
- 静态方式:rabbitmq.config配置文件
- 动态方式:会保存到RabbitMQ的Mnesia数据库中。每一个Shovel link都由一个相应的Parameter定义,这个Parameter可通过rabbitmactl工具、API接口或Web管理界面设置
- 实例:当消息堆积严重时(千万级别),可通过Shovel将消息转发至备份集群中。
- Federation/Shovel与集群的区别和联系
Federation/Shovel | 集群 |
---|---|
各个Broker节点之间逻辑分离 | 逻辑上是一个Broker节点 |
各个Broker节点之间可以运行不同版本的Erlang和RabbitMQ | 各个Broker节点之间可以运行相同版本的Erlang和RabbitMQ |
各个Broker节点之间可以在广域网中相连,必须授予适当的用户和权限 | 各个Broker节点之间必须在可信赖的局域网中相连,通过Erlang内部节点传递消息,但节点间需要有相同的Erlang cookie |
各个Broker节点之间能以任何拓扑逻辑部署,连接是单向或双向的 | 所有Broker节点都是双向连接所有节点 |
从CAP理论中选择可用性和分区容错性,即AP | 从CAP理论中选择可用性和一致性,即CA |
一个Broker中的交换器可以是Federation生成的或是本地的 | 集群中所有Broker节点中的交换器都是一样的,要么全有要么全无 |
客户端能看到它所连接的Broker节点上的队列 | 客户端连接到集群中的任何Broker节点都可以看到所有的队列 |
第九章 RabbitMQ高阶
- 存储机制:持久层包含两个部分:队列索引和消息存储。rabbit_queue_index负责维护队列中落盘消息的消息,包括消息的存储地点、是否已被交付给消费者等,每个队列都有与之对应的一个rabbit_queue_index。而rabbit_msg_store以键值对的形式存储消息,它被所有的队列共享,在每个节点中有且只有一个。
- 队列的结构:队列由rabbit_amqqueue_process和backing_queue组成,rabbit_amqqueue_process负责接收生产者发布的消息、向消费者交付消息、处理消息的确认等。backing_queue是消息存储的具体形式和引擎,并向rabbit_amqqueue_process提供相关的接口以供调用。
- RabbitMQ的队列消息的4种状态
- alpha:消息内容和消息索引都存储在内存中
- beta:消息内容保存在磁盘中,消息索引保存在内存中
- gamma:消息内容保存在磁盘中,消息索引在磁盘和内存中都有。(只有持久化消息才有的状态)
- delta:消息内容和索引都在磁盘中。
- 惰性队列:3.6.0及之后,尽可能的将消息存入磁盘中,而在消费者消费到相应的消息时才会被加载到内存中。它的设计目标是能够支持更多的消息存储。队列的两种模式:default和lazy。
- 内存及磁盘告警:当内存使用超过配置的阈值或磁盘剩余空间低于配置的阈值时,RabbitMQ都会暂时阻塞客户端的连接并停止接收从客户端发来的消息。心跳检测也会失效。
- 流控:基于信用证算法的流控机制来限制发送消息的速率来避免消息的发送速率过快而导致服务器难以支撑的场景
- 流控机制作用于Connection、Channel、Queue。
- 其中rabbit_reader:Connection的处理进程,负责接收、解析AMQP协议数据包等
- rabbit_channel:Channel的处理进程,负责处理AMQP协议的各种方法等
- rabbit_amqqueue_process:队列的处理进程,负责实现队列的所有逻辑。
- rabbit_msg_store:负责实现消息的持久化。
- 镜像队列:可将队列镜像到集群中的其他Broker节点之上,保证服务的可用性。所有对master的操作都会通过组播GM(Guaranteed Multicast)的方式同步到各个slave中。GM模块实现的是一种可靠的组播通信协议,该协议保证组播消息的原子性。
- 每个节点都会监控位于自己左右两边的节点。
第十章 网络分区
- 网络分区的意义:确认一条消息首先会在master节点执行确认命令,然后转向其他的slave节点,保证强一致性,但如果出现网络波动等异常情况,性能就会降低。
- 网络分区的判定:查看RabbitMQ服务日志、rabbitmqctl工具、web管理页面、HTTP API方式。
- 网络分区的模拟:iptables封禁/解封IP地址或端口号、关闭/开启网卡、挂起/恢复操作系统。
- 网络分区的影响:
- 未配置镜像:网络分区发生后,队列会伴随着宿主节点而分散在各自的分区之中。生产者可以成功发送消息,但会有路由失败的现象,消费者可能出现对于已消费消息的ack失效等情况。
- 配置镜像:当有新的slave出现,会同步master中的数据,在同步的过程中集群的整个服务都不可用。客户端连接被阻塞,若mater有大量的消息堆积,同步时间会变长,影响集群服务的可用性。
- 手动处理网络分区:
- 挑选信任分区标准:分区中要有disc节点,分区中节点数、队列数、客户端连接数最多
- 重启节点方式:使用rabbitmqctl stop关闭,然后使用rabbit-server -detached,或使用rabbitmqctl stop_app rabbitmqctl start_app。
- 重启顺序的选择:停止其他非信任分区中的所有节点,再重启这些节点。或关闭整个集群中的节点,再启动每一个节点,确保启动的第一个点在信任的分区中
- 自动处理网络分区的方式:pause-minority模式、pause-if-all-down模式、autoheal模式。默认ignore模式。
第十一章 RabbitMQ扩展
- 消息追踪:
- Firehose功能:可以记录每一次发送或消费消息的记录。
- 开启rabbitmq_tracing插件:对流入流出的消息进行封装,然后存入相应的trace文件之中。
- 负载均衡:软件与硬件
- 客户端内部实现负载均衡的算法:轮询、加权轮询、随机、加权随机、源地址哈希、最小连接数法等
- 使用HAProxy实现负载均衡:一种事件驱动、单一进程模型。支持非常大的并发连接数。
- 使用Keepalived+LVS实现高可靠负载均衡:通过自身健康检查、资源接管功能做高可用(双机热备),实现故障转移。
- LVS是4层负载均衡,支持TCP/UDP的负载均衡,LVS由负载调度器、服务器池、共享内存组成,它的负载均衡方式:VS/NAT、VS/TUN、VS/DR。
《RabbitMQ实战指南》读书笔记相关推荐
- 读书笔记 | 墨菲定律
1. 有些事,你现在不做,永远也不会去做. 2. 能轻易实现的梦想都不叫梦想. 3.所有的事都会比你预计的时间长.(做事要有耐心,要经得起前期的枯燥.) 4. 当我们的才华还撑不起梦想时,更要耐下心来 ...
- 读书笔记 | 墨菲定律(一)
1. 有些事,你现在不做,永远也不会去做. 2. 能轻易实现的梦想都不叫梦想. 3.所有的事都会比你预计的时间长.(做事要有耐心,要经得起前期的枯燥.) 4. 当我们的才华还撑不起梦想时,更要耐下心来 ...
- 洛克菲勒的38封信pdf下载_《洛克菲勒写给孩子的38封信》读书笔记
<洛克菲勒写给孩子的38封信>读书笔记 洛克菲勒写给孩子的38封信 第1封信:起点不决定终点 人人生而平等,但这种平等是权利与法律意义上的平等,与经济和文化优势无关 第2封信:运气靠策划 ...
- 股神大家了解多少?深度剖析股神巴菲特
股神巴菲特是金融界里的传奇,大家是否都对股神巴菲特感兴趣呢?大家对股神了解多少?小编最近在QR社区发现了<阿尔法狗与巴菲特>,里面记载了许多股神巴菲特的人生经历,今天小编简单说一说关于股神 ...
- 2014巴菲特股东大会及巴菲特创业分享
沃伦·巴菲特,这位传奇人物.在美国,巴菲特被称为"先知".在中国,他更多的被喻为"股神",巴菲特在11岁时第一次购买股票以来,白手起家缔造了一个千亿规模的 ...
- 《成为沃伦·巴菲特》笔记与感想
本文首发于微信公众帐号: 一界码农(The_hard_the_luckier) 无需授权即可转载: 甚至无需保留以上版权声明-- 沃伦·巴菲特传记的纪录片 http://www.bilibili.co ...
- 读书笔记002:托尼.巴赞之快速阅读
读书笔记002:托尼.巴赞之快速阅读 托尼.巴赞是放射性思维与思维导图的提倡者.读完他的<快速阅读>之后,我们就可以可以快速提高阅读速度,保持并改善理解嗯嗯管理,通过增进了解眼睛和大脑功能 ...
- 读书笔记001:托尼.巴赞之开动大脑
读书笔记001:托尼.巴赞之开动大脑 托尼.巴赞是放射性思维与思维导图的提倡者.读完他的<开动大脑>之后,我们就可以对我们的大脑有更多的了解:大脑可以进行比我们预期多得多的工作:我们可以最 ...
- 读书笔记003:托尼.巴赞之思维导图
读书笔记003:托尼.巴赞之思维导图 托尼.巴赞的<思维导图>一书,详细的介绍了思维发展的新概念--放射性思维:如何利用思维导图实施你的放射性思维,实现你的创造性思维,从而给出一种深刻的智 ...
- 产品读书《滚雪球:巴菲特和他的财富人生》
作者简介 艾丽斯.施罗德,曾经担任世界知名投行摩根士丹利的董事总经理,因为撰写研究报告与巴菲特相识.业务上的往来使得施罗德有更多的机会与巴菲特亲密接触,她不仅是巴菲特别的忘年交,她也是第一个向巴菲特建 ...
最新文章
- 串口上升时间标准_JESD204B 串行接口时钟需要及其实现
- linux 进程参数文件 /proc/pid/cmdline 简介
- 在Ubuntu下进行安卓开发遇到“insufficient permissions for device: user in plugdev group; ”问题的解决办法
- sql OFFSET 和 ORDINAL
- SpringMVC的请求-文件上传-客户端表单实现
- linux ping库函数,Linux 常用基本命令 ping ifconfig
- 关于Asp.net core配置信息读取的源码分析梳理
- 【剑指offer】面试题15:二进制中1的个数(Java)
- C语言中忽略scanf的价值,c语言的scanf接收到底是忽略空格还是不忽略呢?
- 软考高级报考,科目思维导图概览和介绍
- 传智播客 C/C++学习笔记 二级指针作为输出参数以及空间的释放
- 【收藏的JS库】 Javascript常用的库 (包含图片处理、动画库、语音命令库、视觉检测、机器学习等)
- google四件套之Dagger2。从入门到爱不释手,之:Dagger2进阶知识及在Android中使用
- 【概率论基础01】:通俗解释,啥叫随机变量?
- mysql front下载,MySQL-Front下载
- 用计算机做电子贺卡送祝福,春节祝福电子贺卡模板制作
- android接入facebook登陆
- PHP面向对象编程的基本概念定义操作属性方法
- 在线网校教育平台的开发,题库的搭建必不可少
- Java - JIT即时编译器
热门文章
- 对 Error-State Kalman Filter 的理解
- 揭开POJO的神秘面纱
- YII2使用时出现The file or directory to be published does not exist
- win10神州网信+UOS双系统安装步骤
- 《BREW进阶与精通——3G移动增值业务运营、定制与开发》一书的网店地址
- android studio教程,Android Studio一个完整的APP实例
- 必看!Java 学习路线
- chapter8——消抖技术
- 孙子兵法——3(将,五德五危)
- Bilateral Filter、Cross/Joint Bilateral Filter