观摩了这篇文章后https://www.cnblogs.com/zyblog-coder/p/15013804.html 学到了php还有操作文件扩展属性的扩展

快速安装了一下

sudo apt-get install xattr
sudo pecl install xattr

然后编辑php.ini加一下扩展开启

extension=xattr

然后查看了一下手册学到了这几个函数

xattr_get($file)                      获取文件存储单个key的值
xattr_list($file) 获取文件存储的key列表
xattr_remove($file, $key) 移除文件存储的某个key
xattr_set($file, $key, $value) 设置文件存储的某个key的值
xattr_supported($file) 查看文件是否支持xattr

然后迅速实践了一下,发现在我这个ubuntu系统里面,单个文件,如果只设置一个key,最大长度能写入4040个字符

<?php
$file = "test.log";
is_file($file) || touch($file); for ($i=0; $i < 5000; $i++) {
$value = str_repeat("1", $i);
$result = xattr_set($file, '0', $value);
if(!$result){
var_dump($i);//打印出来的是4041 说明只能存储到4040
exit;
break;
}
}

随着你设置的key越多,那单个key能存储的上限也就逐渐降低下来。

如果设置2个key,平均每个key最大长度能写入2008个字符

如果设置10个key,平均每个key最大长度能写入384个字符

如果设置26个key,平均每个key最大长度能写入136个字符

由此可见,如果你想尽可能多的存储数据,可以只存一个key,然后把数据放入序列化存储,如果你的数据不大想快速的获取数据,你可以把每个key都存储起来,比如一张表的所有字段(当然要求这些字段不是那种很长的text blob类型)

这个扩展属性的优势在于其写入速度很快基本上写入单个key ,value存储4040个字符的时候是0.03-0.04毫秒,读取的时候也基本上是0.04毫秒。

读取使用代码

<?php
$file = "test.log";
is_file($file) || touch($file);
$attr_key_list = xattr_list($file);
foreach ($attr_key_list as $attr_key) {
$new_data[$attr_key] = xattr_get($file, $attr_key);
}

但是随着你的key越来越多比如你存储50个key,每个key存储很短的20个字符的小数据,你会发现写入这50个字段耗时0.2-0.4毫秒左右,读取也是0.2-0.3毫秒左右

同等情况下50个key,每个key存储20个字符,json_encode 序列化然后file_put_contents 耗时 0.16 毫秒,file_get_contents 读取内容然后json_decode耗时0.046毫秒左右

同等情况下50个key,每个key存储20个字符,serialize 序列化然后file_put_contents 耗时 0.15毫秒,file_get_contents 读取内容然后unserialize耗时0.031毫秒左右

同等情况下50个key,每个key存储20个字符,serialize 序列化然后file_put_contents 耗时 0.18毫秒,file_get_contents 读取内容然后unserialize耗时0.027毫秒左右

这里可以做一个表格

存储方式

1个key序列化并写入(毫秒)

1个key读取并反序列化(毫秒) 10个key序列化并写入(毫秒) 10个key读取并反序列化(毫秒) 50个key序列化并写入(毫秒) 50个key读取并反序列化(毫秒)
xattr key存储 0.03 0.02 0.07 0.23 0.2-0.4 0.2-0.3
json+file_put_contents 0.15 0.03 0.16 0.028 0.16 0.046
serialize+file_put_contents 0.14 0.021 0.11 0.017 0.15 0.031
igbinary_serialize+file_put_contents 0.165 0.04 0.14 0.018 0.18 0.027

我们发现多key的时候 xattr并没有什么优势,只有在少量的几个key的时候它的优势才是非常明显的,而且我发现一个奇怪的现象file_put_contents对已有文件写入反而慢,如果之前没有文件使用file_put_contents反而快。

而xattr的操作是已有文件比较快,没有文件的话,还得自己手动新建一个文件就会比较慢。

这说明了这种xattr存储非常适合少量key数据的写入,因为总体来看写入速度是很快的,其读取速度随着key的增加而变慢,毕竟这里用了循环读取key,而序列化的方式还是读取一次文件+序列化一次文件,其成本没有太大开销,所以在key增多的时候反而更加有优势。

比较经典的案例场景是

场景1:有一个总列表数据做了文件缓存,但是有时候业务场景下列表页面只想知道其数量count,这种情况下,去file_get_contents unserialize/json_decode 再count 是很不划算的,因为那样拿到了全部的数据但是又只用到count,此时可以预先在该列表数据文件扩展属性上面增加 total_count 属性,单个key读取其属性返回,根本不用操作文件本身内容,大大提高了速度,可以把一个1ms左右(打开读取并序列化取count一般这样的操作一个文件要1ms)的操作提速50倍。

场景2:还可以用于少量信息及时存储场景,比如有数据需要及时存储投递,但是不需要后续处理,后续处理可以交给定时器异步,那么就可以用这样的方式生成一个临时文件并存储少量4000个(左右)字符内的数据,及时返回写入结果,让后续的处理交给另外的程序来解决,可以将写操作省下大量时间,毕竟写单个小文件是要0.15ms的。(更别提redis连接connect set等一系列操作了)

让我们更加极端一些,就只写入非常简单的字符串。

写入

1. attr写入

<?php
$file = "test.log";
$start_time = microtime(true);
xattr_set($file, 'test_key', 'test_data');
$end_time = microtime(true);
echo ($end_time - $start_time) * 1000 . " ms \r\n";//耗费时间0.03ms

2. file_put_contents 文件写入

<?php
$file = "test.log";
$start_time = microtime(true);
file_put_contents($file, 'test_data');
$end_time = microtime(true);
echo ($end_time - $start_time) * 1000 . " ms \r\n";//耗费时间0.15ms 即使是这么小的文件写入也要0.15ms

3. redis 写入 (为了排除连接connect耗费的时间,我特意把它拿出计算时间的区间外了,只记录一次set时间)

<?php
$file = "test.log";
$redis = new Redis();
$redis->connect("127.0.0.1", 6379);
$start_time = microtime(true);
$redis->set($file, "test_data");
$end_time = microtime(true);
echo ($end_time - $start_time) * 1000 . " ms \r\n";
//首次set耗费时间7.5ms 后面有了key之后再set耗费时间0.1299ms

看到了吗,写入速度是file写入的5倍!

如果你沉迷与内存数据库写入,认为redis非常快,那你错了,redis是很快,但是再快也是有上限的,毕竟虽然大家都说每秒50000次写入,这意味着每次写入要0.02ms,可是我们在本机测试的时候并不会达到这个速度的,我本地写入redis 每秒也就30000次写入撑死了,其速度仍然低于xattr写入速度。

由此可见,作为小数据内容存储并写入其速度是很快的,很适合高速写入。

读取

1. attr读取

<?php
$file = "test.log";
$start_time = microtime(true);
$attr = xattr_get($file, 'test_key');
$end_time = microtime(true);
echo ($end_time - $start_time) * 1000 . " ms \r\n";//耗费时间0.026ms

2. file_get_contents 文件读取

<?php
$file = "test.log";
$start_time = microtime(true);
$attr = file_get_contents($file);
$end_time = microtime(true);
echo ($end_time - $start_time) * 1000 . " ms \r\n";//耗费时间0.034ms

3. redis读取 (同样为了排除连接connect耗费的时间,我特意把它拿出计算时间的区间外了,只记录一次get时间)

<?php
$file = "test.log";
$redis = new Redis();
$redis->connect("127.0.0.1", 6379);
$start_time = microtime(true);
$attr = $redis->get($file);
$end_time = microtime(true);
echo ($end_time - $start_time) * 1000 . " ms \r\n";//get耗费时间0.12ms

读取速度快于file读取23%!而且如果是刚刚描述的场景1下该文件有大量数据,但是只想获得一个count,那就更快了,毕竟文件越大,file_get_contents 越慢,但是获取attr的速度几乎不变。

我们看到redis的读取速度并不是那么理想,也许是我电脑给redis的配置不是最优,但是根据大家所记录的redis get 每秒钟10万次请求来看那就是单次读取0.01ms,我认为这个10万次应该不是单进程读取而是能支撑的多线程多进程读取总量,可是我们往往无法在本机达到那样的速度,这是确实让人遗憾。

总之,综合来看,xattr速度是非常的高啊,非常适合特殊场景进行使用,推荐大家尝试!

另外给这个https://www.cnblogs.com/zyblog-coder/p/15013804.html作者点赞,是他给我提供了一个这样的知识点和灵感

php xattr操作文件扩展属性的更多相关文章

  1. PHP中DirectIO直操作文件扩展的使用

    关于 PHP 的文件操作,我们也将是通过一系列的文章来进行学习.今天我们先学习的是一个很少人使用过,甚至很多人根本不知道的扩展,它与我们日常的文件操作有些许的不同.不过这些差别并不是我们肉眼所能直观看 ...

  2. 在bash shell中使用getfattr查看文件扩展属性

    getfattr用法 用于获取文件扩展属性,返回一系列键值对,参考Linux Man Page. 常用OPTIONS -n name, --name=name Dump the value of th ...

  3. day9:文件相关操作&文件扩展模式&文件相关函数

    文件的操作 # 文件的写入 # 1.打开文件 fp = open("ceshi1.txt",mode="w",encoding="utf-8" ...

  4. 第8章 File I/O,File类操作文件的属性

    1.文件 1.1.什么是文件? 答:文件可认为是相关记录或放在一起的数据的集合 1.2.文件- -般存储在哪里? 答: 磁盘,硬盘,文件夹 1.3.JAVA程序如何访向文件属性? JAVA API:i ...

  5. lsattr 查看文件扩展属性

    1. 命令功能 lsattr查看 是否有chattr设置的权限. 2. 使用范例 [root@localhost data]# lsattr resolv.conf -----a-------e- r ...

  6. 在PHP中操作文件的扩展属性

    在操作系统的文件中,还存在着一种我们可以自己定义的文件属性.这些属性不是保存在文件内容中,也不是直接可以通过 ls -al 所能看到的内容.它们可以将一个键值对信息永久得关联到文件上,一般现在的 Li ...

  7. FME中Cass扩展属性转Shp的方法

    问题:真受不了CAD中的注记,只能方便显示,难于数据交互.好在Cass把属性信息基本写在扩展属性中,但显示又成问题了.此事难两全!我们通过查看实体属性,需要把宗地界线的扩展属性提取出来.即组码为-3, ...

  8. linux中suid/sgid/sticky及扩展属性(attr)

    suid只适用于命令文件.(如/usr/bin/passwd) 当命令文件上有suid权限时,则操作用户的权限变成属主权限.命令文件上无suid权限则操作用户的权限不变. 查看suid权限: [roo ...

  9. 使用File类操作文件或目录的属性

    在学I/O流之前,我先总结一下使用File类操作文件或目录的属性. package com.File; import java.io.File; import java.io.IOException; ...

  10. Linux 文件系统扩展属性【转】

    转自:https://blog.csdn.net/ganggexiongqi/article/details/7661024 扩展属性(xattrs)提供了一个机制用来将<键/值>对永久地 ...

随机推荐

  1. Android : Found byte-order-mark in the middle of a file

    1. 首先,打包App,然后打包报错, views里提示,要加上 android { lintOptions { checkReleaseBuilds false //不检查发布版中的错误 abort ...

  2. CM3和ARM7的差异

    此文章由文心一言生成,引用请标注作者:文心一言CM3通常指的是Cortex-M3,它是ARM公司设计的一种基于ARMv7-M架构的32位处理器内核,主要用于嵌入式系统.而ARM7则是ARM公司早期设计 ...

  3. 忘记 mysql 8.0 root 密码 怎么修改

    本文copy自 Centos7重置Mysql 8.0.1 root 密码 问题产生背景: 安装完 最新版的 mysql8.0.1后忘记了密码,向重置root密码:找了网上好多资料都不尽相同,根据自己的 ...

  4. 全面升级,票据识别新纪元:合合信息TextIn多票识别2.0

    ​ 票据识别 - 自动化业务的守门员 发票.票据识别,是OCR技术和RPA.CMS系统结合的一个典型场景,从覆盖率.覆盖面的角度来说,应该也是结合得最成功的场景之一. 旧瓶装新酒,已经成熟的产品何苦费 ...

  5. ArgoWorkflow教程(五)---Workflow 的多种触发模式:手动、定时任务与事件触发

    上一篇我们分析了argo-workflow 中的 archive,包括 流水线GC.流水线归档.日志归档等功能.本篇主要分析 Workflow 中的几种触发方式,包括手动触发.定时触发.Event 事 ...

  6. 暑假集训CSP提高模拟11

    A.Fate 求次短路方案数. 这题有点小水了,好像之前做过. 具体的方案显然是 DP,考虑枚举当前每一个路径长度,假如比最短路更优则覆盖最短路,之前的最短路用来覆盖次短路. 否则如果比次短路更优,则 ...

  7. std::vector 和 std::map 都支持以下比较运算符

    在 C++ 标准库中,std::vector 和 std::map 都支持以下比较运算符: ==(相等运算符) !=(不等运算符) <(小于运算符) <=(小于等于运算符) >(大于 ...

  8. CF1659 Codeforces Round #782 (Div. 2) 题解

    之前说过的题解,E应该不会补了(大概) A Red Versus Blue 题意非常简单,构造题.给定\(r\)个红色气球和\(b\)个蓝色气球,将它们排成一排,要求使得连续出现的最多的同色气球最少, ...

  9. Guava中的Joiner和Splitter

    目录 Guava 介绍 Joiner list转string map转string 处理嵌套集合 处理null值 Splitter string转list string转map 多个拆分符 输出 代码 ...

  10. Oracle数据库安装配置详细教程汇总(含11g、12c、18c、19c、21c)

    不论你是数据库小白,还是久经沙场的技术专家,你接触和运维Oracle数据库的第一步可能都是安装配置.并且随着软硬件的升级.替换以及业务场景的变化,数据库安装也将是你常常会进行的操作之一. 这里先为大家 ...