{"id":19829658,"url":"https://github.com/workbunny/webman-shared-cache","last_synced_at":"2025-09-09T06:40:44.868Z","repository":{"id":177905776,"uuid":"659693649","full_name":"workbunny/webman-shared-cache","owner":"workbunny","description":"🚀🐇 Webman plugin for shared cache implementation.","archived":false,"fork":false,"pushed_at":"2025-03-04T03:32:19.000Z","size":83,"stargazers_count":30,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-01T14:44:58.570Z","etag":null,"topics":["shared-cache","webman","workbunny"],"latest_commit_sha":null,"homepage":"https://www.workerman.net/plugin/133","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/workbunny.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-06-28T11:08:14.000Z","updated_at":"2025-03-27T08:57:08.000Z","dependencies_parsed_at":"2024-01-02T08:22:40.191Z","dependency_job_id":"0b646a41-cd00-4368-b03b-620afe458af9","html_url":"https://github.com/workbunny/webman-shared-cache","commit_stats":null,"previous_names":["workbunny/webman-shared-cache"],"tags_count":30,"template":false,"template_full_name":null,"purl":"pkg:github/workbunny/webman-shared-cache","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/workbunny%2Fwebman-shared-cache","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/workbunny%2Fwebman-shared-cache/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/workbunny%2Fwebman-shared-cache/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/workbunny%2Fwebman-shared-cache/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/workbunny","download_url":"https://codeload.github.com/workbunny/webman-shared-cache/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/workbunny%2Fwebman-shared-cache/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274255041,"owners_count":25250552,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-09T02:00:10.223Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["shared-cache","webman","workbunny"],"created_at":"2024-11-12T11:19:30.259Z","updated_at":"2025-09-09T06:40:44.799Z","avatar_url":"https://github.com/workbunny.png","language":"PHP","readme":"\u003cp align=\"center\"\u003e\u003cimg width=\"260px\" src=\"https://chaz6chez.cn/images/workbunny-logo.png\" alt=\"workbunny\"\u003e\u003c/p\u003e\n\n**\u003cp align=\"center\"\u003eworkbunny/webman-shared-cache\u003c/p\u003e**\n\n**\u003cp align=\"center\"\u003e🐇 A lightweight shared cache for webman plugin. 🐇\u003c/p\u003e**\n\n# A lightweight shared cache for webman plugin\n\n\n\u003cdiv align=\"center\"\u003e\n    \u003ca href=\"https://github.com/workbunny/webman-shared-cache/actions\"\u003e\n        \u003cimg src=\"https://github.com/workbunny/webman-shared-cache/actions/workflows/CI.yml/badge.svg\" alt=\"Build Status\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/workbunny/webman-shared-cache/releases\"\u003e\n        \u003cimg alt=\"Latest Stable Version\" src=\"https://badgen.net/packagist/v/workbunny/webman-shared-cache/latest\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/workbunny/webman-shared-cache/blob/main/composer.json\"\u003e\n        \u003cimg alt=\"PHP Version Require\" src=\"https://badgen.net/packagist/php/workbunny/webman-shared-cache\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/workbunny/webman-shared-cache/blob/main/LICENSE\"\u003e\n        \u003cimg alt=\"GitHub license\" src=\"https://badgen.net/packagist/license/workbunny/webman-shared-cache\"\u003e\n    \u003c/a\u003e\n\n\u003c/div\u003e\n\n## 常见问题\n\n### 1. 它与 Redis/Memcache 的区别\n\n- shared-cache是基于APCu的本地缓存，它的底层是带有锁的MMAP共享内存；\n- Redis和Memcache本质上是“分布式”缓存系统/K-V数据库，存在网络IO；\n- shared-cache没有持久化，同时也无法实现“分布式”，仅可用于本地的多进程环境（进程需要有亲缘关系）；\n- shared-cache是μs级别的缓存，redis是ms级别的缓存；\n- 网络IO存在内核态和用户态的多次拷贝，存在较大的延迟，共享内存不存在这样的问题；\n\n### 2. 它的使用场景\n\n- 可以用作一些服务器的本地缓存，如页面缓存、L2-cache；\n- 可以跨进程做一些计算工作，也可以跨进程通讯；\n- 用在一些延迟敏感的服务下，如游戏服务器；\n- 简单的限流插件；\n\n### 3. 与redis简单的比较\n- 运行/tests/simple-benchmark.php\n  - redis使用host.docker.internal\n  - 在循环中增加不同的间隔，模拟真实使用场景\n  - 结果如下：\n    ```shell\n    1^ \"count: 100000\"\n    2^ \"interval: 0 μs\"\n    ^ \"redis: 73.606367111206\"\n    ^ \"cache: 0.081215143203735\"\n    ^ \"-----------------------------------\"\n    1^ \"count: 100000\"\n    2^ \"interval: 1 μs\"\n    ^ \"redis: 78.833391904831\"\n    ^ \"cache: 6.4423549175262\"\n    ^ \"-----------------------------------\"\n\t1^ \"count: 100000\"\n\t2^ \"interval: 10 μs\"\n\t^ \"redis: 79.543494939804\"\n\t^ \"cache: 7.2690420150757\"\n\t^ \"-----------------------------------\"\n\t1^ \"count: 100000\"\n\t2^ \"interval: 100 μs\"\n\t^ \"redis: 88.58958697319\"\n\t^ \"cache: 17.31387090683\"\n\t^ \"-----------------------------------\"\n\t1^ \"count: 100000\"\n\t2^ \"interval: 1000 μs\"\n\t^ \"redis: 183.2620780468\"\n\t^ \"cache: 112.18278503418\"\n\t^ \"-----------------------------------\"\n    ```\n\n## 简介\n\n- 基于APCu拓展的轻量级高速缓存，读写微秒级；\n- 支持具备亲缘关系的多进程内存共享；\n- 支持具备亲缘关系的多进程限流；\n\n## 安装\n\n1. **自行安装APCu拓展**\n\t```shell\n\t# 1. pecl安装\n\tpecl instanll apcu\n\t# 2. docker中请使用安装器安装\n\tcurl -sSL https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions -o - | sh -s apcu\n\t```\n2. 安装composer包\n    ```shell\n    composer require workbunny/webman-shared-cache\n    ```\n3. 使用命令进行php.ini的配置\n    - 进入 **/config/plugin/workbunny/webman-shared-cache** 目录\n    - 运行\n\t```shell\n    # 帮助信息\n    sh ./shared-cache-enable.sh --help\n    # or\n    bash ./shared-cache-enable.sh --help\n    ```\n\n## 使用\n\n#### 注：\\Workbunny\\WebmanSharedCache\\Cache::$fuse为全局阻塞保险\n\n### 1. Cache基础使用\n\n- **类似Redis的String【使用方法与Redis基本一致】**\n  - 支持 Set/Get/Del/Keys/Exists\n  - 支持 Incr/Decr，支持浮点运算\n  - 支持 储存对象数据\n  - 支持 XX/NX模式，支持秒级过期时间\n\n- **类似Redis的Hash【使用方法与Redis基本一致】**\n  - 支持 HSet/HGet/HDel/HKeys/HExists \n  - 支持 HIncr/HDecr，支持浮点运算\n  - 支持 储存对象数据\n  - 支持 HashKey的秒级过期时间【版本 ≥ 0.5】\n  \n- **通配符/正则匹配Search**\n  ```php\n  $result = [];\n  # 默认正则匹配 - 以50条为一次分片查询\n  \\Workbunny\\WebmanSharedCache\\Cache::Search('/^abc.+$/', function ($key, $value) use (\u0026$result) { \n      $result[$key] = $value;\n  }, 50);\n  \n  # 通配符转正则\n  \\Workbunny\\WebmanSharedCache\\Cache::Search(\n      \\Workbunny\\WebmanSharedCache\\Cache::WildcardToRegex('abc*'),\n      function ($key, $value) use (\u0026$result) {\n          $result[$key] = $value;\n      }\n  );\n  ```\n  **Tips：Cache::Search()本质上是个扫表匹配的过程，是O(N)的操作，如果需要对特定族群的数据进行监听，推荐使用Channel相关函数实现监听。**\n\n\n- **原子性执行**\n  ```php\n  # key-1、key-2、key-3会被当作一次原子性操作\n  \n  # 非阻塞执行 - 成功执行则返回true，失败返回false，锁冲突会导致执行失败\n  $result = \\Workbunny\\WebmanSharedCache\\Cache::Atomic('lock-test', function () { \n      \\Workbunny\\WebmanSharedCache\\Cache::Set('key-1', 1);\n      \\Workbunny\\WebmanSharedCache\\Cache::Set('key-2', 2);\n      \\Workbunny\\WebmanSharedCache\\Cache::Set('key-3', 3);\n  });\n  # 阻塞等待执行 - 默认阻塞受Cache::$fuse阻塞保险影响\n  $result = \\Workbunny\\WebmanSharedCache\\Cache::Atomic('lock-test', function () { \n      \\Workbunny\\WebmanSharedCache\\Cache::Set('key-1', 1);\n      \\Workbunny\\WebmanSharedCache\\Cache::Set('key-2', 2);\n      \\Workbunny\\WebmanSharedCache\\Cache::Set('key-3', 3);\n  }, true);\n  # 自行实现阻塞\n  $result = false\n  while (!$result) {\n      # TODO 可以适当增加保险，以免超长阻塞\n      $result = \\Workbunny\\WebmanSharedCache\\Cache::Atomic('lock-test', function () { \n          \\Workbunny\\WebmanSharedCache\\Cache::Set('key-1', 1);\n          \\Workbunny\\WebmanSharedCache\\Cache::Set('key-2', 2);\n          \\Workbunny\\WebmanSharedCache\\Cache::Set('key-3', 3);\n      });\n  }\n  ```\n\n- **查看cache信息**\n  ```php\n  # 全量数据\n  var_dump(\\Workbunny\\WebmanSharedCache\\Cache::Info());\n  \n  # 不查询数据\n  var_dump(\\Workbunny\\WebmanSharedCache\\Cache::Info(true));\n  ```\n  \n- **查看锁信息**\n  ```php\n  # Hash数据的处理建立在写锁之上，如需调试，则使用该方法查询锁信息\n  var_dump(\\Workbunny\\WebmanSharedCache\\Cache::LockInfo());\n  ```\n\n- **查看键信息**\n  ```php\n  # 包括键的一些基础信息\n  var_dump(\\Workbunny\\WebmanSharedCache\\Cache::KeyInfo('test-key'));\n  ```\n  \n- **清空cache**\n  - 使用Del多参数进行清理\n  ```php\n  # 接受多个参数\n  \\Workbunny\\WebmanSharedCache\\Cache::Del($a, $b, $c, $d);\n  # 接受一个key的数组\n  \\Workbunny\\WebmanSharedCache\\Cache::Del(...$keysArray);\n  ```\n  - 使用Clear进行清理\n  ```php\n  \\Workbunny\\WebmanSharedCache\\Cache::Clear();\n  ```\n  \n### 2. RateLimiter插件\n\n\u003e 高效轻量的亲缘进程限流器\n\n1. 在/config/plugin/workbbunny/webman-shared-cache/rate-limit.php中配置\n2. 在使用的位置调用\n  - 当没有执行限流时，返回空数组\n  - 当执行但没有到达限流时，返回数组is_limit为false\n  - 当执行且到达限流时，返回数组is_limit为true\n  ```php\n  $rate = \\Workbunny\\WebmanSharedCache\\RateLimiter::traffic('test');\n  if ($rate['is_limit'] ?? false) {\n      // 限流逻辑 如可以抛出异常、返回错误信息等\n      return new \\support\\Response(429, [\n          'X-Rate-Reset' =\u003e $rate['reset'],\n          'X-Rate-Limit' =\u003e $rate['limit'],\n          'X-Rate-Remaining' =\u003e $rate['reset']\n      ])\n  }\n  ```\n\n### 3. Cache的Channel功能\n\n- Channel是一个类似Redis-stream、Redis-list、Redis-Pub/Sub的功能模块\n- 一个通道可以被多个进程监听，每个进程只能监听一个相同通道（也就是对相同通道只能创建一个监听器）\n\n- **向通道发布消息**\n  - 临时消息\n  ```php\n  # 向一个名为test的通道发送临时消息；\n  # 通道没有监听器时，临时消息会被忽略，只有通道存在监听器时，该消息才会被存入通道\n  Cache::ChPublish('test', '这是一个测试消息'， false);\n  ```\n  - 暂存消息\n  ```php\n  # 向一个名为test的通道发送暂存消息；\n  # 通道存在监听器时，该消息会被存入通道内的所有子通道\n  Cache::ChPublish('test', '这是一个测试消息'， true);\n  ``` \n  - 指定workerId\n  ```php\n  # 指定发送消息至当前通道内workerId为1的子通道\n  Cache::ChPublish('test', '这是一个测试消息'， true, 1);\n  ``` \n\n- **创建通道监听器**\n  - 一个进程对相同通道仅能创建一个监听器\n  - 一个进程可以同时监听多个不同的通道\n  - 建议workerId使用workerman的workerId进行区分\n  ```php\n  # 向一个名为test的通道创建一个workerId为1的监听器；\n  # 通道消息先进先出，当有消息时会触发回调\n  Cache::ChCreateListener('test', '1', function(string $channelKey, string|int $workerId, mixed $message) {\n      // TODO 你的业务逻辑\n      dump($channelKey, $workerId, $message);\n  });\n  ```\n\n- **移除通道监听器**\n  - 移除监听器子通道及子通道内消息\n  ```php\n  # 向一个名为test的通道创建一个workerId为1的监听器；\n  # 通道移除时不会移除其他子通道消息\n  Cache::ChRemoveListener('test', '1', true);\n  ```\n  - 移除监听器子通道，但保留子通道内消息\n  ```php\n  # 向一个名为test的通道创建一个workerId为1的监听器；\n  # 通道移除时不会移除所有子通道消息\n  Cache::ChRemoveListener('test', '1', false);\n  ```\n  \n- **实验性功能：信号通知**\n  - 由于共享内存无法使用事件监听，所以底层使用Timer定时器进行轮询，实验性功能可以开启使用系统信号来监听数据的变化\n  ```php\n  // 设置信号\n  // 因为event等事件循环库是对标准信号的监听，所以不能使用自定实时信号SIGRTMIN ~ SIGRTMAX\n  // 默认暂时使用SIGPOLL，异步IO监听信号，可能影响异步文件IO相关的触发\n  Future::$signal = \\SIGPOLL;\n  // 开启信号监听，这时候开启的监听会触发之前的回调和通道回调，不会影响之前的回调\n  Cache::channelUseSignalEnable(true)\n  ```\n  - 当使用的监听信号存在已注册的回调产生回调冲突时，可以手动设置回调事件共享\n  ```php\n  // 设置信号\n  // 因为event等事件循环库是对标准信号的监听，所以不能使用自定实时信号SIGRTMIN ~ SIGRTMAX\n  // 默认暂时使用SIGPOLL\n  Future::$signal = \\SIGPOLL;\n  // 假设\\SIGPOLL存在一个已注册的回调，YourEventLoop::getCallback(\\SIGPOLL)可以获取该事件在当前进程注册的回调响应\n  // 设置回调\n  Future::setSignalCallback(YourEventLoop::getCallback(\\SIGPOLL));\n  // 开启信号监听，这时候开启的监听会触发之前的回调和通道回调，不会影响之前的回调\n  Cache::channelUseSignalEnable(true)\n  ```\n  \u003e 通道信号监听维系了一个事件队列，多次触发信号时，回调只会根据事件队列是否存在事件消费标记而执行事件回调\n### 其他功能具体可以参看代码注释和测试用例\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fworkbunny%2Fwebman-shared-cache","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fworkbunny%2Fwebman-shared-cache","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fworkbunny%2Fwebman-shared-cache/lists"}