0

This seems kinda random but basically I have the following member function in my caching class:

public function increment($key, $expires = 0)
{
    // Requires OPT_BINARY_PROTOCOL
    return $this->cache->increment($key, 1, 0, $expires);
}

So then I want to do flood protection like this:

$cache->increment('foo', 10) > 50

90% of the time it works but for some reason sometimes it returns some ridiculously high integer and I can't pinpoint how/why or how to reproduce. Memory issue????

4
Contributors
13
Replies
81
Views
4 Years
Discussion Span
Last Post by LastMitch
Featured Replies
  • 1
    cereal 1,515   4 Years Ago

    Looking at your first example the increments should be by five, not by one, this is my test: <?php $key = 'never_before_used_key'; $cache = new Memcached; $cache->addServer('127.0.0.1', 11211); $cache->setOption(Memcached::OPT_BINARY_PROTOCOL, TRUE); $cache->set($key,0,5); $limit = 1000; $i = 0; while (true) { $current = $cache->get($key); echo $cache->increment($key, 5). PHP_EOL; $i++; if($i > … Read More

  • 1
    Dani 1,665   4 Years Ago

    No, because I'm using Memcached::increment(), not Memcache::increment(). http://php.net/manual/en/memcached.increment.php Memcached::increment() does create an item if it doesn't already exist. Thanks anyways though!! :) Read More

0

I'm not sure why this happens, but increment and decrement methods seems to be buggy: the library is still using a deprecated function to retrieve results: memcached_fetch instead of memcached_fetch_result. On github there are few pull request that solves most of the open issues with the increment function, but it seems to be no activity from the authors.

So, you could create your own branch, merge the pull request and recompile the library on your own.

Reference:

0

So I've made a bit of progress.

Here is my PHP code:

while (true)
{
    echo $cache->increment('never_before_used_key', 5). '<br />';
}

And here is what the result looks like:

140733713842860
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
...
24921
24922
24923
24924
24925
24926
24927
24928
24929
24930
24931
24932
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

As the page executed [indefinitely], every 5 seconds, the counter would start at 0 again, leaving only the initial value upon loading the page the weird arbitrary number.

Upon refreshing the page while it was still executing (meaning that the key should already exist in the cache because it was touched within the past 5 seconds), here's what I got:

140736194609852
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

This is reproducable behavior for me.

As mentioned, using it as flood protection in a production environment, it works 90% of the time and then every so often gives me this weird input and I can't figure out what it is. Memory address??

0

When I do:

$cache->set('chat_flood_protection', 0);
while (true)
{
    echo $cache->increment('chat_flood_protection', 5). '<br />';
}

Then my output looks like:

0
0
1
2
3
4
5

Is this by design that you need to warm the cache before using increment????? I was under the impression that was the purpose of passing in the value you want to start at as the third parameter.

0

My new (working to the best of my knowledge) chat poll flooding function:

public function poll_flooding()
{
    global $cache;

    // TODO: I'm not sure why I'm randomly getting erroneous numbers back from $cache->increment() for first call of the page
    // return ($cache->increment('cache_chat_flood_protection', 5) > 50);

    if ($foo = $cache->get('cache_chat_flood_protection'))
    {
        $cache->set('cache_chat_flood_protection', $foo + 1, 5);
    }
    else
    {
        $foo = 0;
        $cache->set('cache_chat_flood_protection', 1, 5);
    }

    return ($foo > 50);
}
1

Looking at your first example the increments should be by five, not by one, this is my test:

<?php

$key = 'never_before_used_key';
$cache = new Memcached;
$cache->addServer('127.0.0.1', 11211);
$cache->setOption(Memcached::OPT_BINARY_PROTOCOL, TRUE);
$cache->set($key,0,5);

$limit = 1000;
$i = 0;

while (true)
{
    $current = $cache->get($key);
    echo $cache->increment($key, 5). PHP_EOL;

    $i++;
    if($i > $limit || $key > $current) break;
}

I get this output:

5
10
15
20
25
30
35
40
45
50
55
60
65
70
75
...

What version are you using? Mine is:

STAT version 1.4.13
STAT libevent 2.0.16-stable

You can see that by typing echo stats | nc -v 127.0.0.1 11211 | head

Not sure if this can be useful: https://code.google.com/p/memcached/issues/detail?id=320

0

Looking at your first example the increments should be by five, not by one, this is my test:

Sorry for the confusion. You can see in the OP that $cache is an object of my Memcached wrapper class. As mentioned, it looks like this:

public function increment($key, $expires = 0)
{
    // Requires OPT_BINARY_PROTOCOL
    return $this->cache->increment($key, 1, 0, $expires);
}

So $cache->increment() is calling the wrapper method. $this->cache is the actual Memcached object.

Sorry for the confusion.

0

Unfortunately, as told by the flood of people who said that the chat was just loading a blank page today, my new method of flood protection is massive fail. The reason is because the set() function doesn't work like the increment() function in that it updates the expiration time with each call, while increment does not.

However, I ran into something interesting regarding:

while (true)
{
    echo $cache->increment('chat_flood_protection', 5). '<br />';
}

It turns out that while this gives an erroneous first line, just setting the key name to 'chat' (or anything less than 5 characters, it seems) does not.

Another intersting thing to note, that while (true) seems to be succeptible to this, when I do

for ($i = 1; $i < 10000; $i++)
{
    echo $cache->increment('chat_flood_protection', 5). '<br />';
}

it works just fine!!

It should be noted that in a production environment, $cache->increment() is only being called once per script execution, and the idea is to rate limit the number of script executions happening within a 5 second time frame (aka flood protection lol).

0

Latest progress:

public function foo()
{
    global $cache;

    $i = 0;
    while (true)
    {
        echo $cache->increment('works_with_key_less_than_9_characters_ONLY', 5). '<br />';
        $i++;
        if ($i > 10000)
        {
            break;
        }
    }

}

$cache variable is a member of this class:

class Dani_cache
{
    private $cache;

    public function __construct()
    {
        global $config;

        $this->cache = new Memcached('daniweb');

        if ($this->cache->isPristine())
        {
            $this->cache->setOptions(array(
                Memcached::OPT_NO_BLOCK => true,
                Memcached::OPT_BUFFER_WRITES => true,
                Memcached::OPT_BINARY_PROTOCOL => true,
                Memcached::OPT_TCP_NODELAY => true,
                Memcached::OPT_LIBKETAMA_COMPATIBLE => true,
                Memcached::OPT_DISTRIBUTION => Memcached::DISTRIBUTION_CONSISTENT,
            ));
        }

        if (count($this->cache->getServerList()) == 0)
        {
            // Connect to all memcache servers
            $this->cache->addServers($config['Cache']['memcacheserver']);
        }       
    }

    public function increment($key, $expires = 0)
    {
        // Requires OPT_BINARY_PROTOCOL
        return $this->cache->increment($key, 1, 0, $expires);
    }

}
0

Hey Dani,

I havne't been on lately. I like the new design, keep up the good work!

As your for issue you are having. Have you look at this:

http://www.phpfastcache.com/

Maybe that will fix the gibberish data issue

0

I havne't been on lately. I like the new design, keep up the good work!

Thanks!

http://www.phpfastcache.com/

No, that's just a wrapper class for Memcached and a handful of other caching solutions. Thanks anyways, though!

0

No, that's just a wrapper class for Memcached and a handful of other caching solutions. Thanks anyways, though!

OK

This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.