PHPackages                             aston/memory-cache - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Caching](/categories/caching)
4. /
5. aston/memory-cache

ActiveLibrary[Caching](/categories/caching)

aston/memory-cache
==================

基于 Swoole Hyperf 框架，将 SwooleTable 作为 Redis 的上级缓存

v2.2.2(3y ago)342MITPHPPHP &gt;=7.4

Since Mar 8Pushed 3y ago1 watchersCompare

[ Source](https://github.com/AstonChenDev/hyperf-memory-cache)[ Packagist](https://packagist.org/packages/aston/memory-cache)[ RSS](/packages/aston-memory-cache/feed)WikiDiscussions master Synced today

READMEChangelog (4)Dependencies (9)Versions (5)Used By (0)

hyperf memory cache
===================

[](#hyperf-memory-cache)

基于 Swoole Hyperf 框架，将 SwooleTable 作为 Redis 的上级缓存

安装
--

[](#安装)

使用 composer

```
composer require aston/memory-cache

```

发布配置文件

```
php bin/hyperf.php vendor:publish aston/memory-cache

```

配置文件说明
------

[](#配置文件说明)

```
[
    'default' => [
        'driver' => SwooleTableDriver::class,
        'packer' => PhpSerializerPacker::class,
        'tables' => [
            'cache' => [
                 'enable' => true,//上级缓存开关, false 则完全不走上级缓存
                //内存表最大行数 根据机器内存配置 越大越好
                'table_size' => 1024,
                'column_value' => [
                    'type' => Table::TYPE_STRING,//内存表缓存值的字段类型
                    'size' => 1024//缓存值最大存储长度，缓存不能超过 size 指定的最大长度 否则不做缓存 避免数据不符合预期 根据实际情况配置
                ],
                //拦截读取缓存的redis命令
                'commands' => [
                    'get', 'hGet', 'hGetAll', 'hMGet', 'hLen','hexists','hkeys','hvals' //目前最多支持这么多，可指定拦截命令，留空代表不拦截，
                ]
            ],
        ],
    ],
]
```

### 实现原理：

[](#实现原理)

通过 AOP 拦截 Redis 的读操作（目前只实现了string、hash类型）

```
#[Aspect]
class CacheAspect extends AbstractAspect
{
    public $classes = [Redis::class];

    private const ALLOWED_METHODS = [
        'get', 'hget', 'hgetall', 'hmget', 'hlen', 'hexists', 'hkeys', 'hvals'
    ];
	...

    public function process(ProceedingJoinPoint $proceedingJoinPoint)
    {
        ...

        if (($from_cache = $this->$method(...$arguments)) === null) {
            $this->container->get('miss_counter')->add();
            $this->logger->debug('内存表获取缓存失败， 回源获取: method: ' . $method . '; args: ' . json_encode($arguments));
            $from_redis = $proceedingJoinPoint->process();
            //此处将获取到的数据缓存到内存表
            $this->storeToCache($method, $from_redis, $arguments);
            return $from_redis;
        }
        ...

        $this->container->get('hit_counter')->add();
        return $from_cache;
    }
```

创建自定义进程订阅 Redis 键事件，通过事件维护Swoole Table中的数据过期与删除

```
class RedisEventProcess extends AbstractProcess
{
    public function __construct() {...}

    public function handle(): void
    {
        $pool = $this->container->get(ConfigInterface::class)->get('redis.pool') ?? 'default';
        $db = $this->container->get(ConfigInterface::class)->get("redis.$pool.db") ?? 0;
        $this->redis = $this->container->get(RedisFactory::class)->get($pool);
        $this->redis->setOption(\Redis::OPT_READ_TIMEOUT, -1);
        $this->redis->config('SET', 'notify-keyspace-events', 'KEA'); // 设置参数
        $this->redis->psubscribe([
            "__keyevent@{$db}__:del",
            "__keyevent@{$db}__:expired",
            "__keyevent@{$db}__:hdel",
            "__keyevent@{$db}__:hset",
            "__keyevent@{$db}__:hincrby",
            "__keyevent@{$db}__:hincrbyfloat",
            "__keyevent@{$db}__:set",
            "__keyevent@{$db}__:setrange",
            "__keyevent@{$db}__:append",
            "__keyevent@{$db}__:incrby",
            "__keyevent@{$db}__:incrbyfloat",
            "__keyevent@{$db}__:rename_from",
            "__keyevent@{$db}__:rename_to",
        ], [$this, 'onPublish']);
    }

    public function onPublish($redis, string $pattern, string $event, string $key)
    {
        $arr = explode(':', $event);
        $method = end($arr);
        $this->logger->debug("触发redis键事件, event: $event, , method: $method, key: $key");
        switch (Str::lower($method)) {
            case 'set':
            case 'append':
            case 'incrby':
            case 'incrbyfloat':
                $latest = $this->redis->rawCommand('get', $key);
                if (!$latest) {
                    return;
                }
                $this->logger->debug("刷新string内存缓存 key: $key");
                $this->driver->set($key, $latest);
                break;
            case 'hset':
            case 'hdel':
            case 'hincrby':
            case 'hincrbyfloat':
                $latest = $this->redis->rawCommand('hGetAll', $key);
                if (!$latest) {
                    return;
                }
                $hash = array();
                for ($i = 0; $i < count($latest); $i += 2) {
                    $hash[$latest[$i]] = $latest[$i + 1];
                }
                $this->logger->debug("刷新hash内存缓存 key: $key");
                $this->driver->set($key, $this->driver->packer()->pack($hash));
                break;
            default:
                $this->logger->debug("删除内存缓存 key: $key");
                $this->driver->del($key);
                break;
        }
    }
    ...
}
```

### 使用

[](#使用)

在 Hyperf 中正常调用 Redis 即可，开发中无需关心数据是从内存表中获取还是从 Redis 获取到的。 如果在 config.php 开启了 DEBUG 等级的日志，开发时会打印对应日志。

[![hyperf框架中基于swoole table实现的redis上级缓存](https://camo.githubusercontent.com/1042aaf66c38bc25d101f40da6ce2752f2f69bd7ecce66fb4e228b76fb52bcf0/68747470733a2f2f63646e2e6c6561726e6b752e636f6d2f75706c6f6164732f696d616765732f3230323330332f30372f3130303035382f7858494e7665344141332e706e67216c61726765)](https://camo.githubusercontent.com/1042aaf66c38bc25d101f40da6ce2752f2f69bd7ecce66fb4e228b76fb52bcf0/68747470733a2f2f63646e2e6c6561726e6b752e636f6d2f75706c6f6164732f696d616765732f3230323330332f30372f3130303035382f7858494e7665344141332e706e67216c61726765)

[![hyperf框架中基于swoole table实现的redis上级缓存](https://camo.githubusercontent.com/641a22fb72358951886be4780e50433849341db6b2cbc5db1da48b2de02184d4/68747470733a2f2f63646e2e6c6561726e6b752e636f6d2f75706c6f6164732f696d616765732f3230323330332f30372f3130303035382f64356f774f6d676345722e706e67216c61726765)](https://camo.githubusercontent.com/641a22fb72358951886be4780e50433849341db6b2cbc5db1da48b2de02184d4/68747470733a2f2f63646e2e6c6561726e6b752e636f6d2f75706c6f6164732f696d616765732f3230323330332f30372f3130303035382f64356f774f6d676345722e706e67216c61726765)

### 分析缓存

[](#分析缓存)

```
通过调用 Aston\MemoryCache\DriverManager::analyze() 可以返回缓存的命中次数和miss次数
MemoryCacheDriverInterface::dbCount(); //获取缓存中的key数量
MemoryCacheDriverInterface::dbData(); //获取缓存中的键值对

```

```
{
    "analyze": {
        "hit": 12020,
        "miss": 8292,
        "hit_rate": "59.17%"
    },
    "count": 2151,
    "data": {}
}
```

###  Health Score

24

—

LowBetter than 31% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity11

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity49

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

4

Last Release

1208d ago

Major Versions

v1.0.0 → v2.2.02023-03-09

### Community

Maintainers

![](https://www.gravatar.com/avatar/2635c390557e9de20d0e6f65a286f6c07201d5c65a287cea0a49e6c2b3480d1a?d=identicon)[AstonChen](/maintainers/AstonChen)

---

Top Contributors

[![AstonChenDev](https://avatars.githubusercontent.com/u/45387979?v=4)](https://github.com/AstonChenDev "AstonChenDev (1 commits)")

### Embed Badge

![Health badge](/badges/aston-memory-cache/health.svg)

```
[![Health](https://phpackages.com/badges/aston-memory-cache/health.svg)](https://phpackages.com/packages/aston-memory-cache)
```

###  Alternatives

[symfony/symfony

The Symfony PHP framework

31.4k87.2M2.2k](/packages/symfony-symfony)[laravel/framework

The Laravel Framework.

34.8k543.8M20.1k](/packages/laravel-framework)[symfony/cache

Provides extended PSR-6, PSR-16 (and tags) implementations

4.2k373.5M3.3k](/packages/symfony-cache)[tempest/framework

The PHP framework that gets out of your way.

2.2k34.4k15](/packages/tempest-framework)[ecotone/ecotone

Enterprise architecture layer for Laravel and Symfony — CQRS, Event Sourcing, Durable Workflows (Sagas, Orchestrators), Projections, and Outbox messaging via PHP attributes.

564576.7k51](/packages/ecotone-ecotone)[wikimedia/parsoid

Parsoid, a bidirectional parser between wikitext and HTML5

187557.3k3](/packages/wikimedia-parsoid)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
