For development data, I’ve downloaded a free IP-to-city database available from http://dev.maxmind.com/geoip/geolite. This database contains two important files: Geo-
LiteCity-Blocks.csv, which contains information about ranges of IP addresses and city
IDs for those ranges, and GeoLiteCity-Location.csv, which contains a mapping of city
IDs to the city name, the name of the region/state/province, the name of the country,
and some other information that we won’t use.
We’ll first construct the lookup table that allows us to take an IP address and convert
it to a city ID. We’ll then construct a second lookup table that allows us to take the
city ID and convert it to actual city information (city information will also include
region and country information).
The table that allows us to find an IP address and turn it into a city ID will be constructed
from a single ZSET, which has a special city ID as the member, and an integer
value of the IP address as the score. To allow us to map from IP address to city ID, we
convert dotted-quad format IP addresses to an integer score by taking each octet as a
byte in an unsigned 32-bit integer, with the first octet being the highest bits. Code to
perform this operation can be seen here.
After we have the score, we’ll add the IP address mapping to city IDs first. To construct
a unique city ID from each normal city ID (because multiple IP address ranges can
map to the same city ID), we’ll append a _ character followed by the number of entries
we’ve added to the ZSET already, as can be seen in the next listing.
When our IP addresses have all been loaded by calling import_ips_to_redis(), we’ll
create a ZSET that maps city IDs to city information, as shown in the next listing. We’ll
store the city information as a list encoded with JSON, because all of our entries are of
a fixed format that won’t be changing over time.
Now that we have all of our information in Redis, we can start looking up IP addresses.