This article details the architectural decisions and implementation strategies behind a high-scale IP geolocation service. It focuses on leveraging Redis's partitioned sorted sets and pipelining capabilities to achieve sub-millisecond enrichment for millions of events, addressing challenges like data freshness, query performance, and operational efficiency.
Read original on Medium #system-designBuilding a performant IP geolocation service requires efficient data storage and retrieval, especially when dealing with massive datasets and high query volumes. Traditional database lookups can introduce unacceptable latency. This article explores an architecture designed to handle millions of events with sub-millisecond response times, primarily using Redis as the core data store.
IP ranges are effectively stored and queried using Redis sorted sets. Each sorted set can represent a geographical region (e.g., country, state), with IP ranges stored as members and their start IP (converted to a numerical score) as the score. This allows for efficient range queries using ZRANGEBYSCORE, retrieving all IP ranges that potentially contain a target IP address.
IP to Score Conversion
To effectively use Redis sorted sets for IP range lookups, convert IP addresses into a single numerical score (e.g., unsigned 32-bit integer for IPv4) to enable numerical comparisons and range-based querying.
To scale beyond a single Redis instance, the dataset is partitioned across multiple Redis shards. This involves distributing IP ranges based on a consistent hashing strategy or by geographical region. For instance, different countries or continents could reside on separate Redis instances, allowing for horizontal scaling and better management of individual sorted set sizes.
For batch processing or scenarios where multiple lookups are needed, Redis pipelining significantly reduces network overhead. Instead of sending one command at a time and waiting for a response, multiple commands are buffered and sent to Redis in a single round trip. This is crucial for achieving the targeted sub-millisecond enrichment at scale, as network latency often dominates individual command execution times.