yinqiwen / ardb

A redis protocol compatible nosql, it support multiple storage engines as backend like Google's LevelDB, Facebook's RocksDB, OpenLDAP's LMDB, PerconaFT, WiredTiger, ForestDB.
BSD 3-Clause "New" or "Revised" License
1.83k stars 278 forks source link

HGET issue on complicated key name #424

Open iseriser opened 6 years ago

iseriser commented 6 years ago

Using Redis->hGet causes protocol failure for the following key:

/index.php/aaa-gallery/item/lamar?guid=cA6dwJ1UnvM7&tv=2017100302&type=pidget&sub=www&button_count=1&follow_count=0&pin_count=0&profile_count=0&board_count=0&section_count=0&lang=en&via=http%3A%2F%2Fwww.example.com%2Findex.php%2Faaa-gallery%2Fitem%2Flamar&callback=PIN_1523818972861.f.callback[0]

The error is

Fatal error: Uncaught RedisException: protocol error, got ' in /path_to_script/script.php:line_number
Stack trace:
#0 /path_to_script/script.php(line_number): Redis->hGet('Hash-Name', '/index.php/aaa-...')

Original redis-cli works fine for this hget providing valid value. Ardb is compiled from the latest source (with #420 fix).

yinqiwen commented 6 years ago

this may caused by the value of the field.

can u use redis-cli and telnet to execute the command hget to get the result?

iseriser commented 6 years ago

redis-cli returns correct result (it is easy to check, cause the value is gzip archive and unpack returns valid result with no error)

iseriser commented 6 years ago
echo -e '*3\r\n$4\r\nHGET\r\n$9\r\nHash-Name\r\n$296\r\n/index.php/aaa-gallery/item/lamar?guid=cA6dwJ1UnvM7&tv=2017100302&type=pidget&sub=www&button_count=1&follow_count=0&pin_count=0&profile_count=0&board_count=0&section_count=0&lang=en&via=http%3A%2F%2Fwww.example.com%2Findex.php%2Faaa-gallery%2Fitem%2Flamar&callback=PIN_1523818972861.f.callback[0]\r\n' | nc -w 1 127.0.0.1 6379 > ardb_test2_result.txt

returns the same correct result (byte compared and gunzipped) BTW length value of result prepended with $ is also correct in raw answer

yinqiwen commented 6 years ago

is the php client get same error for accessing same value in redis-server?

iseriser commented 6 years ago

If I extract hget into separate test.php and run it (against ardb-server), everything works fine. So it seems the case is in the sequence. In main script this hget call is preceeded with Redis->eval().

iseriser commented 6 years ago

Just imported database dump into redis-server (Debian 8 repo version). Bug is not reproducible.

yinqiwen commented 6 years ago

is Redis->eval() do lua script invoking?

iseriser commented 6 years ago

Yes it does.

$redis->eval(
          "local e = redis.call('hexists', 'Hash-Name' , [[" . $url. "]])\n"
        . "if e == 0 then\n"
            . "local v = redis.call('hget', 'Old-Hash' , [[" . $url. "]])\n"
            . "if v then\n"
                . "redis.call('hset', 'Hash-Name' , [[" . $url. "]], v)\n"
                . "redis.call('hdel', 'Old-Hash' , [[" . $url. "]])\n"
            . "end\n"
        . "end\nreturn e\n")

Maybe something goes wrong when there is ]]], cause key name ends with ] and special lua string quotes are being used [[]]

yinqiwen commented 6 years ago

tested with the lua script with no bug found.
can u get the actual eval script string when exception catched?