Each time an object is rezzed, each of its primitives receives a new, different, and probably unique key. It is probably worth thinking of llGetKey's result as the key associated with the prim's current existence in the world (or identifying its current session with the world) rather than as a key "for" the prim as such. This behavior is the case whether you have copy permission over the object or not. It almost goes without saying that different copies of the "same" object each have different keys for each of their constituent prims.

Teleporting from one place to another causes attachments to be derezzed and rezzed at the new location. This implies that when teleporting, all attachment scripts will receive an on_rezevent, and each attachment's prims will be given a new key. Scripts making use of llGetKey should update the key in their on_rez event. None of the above applies to the short distance "teleport hack" using llSitTarget, however.

(The above is not true, or no longer true as of 1.18.0. Attachments do not get an on_rez event when teleporting, nor do they get a different key. -- Siann Beck)
(They do, however, get a new key when you relog. -- Chase Marellan)

Email can only be sent to an object (either from the outside world or using llEmail) using a prim's key as part of the email address. Therefore, to get a long-lasting in-world target for email, either redirect it through a relay outside Second Life or make very sure that the target object will never be derezzed.

Modifying a prim (for example, by editing the scripts in it) does not change its key. Resaving a script does give the script itself a new key, but a script's key is retrieved with llGetInventoryKey, not llGetKey.