什么是分布式?
分布式系统是建立在网络上的软件系统。 处理协助任务,然后整合结果。在分布式系统中,一组独立的计算机向用户呈现一个统一的整体,就像一个系统一样。系统具有多种通用的物理和逻辑资源,可以动态分配任务,分散的物理和逻辑资源可以通过计算机网络实现信息交换。系统中有一个分布式操作系统,以全局方式管理计算机资源。通常,对于用户来说,分布式系统只有一个模型或范例。在操作系统之上,一个软件中间件层负责实现这个模型。分布式系统的一个著名例子是万维网,在万维网中,一切看起来都像一个文档(网页)。在计算机网络中,这种统一性、模型和软件是不存在的。用户看到的是实际的机器,计算机网络并没有让这些机器看起来千篇一律。如果这些机器有不同的硬件或不同的操作系统,那么这些差异对用户来说是完全可见的。如果用户想要在远程机器上运行程序,他必须登录到远程机器上并在该机器上运行程序。分布式系统和计算机网络系统的共同点是大部分分布式系统都是建立在计算机网络上的,所以分布式系统和计算机网络的物理结构基本相同。两者的区别在于分布式操作系统和网络操作系统的设计思想不同,这就决定了它们在结构、工作方式和功能上也是不同的。网络操作系统要求网络用户在使用网络资源时首先了解网络资源。网络用户必须了解网络中每台计算机的功能和配置、软件资源和网络文件结构。如果用户想要读取网络中的共享文件,他们必须知道该文件放在哪个计算机和目录中。分布式操作系统以全局方式管理系统资源,可以随意为用户调度网络资源,调度过程“透明”。当用户提交作业时,分布式操作系统可以根据需要选择系统中最合适的处理器,将用户的作业提交给处理程序,在处理程序完成作业后将结果传递给用户。在这个过程中,用户并没有意识到多个处理器的存在,系统就像一个处理器。
这里支持 redis 主从、哨兵、集群三种模式,我这里选择主从即可,集群模式测试异常,没能解决
安装 redis 主从模式:
编写配置文件:
安装:
查看密码:
连接 master:
连接 slave:
读写分离:
读写:
只读:
错误 1:
解决:
参考: https://githubcom/helm/charts/issues/10666
参考: https://docsbitnamicom/kubernetes/infrastructure/redis/administration/kernel-settings/
参考: https://githubcom/helm/charts/tree/master/stable/redis/#user-content-host-kernel-settings
注意:Kubernetes 112+ 可以使用 securityContextsysctls 来设置 pod 的 sysctl,而不需要 initContainer 了:
错误 2:
解决:
使用 initContainer 去修改 sysctl 的方案在生产环境正常,这里却报错了,应该是 securityContext 或 PSP 的问题,这里没有启用 PSP,那就剩下 securityContext 了:
我这里尝试写入如下权限,最终都被修改掉了:
这里暂时没有找到解决方案,但是发现虽然报错了,下面 sysctl 修改是生效了的,因为日志不再报错了
错误 3:
解决:
因为 bitnami/minideb:buster 镜像里没有 sysctl
方法一:替换镜像
方法二:直接安装包,但是这个比较慢
错误 4:
解决:
参考: https://githubcom/docker-library/redis/issues/55
参考: https://githubcom/prometheus/node_exporter/issues/703
注意:它将修改调度了容器的节点的内核设置,从而影响该节点上运行的其他容器。这就是为什么您需要运行特权的 initContainer 或设置 securityContextsysctls 的原因。
错误 5:
解决:
因为将宿主机的 /sys 挂载到容器内的路径变成了 /host-sys
所以要修改路径:
错误 6:
解决:
这里暂时看不受影响
错误 7:
解决:
因为 master 挂掉了
错误 8:
解决:
Redis 提供两种相对有效的备份方法:
利用 RDB 快照的持久化方式不是非常可靠,当运行 Redis 的计算机停止工作、意外掉电、意外杀掉了 Redis 进程那么最近写入 Redis 的数据将会丢。对于某些应用这或许不成问题,但对于持久化要求非常高的应用场景快照方式不是理想的选择。
利用 AOF 文件是一个替代方案,用以最大限度的持久化数据。同样,可以通过配置文件来开闭 AOF。
打开 AOF 持久化功能后,Redis 处理完每个事件后会调用 write(2) 将变化写入 kernel 的 buffer,如果此时 write(2) 被阻塞,Redis 就不能处理下一个事件。
Linux 规定执行 write(2) 时,如果对同一个文件正在执行 fdatasync(2) 将 kernel buffer 写入物理磁盘,或者有 system wide sync 在执行,write(2) 会被 Block 住,整个 Redis 被 Block 住。
如果系统 IO 繁忙,比如有别的应用在写盘,或者 Redis 自己在 AOF rewrite 或 RDB snapshot(虽然此时写入的是另一个临时文件,虽然各自都在连续写,但两个文件间的切换使得磁盘磁头的寻道时间加长),就可能导致 fdatasync(2) 迟迟未能完成从而 Block 住 write(2),Block 住整个 Redis。
为了更清晰的看到 fdatasync(2) 的执行时长,可以使用下面命令跟踪,但会影响系统性能:
Redis 提供了一个自救的方式,当发现文件有在执行 fdatasync(2) 时,就先不调用 write(2),只存在 cache 里,免得被 Block。但如果已经超过两秒都还是这个样子,则会硬着头皮执行 write(2),即使 redis 会被 Block 住。
此时那句要命的 log 会打印:Asynchronous AOF fsync is taking too long (disk is busy) Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis
之后用 redis-cli INFO 可以看到 aof_delayed_fsync 的值被加 1。
因此,对于 fsync 设为 everysec 时丢失数据的可能性的最严谨说法是:
如果有 fdatasync 在长时间的执行,此时 redis 意外关闭会造成文件里不多于两秒的数据丢失。
如果 fdatasync 运行正常,redis 意外关闭没有影响,只有当操作系统 crash 时才会造成少于 1 秒的数据丢失。
方法一:关闭 AOF
如果采用 redis 主从 + sentinel 方式的话,主节点挂了从节点会自己提升为主点,主节点恢复后全量同步一次数据就可以了,关系也不是太大
方法二:修改系统配置
原来是 AOF rewrite 时一直埋头的调用 write(2),由系统自己去触发 sync。默认配置 vmdirty_background_ratio=10,也就是占用了 10% 的可用内存才会开始后台 flush
而我的服务器有 8G 内存,很明显一次 flush 太多数据会造成阻塞,所以最后果断设置了sysctl vmdirty_bytes=33554432(32M) 问题解决
错误 9:
解决:
看着是启动的时候加载 AOF 文件到内存,然后被 liveness 杀掉了
随着命令不断写入 AOF,文件会越来越大,为了解决这个问题,redis 引入了 AOF 重写机制压缩文件。文件能缩小的原因是:
AOF 重写可以手动触发和自动触发:
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 16mb
所以这里处理下,控制 AOF 文件大小:
注意:这里依旧没能解决问题,文件依旧很大,而且会造成大量的磁盘 IO,最终导致 redis 失去响应
彻底解决:
之后 dumprdb 文件一直稳定在 255M
网络直播平台的实现技术,归纳起来主要有如下这些:
一、视音频的采集和编码技术,当前主流的主要是H264、H265这种视频编码技术和AAC、MP3这种音频编码技术。
二、视音频的流媒体传输技术。
三、CDN内容分发技术。
四、终端解码技术。
架构方面,如果要做运营级的服务平台,需要采用分布式的架构方式,不仅包括各个功能模块的分布式部署,还包括各种应用服务器的分布式部署。
流媒体传输技术通常使用的方式主要包括:
1、通过HTTP协议传输,需要通过技术开发来实现高性能的HTTP流媒体服务器;
2、通过RTMP协议传输,需要通过技术开发来实现高性能的RTMP流媒体服务器;
3、通过UDP协议传输,这种方式通常用于大规模的可控网络中,比如IPTV电视直播应用,通过交换机即可支持这种传输方式;
4、通过P2P方式传输,P2P方式所用的传输协议可以由用户自主定义,并且可以基于UDP或TCP来实现,这种方式通常也是用于超大规模组网环境中。
一、实战环境
系统版本:CentOS 58x86_64
JAVA版本:JDK-170_25
Hadoop版本:hadoop-220
192168149128namenode (充当namenode、secondary namenode和ResourceManager角色)
192168149129datanode1 (充当datanode、nodemanager角色)
192168149130datanode2 (充当datanode、nodemanager角色)
二、系统准备
1、Hadoop可以从Apache官方网站直接下载最新版本Hadoop22。官方目前是提供了linux32位系统可执行文件,所以如果需要在64位系统上部署则需要单独下载src 源码自行编译。(如果是真实线上环境,请下载64位hadoop版本,这样可以避免很多问题,这里我实验采用的是32位版本)
1234 Hadoop
Java
2、我们这里采用三台CnetOS服务器来搭建Hadoop集群,分别的角色如上已经注明。
第一步:我们需要在三台服务器的/etc/hosts里面设置对应的主机名如下(真实环境可以使用内网DNS解析)
[root@node1 hadoop]# cat /etc/hosts
# Do not remove the following line, or various programs
# that require network functionality will fail
127001localhostlocaldomain localhost
192168149128node1
192168149129node2
192168149130node3
(注 我们需要在namenode、datanode三台服务器上都配置hosts解析)
第二步:从namenode上无密码登陆各台datanode服务器,需要做如下配置:
在namenode 128上执行ssh-keygen,一路Enter回车即可。
然后把公钥/root/ssh/id_rsapub拷贝到datanode服务器即可,拷贝方法如下:
ssh-copy-id -i ssh/id_rsapub root@192168149129
ssh-copy-id -i ssh/id_rsapub root@192168149130
三、Java安装配置
tar -xvzf jdk-7u25-linux-x64targz &&mkdir -p /usr/java/ ; mv /jdk170_25 /usr/java/ 即可。
安装完毕并配置java环境变量,在/etc/profile末尾添加如下代码:
export JAVA_HOME=/usr/java/jdk170_25/
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=$JAVE_HOME/lib/dtjar:$JAVE_HOME/lib/toolsjar:/
保存退出即可,然后执行source /etc/profile 生效。在命令行执行java -version 如下代表JAVA安装成功。
[root@node1 ~]# java -version
java version "170_25"
Java(TM) SE Runtime Environment (build 170_25-b15)
Java HotSpot(TM) 64-Bit Server VM (build 2325-b01, mixed mode)
(注 我们需要在namenode、datanode三台服务器上都安装Java JDK版本)
四、Hadoop版本安装
官方下载的hadoop220版本,不用编译直接解压安装就可以使用了,如下:
第一步解压:
tar -xzvf hadoop-220targz &&mv hadoop-220/data/hadoop/
(注 先在namenode服务器上都安装hadoop版本即可,datanode先不用安装,待会修改完配置后统一安装datanode)
第二步配置变量:
在/etc/profile末尾继续添加如下代码,并执行source /etc/profile生效。
export HADOOP_HOME=/data/hadoop/
export PATH=$PATH:$HADOOP_HOME/bin/
export JAVA_LIBRARY_PATH=/data/hadoop/lib/native/
(注 我们需要在namenode、datanode三台服务器上都配置Hadoop相关变量)
五、配置Hadoop
在namenode上配置,我们需要修改如下几个地方:
1、修改vi /data/hadoop/etc/hadoop/core-sitexml 内容为如下:
<xml version="10">
<xml-stylesheet type="text/xsl"href=\'#\'" Put site-specific property overrides inthisfile -->
<configuration>
<property>
<name>fsdefaultname</name>
<value>hdfs://192168149128:9000</value>
</property>
<property>
<name>hadooptmpdir</name>
<value>/tmp/hadoop-${username}</value>
<description>A base forother temporary directories</description>
</property>
</configuration>
2、修改vi /data/hadoop/etc/hadoop/mapred-sitexml内容为如下:
<xml version="10">
<xml-stylesheet type="text/xsl"href=\'#\'" Put site-specific property overrides inthisfile -->
<configuration>
<property>
<name>mapredjobtracker</name>
<value>192168149128:9001</value>
</property>
</configuration>
3、修改vi /data/hadoop/etc/hadoop/hdfs-sitexml内容为如下:
<xml version="10"encoding="UTF-8">
<xml-stylesheet type="text/xsl"href=\'#\'" /name>
<value>/data/hadoop/data_name1,/data/hadoop/data_name2</value>
</property>
<property>
<name>dfsdatadir</name>
<value>/data/hadoop/data_1,/data/hadoop/data_2</value>
</property>
<property>
<name>dfsreplication</name>
<value>2</value>
</property>
</configuration>
4、在/data/hadoop/etc/hadoop/hadoop-envsh文件末尾追加JAV_HOME变量:
echo "export JAVA_HOME=/usr/java/jdk170_25/">> /data/hadoop/etc/hadoop/hadoop-envsh
5、修改 vi /data/hadoop/etc/hadoop/masters文件内容为如下:
192168149128
6、修改vi /data/hadoop/etc/hadoop/slaves文件内容为如下:
192168149129
192168149130
如上配置完毕,以上的配置具体含义在这里就不做过多的解释了,搭建的时候不明白,可以查看一下相关的官方文档。
如上namenode就基本搭建完毕,接下来我们需要部署datanode,部署datanode相对简单,执行如下操作即可。
1 fori in`seq 129130` ; doscp -r /data/hadoop/ root@192168149$i:/data/ ; done
自此整个集群基本搭建完毕,接下来就是启动hadoop集群了。
0条评论