Assume a map-reduce program has $m$ mappers and $n$ reducers ($m > n$). The output of each mapper is partitioned according to the key value and all records having the same key value go into the same partition (within each mapper), and then each partition is sent to a reducer. Thus there might be a case in which there are two partitions with the same key from two different mappers going to 2 different reducers. How to prevent this from occurring? That is, how to send all partitions (from different mappers) with the same key to the same reducer?
Let's take a simple example, Counting word into a distributed set of documents:
each mapper takes in input a list of document, and returns a list of pairs word and how many times this word occurs. There is an intermediate layer that takes the outputs of all the mapper and groups values by key. After that the reducer will sum each of this value. This is a practical example:
Output of 3 mappers
before give these data to the reducer the intermediate layer will group them by key. obtaining :
After that reducers take in input these pairs and sum values:
The MapReduce idea comes from a paper by google that you can find here: http://research.google.com/archive/mapreduce.html
reading this article you will notice that the mapper gives in output a list of pairs, but the reducer takes in input a pair of (key , list(value)) this implies that there is something in between that "lists" all values with the same keys. This task is done on the output of ALL the mappers, this task is optimized , sorting values ecc.. but as i say is in practice done on all the mapper.
If you know a little of java i suggest you to try something using the Hadoop framework by Apache
as you can see in the linked example the CombinerFunction(the intermediate layer that i've mentioned) works on the same input of the reducers.