纯真ip数据库怎么使用(暴力生成 IP 库)
在移动互联网的应用中,经常需要根据用户的位置信息等做一些用户侧信息的统计分析。而要拿到用户的位置信息,一般有两个方法: GPS 定位的信息和用户 IP 地址。由于每个手机都不一定会打开 GPS,而且有时并不太需要太精确的位置(到城市这个级别即可),所以根据 IP 地址入手来分析用户位置是个不错的选择。 要做到这个功能得需要一个 IP 和地理位置的映射关系库,并依赖这个库启动一个 IP 转地理位置的服务。本文从需求入手,结合 Github 上拥有 8.4k 星的 ip2region 来分析映射关系库的设计以及 IP 如何快速转换成地理位置。
介绍
IP 定位服务很常见,而且很多公司都提供了类似的付费服务,比如阿里,高德,百度等,当然也有公开的免费服务,像 GeoIP,纯真IP等。这些服务要么通过 HTML 页面解析,要么通过接口请求,但不管怎样都离不开一次 http 请求,更不用说大部分服务都对 QPS 作了限制。下表枚举了一些常见的通过 IP 获取地址的方式。
(相关资料图)
在日常工作通常需要将大量用户请求日志中 IP 转换成用户位置信息,用作后续的分析。这其中的关键是数据量大,处理要快。显然每次都通过请求 API 公共服务的方式无法满足我们的日常需求。
暴力生成 IP 库
对于日常的需求,一种简单粗暴的做法就是提前通过 API 获取所有公网 IP 对应的位置信息,按照下面的 TIPS 中我们可以估算出如果通过访问淘宝IP地址库来遍历 3.3 亿的国内 IP 地址要 10 年。如果是高德的企业用户遍历国内 IP 地址大概要 11 天。感觉这个 11 天还是能够接受的。
TIPS: IPv4
目前所说的 IP 地址是指 IPv4,它是使用 32 位(4 字节)地址,因此地址空间约有 42.9 亿$2^32=4294967296$个, 不过一些地址是作为特殊用途所保留的,如专用网络(约 1800 万个)和多播地址(约 2.7 亿个),这些减少了可在互联网上路由的地址数量。 据 wiki 上统计,中国的 IPv4 数量达到 3.3 亿,而美国有 15.4 亿个。
这里我们约定一下位置信息的数据格式: 国家|区域|省份|城市|ISP,如果接口中返回的字段没有对应的信息,则对应的字段填充0。那么我们通过顺序请求 API 服务可以获取到如下文件数据(地址依次递增):
0.0.0.0|0|0|0|内网IP|内网IP0.0.0.1|0|0|0|内网IP|内网IP...1.0.15.255|中国|0|广东省|广州市|电信...255.255.255.255|0|0|0|内网IP|内网IP
只要有了这个文件,可以将其读到内存中,使用字典保存,键为 IP 地址,值为位置信息。程序可以在 O(1) 时间复杂度内返回位置信息,不过该程序或文件占用的大小我们可以粗略的计算一下。 假定我们使用 utf-8 进行存储,一条记录最短的情况是 0.0.0.0|0|0|0|0|0,占用17个字节,IP 库文件的大小为 17*4294967296 = 73014444032 B = 71303MB = 71GB。这个大小是任意一个程序不能接受的。
空间优化
IP 库文件优化
从上面的文件数据发现大量的相邻 IP 拥有相同的位置信息(客户在申请一段 IP 地址都会尽量连在一起),所以我们可以将这样的记录合成一条记录。如下文件数据(地址段依次递增):
0.0.0.0|0.255.255.255|0|0|0|内网IP|内网IP...1.0.8.0|1.0.15.255|中国|0|广东省|广州市|电信...224.0.0.0|255.255.255.255|0|0|0|内网IP|内网IP
ip2region 库中最新的 ip.merge.txt 共有 658207 记录,文件大小 39 M。
IP地址优化
从上面的文件数据发现大量的IP地址以字符串形式存储,而 IPv4 是使用 32 位地址。所以将其转换成整型进行存储可以大大节省空间,比如像最短的字符串 0.0.0.0 占据 7 字节,最长的字符串 111.111.111.111 占据 15 字节,如果将其转换成整型,他们都占据 4 字节。0.0.0.0 是 int(0), 111.111.111.111 是 int(1869573999)。
位置信息优化
从上面的文件数据发现相同的位置信息会对应不同的 IP 段(客户可能在不同的时间段去申请 IP 段),所以还是有大量的位置信息在 IP 库文件中,在内存中我们可以只保留一份位置信息,并使用指针或者文件偏移量+数据长度来获取对应的位置信息。
优化后的IP库
根据上面的优化,我们可以生成最终的IP库:ip2region.db,该文件只有8.1M。
IP库的结构
IP 库文件ip2region.db的结构分为四个部分:super 块, header索引区,数据区,索引区。具体如下图所示:
super 块用来保存索引块的起始地址和结束地址,第一个索引指针指向索引块的开始位置,也就是第一个索引分区的第一个索引块, 最后一个索引指针 指向索引块的结束位置-12,也就是最后一个索引分区的最后一个索引块的头地址。这样查询的时候直接读取super块 8 个字节,就能快速获取索引块的地址范围。header 索引区
header索引是对索引块的二级索引,专门为b+tree搜索服务的。索引区总长度除以索引分区长度12*(1024*8/12-1)就是 header 索引的实际索引数。该区域大小为 2048*8 bytes, 由 2048 个 8 bytes 的 header 索引块组成。header索引块前四个字节存储每个索引分区第一个索引块的起始ip值,后四个字节指向该索引块的地址。
header索引区之所以定义为接近16k,是因为可以通过四次磁盘读取读取整个header索引区,然后在内存中进行查询,查询的结果可以确定该ip在索引区的某个索引分区内,然后再根据地址两次读取8k 索引分区到内存,再在内存中查询,从而减少磁盘读取的次数。数据区
保存的数据,数据格式如下:中国|华南|广东省|深圳市|鹏博士, 分别表示国家,区域,省份,城市,运营商索引区
索引区是由索引块构成, 每个索引块占 12 字节,包括起始IP, 结束IP, 数据信息。数据信息中前三个字节保存数据地址,后一个字节保存数据长度。 每一条索引块对应 ip.merge.txt 中的一条记录,表示一个 IP 段的索引。在检索中当指定 IP 在某个索引块的起始IP和结束IP中间,即表示命中索引。再通过索引块中的数据地址和数据长度,就能从 ip2region.db 读取对应的位置信息数据。
IP库的生成
ip2region 的 Github 仓库中提供了 ip2region.db 的生成过程,是用 JAVA 写的,其类图如下所示:
通过熟悉生成 ip2region.db 的源码,简述一下其生成过程如下:
通过 RandomAccessFile 在文件中预留 8 bytes 的 super 块和 2048*8 bytes 的 header 索引区扫描 ip.merge.txt 文件,对每一条记录作如下处理:依据每一条记录的起始IP, 结束IP 和数据,生成一个索引块, 前四个字节存储起始IP, 中间四个字节存储结束IP, 后四个字节存储已经计算出的数据地址(通过 RandomAccessFile 写入,这里维护一个位置信息到文件位置的字典,保证同一个位置信息只写入一次。),并将索引块暂存在 indexPool 链表中。这一步会将数据区的所有位置信息确定。扫描完 ip.merge.txt 中所有的记录, 将 indexPool 中所有的索引块写到数据区后面。在此过程中将 int(1024*8/12-1)= 681 个索引块组成一个索引分区,并记录下每个索引分区第一个索引块的起始IP和地址信息(header块),并暂存在 headerPool 链表中。此外还会将索引区的起始位置和结束位置记录下来。调整 RandomAccessFile 指向文件开头,写入索引区的起始位置存储到 super 块的前四个字节,结束位置存储到 super 块的后四个字节。继续将 headerPool 中的 header 块写入到 header 区。调整 RandomAccessFile 指向文件结尾,写入时间戳和版权信息。
TIPS: ip2region 仓库中还使用了 global_region.csv 数据,该文件有5列(行号,,区域,,邮政编码),对应着区域的具体信息,可以往数据区每个位置信息中填充。
快速搜索
ip2region 提供三种查询算法,最差的查询耗时都是ms级别的。分别是内存二分搜索,b+tree搜索,二分查找。耗时依次增加。其搜索结构图如下:
二分搜索
通过 super 块可以拿到索引区的起始位置和结束位置,而且每个索引块都是 12 bytes,其中的 IP 地址都是递增的,所以可以使用二分搜索来快速获取位置信息。其步骤如下:
把 IP 值通过 ip2long 方法转为整型读取 super 块获取索引区的起始位置和结束位置,二者相减 +1 可得索引块的总个数采用二分法直接求解,比较索引块中起始IP,结尾IP 和当前 IP 的大小,即可找到该 IP 对应的索引块,根据索引块后面四个字节得到数据地址和数据长度,从而拿到位置信息。b+tree搜索
b+tree 搜索用到了 header 索引区,第一步先在 header 索引区中使用二分搜索,定位到某个索引分区后,再在对应的索引分区中使用二分搜索。相比较二分搜索而言,它的速度更快,原因是读磁盘的次数远低于二分搜索。其步骤如下:
把 IP 值通过 ip2long 转为整型使用二分法在 header 索引区中搜索,比较得到对应的 header 索引块以及其对应的索引分区。读取对应索引分区,再通过二分法定位到对应的索引块,从而获得位置信息。基于内存的二分搜索
该方法和二分搜索方法类似,区别就是前者将 ip2region.db 全部读进内存中,后者则是通过不断读取 ip2region.db 文件。
总结
ip2region 库只解决了一个非常常见的 IP 定位问题,但将这个服务做到了又小又快(当然还提供了多语言的客户端),从而在 Github 上获得了 8.4k 的 star。
占用内存小
相邻 IP 的位置信息相同,通过 IP 段来解决相邻 IP 对应相同位置信息,避免位置信息被重复存储IP 转换成 INT,像字符串 111.111.111.111 被转换成int(1869573999),从 15Byte 缩小到 4Byte不同的 IP 段也有相同的位置信息,通过指针来指向特定的位置信息,保证位置信息只保存一次(全量扫描存储进字典中)搜索速度快
IP 有序,使用二分搜索将时间复杂度降到 O(logN)二级索引 header 索引区的使用,降低磁盘读写频率,先确定索引分区,再从索引分区确定索引位置,在确定位置信息数据。多语言客户端支持
支持 java、C#、php、c、python、nodejs、php扩展(php5和php7)、golang、rust、lua、lua_c, nginx。
参考文献
ip2region 数据库文件结构及原理ip2region源码ipv4的维基百科各国IPv4地址分配列表高德地图api百度地图api标签: ip地址
相关阅读
-
世界关注:十大ktv软件电脑版(电脑版ktv点歌软件推荐:电视K歌软件)
随着家庭卡拉OK模式走进大众视野,越来越多的人选择自己购置设备,打造家庭KTV。近几年,随着电视越来越...
2022-12-20 -
每日消息!cucci包真假看什么地方(手把手教你鉴别古驰包包真假)你学会了吗
Gucci包包近些年转型成功,在国内市场迎来了大爆发,牢牢占据了奢侈品榜单的前列,市场上也随之出现了大...
2022-12-20 -
vfp程序设计教程(foxpro数据库编程) 重要文件扩展名
一、重要文件扩展名 dbc数据库 dbf表 fpt表备注 idx单索引 cdx复合索引 qpr查询 prg程序 fxp编...
2022-12-20 -
世界新动态:Wifi密码修改器推荐(如何选择WIFI网卡配置器)
WIFI安全审计中一定要注意的重点就是“Mac”地址;假设当你入侵一个WIFI利用完毕以后你不可能直接丢掉你...
2022-12-20 -
workstation无法启动怎么办(修复workstation服务介绍)
说明:以下是VMwareWorkstation虚拟机软件Linux版本在Linux操作系统下如何安装,使用,缷载的方法。首先...
2022-12-20 -
动态焦点:莱卡相机多少钱一台(莱卡相机最新报价及测评)来看看怎么样
在第一代徕卡Q相机推出近四年后,徕卡终于在2019年年初发布了徕卡Q2相机。相比前代,二代产品不仅使用了...
2022-12-20 -
环球快报:如何打开dps文件(dps格式文件打开方式)看完下文你就明白了
一些网友在网上下载的文件的后缀名是:dps,dps文件是一款比较陌生的文件,许多网友看到的第一感觉就是...
2022-12-20 -
环球观天下!吴雅婷家境-吴雅婷自曝曾患产后抑郁,吴雅婷婚姻失败的原因是什么?
1、吴雅婷家庭背景:吴雅婷自曝曾患产后抑郁症。为什么这是大多数女性产后的真实写照?吴雅婷在曾的节目...
2022-12-20
精彩推荐
阅读排行
相关词
- 天天快讯:再回首原唱是谁,再回首发布于哪一年
- 黄绮珊个人简历 黄绮珊几段婚史 黄绮珊个人介绍
- 全球微速讯:南宫仆射的结局,南宫仆射是男是女 一起来看看吧
- 曹贵修结局,曹贵修介绍 演员阵容有谁
- 张凯丽个人简历-张凯丽个人资料孩子 今年多大了?
- 环球观天下!吴雅婷家境-吴雅婷自曝曾患产后抑郁,吴雅婷婚姻失败的原因是什么?
- 天天百事通!教授等级分多少级,教授等级的历史 一起来了解下吧
- 全球微头条丨巴比龙故事原型 巴比龙讲述了什么
- 弯弯的河水从天上来是什么歌 原唱是谁?
- 即时焦点:歌手周深是男是女,歌手周深简介 什么时候出道的
- 全球滚动:玉娘扮演者,玉娘角色介绍 《笑傲江湖》人物介绍
- 全球讯息:白沙县气象台发布寒冷黄色预警【Ⅲ级/较重】
- 【环球速看料】《全民奇迹》12月20日8周年庆典版本来袭
- 热资讯!《勇者秘境》现已首发 冒险者们的肉鸽生存之战
- 定安运用“三个一”巡察走访工作法 推动解决群众急难愁盼问题
- 天天日报丨《横扫天下》安卓删档计费测试公告
- 每日动态!《弹弹堂大冒险》梅恩兰德新风尚-摩羯潮装
- 世界视点!查干湖生态保护的新鲜事
- 《时空战场》首次删档测试-12月27日正式开启
- 《巫师3》Steam在线峰值接近9万:超受玩家喜爱!
- 环球快报:推进资本市场高水平开放 互联互通再扩容
- 《原神》发布剧情PV-「秋津羽戏」
- 全球新资讯:“投放专精特新已成银行必修课”——一位信贷经理视角下的贷款投放新动向
- 世界动态:神谷英树将《猎天使魔女:起源》比作童心绘本
- Steam喜加一:圣诞主题像素排球游戏《Jollyball》
- 精选!调控力度加大 财政货币政策协同发力
- 环球微动态丨因被指控侵犯隐私诱导消费 Epic支付天价和解金
- 要闻:雅居乐集团:拟以先旧后新方式配售股份,净筹6.172亿港元
- 【播资讯】十一部门多措并举推动家政进社区
- 今日看点:ARPG《致命躯壳:完整版》推出Switch版
- 天天日报丨手游《古惑狼:全速冲锋》将停服 发售不到2年
- Steam喜加一 《Jollyball》免费领
- 世界热点!《水浒风云传》发布全平台发售预告
- 世界观热点:微软、谷歌之后 欧盟反垄断又对美国Meta下手:可罚款上百亿美元
- 环球今亮点!联想控股:预计将联泓新科的持股比例降至43.14%
- 鲁泰A:公司没有N95口罩的生产
- 聚焦:主流甜味剂价格环比上周持平,甜味剂行业公司跌多涨少
- 世界微资讯!琼中县气象台发布大雾黄色预警【Ⅲ级/较重】
- 当前热文:第四届海南岛国际电影节开幕
- 环球今日讯!中信证券:房地产行业正处于周期的底部,关注三条投资主线
- 时讯:著名画家宋陆京新作《白云拖玉进湾区》亮相
- 世界视讯!150件中阿艺术家作品亮相千年瓷都
- 因抱怨马斯克推文和公司政策 两名特斯拉员工遭解雇
- 当前速递!马斯克发起投票决定自己去留,过半网友希望他离开推特
- 环球热推荐:元宇宙迎来头号玩家!韩国游戏巨头Nexon宣布与腾讯合作
- 多地推行布洛芬等拆零销售 退烧药市场高温渐退
- 海南一酒吧内,男子酒后多次掀起女子衣服引发冲突!11人被刑拘!
- 月活8亿完成千亿目标? 战略确定后 视频号提速明显
- 说《氓》
- “阳康”后15天才能产生抗体?以后可以放心嗨了?专家解读
- 环球今日报丨Asmodee中国区总经理刘洪峰:与带社交属性行业深度合作,培养桌游文化土壤
- 天天热文:“娃娃书记”让土店子变“潮”了
- 《甲骨文摹本大系》发布:系目前收录甲骨最多的大型甲骨著录书
- 【天天热闻】曝光!海南交警公示83名酒驾醉驾人员名单
- 焦点消息!《模拟城市:我是市长》12月23日更新公告
- 天天速读:11部门印发意见 多措并举推动家政进社区
- 香港特区政府欢迎扩大沪深港通合资格股票范围
- 要闻:海南省公布331家发热门诊网点信息
- 百事通!海南省牵头第一批封关运作项目全部开工,总投资约117亿元
- 即时:魔域正版手游账号交易平台哪个好 靠谱的手游账号买卖软件官网下载
- 六水共治|东方大田镇抱板村:打造生态河清水绿“新样板”
- 箭牌家居:公司通过持续创新掌握了覆盖全品类的抑菌抗菌技术
- 达美乐比萨中国特许经营商达势股份:延迟全球发售
- 世界快播:Temu的第一批淘金商户怎么样了?
- 天天百事通!纯电Macan预计2024年上市,保时捷还将推全新纯电SUV
- 当前简讯:港股里的卫龙,一根不香的辣条
- 天天即时:张兰拼命卖的酸辣粉,是从哪儿来的?
- 环球今日报丨海南省牵头第一批自贸港封关运作项目全部开工
- 热讯:买万国觉醒账号的平台有哪些 专业万国觉醒买号软件推荐
- 环球今亮点!2022中国超模大赛总决赛在三亚开赛
- 河北工信厅联合京东健康定向投放布洛芬、连花清瘟、抗原试剂盒等抗疫物资
- 当前头条:有哪些召唤与合成2账号交易市场 召唤与合成2买号软件推荐
- 世界微资讯!魔兽账号交易平台哪个好 靠谱的魔兽世界账号交易app介绍
- 天天看热讯:《深圳市绿色低碳发展年度报告(2022)》发布
- 今日精选:cfm买号平台叫什么 穿越火线枪战王者买号平台推荐
- 证监会:原则同意两地交易所进一步扩大股票互联互通标的范围
- 各地医护人员全力保障群众就医需求
- 热消息:第四届海南岛国际电影节开幕
- 天天快看:广期所:上海、江苏、浙江成为工业硅期货基准交割区域
- 世界新消息丨广发证券:第一大股东吉林敖东药业增持H股比例超过1%
- 稳健医疗:近期抗原试剂实现收入已超2022年前面几个月总和
- 新动态:应对新的变化,告别心理焦虑
- 速讯:北京人艺重温莫里哀人生谢幕之作
- 焦点报道:【新疆故事】新疆民间艺人:把家乡风物呈现在木雕里
- 乡村新面貌|新疆阿图什温室草莓“抢鲜”上市
- 报道:丰原药业:拟收购安徽泰格生物科技51%股权 明日起停牌
- 全球新消息丨李召虎带队赴海南推进科研合作和人才培养工作
- 环球短讯!海南这十年·遇见自贸港|大山中的“林三代”
- 使命召唤手游账号出售 使命召唤手游账号估价教程
- 全球快播:问政海南·一追到底丨应对海口“断头路”排长龙 校方、家长盼采取搭便桥、修临时路疏堵
- 无尽的拉格朗日游客账号交易app叫什么 安全的账号交易平台推荐
- 世界观热点:创文进行时(四)——旧颜换新貌 三亚市公安局紧抓创文不松懈
- 国资委:要强化战略性资源供应保障
- 短讯!西藏一隧道贯通 将缩短藏东到拉萨里程近300公里
- 即时看!京东集团荣获和讯第20届中国财经风云榜“2022年度企业社会责任优秀榜样”
- 国资委:要加快国有经济布局优化和结构调整
- 魏建国:要重新认识经济“三驾马车”,平台经济迎来发展好时机
- 世界百事通!普益标准:上周全市场新发590款理财产品,环比增加63款
- 快资讯:中国医药:已与辉瑞签订进口分销协议,预计对经营无重大影响
- 【全球新要闻】财政金融齐发力 扩内需稳增长
- 今日聚焦!《玛法降魔传》12月20日主宰5服火爆开启
- 《玛法降魔传》12月20日主宰4服火爆开启
- 《泡打三国》12月20日火爆开启--官渡S45
- 三部总台出品新片亮相海南岛国际电影节
- 全球资讯:建造“太空豪宅”!他们让中国“天宫”闪耀太空
- 北汽集团:复工复产加速跑全力冲刺收官战
- 视点!今晚24时,海南油价下调!
- 退烧药原料药年产能超10万吨,为什么还买不到布洛芬、扑热息痛?| 焦点分析
- 滚动:《萌斗魏蜀吴》虎贲9服12月20日火爆开启
- 环球观热点:真养猪还是“接盘侠”?卖面条的克明食品意欲收购大股东的生猪养殖项目
- 当前焦点!年末国内成品油价迎来“三连跌” 加满一箱汽油节省近19元
- 当前快看:北美票房:《阿凡达:水之道 》强势拉动北美票房回升
- 环球视讯!《阿凡达2》能成为影史第几?
- 【速看料】偷拿工友手机给自己转账11100元!昌江一男子已被刑拘
- 环球观速讯丨《保卫萝卜4》周赛图文攻略12.18
- 海口城市文化印记摄影大赛获奖名单揭晓 有你PICK的那一幅吗?
- 热门:创新药龙头罕见大跌 主力出逃医药板块!电解水制氢重大突破 布局公司全名单出炉 4股市盈率不到20倍
- 百事通!暖雪青蛇怎么样
- 新资讯:文明守法 平安回家|宣导查纠“双驱动” 守护出行“平安路” 三亚交警持续开展两轮电动车交通安全劝导行动
- 【环球速看料】大航海之路芳香之柱在哪找 大航海之路芳香之柱位置分享
- 全球今日讯!《喷射战士3》冬季CM预告中文版 美好生活属于你
- 全球微头条丨暖雪养战怎么样
- 航海王热血航线伙伴猜猜猜12.19答案是什么
- 天天滚动:自制电解质水差点意思?能正常饮食可不喝电解质水
- 齐鲁银行可转债正式上市交易 首日“破发”
- 《大富翁10》现已上架港服PSN 会员限时半价特惠
- 《海贼王:时光旅诗》明年1.10发布试玩版 支持存档
- 今日精选:新能源汽车被中央经济工作会议“点名” 全产业链有望被盘活
- 【速看料】「色彩里的中国」内蒙古千里草原换银装
- 【环球聚看点】远洋集团与邮储银行签署全面战略合作协议 获180亿元授信额度
- 天天观速讯丨中国石化销售广东石油分公司启动2023年“情暖驿站”公益活动
- 全球视讯!药剂工艺炼金模拟器人气提升方法指南
- 当前速讯:变废为宝 城市“清道夫”守护美丽家园
- 环球今头条!三亚“执念”领跑复苏,“携程们”的春天回来了?
- 今日观点!《无期迷途》嘟嘟嘟活动高分通关攻略
- 药剂工艺自定义外观方法 药剂工艺自定义外观怎么做
- 【天天播资讯】冬交看海垦|线上线下齐发力 海垦集团2022年冬交会成果丰硕
- 【世界速看料】《女神异闻录3P/4G》Switch版容量大小曝光
- 天天热推荐:耕耘齐鲁 为农担当——山东农担五周年宣传片《这五年 每一分钟》发布
- 天天播报:《药剂工艺炼金模拟器》火焰药剂配方制作方法
- 花生怎么吃最有营养 花生怎么泡才好吃
- 天天视点!《猫咪公寓2》猫猫春日大作战攻略
- 世界快资讯丨玩家用Mod重做《魔兽3重制版》 实现最初预告片效果
- 世界快资讯:多地加快建设慢行系统,市民慢出行意愿上升——慢行系统让出行更便利
- 国产独立游戏《特修斯协议》即将登陆Steam 抢先体验
- 环球快讯:报告:科技赋能银行业务数字化转型
- 今日24时起 汽、柴油每吨降低480元和460元
- 上证50股指期权19日挂牌上市 首日运行平稳交易规模适度
- 世界实时:北京企联发布创新成果,促进北京企业实现高质量发展
- 天天实时:卫星视角看白鹤滩水电站建设历程