大家好,又见面了,我是你们的朋友全栈君。
本文翻译自vdbench的使用手册中的数据校验章节,如有纰漏,还请不吝赐教。
数据校验在性能测试的时候不应该被使用,处理器开销可能影响性能测试的结果。
在我开始之前,我想问一个想了很多次的问题:“为什么我使用vdbench去检查数据冲突?我也可以写一个大文件,计算校验和,然后重新读这个文件并比较校验和。”当然,你可以这样做,但是这种方法真的足够好吗?你正在做的一切都是在检查数据在顺序传输时的冲突问题。但是对于随机IO怎么办呢?检查不是也很重要吗?如果你对同一个block写了X次,然后你发现内容是正确的。难道这不意味着你可能丢了X-1次连续写入而没有注意到?你花了24小时去写,然后重新读一个某个块已经是坏了的大文件?这个块什么时候被写?什么时候再次被读?是的,你可以高兴的说:我用了一个周末的时间去计算出了错误的校验和。这样说可能更有用:“我在某个block发现了某个错误,我也知道这个错误什么时候被写入,什么时候被发现的”。这个错误的块也可能来自错误的磁盘。
看data_errors= 获取数据问题的信息。
数据校验流程如下:每次对SD或者FSD的写入操作将被记录在一个内存表里。被写入的block的每一个512字节的扇区包含8字节的LBA和一个字节的数据校验key。当对同一个block进行进行写入时这个key会从1增加到126。一旦到达126,它将被回滚至1。0是一个内部的值,表示某个块还没有被写入。这个key方法被用于识别丢失的写入。如果一个块被写入多次,但是都没修改这个块的内容,这是不可能发现是否丢了一次或者更多次写。使用这个key方法,我们只有丢失126次对同一个块的连续写入才会发现不了。
一个block被写入一次后,每次对这个block的读操作都会进行数据校验。写入操作之前会有一个读操作,以确定原始数据是正确的。使用-vr执行参数强制每次写入之后都被立即读。然后这并不能保证写入的数据一定到达了物理磁盘驱动,数据也可能是从缓存中读出来的。
注意:从vdbench50407开始,数据校验key不再从1开始。这是一个很重要的改变,为什么?你执行一次测试,以key=1开始写入一个block。这笔写入丢失了。当你读的时候,你发现是过去的数据内容,因此并不认为数据冲突。通过让每个block的key都从一个随机数开始,我们可以保证这样的冲突可以被识别到。当然,在连续的测试中同一个block随机生成同样的key,这仍然有1/126的概率。但这还是比每次都从一个同样的key开始更好一些。针对重复块的重删flipflop机制也从一个随机的key开始,并且zhi有最后一个bit被翻转。
Vdbench50407引入了Owner ID的概念。对于正常的数据校验来说,这将是Master vdbench的进程ID;对于journaling,它是日志文件第一个被创建时master vdbench的进程id。Owner ID总是存储在每个扇区的28-31字节的位置。当使用重删的时候,它会存储在每个重删块的第8-11字节的位置。Owner ID的内容将检查其有效性。Owner ID 的检查是非常有用的:我经常遇到针对同一存储的两个vdbench测试,互相踩了对方的数据。因为Owner ID已经在status.html中被报告了,找到谁覆盖写了你的存储而导致的数据冲突应该会很容易。
因为data validation tables被保存在内存中,在vdbench终止后,或者系统宕机重后,数据校验将变得不可用。为了继续使用数据校验,可以使用journal。
Journaling:能够在vdbench或者系统掉电后进行数据校验,每笔写入都被记录在日志文件中。每次更新后,日志文件会被同步的刷到磁盘。每次日志更新都会写512字节到磁盘。每一个journal entry是8字节,因此,单个journal record包含63个journal entry和一个8字节的head。当一个journal record中最后一个journal record被写入时,额外的512字节的全零数据将被追加写到日志文件中,这可以让vdbench追踪日志文件的结尾。每一笔写入的前后都会写入一个journal entry。
注意:我遇到过一个场景:日志文件被维持的很好,但是日志文件所在的文件系统在系统掉电之后变得无效。我因此要求日志文件设备去规避这个问题。
因为每一个vdbench负载写引发两个同步的日志写,journaling将影响vdbench的负载的吞吐/性能。极力推荐你去使用一个开启了后写缓存的磁盘存储单元。这将把vdbench负载的性能影响最小化。为了在日志写入时使用文件系统缓存,可以指定’-jn’或者‘-jrn’去防止强刷。这样做将加速日志的写入,但是在系统异常关机时这些日志可能丢掉。进一步推荐把日志写入到一个可被称为”safe”的磁盘。不要往一个你正在进行故障注入或者其它吓人的事情的磁盘上写入日志文件。使用不可靠的journal,数据校验可能不工作。
在快照场景下如果你想使用journal,不要担心在vdbench测试时你的操作系统或者存储会挂掉。在这种情况下,before/after写入时不是很有必要。指定”journal=maponly”,vdbench将不再写before/after记录,但仍旧会从内存中拷贝数据校验map到日志文件。再次说明:这仅仅对正常停止的vdbench才会有用。
开启日志运行的vdbench开始的时候,将创建两个文件:一个map备份文件(.map),一个日志文件(.jnl)。在内存中的数据校验表内容将会被写到备份文件和日志文件(所有的key都是0)。更新的journal将不断写到日志文件的尾部(参考”journal=(max,nn)”)。在系统出错后,vdbench重新启动, 日志恢复被请求,原始map从日志文件的开始被读出,日志文件中的所有更新被应用到该map。一旦到达了日志文件的结尾,所有被标记“modified”的块将被读并且其内容是有效的。接着,内存中的map将写到日志文件的开头,然后写入到map的备份文件。journal record将被立即被写入到日志文件中map的后面。如果由于系统掉电,map写入到日志文件失败,备份文件仍旧包含包含从上次运行开始之后的原始map。如果在下次日志恢复的时候,发现日志文件中并不是所有的map都写入完成,map将从备份文件中恢复,在不完整的map之后并且仍旧在日志文件中的journal entry将再次被用于日志更新。
在一次日志恢复之后,有一种情形需要特别注意。因为每一个写操作都有一个before/after条目,但系统掉电时,可能发生after entry可能还没有写入。在这种情况下,请求中的块是否包含了before/after数据是不清楚的。在这种情况下,那个block将被读,被比较的数据可能由两个值组成,新数据或者老数据。
提示:journal=ignore_pending 或者执行参数 ‘-jri’将忽略这些挂起的写入。
提示:我认为任何在写入过程中间被中断的存储设备都必须有足够的冗余电源去完成当前正在被写的512字节的写入,或者忽略。这意味着,如果一个扇区包含了新数据和老数据,这可能导致数据冲突。
一旦日志恢复被完成,在map中被标识为至少写入一次的所有块都被顺序读并且检查他们内容的有效性,除非指定”journal=skip_read_all”
一次测试正常终止时,数据校验map被写入到journal。这扮演着两个目的:日志文件的结尾将被重置为map之后的位置,因此节省磁盘空间,并且这会避免重读整个日志文件的需求,应用它在map的开始位置防止再做另一次日志恢复。
提示:由于正在写入的所有数据的历史都是在一个Vdbench中使用不同的数据传输大小逐块维护的,因此执行有以下限制:不同的数据传输大小是被允许的,只要他们是彼此倍数。如果一个实例中,你使用了1k,4k,8k数据传输大小,数据校验将使用1k作为数据校验的块大小,因此一个4k的块占用4个小的数据校验块。
提示:当你对一个大容量的磁盘空间进行数据校验测试的时候,第二次访问一个随机块可能需要一段时间。这意味着相对短的运行时间可能看起来是成功的,然而事实上并没有数据block被重新读并进行数据校验。因此从vdbench5.0开始,vdbench追踪实际有多少块被读和校验。如果运行结束的时候,已校验的块的数量为0,vdbench将中止。
例如:对于一个运行100 iops,8k块小的1TB的LUN,让每一个随机块至少访问两次,这将需要744小时或者31天。
提示:当运行数据校验时,一个块的重写实现了一个预读,我建议当你需要指定读操作的百分比时,指定rdpct=0。特别是在刚开始测试的时候,这将阻止读到还没有写入的块,这并不能被比较,浪费宝贵的iops和带宽。但这些运行时,你将看到读百分比从0开始,但是一点vdbench开始写以前已经写入的block,读百分比会慢慢爬到50%。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/144377.html原文链接:https://javaforall.cn