Experiencia con el almacenamiento de direcciones IP en PostgreSQL

Descripción del problema

Más de una vez, nuestro equipo en Karuna enfrentó el desafío de almacenar y usar direcciones IP en una base de datos. Supongamos que hay una tarea típica: necesita analizar una gran cantidad de rangos de direcciones (~ 300k) de un  recurso conocido y luego determinar el país por la dirección IP del cliente. No parece nada especial. Esto se puede resolver de manera bastante simple mediante cualquiera de los métodos descritos a continuación con cargas bajas. ¿Pero si tenemos miles de usuarios, o nuestro servicio es un proxy frente a todos los demás? En este caso, no quieres ser un cuello de botella y tienes que luchar por cada fracción de segundo.





Un poco sobre abordar

Hay 2 tipos de direccionamiento de red





INET ( IP-) — , 1981 1993 . .





CIDR (Classless Inter-Domain Routing,  ) — IP-, .





 address/y,  y — . , /28 , 28 IP- , 4  — , .





,  192.168.5.0/24   192.168.5.1  192.168.5.254,  192.168.5.0 —  192.168.5.255 — .





inet cidr

PostgreSQL 2 IP- : inet  cidr.  inet/cidr.





 inet  , .  address/y.  y , 32 ( IPv4), .





 cidr  IPv4 ( IPv6).  address/y.  y  , (INET).





,  inet  ,  cidr . /8,  cidr , 24 , inet  . , 255.0.0.2/8  cidr .. 255.0.0.0  ( 2 ). 255.128.128.7/24, 255.255.255.255/31 — ,  inet  .





-?

(MacBook 16, 2019 2,6 GHz 6-Core Intel Core i7). IP-:





CREATE INDEX ON ip_ranges USING GIST (ip_range inet_ops);
      
      



(1.000.000) IP- :





DO
$$
DECLARE 
 i RECORD;
BEGIN
 FOR i IN 1..1000000 LOOP
  PERFORM country_id FROM ip_ranges WHERE ip_range >>= ‘{random_ip}’;
 end loop;
END;
$$
;
      
      



.





inet





cidr





749





891





ip4r

—  ip4r, .





, , PostgreSQL. . , .





 38 .





( ?)

 nginx,  geo , IP- .  docker-compose.yml:





version: '3.7'

services:
  web:
    image: nginx:latest
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./GeoIP.dat:/var/geo/GeoIP.dat
      - ./geo.conf:/var/geo/geo.conf
    ports:
      - "8080:80"
    environment:
      - NGINX_PORT=80
      
      



 nginx:





http {
        ...
    geo $geo {
        default        NONE;
        include        /var/geo/geo.conf;
    }
    geoip_country /var/geo/GeoIP.dat;
        ...
    server {
        ...
        location / {
            ...
            add_header Geo-By-File $geo;
            add_header Geo-By-Binary $geoip_country_code;
        }
    }
}
      
      



,  $geo,  geo.conf :





128.0.0.0/1 US;
...
      
      



 GeoIP.dat  , ($geoip_country_code).





, . , ( , , ..).





, PostgreSQL — . , .





, ( ). , .. , - .





, , ,  inet  cidr, .  ip4r  ~20 .








All Articles