Three Letter Codes
The three-letter codes are assigned by IATA, the airlines' trade association. There is no system, an airport can request any code it wants and, if it is free, it will be granted. Usually an airport chooses something mnemonic: SFO, BOS(ton), AMS(terdam), FRA(nkfurt). Sometimes the mnemonic is for the name of the airport rather than the city it serves: JFK, HND (Tokyo Haneda), ARN (Stockholm Årlanda), ORY (Paris Orly).
Airports sometimes change names, and sometimes new airports are built which replace an older one. Sometimes the codes follow, sometimes they don't. When New York's Idlewild (IDL) was renamed John F Kennedy following his assassination, it became JFK. But when Chicago's Orchard Field (ORD) was renamed O'Hare, it kept its old code. LED made perfect sense for Leningrad's airport, but is less obvious now the city is called St Petersburg. The same applies to PEK(ing) for Beijing and CAN(ton) for Guangzhou. Hong Kong got a brand new airport, replacing the cramped and challenging Kai Tak, but kept the same code, HKG.
That still leaves quite a few mysteries. Sometimes the code reflects local knowledge: Shanghai is PVG for its immediate locality, Pudong. Cincinatti, Ohio is CVG because the airport is actually across the state line in Covington, Kentucky.
Canada chose to have all its airport codes begin with Y. The story goes that originally they used two letter codes, for example VR for Vancouver. When the world standardised on three-letter codes, they just added Y to the front, making YVR. Since then, though, they seem to be allocated at random. The best known is YYZ, for Toronto.
In the US, the FAA has a say too. It assigns three-letter codes for many small airports with no airline service, which frequently conflict with IATA codes. One of the most flagrant is HND, a reliever airport for Las Vegas in Henderson, Nevada. But IATA's HND is Tokyo Haneda, the fifth busiest airport in the world. Presumably anticipating commercial service, Henderson now has an IATA code too, HSH.
The FAA reserves the initial letter N for US Navy facilities - for example Google's home airport, Moffett Field in Mountain View, California, which is NUQ. In consequence, civil airports have to jump through hoops to avoid the letter: EWR for Newark, New Jersey, ORF for Norfolk, Virginia, BNA for Nashville, Tennessee. In the past it also reserved K and W, which were used for radio stations, so Key West, Florida is EYW. But that seems now to have been relaxed, allowing for example WVI for Watsonville, California.
Like Canada, the US originally used two-letter codes. Generally these just got an X added to them, e.g. LAX, PDX (Portland, Oregon). San Francisco was SF, but added an O to become the more mnemonic SFO. The letters Q and X often show up as filler letters, for example TXL for Berlin Tegel.
Four Letter Codes
So much for the three letter codes. ICAO, the International Civil Aviation Organization, assigns four letter codes. In the US, this is very simple. The country is assigned the initial letter K, which it simply applies as a prefix to the FAA code. So San Francisco becomes KSFO, New York JFK becomes KJFK. Canada did the same thing, with initial letter C, so Toronto is CYYZ, Vancouver is CYVR.
There aren't enough letters for each country to have its own, so almost all countries have a two letter identifier. The first letter identifies the region, e.g. E for northern Europe, and the second the country, so EG is the United Kingdom. Within that, every country does what it wants. Many countries assign the third letter to some kind of internal region, often on a basis which is hard to figure out. EGL is the region around Heathrow, whose full code is EGLL. White Waltham airfield a few miles to the west is EGLM. This does lead to oddities. The code EGGW is assigned... to Luton, north of London. Gatwick, south of London, is EGKK. I'm sure this once made sense to someone.
France has the prefix LF. L is southern Europe, and is full - all 26 letters are in use, so when Kosovo became a country it had to steal its prefix from the North Atlantic region becoming BK along with BG (Greenland) and BI (Iceland). LFB is the Bordeaux region, so Toulouse is LFBO, which makes no sense at all.
A handful of other countries have single letter codes. U was the Soviet Union. Some codes are assigned to former USSR regions, e.g. UK for Ukraine. Z is mainly China, though ZK and ZM are North Korea and Mongolia respectively.
Australia somehow managed to wangle Y for itself, though it has fewer airports than many two-letter countries. It could have taken the same path as the US and Canada, so Melbourne for example would be YMEL. But somewhere a bureaucrat decided this would be too simple, so they have they same regional approach as the UK. Still, YM is the Melbourne region, but evidently the same bureaucrat's compulsive nature would not allow YMEL. Melbourne's main airport is YMML, and Sydney's main airport is YSSY.
The South Pacific region is N, allowing New Zealand to be NZ - surely not a coincidence. This also gives rise to the only airport in the world whose ICAO code is the same as its name: NIUE.
Japan does things differently. Its best known airport is Tokyo Narita, which becomes RJAA. Tokyo Haneda is RJTT, presumably T for Tokyo. The old Osaka airport is RJOO, though the new one, generally known (like LAX) by its IATA code, KIX, is RJKI.
It is one of life's great mysteries why the US was assigned K, rather than U or A which went to Western South Pacific, e.g. AY for Papua New Guinea. Strictly, this only applies to the "lower 48". Alaska is PA, conveniently allowing Anchorage (IATA ANC) to be PANC, while Hawaii is PH, allowing Honolulu (IATA HNL) to be PHNL.
There's a wonderful site at airportcod.es that lists and explains nearly all the three-letter IATA codes. For the ICAO codes, the Wikipedia page is the best resource. There are also quite a lot of articles out there covering various interesting subsets of the three-letter codes, for which Google is your friend.