一.rabbitmq publisher(生产者)注意的几个点
1.深刻理解异步模式
1.1默认情况,publisher->server,server不会将publisher的请求的执行情况,返回给publisher。换句话说,默认,publisher只知道执行了生产消息的动作,不知道server是否已成功存储msg,更不知道msg是否已被consumer消费。
1.2如果,使用confirm模式,publisher->server,server只会告知publisher,是否接收到了请求。publisher只知道server接收到了msg,但不知道msg是否成功存储到queue。
1.3如果,使用了mandatory标志位,publisher->server,server会告知publisher,是否正确找到对应的queue,并把msg保存到了queue中。
1.4如果,使用了immediate标志位,publisher->server,server上如果该消息关联的queue上有消费者,则马上将消息投递给它,如果所有queue都没有消费者,直接把消息返还给生产者,不用将消息入队列等待消费者了。RabbitMQ 3.0.0以后的版本中去掉了immediate参数支持


2.关于失败重连模式
2.1最简单方式,捕获异常,判断异常信息,重新连接。try.....,except,(catch)。
2.2也可以调用对应的类对象,实现重连。比如java client 方法
ConnectionFactory factory = new ConnectionFactory();
factory.setAutomaticRecoveryEnabled(true); //设置网络异常重连
factory.setNetworkRecoveryInterval(10000);//设置 没10s ,重试一次
factory.setTopologyRecoveryEnabled(true);//设置重新声明交换器,队列等信息。
#http://www.rabbitmq.com/nightlies/rabbitmq-java-client/current-javadoc/


3.关于持久化
3.1msg,交换器,队列,都做持久化是保证msg被持久化的条件之一。
3.2需要配置confirm模式及mandatory标志位,保证msg被存储到queue中(见1.4)


4.关于集群写入数据模式
4.1rabbitmq底层,采用mnesia分布式数据库,存储数据。
4.2有镜像队列的集群中msg的写入,mnesia数据库事务模式有好几种,rabbitmq采用 sync_transaction 模式写入数据,来保证各个节点数据一致。
4.3虽然rmq,使用mnesia的sync_transaction模式,但是仔细研究两阶段事务提交协议,极个别情况下,也会出现,server反馈给client,master写入失败,但是其它节点写入成功的情况。也就说极个别情况,客户端会得到server写入失败的信息,实际是写入成功的。这种情况,client可能会再写一个msg。导致队列中消息重复。解决这个问题,需要消费者去保证,确定msg是否是已消费过的。
#
#http://wqtn22.iteye.com/blog/1567715
#https://github.com/sky-big/RabbitMQ


5.关于集群中出现重复数据
5.1需要确认是不是publisher重复发送msg导致的。
5.2rmq底层采用mnesia数据库做存储。mnesia的事务执行的流程,存在这种可能性,即如果事务发起者节点本身挂掉了,远端节点间会相互询问事务的最终执行结果,如果有节点成功提交,那么其他节点也会得到通知并执行提交动作,相反如果没有节点成功提交,那么所有节点都会终止该事务的提交。
这种情况,“有节点成功提交,那么其他节点也会得到通知并执行提交动作”会导致整个集群节点事务提交成功.
但因为master挂了,publisher会获取到提交事务失败。之后如果publisher重试,重新发送msg,这就导致msg是重复的。
5.3publisher->server,server将msg存储完之后,server宕机,没有将最后的ack返回给publisher。这时,对client而言,写入失败,对server而言,写入成功。如果publisher重连其它节点,重写msg,就会导致msg重复。
5.4所以 msg/数据 是否重复,不应该由server保证,应该由应用方保证。金融类系统,需要注意。
#http://bravenewgeek.com/you-cannot-have-exactly-once-delivery/
#http://fengchj.com/?p=2367