定制 fab2s/filelock 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

fab2s/filelock

Composer 安装命令:

composer require fab2s/filelock

包简介

A fluent Helper to properly handle file locking with flock

README 文档

README

Build Status Total Downloads Monthly Downloads Latest Stable Version Scrutinizer Code Quality PRs Welcome License

A fluent Helper to properly handle file locking based on flock().

FileLock offers two locking strategies and several options. Just like flock(), FileLock can either wait until an exclusive lock is acquired (Blocking), or fail immediately (Non Blocking), but it can also try a configurable amount of time to acquire a Non Blocking exclusive lock, and wait a configurable amount of time between each attempts. FileLock can either lock a file (Self Locking) or create a file.lock and lock it instead (External Locking)

Installation

Math can be installed using composer :

composer require "fab2s/filelock"

FileLock is also included in OpinHelper which packages several bellow "Swiss Army Knife" level Helpers covering some of the most annoying aspects of php programing, such as UTF8 string manipulation, high precision Mathematics or properly locking a file

Should you need to work with php bellow 7.1, you can still use OpinHelper 0.x

Prerequisites

FileLock has no specific dependencies

External Locking

This locking strategy does not lock the input filePath itself but rather creates a new file $lockFilePath = "$inputFilePath.lock"; and attempts to flock() it instead This method is preferred in highly concurrent usages, where many processes will try to write the same file at once, such as file caching. Because this allows us to first try to open the .lock file in write mode and fail back to read mode before a flock() is eventually attempted

By using a separate file for locking, we make sure that every write waiting for the lock (this should be done in Blocking mode) does not hold any handle on the cache file itself while it is most likely already being intensively read

By failing back to read mode when write failed, we again lower the write handles to a single one, only when the external .lock file needs to be created. Altogether, this means that after warm up, each process waiting to write on the same file will be holding a read handle on the .lock file, while a single write one is at most used to actually write the cache file. As write handles are costly to open, approximately ten times slower than read handles, doing this can end up making some difference

External locking can also be useful when you do not want to actually flock() a file (could be already locked or used by some other program/process), or because you just need exclusivity for something as the lock file is then created for you and every PHP process will be able to check its existence

Please note that the external and empty .lock file is never deleted by FileLock and that its presence does not necessarily means that the lock is active

If the $lockFilePath = "$inputFilePath.lock"; version of the .lock file (that is where the $inputFilePath directory) is not writable, it is created in sys_get_temp_dir() instead, with a hashed basedir($inputFilePath) prefix in filename

$filePath = "/some/dir/some.file.ext";
$lock = new FileLock($filePath, Filelock::LOCK_EXTERNAL); // will create /some/dir/some/file.ext.lock or /tmp/sha1(/some/dir/some)_file.ext.lock

Self Locking

This locking strategy does acquire a lock on the input filePath itself. It provide with more guarantees than the External Locking strategy as the file will be locked for any process, not just the ones checking the lock through FileLock and it is preferred when write sessions are not instant

$filePath = "/some/dir/some.file.ext";
$lock = new FileLock($filePath, Filelock::LOCK_SELF); // will directtly flock() /some/dir/some/file.ext

It could make sense under specific circumstances to use a double lock, both External and Self, using two FileLock instances

In practice

In both External and Self locking, once you have an instance you can:

  • Acquire a Blocking lock:

    $lock->doLock(true);
    // we either own the lock or php timed out
  • Attempt to acquire a Non Blocking lock:

    if ($lock->doLock()) {
        // we got the lock
    }
  • Attempt to acquire a Non Blocking lock several time before failing:

    $isLocked = $lock->setLockTry(5) // default is 3
        ->setLockWait(0.01) // default is 0.1 second
        ->obtainLock(); // will try 5 times and wait 0.01 second in between
    if ($isLocked) { // could call $lock->isLocked()
        // we got the lock
    }

From there, you can get the underlying handle:

$lockHandle = $lock->getHandle();

This is mostly useful when Self locking as you probably need the handle to actually write something.

Release lock

In all cases, locks are either released upon instance destruction or manually:

$lock->unLock(); // doing so also fclose() underlying handle

It is IMPORTANT to notice that when you acquire an Self lock, you need to keep the $lock instance alive until you are done with manipulating the file. Because FileLock is set to release its locks and handles when destroyed. This could happen if you where to acquire a lock in some function without storing the resulting instance outside of its scope.

Open Factory

FileLock comes with an handy factory to ease exclusively and self locked file opening:

    /**
     * @param string     $file
     * @param string     $mode fopen() mode
     * @param int|null   $maxTries 0|null for single non blocking attempt
     *                             1 for a single blocking attempt
     *                             1-N Number of non blocking attempts
     * @param float|null $lockWait Time to wait between attempts in second
     *
     * @return null|static
     */
    public static function open($file, $mode, $maxTries = null, $lockWait = null)

Usage is pretty similar to fopen() except it returns a FileLock instance upon success (open + lock) instead of a resource and null when it failed.

$filePath = "/some/dir/some.file.ext";
$mode = 'wb'; // any fopen() mode
$fileLock = Filelock::open($filePath, $mode); // returns null or FileLock instance

if ($fileLock) {
	// we got it opened and locked
	$handle = $fileLock->getHandle();
}

Requirements

FileLock is tested against php 7.1, 7.2, 7.3, 7.4 and 8.0

Contributing

Contributions are welcome, do not hesitate to open issues and submit pull requests.

License

FileLock is open-sourced software licensed under the MIT license.

fab2s/filelock 适用场景与选型建议

fab2s/filelock 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 307.84k 次下载、GitHub Stars 达 2, 最近一次更新时间为 2019 年 08 月 11 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「php」 「file」 「Simple」 「helper」 「lock」 「flock」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 fab2s/filelock 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 fab2s/filelock 我们能提供哪些服务?
定制开发 / 二次开发

基于 fab2s/filelock 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 307.84k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 2
  • 点击次数: 33
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 2
  • Watchers: 1
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2019-08-11