数据库大概存储几十万条IP记录,记录集如下:
+----------+----------+------------+---------+---------+--------+--------+
| ip_begin | ip_end | country_id | prov_id | city_id | isp_id | netbar |
+----------+----------+------------+---------+---------+--------+--------+
| 0 | 16777215 | 2 | 0 | 0 | 0 | 0 |
| 16777216 | 33554431 | 2 | 0 | 0 | 0 | 0 |
| 33554432 | 50331647 | 2 | 0 | 0 | 0 | 0 |
| 50331648 | 67108863 | 3 | 0 | 0 | 0 | 0 |
| 67108864 | 67829759 | 3 | 0 | 0 | 0 | 0 |
+----------+----------+------------+---------+---------+--------+--------+
这样做查询需要用到如下SQL:
$sql = 'SELECT * FROM i_m_ip WHERE ip_begin = $client_ip';
?>
这样的检索显然用不到索引,即使用到,MySQL查询效率也不大可能达到每秒500次以上,我做了很多并发优化,最终平均查询效率也只有每秒200次左右,实在是头痛。一开始我也有想到借鉴纯真IP库的检索方法,但是我一直对算法有抵触,也以为二分法很难,所以就没有尝试使用,直到最后没有办法了,才最终实现了二分法的IP地址检索。
从上表可以看到IP库是从0到4294967295的一个连续数值,这个数值要是拆开存储,会有几百G的数据,所以没办法使用索引也没办法哈希。最终我使用PHP将这些东东转为二进制存储,抛弃了数据库的检索。可以看到IP起止长度为一个4字节的长整型,后面的国家ID、省份ID等,可以使用2个字节的短整型来存储,总共一行数据就有18个字节,总共31万条数据,算起来也就5M的样子。具体IP库生成代码如下:
/*
IP文件格式:
3741319168 3758096383 182 0 0 0 0
3758096384 3774873599 3 0 0 0 0
3774873600 4026531839 182 0 0 0 0
4026531840 4278190079 182 0 0 0 0
4294967040 4294967295 312 0 0 0 0
*/
set_time_limit(0);
$handle = fopen('./ip.txt', 'rb');
$fp = fopen("./ip.dat", 'ab');
if ($handle) {
while (!feof($handle)) {
$buffer = fgets($handle);
$buffer = trim($buffer);
$buffer = explode("\t", $buffer);
foreach ($buffer as $key => $value) {
$buffer[$key] = (float) trim($value);
}
$str = pack('L', $buffer[0]);
$str .= pack('L', $buffer[1]);
$str .= pack('S', $buffer[2]);
$str .= pack('S', $buffer[3]);
$str .= pack('S', $buffer[4]);
$str .= pack('S', $buffer[5]);
$str .= pack('S', $buffer[6]);
fwrite($fp, $str);
}
}
?>
这样IP就按照顺序每18字节一个单位排列了,所以很容易就使用二分法来检索出IP信息:
function getip($ip, $fp) {
fseek($fp, 0);
$begin = 0;
$end = filesize('./ip.dat');
$begin_ip = implode('', unpack('L', fread($fp, 4)));
fseek($fp, $end - 14);
$end_ip = implode('', unpack('L', fread($fp, 4)));
$begin_ip = sprintf('%u', $begin_ip);
$end_ip = sprintf('%u', $end_ip);
do {
if ($end - $begin fseek($fp, $begin + 8);
$info = array();
$info[0] = implode('', unpack('S', fread($fp, 2)));
$info[1] = implode('', unpack('S', fread($fp, 2)));
$info[2] = implode('', unpack('S', fread($fp, 2)));
$info[3] = implode('', unpack('S', fread($fp, 2)));
$info[4] = implode('', unpack('S', fread($fp, 2)));
return $info;
}
$middle_seek = ceil((($end - $begin) / 18) / 2) * 18 + $begin;
fseek($fp, $middle_seek);
$middle_ip = implode('', unpack('L', fread($fp, 4)));
$middle_ip = sprintf('%u', $middle_ip);
if ($ip >= $middle_ip) {
$begin = $middle_seek;
} else {
$end = $middle_seek;
}
} while (true);
}
以上$fp为打开ip.dat的文件句柄,由于是循环检索,所以写在函数外面,免得每次检索都要打开一次文件,30W行数据二分法最多也只需要循环7次(2^7)左右即可找到准确的IP信息。之后本来还想将ip.dat放在内存中加快检索速度,后来发现,字符串定位函数的效率,根本和文件指针的偏移定位不是在一个数量级的,所以还是放弃使用内存来存放IP库。
这个实现,使IP检索效率提高了近百倍,只是一个简单的二分法的应用,从此算法在WEB应用中不重要的观念彻底打消了。其实要实现这个,我还请教了金狐,我一开始是请他帮我生成一个纯真格式的IP库,然后用Discuz的IP查询函数来检索,不过他不肯帮我,最后造就了我的这个实践和学习。有时候,求人不如求己。

PHP와 Python은 각각 고유 한 장점이 있으며 선택은 프로젝트 요구 사항을 기반으로해야합니다. 1.PHP는 간단한 구문과 높은 실행 효율로 웹 개발에 적합합니다. 2. Python은 간결한 구문 및 풍부한 라이브러리를 갖춘 데이터 과학 및 기계 학습에 적합합니다.

PHP는 죽지 않고 끊임없이 적응하고 진화합니다. 1) PHP는 1994 년부터 새로운 기술 트렌드에 적응하기 위해 여러 버전 반복을 겪었습니다. 2) 현재 전자 상거래, 컨텐츠 관리 시스템 및 기타 분야에서 널리 사용됩니다. 3) PHP8은 성능과 현대화를 개선하기 위해 JIT 컴파일러 및 기타 기능을 소개합니다. 4) Opcache를 사용하고 PSR-12 표준을 따라 성능 및 코드 품질을 최적화하십시오.

PHP의 미래는 새로운 기술 트렌드에 적응하고 혁신적인 기능을 도입함으로써 달성 될 것입니다. 1) 클라우드 컴퓨팅, 컨테이너화 및 마이크로 서비스 아키텍처에 적응, Docker 및 Kubernetes 지원; 2) 성능 및 데이터 처리 효율을 향상시키기 위해 JIT 컴파일러 및 열거 유형을 도입합니다. 3) 지속적으로 성능을 최적화하고 모범 사례를 홍보합니다.

PHP에서, 특성은 방법 재사용이 필요하지만 상속에 적합하지 않은 상황에 적합합니다. 1) 특성은 클래스에서 다중 상속의 복잡성을 피할 수 있도록 수많은 방법을 허용합니다. 2) 특성을 사용할 때는 대안과 키워드를 통해 해결할 수있는 방법 충돌에주의를 기울여야합니다. 3) 성능을 최적화하고 코드 유지 보수성을 향상시키기 위해 특성을 과도하게 사용해야하며 단일 책임을 유지해야합니다.

의존성 주입 컨테이너 (DIC)는 PHP 프로젝트에 사용하기위한 객체 종속성을 관리하고 제공하는 도구입니다. DIC의 주요 이점에는 다음이 포함됩니다. 1. 디커플링, 구성 요소 독립적 인 코드는 유지 관리 및 테스트가 쉽습니다. 2. 유연성, 의존성을 교체 또는 수정하기 쉽습니다. 3. 테스트 가능성, 단위 테스트를 위해 모의 객체를 주입하기에 편리합니다.

SplfixedArray는 PHP의 고정 크기 배열로, 고성능 및 메모리 사용이 필요한 시나리오에 적합합니다. 1) 동적 조정으로 인한 오버 헤드를 피하기 위해 생성 할 때 크기를 지정해야합니다. 2) C 언어 배열을 기반으로 메모리 및 빠른 액세스 속도를 직접 작동합니다. 3) 대규모 데이터 처리 및 메모리에 민감한 환경에 적합하지만 크기가 고정되어 있으므로주의해서 사용해야합니다.

PHP는 $ \ _ 파일 변수를 통해 파일 업로드를 처리합니다. 보안을 보장하는 방법에는 다음이 포함됩니다. 1. 오류 확인 확인, 2. 파일 유형 및 크기 확인, 3 파일 덮어 쓰기 방지, 4. 파일을 영구 저장소 위치로 이동하십시오.

JavaScript에서는 NullCoalescingOperator (??) 및 NullCoalescingAssignmentOperator (?? =)를 사용할 수 있습니다. 1. 2. ??= 변수를 오른쪽 피연산자의 값에 할당하지만 변수가 무효 또는 정의되지 않은 경우에만. 이 연산자는 코드 로직을 단순화하고 가독성과 성능을 향상시킵니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

Atom Editor Mac 버전 다운로드
가장 인기 있는 오픈 소스 편집기

드림위버 CS6
시각적 웹 개발 도구

ZendStudio 13.5.1 맥
강력한 PHP 통합 개발 환경

에디트플러스 중국어 크랙 버전
작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음
