不要開啓 php redis 擴展的自動序列化選項

php redis 擴展有自動序列化選項,在存儲kv數據的時候,能夠少寫點代碼就打開了,使用的過程當中突然發現了一個使人鬱悶的地方。php

擴展沒有對你要存儲的值作類型判斷,任何類型的值都作了自動序列化,好比下面這段代碼redis

$rd = new Redis();
$r = $rd->connect(
    '127.0.0.1', 6379, 1
);
$rd->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP);
$rd->set('k', 1);
var_dump($rd->incr('k'));
echo $rd->getLastError(), PHP_EOL;
echo $rd->get('k');

你存儲了一個int進去,而後在incr,就會失敗架構

bool(false)
ERR value is not an integer or out of range

1

直接用redis-cli去看下,發現,value 被序列化了memcached

127.0.0.1:6379> get k

"i:1;"

這是php redis 擴展序列化的部分代碼(在源碼包的library.c),你會發現,這個序列化並無像memcached擴展同樣作類型判斷,而是所有序列化。code

PHP_REDIS_API int
redis_serialize(RedisSock *redis_sock, zval *z, char **val, strlen_t *val_len
                TSRMLS_DC)
{
    ……
    switch(redis_sock->serializer) {
        case REDIS_SERIALIZER_NONE:
        ……
        case REDIS_SERIALIZER_PHP:
#if ZEND_MODULE_API_NO >= 20100000
            PHP_VAR_SERIALIZE_INIT(ht);
#else
            zend_hash_init(&ht, 10, NULL, NULL, 0);
#endif
            php_var_serialize(&sstr, z, &ht);
#if (PHP_MAJOR_VERSION < 7)
            *val = estrndup(sstr.c, sstr.len);
            *val_len = sstr.len;
#else
            *val = estrndup(ZSTR_VAL(sstr.s), ZSTR_LEN(sstr.s));
            *val_len = ZSTR_LEN(sstr.s);
#endif
            smart_str_free(&sstr);
#if ZEND_MODULE_API_NO >= 20100000
            PHP_VAR_SERIALIZE_DESTROY(ht);
#else
            zend_hash_destroy(&ht);
#endif
            return 1;
        case REDIS_SERIALIZER_IGBINARY:
        ……

    }
    return 0;
}

看來php redis 這擴展出來這麼久,用戶量這麼大,可是文檔都沒進到php官方文檔,也不是沒有緣由的。文檔

更多架構、PHP、GO相關踩坑實踐技巧請關注個人公衆號:PHP架構師get

相關文章
相關標籤/搜索