C1.大规模Web服务的开发定位
一.小规模服务和大规模服务的区别:
1.保证可扩展性,负载均衡的必要性:
1). 对于大规模访问量: 用横向扩展(增加服务器数量,廉价)
2).用户请求如何分配:负载均衡
3).数据同步
4).网络延迟
2.保证冗余性
二.应对大规模数据量:数据处理流程
1)磁盘--->内存--->CPU缓存(指令)--->CPU
2)数据量小时,内存就能完成所有的处理
C2.大规模数据处理入门
一.大规模数据处理的感觉:
记录数以千万为单位,数据大小为几GB到几百个GB。数据规模到了这种程度,漫不经心的查询根本无法返回结果。(select)
二.大规模数据处理的难点:内存和磁盘
1.难点为无法在内存中计算
1) 大数据无法存储在内存中计算,必须搜索磁盘的数据
2) 磁盘十分缓慢,I/O十分耗时。(a.磁盘搜索是物理过程,内存是电子产品。b.数据可能散落在磁盘各处. c.内存到CPU总线的速度7.5GB/S,磁盘58MB/S。传输时间长)
2.操作系统层加速原理:
操作系统将连续的数据放在同一处。然后在读取数据时并不是逐个字节读取,而是一次读取4KB左右
3.只有一台服务器性能被发挥到了极致,多态服务器负载均衡才有意义
三.可扩展性要点: CPU负载/IO负载
1.Web应用程序的三层结构:
代理服务器 --- (负载均衡) --- 应用服务器(CPU负载,负责计算,可横向扩展,做同样的事情) ----- 数据库(I/O负载,缓存,横向扩展有难度,数据同步)
四.处理大规模数据的基础知识:
1.处理大规模数据的重点
1) 能在内存中完成多少(减少寻道次数/实现分布式)
2) 能应对数据量增加的算法和数据结构(查找算法..)
3) 数据压缩,信息搜索技术
C3.操作系统的缓存和分布式(减少IO负载)
一. 页面缓存:
1. 虚拟内存: 内存不够,将硬盘等作为虚拟内存,有自己的连续的逻辑地址,对应着真正的可能不连续的物理地址。这样时进程不需要考虑需要的内存位于什么地方,只知道是连续的
2.操作系统以页面(4kb)为单位分配分配物理内存并管理,这样一次不是一个字节一个字节读,而是一个页面一个页面读了
3. Linux的页面缓存:
1) 过程: 操作系统从硬盘中读出4kb(一页)的块 -----> 将内容放到内存中 ----> 操作系统将该内存的地址(逻辑地址)告诉进程 ---> 进程访问该内存进行操作 ---> 操作完成后该内存不会被释放而是保留下来(页面缓存) ---> 下次访问同一块硬盘时直接读内存(所以第二次比第一次更快)
2) 虚拟文件系统(VFS): 硬件 --- 设备驱动程序 --- 文件系统 --- 虚拟文件系统(管理文件系统上的函数,页面缓存) --- 操作系统
3) Linux 以页面为单位缓存磁盘: 页面是虚拟内存的最小单位。更新策略是放弃最老的保留最近的
4) Linux 只要有空闲内存就会缓存,没有空闲内存供缓存使用时,才用心缓存替换旧缓存
5) 先读取一次磁盘才会有页面缓存,所以服务器重启后无缓存 ,要先读一遍再放到生产环境中
4.降低I/O负载的策略:
1)以缓存为前提降低I/O负载的策略
a. 如果内存大于数据规模(包括将磁盘文件压缩) ----> 全部缓存
b. 考虑经济成本的平衡性
2) 当数据规模大于内存无法全部缓存
a.首先考虑扩展到多台服务器,对应用服务器(CPU负载,负责计算,可横向扩展,做同样的事情) 有效,数据库(I/O负载,横向扩展有难度,数据同步)无效
二.利用局部性的分布式: 根据访问模式进行分散,增加缓存容量
1. 例:热门链接与用户自定义书签表,分配到两个不同的数据库服务器上,互不干扰。从系统整体上看,放入内存的数据量就增加了。
2. 分区方式:在局部性的基础实现分散,将一个数据库分割到多台服务器上
1) 以表为单位进行分割: 经常同时被访问的表放在同一台server上
2) 从数据中间分割: 根据数据的特点将一张表分割成多个小表。 a-d,e-m....
3) 根据用途将系统分成岛: 将容易缓存的请求和不容易缓存的请求放在不同的岛上处理,前者让缓存内容更稳定,后者会打乱前者的缓存
用户请求/ API/ 爬虫 ---- 用User-Agent(Http) 和URL进行分割
C4. 数据库的横向扩展策略
一. 分布式 MySQL应用的三大要点
1. 操作系统缓存:准备容纳大量数据的表,要设计的紧凑一些,让记录尽可能的小
2. 索引
1) B树: 向B树中插入数据需要遵循一定的规则,借助此规则,搜索时只需沿着一部分节点前进,就能自然的找到要搜索的数据。搜索时,对子节点的搜索次数最多只相当于树的高度
a.B树与二叉树的区别: B树可以使各节点的大小,二叉树只能有一个节点; B树使节点为4kb,每个节点保存在一个块内,将寻道次数降低到与节点访问次数相等。操作系统会一次性将同一节点内的数据全部读入内存,无需寻道就可以搜索.
b. B+树为了在数据库中保存数据而进一步优化数据结构: 各个节点中只有指向子节点的指针,实际数据保存在最后的叶节点中 O(n) ---> O(logn)
c. MySQL建立索引的数据结构就是B+树
d. 规模越大,有无索引的差别就越大。 数据有1000条左右时,利用树搜索的额外开销反而越大
3. 以横向扩展为前提的设计
1) n台AP(服务器) ---> 负载均衡器 ---> n台MySQL slave ---> 一台MySQL master.
2) slave会根据master更新,查询发给slave,更新发给master
3) 查询好扩展,增加slave服务器就可以
4) master不好扩展,可以通过表分割或者更换实现方法来解决
5) 表分割:
a. MySql不支持位于不同服务器表的join查询,所以join查询基本上只有保证了对象表以后不会分割在不同服务器上的前提才能使用
b. 避免使用join, 用where .... in ...
6) 冗余化: 至少有四台: 三台 slave, 一台坏掉,一台运行,一台给另一台备份,并且如果master坏了,一个slave转换成master
C5. 大规模数据处理"实践入门"
一. 根据特殊用途创建索引: 超出RDBMS能力时
1.架构:
1) 数据库--定期取-->索引服务器<----->应用服务器
2) 不在应用服务器cache索引因为应用服务器内存不够,不适合使用大规模索引
C6. 压缩编程
一. 压缩
1.压缩基础: 经常出现的符号分配短编码,很少出现的分配长编码
2.哈夫曼编码:从头开始分析各个文字符号的出现频率,求出概率分布之后,再据此生成最佳符号
C7. 算法实用化
一.复杂度
O(logn)比O(n)快很多
二.关键字链接: 写博客时部分关键字自动加上链接
1.编译正则表达式的处理:
1)预先创立,缓存在磁盘中
2.用正则表达式进行模式匹配:
1) Trie树:
以前缀搜索,一个字母一个字母匹配,这样不会走重复的路
a --- b ---c
--- e
----c ----d
2) 数据量小时采用简单方法反而效果更好:
三.机器学习和大规模数据:
1. 文档分类: 某篇文档D, 该文档所属概率最高的分类C
贝叶斯算法: P(C|D) = P(D|C)P(C)|P(D), 因为只需要求出概率的最大者,所以不需要计算出来。所以只需要关心P(D|C) 与P(C)
P(C) 是某个分类出现的概率,只需事先保存学习数据被保存到各个分类中的次数,即可计算
P(D|C) 可以近似看成其中的单词 P(W1|C)P(W2|C)P(W3|C)P(W4|C)P(W5|C);这样将文档D分割成单词,求出每个单词被分类到各类别的次数
提示正确: http://andynjux.blogbus.com/logs/48219445.html
C9. 挑战全文搜索技术
一. 挑战全文搜索技术:contians
1. 之前是用关系型数据库: 新文章先提出所有的关键词与文章的关系在数据库存起来,但是当数据多的时候就有问题
2. 根据实际用途建立搜索
二.搜索系统的架构
1.所需步骤:
1). 爬行: 存储搜索的目标文档
2).存储:将文档保存(分布式数据库)
3).建立索引
4).搜索:
5).评分:
6).结果显示
2.种类:
1) grep类型:
将搜索对象文档全部读出,然后找匹配,可保证实时性,无遗漏,但数据量太大
2)后缀类型
用可搜索的形式将文档全部存储到内存中(Trie)
3) 逆向索引类型
搜索之前要预先创建逆向索引,实时性不好
3.逆向索引内部结构:dictionary + postings
a.建立索引:
I.找单词: 英文有空格隔开,中日文靠词典或者靠语素分析推测
搜索遗漏: 词性变化
* 可用n-gram切分的结果作为term,用同样的规则切分查询.但过滤要花很多时间
评判标准: 查全率和查准率
b. 根据词直接查: 单词1 --> 文档编号1 文档编号2...
单词2 ---> 文档编号1 文档编号4...
C11.保证冗余性和系统的稳定化
一.应该在极限的70%左右运行
二.提高效率,硬件利用率:虚拟化
1.CPU空闲---->WEB服务器
2.I/O资源空闲--->数据库服务器
3.内存资源空闲--->缓存服务器