RabbitMQ differs from brokers such as ActiveMQ because it uses a level of indirection between the producer and a consumer. The exchanges implement such indirection similarly (but not quite the same!) to how post offices are in the middle between who sends a postcard and who receives it.
The producer sends a message to an exchange specifying a routing key. The exchange finds all the queues listening to that particular routing key and propagates a copy of the message.
There are four types of exchanges: Direct, Topic, Fanout, and Header.
Direct matches the routing key exctly. If a message has routing key foo.bar, only the queues listening to foo.bar will receive the message.
Topic matches the routing key and allows wildcards. If a message has routing key foo.bar, the queues listening to foo.bar, to foo.*, and to *.bar will receive the message.
Fanout is the simplest: it broadcasts all the messages to all the queues ignoring the routing key.
Header works like Topic, but using headers.
Recommendation
The recommendation is to use only Topic (the most flexible) or Direct (slightly faster) and to have only one exchange. Having multiple exchanges may be useful for the design, but it has costs in terms of performances.
Examples
Scenario: 1 producer, 2 consumers
With Direct Exchange
the producer and the consumers use my.routing.value
- both consumers receive all the messages
the producer uses my.routing.value, one consumer uses my.*.value, and the second consumer uses my.routing.value
- only the second consumer (with my.routing.value) receives a message
one consumer uses both my.routing.value1 and my.routing.value2, the other consumer uses both my.routing.value1 and my.routing.value3
- when the producer uses
my.routing.value1both consumers get the messages - when the producer uses
my.routing.value2only one consumers gets the messages
With Topic Exchange
the producer and the consumers use my.routing.value
- both consumers receive all the messages
the producer and one consumer use my.routing.value, and the second consumer uses my.*.value
- both consumers receive all the messages
the producer uses my.something.value, one consumer uses my.routing.value, and the second consumer uses my.*.value
- only the second consumer (with
my.*.value) gets the message
the producer uses my.*.value, one consumer uses my.foo.value, and the second consumer uses my.bar.value
- no consumer receive anything


Final note
It is possible to bind the same queue to two different exchanges / routing keys
eg.
exchange-1-routing-key1exchange-2-routing-key2
a queue can bind on both and receive all the messages