Pengalaman menyimpan alamat IP di PostgreSQL

Deskripsi masalah

Lebih dari sekali, tim kami di Karuna menghadapi tantangan untuk menyimpan dan menggunakan alamat IP dalam database. Mari kita asumsikan bahwa ada tugas umum: Anda perlu mengurai sejumlah besar rentang alamat (~ 300k) dari  sumber daya yang dikenal , dan kemudian menentukan negara berdasarkan alamat IP klien. Sepertinya tidak ada yang istimewa. Ini dapat diselesaikan dengan cukup sederhana dengan salah satu metode yang dijelaskan di bawah ini pada beban rendah. Tetapi jika kami memiliki ribuan pengguna, atau apakah layanan kami merupakan proxy di depan semua orang? Dalam hal ini, Anda tidak ingin menjadi hambatan dan Anda harus berjuang untuk setiap sepersekian detik.





Sedikit tentang mengatasi

Ada 2 jenis pengalamatan jaringan:





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