表单
- <form>...</form>创建HTML表单
- 用于向服务器提交数据
- 登录方式
- form-data
- x-www-form-urlencoded
- ajax以json方式提交数据
- 登录是为了得到 cookie
- 登录成功后 Header 会有设置 cookie 的相关信息
- 把服务器返回的 cookie,放入后续请求的 header 中
- 网络框架
- wamp:Windows+Apache+MySQL+PHP
- Lamp:Linux+...
- Apache:80 http service
- 语言比较
- PHP:不需编译,所见即所得,类似Python,但速度较慢,且无法跑任务,只能被动运行,轻任务,online
- Java:作为一个进程,可以跑任务,速度快,重任务,online
- Python:库很全,数据分析,小而快的任务,不适合web服务,扛不住并发,offline
- C++:速度快,图形图像,游戏,开发难度大,问题多
数据库
- MySQL
- 传统关系型数据库
- 将爬虫部署在多台主机,需要设置防火墙策略
- HDFS
- 分布式文件系统
- 不支持随机读写(通过HBASE效率低)
- 传统文件树支持按路径随机读取,但有大量碎片
- 连续读取文件很快
- 大数据处理:不关心每一项数据,而是一批数据的综合表现
- HBASE
- 列数据库
- 一般规模用不到
- MongoDB
- 文档数据库
- 保存原始HTML文档(可存几千万)
- 易扩展
- findOneAndUpdate()
- upsert:找不到是否insert
- returnNewDocument:是否创建副本
- 优化
- url md5 后作为 id
- find_one() 全库扫描
- 每个网页对应几百次插入,到了 depth = 3 时基数网页是百万级,插入检查是亿级,先用 redis 判断是否存在,再写到 mongo
- Redis
- 基于key-value的内存数据库
- 保存临时数据
- 支持复杂的对象模型
- 支持Replication,实现集群
- 所有操作都是原子性的
- 异步序列化到磁盘(Persistent = True)
- 不完全支持 CAID
- Java Heap<->Redis<->MySQL
常见概念
- 锁
- 表级锁:开销小,锁定整张被访问的表(MyISAM)
- 行级锁:开销大,支持并发(INNODB)
- 事务(ACID)
- Automicity:原子性。一个事物被视为一个不可分割的最小单元
- Consistency:一致性。数据库总是从一个状态转换到另一个状态,如执行过程崩溃,数据库恢复后状态不变
- Isolation:隔离性。事物所做的修改最终提交前,对其他事物不可见
- Durability:持久性。一旦事物提交,其所有修改会永久保存到数据库,即使系统崩溃也不会丢失
- 死锁
- 多个事物在同一资源上相互占用,并请求锁定对方占用的资源
- INNODB有预测机制
- 多线程,共享资源,抢占
- AUTOCOMMIT
- MySQL默认采用自动提交
MySQL
引擎
- InnoDB
- 存储框架
- 一张表存在一个或多个文件里
- 表包含多个Segment,索引、数据、回滚记录都是独立的Segment
- 每个Segment包含多个Extent
- Extent包含64个Page
- 每个Page包含若干Row
- 每个Row包含了数据域
- 操作
- 主键索引既存储索引值,又在叶子中存储行数据(聚簇索引)
- 没有主键,Unique key做主键
- 没有Unique,生成一个内部的rowid做主键
- 次索引需同时存储主键ID
- 对主键查询性能极高,二级索引必须包含主键列
- 支持事物,并发,行级锁,颗粒度小,但加锁复杂
- 崩溃后可安全恢复
- 存储框架
- Myisam
- 不支持事物,不能安全恢复
- 表级锁,读的时候所有读到的表加共享锁,写的时候加排他锁
- 加锁效率高,并发支持效率低
- 设计简单,数据紧密格式存储,某些场景下性能好
- 选择
- 默认选InnoDB
- 不使用混合引擎(如10张写多的用InnoDB,10张读多的用Myisam)
- 需要事物,InnoDB稳定;主要是SELECT或INSERT,MyISAM更合适,如日志类型使用
- 需要热备份,用InnoDB
- 重要数据用InnoDB
- 大多数情况下,InnoDB远比MyISAM快
- 只读的表,优先考虑MyISAM
设计要点
- 避免太多的列:存储引擎API在服务器层与存储引擎层通过行缓冲格式拷贝数据,然后在服务器层将缓冲内容解码到各个列,从行缓冲将编码过的列转换成行的代价非常高
- 避免太多关联:MySQL限制最多关联61张表
- 避免使用NULL:带来存储及大量优化问题
- 汇总表:把一些历史汇总数据,离线或定时汇总,最后结果是汇总结果加当前结果。计算量大幅减小,写变慢,读性能大幅提升
B+ Tree
- 用来排序、范围查找、全值或前缀查找
- 顺序读取很高效
- InnoDB索引采用B+ Tree
查询
- 没有建索引的话会全表扫描
- 临时结果会缓存在一个文件里,然后等其他关联结果出来后再进一步合并,过滤
深翻页
- 缓存的结果不能顺序访问,需要顺序扫描(类似链表),非常耗时
- 查询时尽量避免,不是人类行为
- 搜索引擎对翻页深度有限制
优化
- 原则
- 代码:逻辑,最重要
- 算法:不同算法适用不同场景
- 空间:Android,预编译;JIT(Just In Time)
- 爬虫数据特点
- 文件小,大量KB级别文件
- 文件数量大
- 增量方式一次性写入,极少需要修改
- 顺序读取
- 并发的文件读写
- 可扩展
- 爬取过程
- Spider 爬取网页信息放入 Master
- Master 把网页信息交给消息队列
- 消息队列把存入 MongoDB
- MongoDB 读网页信息,创建新的爬取任务(url)交给 Master
- Spider 从 Master 取任务爬取
- 组合
- 查找是否存在用 Redis,写入用 MongoDB
- 串行化
- 防止数据库被过度访问
- 由前端统一管理任务队列
- 在前端消息请求与数据库间建立一层任务队列(Kafka等),隔离一部分数据更新操作
- 异步爬取,把爬到的内容放到队列后继续爬取,由队列进行异步更新(对时效性无要求)
- 取时直接访问数据库(对时效性有要求,防止被多个爬虫取走,重复爬取)
- 批量处理
- 由 Master 管理,串行化处理时,批量处理数据,加快处理速度,否则每次查询都需要创建实例、初始化、编译、查询
- Spider 写的压力大(爬一个网页可能得到上百新的网页),可批量化
- Spider 读的压力不大(2s爬取一次),不需批量化
- 消息队列
- 实现解耦、异步处理、流量缓冲
- 日志系统:先写缓冲区,缓冲区写满后写入磁盘(远程数据库),高峰期写磁盘会造成阻塞(网络IO),可先通过消息发送给logger,由 logger 负责同步
- 数据同步:将 MySQL 数据变更同步到 Redis 里
- 任务队列:对于爬虫,爬取状态的更新不需要原子性操作,可通过消息队列把更新的任务放到独立的队列里,依次完成对爬取状态的更新,使爬虫状态更新的线程可以快速返回
- MySQL与Redis同步
- 通过 databus 实现 MySQL 与 Redis 的更新操作,把 MySQL 的数据变化同步到 Redis
- 下次用的时候直接从 Redis 获取
- 过程
- enqueue:在 redis 判断,如果已存在就丢弃,不存在就放入 mongo,status = new
- dequeue:取出 mongo 中 status = new 的 url,同时把状态改为 downloaded,下载完 status = done
标签:Python,数据库,爬虫,爬取,队列,Part.4,InnoDB,MySQL,数据 From: https://www.cnblogs.com/cxc1357/p/12563437.html