Spark:持久化存储等级选取策略 /persist() / cache() /Storage Level

本文阐述了Spark中存储级别的选择原则,包括考虑内存与CPU资源的平衡、避免频繁磁盘读取、采用备份机制加快失败恢复,以及在大内存场景下使用OFF_HEAP的优势。文章还解释了LRU缓存策略及手动移除缓存的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

那么我们应该如何选取持久化的存储级别呢?

实际上存储级别的选取就是Memory与CPU之间的双重权衡,可以参考下述内容:

(1)如果RDD的数据量对于集群内存容量压力较小,可以很好地兼容默认存储级别(MEMORY ONLY),那么优先使用它,这是CPU工作最为高效的种方式, 可以很好地提高运行速度。

(2)如果(1)不能满足,即集群的内存资源相较于cpu资源十分匮乏,则尝试使用MEMORY_ ONLY_ SER,且选择一种快速 的序列化工具,也可以达到一种不错的效果。

(3)一般情况下不要把数据持久化到磁盘, 除非计算是非常“昂贵”的或者计算过程会过滤掉大量数据,因为重新计算一个 分区数据的速度可能要高于从磁盘读取一个分区数据的速度。

(4)如果需要快速的失败恢复机制,则使用备份的存储级别,如MEMORY_ONLY_2.MEMORY_AND_DISK_2;虽然所有的存储级别都可以通过重新计算丢失的数据实现容错,但是备份机制使得大部分情况下应用无须中断,即数据丢失情况下,直接使用备份数据,而不需要重新计算数据的过程;

(5)如果处于大内存或多应用的场景下,OFF_ HEAP可以带来以下的好处:

它允许Spark Executors可以共享Tachyon的内存数据;

它在很大程度上减少JVM垃圾回收带来的性能开销;

Spark Executors故障不会导致数据丢失。

如果要缓存的数据太多,内存中放不下,Spark 会自动利用最近最少使用(LRU)的缓存策略把最老的分区从内存中移除。对于仅把数据存放在内存中的缓存级别,下一次要用到已经被移除的分区时,这些分区就需要重新计算。但是对于使用内存与磁盘的缓存级别的分区来说,被移除的分区都会写入磁盘。不论哪种情况,都不必担心你的作业因 为缓存了太多数据而被打断。不过,缓存不必要的数据会导致有用的数据被移出内存,带来更多重算的时间开销。最后,RDD还有一个方法叫作unpersist(), 调用该方法可以手动把持久化的RDD从缓存中移除。

 

<think>我们正在处理一个关于在Android 7.0系统中创建持久化目录/vendor/persist/的问题。 根据Android系统的特性,持久化目录通常是指在设备重启后仍然保留的目录。在Android中,常见的持久化存储位置包括/data分区和/sdcard等,但/vendor分区通常是只读的,所以我们需要考虑如何实现。 参考引用内容: [^1]提到:在编译Android系统源码时,在生成的根文件系统中,并不存在这些目录(指系统运行时的目录),它们是系统运行时的目录,即当系统终止时,就会消失。 [^2]提到:生成的apk需要系统签名,并放在源码vendor\customer\目录下通过mm编译,然后push到system/priv-app/,重启手机。 [^3]提到:属性在Android系统中大量使用,用来保存系统设置或在进程间传递一些简单的信息。 因此,创建持久化目录/vendor/persist/可能涉及以下方面: 1. 在编译时创建目录:我们可以在Android编译系统的makefile中添加创建该目录的步骤,并将目录编译到系统镜像中。 2. 确保目录可读写:由于/vendor分区通常是只读的,我们需要考虑将目录放在可读写的位置,或者将/vendor/persist/挂载为一个可读写分区(如通过init.rc脚本挂载)。 3. 使用属性系统:可能通过属性系统来设置和获取该目录的状态。 然而,注意:/vendor分区在Android中通常是只读的,所以将持久化目录放在/vendor下可能不是最佳实践。通常,持久化数据应放在/data分区。但如果项目要求必须放在/vendor/persist/,我们可以尝试以下方法: 方法一:在编译时创建目录并设置权限 1. 在Android源码中,我们可以修改device/<manufacturer>/<device>/device.mk文件,添加: ``` # 创建/vendor/persist目录 PRODUCT_COPY_FILES += \ $(LOCAL_PATH)/file_contexts:$(TARGET_COPY_OUT_VENDOR)/file_contexts ``` 同时,需要确保在file_contexts中定义该目录的安全上下文(SELinux相关)。 2. 但是,由于/vendor分区是只读的,我们无法在运行时写入。因此,另一种思路是将该目录链接到/data分区下的一个目录(通过符号链接或挂载)。 方法二:在启动时挂载(推荐) 在init.rc文件中,我们可以将/data/persist目录挂载到/vendor/persist。这样,实际存储位置在/data分区,但路径表现为/vendor/persist。 步骤: 1. 在init.<device>.rc文件中添加: ``` mkdir /data/persist 0770 root root mount none /data/persist /vendor/persist bind ``` 或者使用bind mount将/data/persist挂载到/vendor/persist。 2. 注意:在Android 7.0中,init.rc的语法支持mount命令,但需要确保在挂载之前/data分区已经挂载(因为/data分区是加密的,可能需要等待解密)。 3. 同时,需要为/data/persist设置正确的权限和SELinux上下文。 方法三:在系统启动后通过脚本创建(不推荐,因为每次重启都要重新创建,但实际数据需要持久化,所以应该挂载到/data分区) 考虑到持久化的要求,我们使用方法二(挂载方式)更为合适。 具体步骤: 1. 修改init.rc(或设备特定的init.<device>.rc)文件,添加以下内容: ``` on post-fs-data # 创建/data/persist目录,并设置权限 mkdir /data/persist 0770 root root # 将/data/persist挂载到/vendor/persist mount none /data/persist /vendor/persist bind # 设置目录的SELinux上下文 restorecon_recursive /data/persist ``` 注意:`post-fs-data`阶段是在/data分区挂载后,并且可以进行读写操作的阶段。 2. 修改SELinux策略,确保init进程有权执行上述操作。 可能需要添加的SELinux规则: ``` allow init rootfs:dir { create_dir_perms }; allow init persist_file:dir { create_dir_perms }; allow init persist_file:file { create_file_perms }; ``` 具体需要根据SELinux的denied log来调整。 3. 编译系统并刷机。 另外,如果不想修改init.rc,也可以考虑在系统启动后通过一个服务来创建,但这样可能会延迟目录的可用时间。 注意:在Android 7.0中,/vendor分区是独立于/system分区的,并且由厂商负责。因此,修改/vendor分区的内容需要重新编译vendor镜像。 总结步骤: 1. 在init.rc的`post-fs-data`阶段创建/data/persist目录,并将其bind mount到/vendor/persist。 2. 处理SELinux权限问题。 3. 重新编译vendor.img和boot.img(如果init.rc在boot.img中)或system.img(如果init.rc在system.img中)?实际上,init.rc通常位于boot.img的ramdisk中,所以需要修改ramdisk并重新打包boot.img。 但是,具体设备可能有所不同,请根据设备的实际情况调整。 相关问题: 1. 如何在Android中修改init.rc文件? 2. 如何为Android设备添加SELinux规则? 3. Android系统启动过程中各阶段(如post-fs-data)的执行顺序是怎样的? 4. 如何重新编译Android系统并生成boot.img和vendor.img?</think>在 Android 7.0 系统中创建持久化目录 `/vendor/persist/` 需要修改系统源码和配置文件,以下是具体步骤: ### 一、修改文件系统配置 1. **在 `fstab` 中声明分区** 编辑设备对应的 `fstab` 文件(如 `device/<厂商>/<设备>/fstab.<设备>`),添加持久化分区的挂载点: ```conf /dev/block/bootdevice/by-name/persist /vendor/persist ext4 noatime,nosuid,nodev,barrier=1,data=ordered,nodelalloc,noauto_da_alloc,errors=continue wait,check ``` *说明*:`errors=continue` 确保分区异常时仍可启动[^1]。 2. **创建 SELinux 安全上下文** 在 `file_contexts` 文件中定义目录安全标签: ```conf /vendor/persist(/.*)? u:object_r:vendor_persist_file:s0 ``` ### 二、修改 init 启动脚本 1. **在 `init.rc` 中创建目录** 添加以下命令到 `init.<device>.rc`: ```rc on early-init mkdir /vendor/persist 0770 root system restorecon_recursive /vendor/persist ``` 2. **设置分区挂载后操作** 在 `on post-fs-data` 阶段添加: ```rc chmod 0770 /vendor/persist chown root system /vendor/persist ``` ### 三、配置 SELinux 策略 1. **新建策略文件 `vendor_persist.te`** 内容: ```te type vendor_persist_file, file_type, data_file_type; allow init vendor_persist_file:dir { create_dir_perms }; ``` 2. **在 `BoardConfig.mk` 中引用策略** ```makefile BOARD_SEPOLICY_DIRS += device/<厂商>/<设备>/sepolicy ``` ### 四、编译与部署 1. **编译系统镜像** 执行编译命令: ```bash source build/envsetup.sh lunch <设备代号> make -j8 ``` 2. **刷入持久化分区** 使用 `fastboot` 刷写分区: ```bash fastboot flash persist out/target/product/<设备>/persist.img ``` ### 注意事项 1. **分区大小**:需在 `BoardConfig.mk` 中配置分区大小: ```makefile BOARD_PERSISTIMAGE_PARTITION_SIZE := 67108864 # 64MB ``` 2. **权限控制**:普通应用无法直接访问该目录,需通过系统服务代理访问。 3. **数据持久性**:存储在 `/vendor/persist/` 的数据在恢复出厂设置时会被保留(与 `/data` 分区隔离)[^3]。 --- ### 相关问题 1. 如何在 Android 系统中为新增分区配置 SELinux 策略? 2. 设备启动时挂载文件系统的顺序是怎样的? 3. Android 系统恢复出厂设置时哪些分区会被清除? 4. 如何验证自定义分区的读写权限是否生效? [^1]: 文件系统挂载配置需在 `fstab` 中声明,确保分区正确初始化 [^2]: 系统编译时需通过 `.mk` 文件控制镜像生成路径 [^3]: `/vendor/persist/` 分区独立于用户数据区,恢复出厂时不受影响
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值