3

I am using redis bitmap to record user action in a year, if user login in the first day in the year, I'll set the first bit of key to 1. the redis value like this:

key: user.18.action(18 is user id)
value: (bitmap) 000100000000000000000000...(about 365 bit long)

but when I was trying to get the value, GET user.18.action returns "\x10".

In PHP, how do I convert these strings to the 000100000000000000000000... thing?

Actually, I use the code below to implement it, but is this all right? and is there a better resolution?

$bitmap = $this->redis->get('user.18.action');
$binstrlen = strlen($bitmap);
$hex = bin2hex($bitmap);
$str = str_baseconvert($hex, 16, 2);
var_dump(str_pad($str, $binstrlen * 8, '0', STR_PAD_LEFT));

function str_baseconvert($str, $frombase=10, $tobase=36) { 
    $str = trim($str); 
    if (intval($frombase) != 10) { 
        $len = strlen($str); 
        $q = 0; 
        for ($i=0; $i<$len; $i++) { 
            $r = base_convert($str[$i], $frombase, 10); 
            $q = bcadd(bcmul($q, $frombase), $r); 
        } 
    } 
    else $q = $str; 

    if (intval($tobase) != 10) { 
        $s = ''; 
        while (bccomp($q, '0', 0) > 0) { 
            $r = intval(bcmod($q, $tobase)); 
            $s = base_convert($r, 10, $tobase) . $s; 
            $q = bcdiv($q, $tobase, 0); 
        } 
    } 
    else $s = $q; 

    return $s; 
}
4
  • So you need a 365 bit long binary data to be assigned and retrieved?? Commented Oct 30, 2015 at 4:20
  • 1
    will, the value length will grow under redis control, all I need to do is just SETBIT. Commented Oct 30, 2015 at 4:49
  • clarification required : is it 365 bit long always?? Only one bit will be set as 1?? @missingcat92 Commented Oct 30, 2015 at 4:50
  • 1
    no, the value length is not fixed, it will grow with the day user logined. see redis.io/commands/setbit Commented Oct 30, 2015 at 4:54

2 Answers 2

5
function bitmap_human($bitmap){
    $bytes = unpack('C*', $bitmap);
    $bin = join(array_map(function($byte){
        return sprintf("%08b", $byte);
    }, $bytes));
    return $bin;
}

I figured this out, works all right.

Sign up to request clarification or add additional context in comments.

Comments

0

The bitmap_human func is on my head

 /**
 * @param \Redis $redis
 * @param $key
 * @param $or_login_user
 * @return array
 */
protected function parseUserList(\Redis &$redis, $key)
{
    $bitmap = $this->bitmap_human($redis->get($key));
    $bitmap_length = strlen($bitmap);
    $bitSet = [];

    for ($i = 0; $i < $bitmap_length; $i++) {
        if (1 == $bitmap[$i]) {
            $bitSet[] = $i;
        }
    }

    if(empty($bitSet)){
        return [];
    }

    $login_user = M('user')->cache(600)->field('id,phone,nickname')->where(['id'=>['in',$bitSet]])->select();

    return $login_user;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.