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