安安 - 存储
type: channel
link: https://blog.90.vc/tag/%E5%AD%98%E5%82%A8/
items: Kafka的集群部署实践及运维相关
items: Kubernetes 内部组件工作原理
items: RAID5 真的安全吗
items: Oracle数据库RAC安装部署
items: JVM内存模型及内存分配过程
items: Cache 和 Buffer 有什么区别？

Kafka的集群部署实践及运维相关
type: item
date: 2020-04-02T15:55:00+00:00
description: 一、Kafka的生产集群部署1.1 方案背景假设每天集群需要承载10亿数据。一天24小时，晚上12点到凌晨8点几乎没多少数据。使用二八法则估计，也就是80%的数据（8亿）会在16个小时涌入，而且8亿的80%的数据（6.4亿）会在这16个小时的20%时间（3小时）涌入。QPS计算公式：640000000 ÷ (3x60x60) = 60000，也就是说高峰期的时候Kafka集群要扛住每秒6万的并发。磁盘空间计算，每天10亿数据，每条50kb，也就是46T的数据。保存2个副本（在上一篇中也提到过其实两个副本会比较好，因为follower需要去leader那里同步数据，同步数据的过程需要耗费网络，而且需要磁盘空间，但是这个需要根据实际情况考虑），46 2 = 92T，保留最近3天的数据。故需要 92 3 = 276T1.2 QPS方面部署Kafka，Hadoop，MySQL···等核心分布式系统，一般建议直接采用物理机，抛弃使用一些低配置的虚拟机的想法。高并发这个东西，不可能是说，你需要支撑6万QPS，你的集群就刚好把这6万并发卡的死死的。加入某一天出一些活动让数据量疯狂上涨，那整个集群就会垮掉。但是，假如说你只要支撑6w QPS，单台物理机本身就能扛住4~5万的并发。所以这时2台物理机绝对绝对够了。但是这里有一个问题，我们通常是建议，公司预算充足，尽量是让高峰QPS控制在集群能承载的总QPS的30%左右（也就是集群的处理能力是高峰期的3~4倍这个样子），所以我们搭建的kafka集群能承载的总QPS为20万~30万才是安全的。所以大体上来说，需要5~7台物理机来部署，基本上就很安全了，每台物理机要求吞吐量在每秒4~5万条数据就可以了，物理机的配置和性能也不需要特别高。1.3 磁盘方面1.3.1 磁盘数量需要5台物理机的情况，需要存储276T的数据，平均下来差不多一台56T的数据。这个具体看磁盘数和盘的大小1.3.2 SAS还是SSD现在我们需要考虑一个问题：是需要SSD固态硬盘，还是普通机械硬盘？SSD就是固态硬盘，比机械硬盘要快，那么到底是快在哪里呢？其实SSD的快主要是快在磁盘随机读写，就要对磁盘上的随机位置来读写的时候，SSD比机械硬盘要快。比如说MySQL这种就应该使用SSD了（MySQL需要随机读写）。比如说我们在规划和部署线上系统的MySQL集群的时候，一般来说必须用SSD，性能可以提高很多，这样MySQL可以承载的并发请求量也会高很多，而且SQL语句执行的性能也会提高很多。因为写磁盘的时候kafka是顺序写的。机械硬盘顺序写的性能机会跟内存读写的性能是差不多的，所以对于Kafka集群来说其实使用机械硬盘就可以了。如果是需要自己创业或者是在公司成本不足的情况下，经费是能够缩减就尽量缩减的。1.4 内存角度JVM非常怕出现full gc的情况。kafka自身的jvm是用不了过多堆内存的，因为kafka设计就是规避掉用jvm对象来保存数据，避免频繁full gc导致的问题，所以一般kafka自身的jvm堆内存，分配个10G左右就够了，剩下的内存全部留给os cache。那服务器需要多少内存呢。我们估算一下，大概有100个topic，所以要保证有100个topic的leader partition的数据在操作系统的内存里。100个topic，一个topic有5个partition。那么总共会有500个partition。每个partition的大小是1G（在上一篇中的日志分段存储中规定了.log文件不能超过1个G），我们有2个副本，也就是说要把100个topic的leader partition数据都驻留在内存里需要1000G的内存。我们现在有5台服务器，所以平均下来每天服务器需要200G的内存，但是其实partition的数据我们没必要所有的都要驻留在内存里面，只需要25%的数据在内存就行，200G * 0.25 = 50G就可以了（因为在集群中的生产者和消费者几乎也算是实时的，基本不会出现消息积压太多的情况）。所以一共需要60G（附带上刚刚的10G Kafka服务）的内存，故我们可以挑选64G内存的服务器也行，大不了partition的数据再少一点在内存，当然如果能够提供128G内存那就更好。1.5 CPU coreCPU规划，主要是看你的这个进程里会有多少个线程，线程主要是依托多核CPU来执行的，如果你的线程特别多，但是CPU核很少，就会导致你的CPU负载很高，会导致整体工作线程执行的效率不太高，上一篇的Kafka的网络设计中讲过Kafka的Broker的模型。acceptor线程负责去接入客户端的连接请求，但是他接入了之后其实就会把连接分配给多个processor，默认是3个，但是一般生产环境建议大家还是多加几个，整体…

Kubernetes 内部组件工作原理
type: item
date: 2020-03-31T14:32:00+00:00
description: 翻译自:https://blog.heptio.com/core-kubernetes-jazz-improv-over-orchestration-a7903ea92ca原作者：Joe Beda (Dad of two. CTO of Heptio. Started Google Compute Engine, Kubernetes and Google Container Engine.)本篇文章讲述了Kubernetes内部组件的工作原理，及创建POD的流程。如果你是运维人员或者是Kubernetes的使用者，你可以不需要知道Kubernetes的内部工作原理，但是如果你想理解Kubernetes内部的工作原理，这篇文章非常适合你。读这篇文章的前提是，你已经大致了解并会运用Kubernetes。这篇文章不会去描述什么是Kubernetes及其组件（如：Pod, Node, Kubelet）。 本篇将讨论Kubernetes核心组件及这些核心组件是如何让Kubernetes 对"爵士乐即兴演奏"。通常将像Kubernetes这样的通用系统称为容器的 "管弦乐编排"。但是管弦乐编排，必须有一个预先计划的指挥家。因此，这并不是Kubernetes的一个好的描述。相反，Kubernetes更像是爵士乐即兴演奏，有一系列演员互相配合协调完成演奏。接下来，开始介绍每个核心组件的功能。然后将看一个典型的调度和启动一个Pod的流程。1. Datastore: EtcdEtcd是Kubernetes的存储状态的数据库。虽然Kubernetes系统中有重要的内存缓存，但Etcd被认为是记录系统状态。Etcd的快速总结：它是一个集群分布式数据库，它可以提供分布式数据的一致性。这类的系统（如Zookeeper, Consul）是在 Google开发的chubby系统之后形成的，这些系统也称为"锁服务器"，因为他们可以实现分布式锁。Etcd和chubby的数据模型是一个简单的层次化的Key，并存储了简单的非结构化value，这看起来像是一个文件系统。有意思的是，在Google, chubby 被频繁用于为实现访问本地文件和对象存储的功能的抽象文件接口。然而，分布式数据库的高度一致性，提供了数据的严格写入顺序并允许client原子性的对数据做更新操作。可靠的系统的状态管理是任何系统中非常困难的一件事情。在分布式系统中，它是更加困难的，因为它引入了一致性算法，如raft或paxos。通过使用etcd，Kubernetes可以专注系统的其他部分。Etcd的watch机制是Kubernetes工作的关键。系统允许client去执行轻量级的对于Key值变化事件的订阅。当要watch的数据发生变化时, client会立即得到通知。这可以用作分布式系统组件之间的协调机制。 一个组件一旦写入etcd，其他组件可以立即对该变化作出反应。Etcd的消息机制正好和PubSub消息队列机制相反。在许多消息队列系统系统中，topic不存储真正的用户数据，但发布到这些topic的消息含有丰富的数据。对于像Etcd这样的系统，Key（类似于主题）存储了真实的数据而消息（数据变化通知）不含独特的丰富消息。换句话说，对于消息队列来说，topic很简单，而像Etcd则正好相反。（译者认为此处概括的非常准确）2. Policy Layer: API ServerKubernetes的核心组件是API Server，它是Kubernetes系统和Etcd直接对话的唯一组件。实际上，etcd是API server的实现细节，理论上也可以用其他分布式存储系统来支持Kubernetes.API server是一个策略组件，提供对Etcd的过滤访问。它的作用本质上是相对通用的，目前正在被分解处理。因此，API Server也可以用于其他系统的控制平面。API server的主要货物是资源，通过暴露简单的REST API 向外提供服务。这些资源有一个标准结构可以实现一些扩展功能。无论如何，API Server，允许各类组件创建，读取，写入，更新，和监视资源。API Server的具体的功能：认证和授权。Kubernetes有一个可插拔的认证系统。有一些内置的用户认证机制和授权这些用户访问资源。此外，还有一些方法可用于向外部服务提供这些服务。这种可扩展性是Kubernetes构建的核心功能。API Server运行一组可以拒绝或修改请求的准入控制器。 这些允许策略被应用并设置默认值。 这是确保在API Server客户端仍在等待请求确认时进入系统的数据有效性的关键。 虽然这些准入控制器目前正在编译到API Server中，但目前正在进行的工作是使其成为另一种可扩展性机制。API Server 有助…

RAID5 真的安全吗
type: item
date: 2020-03-02T14:01:00+00:00
description: 转载自知乎一句话结论：现代大容量硬盘组成的RAID 5单盘故障后，重建失败的概率相当高，不可忽略；但数据本身还是基本安全的（会丢失部分文件），只是可能需要一个比较麻烦的恢复方案。楼上包括高赞回答在内一堆说两个硬盘同时坏的，要加一个热备盘的，都是没仔细看过问题里面的链接就回答的。在回答问题的现在，这个链接失效了，但网上还是有人转载过的，例如这篇[1]：DBA亲，你们的RAID5阵列有保障吗？marbury关注0人评论10546人阅读2014-02-21 10:30:24 该文章主要整理论坛内容。（论坛地址：http://bbs.et8.net/bbs/showthread.php?t=1026112）很多人遇到过服务器RAID5挂掉，往往掉一个盘后，第二个盘也立刻挂掉。引用：RAID 5也是以数据的校验位来保证数据的安全，但它不是以单独硬盘来存放数据的校验位，而是将数据段的校验位交互存放于各个硬盘上。这样，任何一个硬盘损坏，都可以根据其它硬盘上的校验位来重建损坏的数据。硬盘的利用率为n-1。如果挂掉两个盘，数据就玩完了。 理论上两个硬盘同时失效的概率是很低的，但为什么会这样呢？ 引用：从数学角度说，每个磁盘的平均无故障时间 (MTBF) 大约为 50 万至 150 万小时(也就是每 50～150 年发生一次硬盘损坏)。实际往往不能达到这种理想的情况，在大多数散热和机械条件下，都会造成硬盘正常工作的时间大幅减少。考虑到每个磁盘的寿命不同，阵列中的任何磁盘都可能出现问题，从统计学角度说，阵列中 N 个磁盘发生故障的机率比单个磁盘发生故障的机率要大 N 倍。结合上述因素，如果阵列中的磁盘数量合理，且这些磁盘的平均无故障时间 (MTBF) 较短，那么在磁盘阵列的预期使用寿命过程中，就很有可能发生磁盘故障(比方说每几个月或每隔几年就会发生一次故障)。 两块磁盘同时损坏的几率有多大呢(“同时”就是指一块磁盘尚未完全修复时另一块磁盘也坏掉了)?如果说 RAID 5 阵列的MTBF相当于MTBF^2，那么这种几率为每隔10^15个小时发生一次(也就是1万多年才出现一次)，因此不管工作条件如何，发生这种情况的概率是极低的。从数学理论角度来说，是有这种概率，但在现实情况中我们并不用考虑这一问题。不过有时却是会发生两块磁盘同时损坏的情况，我们不能完全忽略这种可能性，实际两块磁盘同时损坏的原因与MTBF基本没有任何关系。 对这种情况来说，这里首先要引入一个一般人不常接触到的概念：BER 硬盘误码率,英文是BER(Bit Error Rate),是描述硬盘性能的一个非常重要的参数,是衡量硬盘出错可靠性的一个参数。这个参数代表你写入硬盘的数据，在读取时遇到不可修复的读错误的概率。从统计角度来说也比较少见，一般来说是指读取多少位后会出现一次读取错误。 随着硬盘容量增加，驱动器读取数据的误读率就会增加，而硬盘容量暴涨，误码率的比例一直保持相对增加。一个1TB的驱动器是需要更多读取整个驱动器，这是在RAID重建期间发生错误的概率会比300G 驱动器遇到错误的几率大。 那这个错误的几率到底有多大呢？或者说，我们写入多少GB数据，才会遇到1byte的读取错误呢？看这篇文章：http://lenciel.cn/docs/scsi-sata-reliability/对于不同类型的硬盘（以前企业级、服务器、数据中心级硬盘用SCSI/光纤，商用、民用级别是IDE；现在对应的则是SAS/SATA； 他们的MRBF（平均无故障时间）是接近的，但是BER便宜的SATA硬盘要比昂贵的SCSI硬盘的误码率（BER）要高得多。 也就是说，出现某个sector无法读取的情况，SATA要比SCSI严重得多。具体区别在固件上：遇到读取不过去，或者写入不过去的坏道时，家用硬盘会花费1分钟以上的时间去尝试纠正错误，纠正不了就直接用备用扇区代替，这个时间超过阵列控制器能容忍的限度，所以遇到这种情况直接掉盘；企业级的磁盘会把这项工作放在后台进行，不需要停顿1分钟左右的时间，从而不影响阵列运行。在BER 硬盘误码率上没有任何区别。 按照文中的计算，一个1TB的硬盘，通常你无法读取所有sector的概率达到了56%，因此你用便宜的大容量SATA盘，在出现硬盘故障的情况下重建RAID的希望是：无法实现。 用1TB的SATA硬盘做RAID5的话，当你遇到一个硬盘失效的情况，几乎剩下的两个以上硬盘（RAID5最少组合是3个）铁定会遇到一个硬盘读取错误，从而重建失败。 所以，以前小硬盘做RAID5，基本很少遇到同时挂掉两个盘的情况；现在硬盘大了，出问题的概率也越来越大了。 对于跑RAID的用户，对整个硬盘进行读取的事情经常发生。即使系统足够和谐，知道不对你报告那些出现在你从不读取的文件中的坏道，但是也只是略过了…

Oracle数据库RAC安装部署
type: item
date: 2020-03-01T10:05:00+00:00
description: Oracle RAC数据库安装实施文档一 数据库RAC安装规划1.1. 集群节点及实例节点名称实例名称数据库名称RAMOSnode1orcl1orcl16GRHEL 6.9 64bitnode2orcl2orcl16GRHEL 6.9 64bit1.2. 网络配置标识名称类型IP地址解析node1 Publicnode1public172.16.2.1/etc/hostsnode1 privatenode1-privprivate192.168.1.1/etc/hostsnode1 VIPnode1-vipVirtual172.16.2.11/etc/hostsnode2 Publicnode2public172.16.2.2/etc/hostsnode2 privatenode2-privprivate192.168.1.2/etc/hostsnode2 Vipnode2-vipVirtual172.16.2.12/etc/hostsScan vipscan-clusterVirtual172.16.2.13/etc/hosts1.3. Oracle软件部分Software CompanetnsGrid InfrstructureOracle RAC操作系统用户gridOracle主要属组oinstalloinstall辅助属组dbadbaHome目录/home/grid/home/oracleOracle Base/u01/app/grid/u01/app/oracleOracle Home/u01/app/11.2.0/grid/u01/app/oracle/product/11.2.0/db_1软件版本Oracle 11.2.0.4 1.4. 用户组规划GroupNameGroup ID说明HOSToinstall2001Oracle清单和软件所有者node1 node2dba2002数据库管理员 1.5. 用户规划UserIDPrimaryGroupGroup说明HOST默认口令2001gridoinstall dbaOracle Cluster用户node1 node2oracle2002oracleoinstall dbaOracle数据管理员node1 node2oracle1.6. 存储规划存储建议采用RAID 10的存储方式。存储项文件系统大小ASM磁盘组冗余方式OCR/VotingASM2G*3OCRVTNormalDatafile/ArchivelogASM900GDATAExternal说明：一般情况下存储会做Raid，有磁盘级别的镜像和保护，因此建议OCR磁盘组使用Normal方式镜像，同时归档和数据库磁盘为外部冗余方式。二 安装前准备配置2.1 检查两台机器物理内存[root@ node1 ~]# top | grep Mem Mem: 16170748k total, 15670912k used, 499836k free, 278212k buffers [root@ node2 ~]# top | grep Mem Mem: 16170748k total, 15658388k used, 512360k free, 276632k buffers 2.2 检查两台机器swap和/tmp[root@ node 1 ~]# top | grep Swap Swap: 16777212k total, 40868k used, 16736344k free, 12668624k cached [root@ node 2 ~]# top | grep Swap Swap: 16777212k total, 40868k used, 16736344k free, 12668624k cached [root@ node1 ~]# df -h /tmp/ Filesystem Size Used Avail Use% Mounted on /dev/sda3 28G 3.8G 22G 15% / [root@ node 2 ~]# df -h /tmp/ Filesystem Size Used Avail Use% Mounted on /dev/sda3 28G 3.8G 22G 15% /2.3 验证操作系统版本和bit[root@ node1 ~]# uname -a Linux node2 2.6.32-504.el6.x86_64 #1 SMP Tue Sep 16 01:56:35 EDT 2014 x86_64 x86_64 x86_64 GNU/Linux [root@ node1 ~]# cat /etc/redhat-release Red Hat Enterprise Li…

JVM内存模型及内存分配过程
type: item
date: 2020-02-11T02:29:45+00:00
description: 一、JVM内存模型JVM主要管理两种类型内存：堆(Heap)和非堆（Permanent区域）。Heap是运行时数据区域，所有类实例和数组的内存均从此处分配。Heap区分两大块，一块是 Young Generation，另一块是Old Generation：在Young Generation中，有一个叫Eden Space的空间，主要是用来存放新生的对象，还有两个Survivor Spaces（from,to），它们的大小总是一样，它们用来存放每次垃圾回收后存活下来的对象。在Old Generation中，主要存放应用程序中生命周期长的内存对象。Permanent区：Permanent Generation，主要是存储的是java的类信息，包括解析得到的方法、属性、字段等等。永久带基本不参与垃圾回收。Permanent generation 不是Heap的一部。二、内存大小Heap内存分配JVM初始分配的内存由-Xms指定，默认是物理内存的1/64；JVM最大分配的内存由-Xmx指 定，默认是物理内存的1/4。默认空余堆内存小于40%时，JVM 就会增大堆直到-Xmx 的最大限制，可以由 -XX:MinHeapFreeRatio 指定。默认空余堆内存大于70%时，JVM 会减少堆直到-Xms的最小限制，可以由 -XX:MaxHeapFreeRatio 指定。Permanent区域内存分配JVM使用-XX:PermSize设置非堆内存初始值，默认是物理内存的1/64；由XX:MaxPermSize设置最大非堆内存的大小，默认是物理内存的1/4。三、JVM内存分配过程JVM 会试图为相关Java对象在Eden中初始化一块内存区域。当Eden空间足够时，内存申请结束；否则到下一步。JVM 试图释放在Eden中所有不活跃的对象（这属于1或更高级的垃圾回收）。释放后若Eden空间仍然不足以放入新对象，则试图将部分Eden中活跃对象放入Survivor区。Survivor区被用来作为Eden及Old的中间交换区域，当Old区空间足够时，Survivor区的对象会被移到Old区，否则会被保留在Survivor区。当Old区空间不够时，JVM 会在Old区进行完全的垃圾收集（0级）。完全垃圾收集后，若Survivor及Old区仍然无法存放从Eden复制过来的部分对象，导致JVM无法在Eden区为新对象创建内存区域，则出现”out of memory”错误。

Cache 和 Buffer 有什么区别？
type: item
date: 2019-12-19T07:57:38+00:00
description: Cache和Buffer是两个不同的概念，简单的说，Cache是加速“读”，而buffer是缓冲“写”，前者解决读的问题，保存从磁盘上读出的数据，后者是解决写的问题，保存即将要写入到磁盘上的数据。在很多情况下，这两个名词并没有严格区分，常常把读写混合类型称为buffer cache，本文后续的论述中，统一称为cache。Oracle中的log buffer是解决redo写入的问题，而data buffer cache则解决data block的读写问题。对于Oracle来说，如果IO没有在SGA中命中，都会发生物理IO，Oracle并不关心底层存储的类型，可能是一套存储系统，可能是本地磁盘，可能是RAID 10，也可能是RAID 5，可能是文件系统，也可能是裸设备，或是ASM。总之，Oracle把底层的存储系统称为存储子系统。在存储系统中，cache几乎无处不在（在后面的论述中，我们统称为cache），文件系统有cache，存储有cache，RAID控制器上有cache，磁盘上也有cache。为了提高性能，Oracle的一个写操作，很有可能写在存储的cache上就返回了，如果这时存储系统发生问题，Oracle如何来保证数据一致性的问题。Oracle数据库最重要的特性是：Write ahead logging，在data block在写入前，必须保证首先写入redo log，在事务commit时，同时必须保证redo log被写入。Oracle为了保证数据的一致性，对于redo log采用了direct IO，Direct IO会跳过了OS上文件系统的cache这一层。但是，OS管不了存储这一层，虽然跳过了文件系统的cache，但是依然可能写在存储的cache上。一般的存储都有cache，为了提高性能，写操作在cache上完成就返回给OS了，我们称这种写操作为write back，为了保证掉电时cache中的内容不会丢失，存储都有电池保护，这些电池可以供存储在掉电后工作一定时间，保证cache中的数据被刷入磁盘，不会丢失。不同于UPS，电池能够支撑的时间很短，一般都在30分钟以内，只要保证cache中的数据被写入就可以了。存储可以关闭写cache，这时所有的写操作必须写入到磁盘才返回，我们称这种写操作为write throuogh，当存储发现某些部件不正常时，存储会自动关闭写cache，这时写性能会下降。RAID卡上也有cache，一般是256M，同样是通过电池来保护的，不同于存储的是，这个电池并不保证数据可以被写入到磁盘上，而是为cache供电以保护数据不丢失，一般可以支撑几天的时间。还有些RAID卡上有flash cache，掉电后可以将cache中的内容写入到flash cache中，保证数据不丢失。如果你的数据库没有存储，而是放在普通PC机的本地硬盘之上的，一定要确认主机中的RAID卡是否有电池，很多硬件提供商默认是不配置电池的。当然，RAID卡上的cache同样可以选择关闭。磁盘上的cache，一般是16M-64M，很多存储厂商都明确表示，存储中磁盘的cache是禁用的，这也是可以理解的，为了保证数据可靠性，而存储本身又提供了非常大的cache，相比较而言，磁盘上的cache就不再那么重要。SCSI指令中有一个FUA(Force Unit Access)的参数，设置这个参数时，写操作必须在磁盘上完成才可以返回，相当于禁用了磁盘的写cache。虽然没有查证到资料，但是我个人认为一旦磁盘被接入到RAID控制器中，写cache就会被禁用，这也是为了数据可靠性的考虑，我相信存储厂商应该会考虑这个问题。至此，我们可以看到Oracle的一个物理IO是经历了一系列的cache之后，最终被写入到磁盘上。cache虽然可以提高性能，但是也要考虑掉电保护的问题。关于数据的一致性，是由Oracle数据库，操作系统和存储子系统共同来保证的。