视频推荐
丢数据的问题一般发生在产品运行现场有频繁数据写入的情形,特别是在使用了数据库的时候。一般有以下表现:
轻微表现:数据库最新记录的数据项无故丢失;
比较严重情况:较多记录项数据丢失;
严重情形:文件名丢失或者乱码;
非常严重情形:系统文件丢失,或者整个/opt分区无数据。
像硬件部分,电源是重中之重,驱动层面的话,稳健可靠的驱动程序是至关重要的。但仅仅做好这两方面,如果应用软件没进行系统优化或者数据处理优化,同样也会带来丢数据的风险。下面分别从这几方面来做一些阐述。
1. 基本思路:硬件设计+系统设计+软件优化
稳定可靠的电源,掉电检测电路,后备电源,系统设计的掉电检测设计,应用程序对掉电的响应,以及平时的数据冗余备份等措施。
首先,电源稳定是产品稳定的基础。如果没稳定的电源,谈产品的可靠性和稳定性都是空中楼阁,无从谈起。所以,务必设计稳定可靠的电源,包括电源的功率、对纹波的抑制等。稳定的电源解决的是产品正常工作时候的供电问题,这样能避免很多隐蔽性很强的问题。
如果现场电源异常断电无法克服,就可以考虑增加备用电源,同时增加主电源的掉电检测电路,系统检测到电源掉电后,进行数据方面的处理,确保已经写入缓存的数据能及时写入到磁盘中,保证数据的完整性。这需要硬件、系统驱动以及应用程序几方面配合才能达到目的。
如果运行时产生的数据非常关键,特别是涉及到支付的数据,建议对数据进行冗余备份保护。如果本地存储空间允许,可以在本地进行双备份;如果系统联网,可以通过网络方式将数据发送到远程服务器进行实时备份,这种方式非常安全;当然如果有云存储功能,将数据实时存放云端也是非常安全的。如果进行了实时数据远程备份,那异常掉电对数据的影响就非常小了。
2. 解决现场丢数据的问题,需要从硬件、驱动、应用设计多方面入手才能妥善解决
2.1 选择合适的文件系统
不同的存储介质需要适配不同的文件系统,在嵌入式设备中常用的存储器是NAND Flash和eMMC。
适合NAND Flash的文件系统是UBIFS和YAFFS2。UBIFS和YAFFS2的不同之处在于它们的存储方式、性能、垃圾回收机制和应用场景:
2.1.1 存储方式
UBIFS是基于块存储的,而YAFFS2是基于页存储的。YAFFS2将文件数据划分为固定大小的页,可以更好地适应NAND Flash的物理特性,减少存储空间的浪费,提高了存储空间的利用率。而块的大小通常比页大,这意味着UBIFS可以更有效地管理存储空间。与YAFFS2相比,UBIFS使用的块更大,从而减少了存储空间的浪费和碎片化的可能性。另一方面,UBIFS的块存储机制可以适应不同大小和容量的闪存设备,并能根据实际需求进行动态调整,具备更好的可扩展性和灵活性。
2.1.2 性能方面
UBIFS支持write-back,其写入的数据会被cache,直到有必要写入时才写到flash,可以大大地降低分散小区块数量并提高I/O效率。YAFFS2则是实时写入,这会影响一部分I/O性能,但由于页是YAFFS2最小的存储单位,所以YAFFS2可以迅速定位到特定的页,并只读取或写入所需的数据,而不需要处理整个文件。这种局部性的访问方式可以减少不必要的读取和写入操作。
2.13 垃圾回收机制方面
UBIFS是基于日志型的垃圾回收,日志的垃圾回收机制提供了一种原子性和一致性的保证。所有的文件更新操作首先会被记录到日志区域,而不是直接写入到主存储区域。只有当这些更新操作被成功记录到日志后,才会进行实际的数据更新。这种方式确保了在更新操作过程中出现意外中断或系统崩溃时,文件系统能够恢复到一致的状态。
其次,日志型的垃圾回收机制实际的数据更新是异步进行的,即不会每次都同步到flash,因此写操作的延迟被显著降低,同时也减少了闪存擦除的次数。这种设计使得UBIFS在面对大量的写操作时能够保持较高的性能。
YAFFS2使用段式的垃圾回收。当文件系统中的数据被修改或删除时,会标记相应的段为无效或可回收。段式回收的过程包括扫描这些无效的段,并将其中的数据进行擦除和回收,以便重新利用这些存储空间。
段式回收的好处是可以批量处理无效数据,提高垃圾回收的效率。相对于基于页的回收机制,段式回收减少了对闪存的频繁擦除操作,从而延长了闪存的使用寿命。此外,由于回收操作是在段的级别上进行的,它能够更有效地管理存储空间,减少了存储碎片化的可能性。
2.1.4 在应用场景上
UBIFS更适合大容量存储系统,而YAFFS2更适用于中小容量的NAND Flash存储设备。
适合eMMC的文件系统是FAT32和Ext4。其差异主要体现在兼容性、性能、安全性和磁盘空间利用这几个方面:
兼容性方面:FAT32是一个较老的文件系统,但它具有广泛的兼容性,被大多数操作系统支持。而Ext4是Linux下的一个文件系统,不支持Windows。
性能方面:FAT32不支持单个大于4GB的文件,一旦超过容量限制,系统就会提示磁盘空间不足。另外,FAT32不支持软链接文件,所有在FAT32中的软链接文件都会失效,这些方面在一定程度上影响了其性能。而相比之下,EXT4则没有上述问题,有更好的性能表现。
安全性方面:FAT32不支持磁盘配额,安全性能较低。而EXT4可以进行加密、修改、运行、读取目录及写入权限的设置,提高了文件系统的安全性。
磁盘空间利用方面:FAT32的磁盘利用率相对较低,尤其是在分区大小较大时,其簇的大小也会变得相对较大,从而降低了磁盘空间的利用率。而EXT4则能够更有效地利用磁盘空间,提高了存储效率。
选择哪个文件系统取决于具体的应用场景和需求。
对于NAND Flash,如果存储器容量较大且能保证设备长期运行的情况下,UBIFS是个很好的选择。如果设备需要经常读写文件,且存在偶发性断电,则YAFFS2更合适。
对于eMMC来说,如果需要广泛的兼容性和简单的操作,FAT32可能是一个不错的选择。然而,在需要更高的性能、安全性和稳定性时,EXT4可能更适合。
2.2 系统挂载方式
在Linux系统下必须先挂载对应设备,然后才能被访问,挂载方式有很多,包括同步挂载(sync)、异步挂载(async)、只读挂载(ro)、读写挂载(rw)等,不同的挂载方式会直接影响系统的功能与性能:
async方式挂载中,所有涉及文件系统I/O的操作都是异步处理,即数据不会同步写入到磁盘,而是写入到缓冲区中,这种设置会提高系统的性能,但同时也会降低数据的安全性,一般在生产环境下不推荐使用。除非对性能要求很高,对数据可靠性要求不高的场景。
sync 与async相反,即有I/O操作时,都会同步处理I/O,把数据同步写入硬盘,此参数会牺牲一部分I/O性能,但是换来的是系统突发宕机后数据的安全性。
ro为只读挂载,可以有效保护分区中的内容,防止分区中的文件被删除和修改。
rw为读写挂载,可以修改分区内容。
Linux在使用mount命令挂载时,如果不指定挂载参数,其默认的挂载方式为异步可读写方式,如果需要使用其它挂载方式,可以通过“-o”参数指定,例如:
[root~]# mount -o ro /dev/mmcblk0p2 /mnt //只读挂载
如果修改挂载方式,可以使用“-o remount”来指定,多个挂载参数可以用“,”隔开:
[root~]# mount -o remount,rw /dev/mmcblk0p2 /mnt //重新挂载为可读写方式
如果需要修改系统的自动挂载方式,可以通过在/etc/fstab文件下添加对分区的挂载描述,fstab文件内容如下:
[root@user:~]# cat /etc/fstab
#stock fstab - you probably want to override this with a machine specific one
/dev/root / auto defaults 1 1
proc /proc proc defaults 0 0
devpts /dev/pts devpts mode=0620,gid=5 0 0
usbdevfs /proc/bus/usb usbdevfs noauto 0 0
tmpfs /run tmpfs mode=0755,nodev,nosuid,strictatime 0 0
tmpfs /var/volatile tmpfs defaults,size=50M 0 0
tmpfs /media/ram tmpfs defaults,size=16M 0 0
其中,第4列为对应分区的挂载方式(类似于mount -o),可以通过修改该列来实现不同挂载方式。