{"id":15788388,"url":"https://github.com/mevdschee/tqdmemcachebundle","last_synced_at":"2025-10-10T14:41:16.628Z","repository":{"id":57072308,"uuid":"64381608","full_name":"mevdschee/TqdMemcacheBundle","owner":"mevdschee","description":" Symfony bundle for Memcache Doctrine caching and session storage in the Web Debug Toolbar. ","archived":false,"fork":false,"pushed_at":"2016-11-29T20:42:00.000Z","size":289,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-08-06T13:53:50.153Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","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/mevdschee.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}},"created_at":"2016-07-28T09:18:37.000Z","updated_at":"2017-03-02T21:02:27.000Z","dependencies_parsed_at":"2022-08-24T10:40:55.505Z","dependency_job_id":null,"html_url":"https://github.com/mevdschee/TqdMemcacheBundle","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/mevdschee/TqdMemcacheBundle","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mevdschee%2FTqdMemcacheBundle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mevdschee%2FTqdMemcacheBundle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mevdschee%2FTqdMemcacheBundle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mevdschee%2FTqdMemcacheBundle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mevdschee","download_url":"https://codeload.github.com/mevdschee/TqdMemcacheBundle/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mevdschee%2FTqdMemcacheBundle/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279004184,"owners_count":26083689,"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-10-10T02:00:06.843Z","response_time":62,"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":[],"created_at":"2024-10-04T21:42:04.064Z","updated_at":"2025-10-10T14:41:16.589Z","avatar_url":"https://github.com/mevdschee.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/mevdschee/TqdMemcacheBundle.svg)](https://travis-ci.org/mevdschee/TqdMemcacheBundle)\n[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/mevdschee/TqdMemcacheBundle.svg)](http://isitmaintained.com/project/mevdschee/TqdMemcacheBundle \"Average time to resolve an issue\")\n[![Percentage of issues still open](http://isitmaintained.com/badge/open/mevdschee/TqdMemcacheBundle.svg)](http://isitmaintained.com/project/mevdschee/TqdMemcacheBundle \"Percentage of issues still open\")\n[![Total Downloads](https://img.shields.io/packagist/dt/tqdev/memcache-bundle.svg?style=flat-square)](https://packagist.org/packages/mevdschee/memcache-bundle)\n\nTqdMemcacheBundle\n=================\n\n![screenshot](https://raw.githubusercontent.com/mevdschee/TqdMemcacheBundle/master/screenshot.png)\n\nIf you want to optimize your web application for high load and/or low load times Memcache is an indispensable tool.\nIt will manage your session data without doing disk I/O on web or database servers. You can also run it as a\ncentral object storage for your website. In this role it is used for caching database queries using the Doctrine \ncaching support or expensive API calls by implementing the caching using Memcache \"get\" and \"set\" commands.\n\nThis Symfony bundle will provide Memcache integration into Symfony and Doctrine for session storage and caching. \nIt has full Web Debug Toolbar integration that allows you to analyze and debug the cache behavior and performance.\n\n[Read the TQdev.com blog about TqdMemcacheBundle](http://tqdev.com/2016-symfony-memcache-bundle-v3-released)\n\n### Requirements\n\n- PHP 5.3.10 or higher (PHP 7 supported)\n- php-memcache 3.0.6 or higher\n- memcached 1.4 or higher\n\n### Installation\n\nTo install TqdMemcacheBundle with Composer just run the following command:\n\n    php composer.phar require tqdev/memcache-bundle\n\nFinally, add the bundle to the registerBundles function of the AppKernel class in the 'app/AppKernel.php' file:\n\n    public function registerBundles()\n    {\n        $bundles = array(\n            ...\n            new Tqd\\MemcacheBundle\\TqdMemcacheBundle(),\n            ...\n        );\n\nConfigure the bundle by adding the following to app/config/config.yml':\n\n```yml\ntqd_memcache:\n    session:\n        pool: default\n    pools:\n        default:\n            servers:\n              - { host: localhost, tcp_port: 11211 }\n```\n\nInstall the following dependencies (on Ubuntu based systems using 'apt-get'):\n\n    apt-get install memcached php-memcache\n\nNB: In PHP5 this last package was called `php5-memcache`.\n\nDo not forget to restart you web server after adding the Memcache module. Now the Memcache\ninformation should show up with a little double arrow (fast-forward) icon in your debug toolbar.\n\n### Usage\n\nWhen you want to use the cache from the controller you can simply call:\n\n    $this-\u003eget('memcache.default')-\u003eset('someKey', 'someValue', 0, $timeToLive);\n    $this-\u003eget('memcache.default')-\u003eget('someKey');\n\nThe above example shows how to store value 'someValue' under key 'someKey' for a maximum of $timeToLive\nseconds (the 0 parameter are the 'flags'). In the second line the value is retrieved from Memcache.\nIf the key can not be found or the specified number of seconds have passed the 'get' function returns\nthe value 'false'.\n\n### Configuration\n\nBelow you can see an example configuration for this bundle.\n\n```yml\ntqd_memcache:\n    pools:\n        default:\n            servers:\n                - { host: 10.0.0.1, tcp_port: 11211, weight: 15 }\n                - { host: 10.0.0.2, tcp_port: 11211, weight: 30 }\n            options:\n\t\t        allow_failover: true\n\t\t        max_failover_attempts: 20\n\t\t        default_port: 11211\n\t\t        chunk_size: 32768\n\t\t        protocol: ascii\n\t\t        hash_strategy: consistent\n\t\t        hash_function: crc32\n\t\t        redundancy: true\n\t\t        session_redundancy: 2\n\t\t        compress_threshold: 20000\n\t\t        lock_timeout: 15\n        sessions:\n            servers:\n                - { host: localhost, tcp_port: 11212 }\n```\n\n### Session Support ###\n\nThis bundle also provides support for storing session data on Memcache servers. To enable session support\nyou will have to enable it through the ```session``` key (```auto_load``` is true by default). Note that the only\nrequired subkey of the session support is ```pool``` (a valid pool). You can also specify a key ```prefix```\nand a ```ttl```.\n\n```yml\ntqd_memcache:\n    session:\n        pool: sessions\n        auto_load: true\n        prefix: \"session_\"\n        ttl: 7200\n        locking: true\n        spin_lock_wait: 150000\n    # pools\n```\n\nNote that the session locking is enabled by default and the default spin lock is set to poll every 150 milliseconds (150000 microseconds).\n\n### Doctrine Support ###\n\nThis bundle also provides support for Doctrine caching on Memcache servers. To enable Doctrine caching\nyou will have to enable it through the ```doctrine``` key. Note that you can specify all three kinds of\nDoctrine caching: 'metadata', 'result' and 'query'. The required keys within those subkeys are both \n```pool``` (a valid pool) and ```entity_manager``` (normally: default). You can also specify a ```prefix```.\n\n```yml\ntqd_memcache:\n    doctrine:\n        metadata_cache:\n            pool: default\n            entity_manager: default          # the name of your entity_manager connection\n            document_manager: default        # the name of your document_manager connection\n        result_cache:\n            pool: default\n            entity_manager: [default, read]  # you may specify multiple entity_managers\n            prefix: \"result_\"                # you may specify a prefix for the entries\n        query_cache:\n            pool: default\n            entity_manager: default\n    # pools\n```\n\n### Firewall Support ###\n\nThis bundle also provides support a firewall that limits the number of concurrent requests per IP address.\nIt maintains a counter of running requests per IP address and delays (throttles) the requests if nessecary. \nTo enable firewall support you will have to enable it through the ```firewall``` key. Note that the only\nrequired subkey of the firewall support is ```pool``` (a valid pool). You can also specify a key ```prefix```\nand a ```concurrency``` (default is 10). If you use one or more reverse proxies, then specify them in the\n```reverse_proxies``` key.\n\n```yml\ntqd_memcache:\n    firewall:\n        pool: firewall\n        prefix: \"firewall_\"\n        concurrency: 10\n        reverse_proxies: [10.0.0.1]\n    # pools\n```\n\n### ADP: Anti Dog Pile\n\nLet us examine a high traffic website case and see how Memcache behaves:\n\nYour cache is stored for 90 minutes. It takes about 3 second to calculate the cache value and 1 ms second to read the cached value from the cache. You have about 5000 requests per second and let's assume that the value is cached. You get 5000 requests per second taking about 5000 ms to read the values from cache. You might think that that is not possible since 5000 \u003e 1000, but that depends on the number of worker processes on your web server. Let's say it is about 100 workers (under high load) with 75 threads each. Your web requests take about 20 ms each. Whenever the cache invalidates (after 90 minutes), during 3 seconds, there will be 15000 requests getting a cache miss. All the threads getting a miss will start to calculate the cache value (because they don't know the other threads are doing the same). This means that during (almost) 3 seconds the server wont answer a single request, but the requests keep coming in. Since each worker has 75 threads (holding 100 x 75 connections), the amount of workers has to go up to be able to process them.\n\nThe heavy forking will cause extra CPU usage and the each worker will use extra RAM. This unexpected increase in RAM and CPU is called the 'dog pile' effect or 'stampeding herd' or 'thundering herd' and is very unwelcome during peak hours on a web service.\n\nThere is a solution: we serve the old cache entries while calculating the new value and by using an atomic read and write operation we can make sure only one thread will receive a cache miss when the content is invalidated. The algorithm is implemented in AntiDogPileMemcache class in TqdMemcacheBundle. It provides the getAdp(), setAdp() and deleteAdp() functions that can be used as replacements for the normal get, set and delete.\n\nPlease note:\n\n- ADP might not be needed if you have low amount of hits or when calculating the new value goes relatively fast.\n- ADP might not be needed if you can break up the big calculation into smaller, maybe even with different timeouts for each part.\n- ADP might get you older data than the invalidation that is specified. Especially when a thread/worker gets \"false\" for \"get\" request, but fails to \"set\" the new calculated value afterwards.\n- ADP's \"getAdp\", \"setAdp\" and \"deleteAdp\" are more expensive than the normal \"get\", \"set\" and \"delete\", slowing down all cache hits.\n- ADP does not guarantee that the dog pile will not occur. Restarting Memcache, flushing data or not enough RAM will also get keys evicted and you will run into the problem anyway.\n\n### Known issues\n\nThe session write that invokes a memcache set operation is executed after the page has been rendered.\nThe collect call of the memcache data collector is executed before the rendering of the page is complete\nand therefor also before the session write is executed. This causes the session writes not to show up in\nthe Web Debug Toolbar.\n\n### Credits\n\nDoctrine support is based on the implementation in SncRedisBundle:\n\nhttps://github.com/snc/SncRedisBundle by Henrik Westphal\n\n- DependencyInjection/TqdMemcacheExtension.php\n- DependencyInjection/Configuration.php\n- DependencyInjection/Compiler/EnableSessionSupport.php\n\nAre based on implementation in:\n\nhttps://github.com/Emagister/MemcachedBundle by Christian Soronellas\n\n- Command/StatisticsCommand.php\n\nIs based on an implementation in:\n\nhttps://github.com/beryllium/CacheBundle by Kevin Boyd\n\n### License\n\nThis bundle is under the MIT license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmevdschee%2Ftqdmemcachebundle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmevdschee%2Ftqdmemcachebundle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmevdschee%2Ftqdmemcachebundle/lists"}