Node-redis: Datenkorruption bei `get`

Erstellt am 20. Juli 2016  ·  9Kommentare  ·  Quelle: NodeRedis/node-redis

Es wurde eine seltsame Datenbeschädigung bei get .

Versucht mit den neuesten Redis: 3 und Redis: 2 in Docker + Node Version 6.3.0 und 5.12.0.
Es wurde versucht, die Paketversion von redis zu halbieren, und es wurde festgestellt, dass der Fehler in Version 2.6.0 eingeführt wurde.

Test zur Reproduktion:

const assert = require('assert');

const redis = require('redis').createClient();

const data = JSON.stringify({
    "city_name": "Санкт-Петербург" // (russian language)
});
const key = 'somekey';

describe('redis', () => {

    before(done => redis.set(key, data, done));
    after(done  => redis.del(key, done));

    for (let i = 0; i < 10000; ++i) {
        it(`pass ${i}`, done => {
            redis.get(key, (err, results) => {
                assert(!err);
                assert.strictEqual(results, data);

                done();
            });
        })
    }

});

package.json:

{
  "devDependencies": {
    "mocha": "^2.5.3"
  },
  "dependencies": {
    "redis": "=2.6.0"
  }
}

Ausgabe:

    ... (skipped)
    ✓ pass 1217
    ✓ pass 1218
    1) pass 1219
    2) "after all" hook

  1219 passing (4s)
  2 failing

  1) redis pass 1219:

      Uncaught AssertionError: '{"city_name":"��анкт-Петербург"}' === '{"city_name":"Санкт-Петербург"}'
      + expected - actual

      -{"city_name":"��анкт-Петербург"}
      +{"city_name":"Санкт-Петербург"}

Die Nummer des fehlgeschlagenen Durchgangs ist schwebend. Mocha wird mit dem Flag -b , um beim ersten Fehler zu stoppen. Wenn wir es jedoch ohne dieses Flag testen, schlägt es nach dem ersten fehlerhaften Durchlauf weiterhin fehl:

    ... (skipped)
    ✓ pass 2477
    ✓ pass 2478
    1) pass 2479
    2) pass 2480
    3) pass 2481
    4) pass 2482
    5) pass 2483
    ... (all passes are failed until the end)

Beim ersten Fehler geht es um Datenbeschädigung, beim nächsten Fehler geht es um err im Rückruf:

{ AbortError: Fatal error encountert. Command aborted. It might have been processed.
    at RedisClient.flush_and_error (/Users/silent/Projects/redis-test/node_modules/redis/index.js:350:23)
    at JavascriptRedisParser.Parser.returnFatalError (/Users/silent/Projects/redis-test/node_modules/redis/index.js:199:18)
    at handleError (/Users/silent/Projects/redis-test/node_modules/redis-parser/lib/parser.js:172:10)
    at parseType (/Users/silent/Projects/redis-test/node_modules/redis-parser/lib/parser.js:224:14)
    at JavascriptRedisParser.execute (/Users/silent/Projects/redis-test/node_modules/redis-parser/lib/parser.js:404:20)
    at Socket.<anonymous> (/Users/silent/Projects/redis-test/node_modules/redis/index.js:267:27)
    at emitOne (events.js:96:13)
    at Socket.emit (events.js:188:7)
    at readableAddChunk (_stream_readable.js:177:18)
    at Socket.Readable.push (_stream_readable.js:135:10)
    at TCP.onread (net.js:542:20)
  code: 'NR_FATAL',
  command: 'GET',
  args: [ 'somekey' ],
  origin:
   ReplyError: Protocol error, got "c" as reply type byte. Please report this.
       at parseType (/Users/silent/Projects/redis-test/node_modules/redis-parser/lib/parser.js:224:34)
       at JavascriptRedisParser.execute (/Users/silent/Projects/redis-test/node_modules/redis-parser/lib/parser.js:404:20) } undefined

oder manchmal damit:

     Uncaught RangeError: out of range index
      at RangeError (native)
      at concatBuffer (node_modules/redis-parser/lib/parser.js:357:13)
      at JavascriptRedisParser.execute (node_modules/redis-parser/lib/parser.js:389:21)
      at Socket.<anonymous> (node_modules/redis/index.js:267:27)
      at readableAddChunk (_stream_readable.js:177:18)
      at Socket.Readable.push (_stream_readable.js:135:10)
      at TCP.onread (net.js:542:20)

Kann nicht nur mit lateinischen Zeichen reproduziert werden. Kann auch nicht mit return_buffers: true reproduzieren.

Hier ist der Wert über redis-cli , vielleicht ist es hilfreich:

127.0.0.1:6379> get somekey
"{\"city_name\":\"\xd0\xa1\xd0\xb0\xd0\xbd\xd0\xba\xd1\x82-\xd0\x9f\xd0\xb5\xd1\x82\xd0\xb5\xd1\x80\xd0\xb1\xd1\x83\xd1\x80\xd0\xb3\"}"
bug fixed / done

Alle 9 Kommentare

Auch reproduzierbar mit der einfachen Zeichenfolge Санкт-Петербург , ohne JSON.{parse,stringify} .

127.0.0.1:6379> get somekey
"\xd0\xa1\xd0\xb0\xd0\xbd\xd0\xba\xd1\x82-\xd0\x9f\xd0\xb5\xd1\x82\xd0\xb5\xd1\x80\xd0\xb1\xd1\x83\xd1\x80\xd0\xb3"

@silentroach Welche Parser- Version verwenden Sie derzeit? Ich habe versucht, dies ohne Erfolg zu reproduzieren.

Standardparser. Hier ist ein Archiv zu reproduzieren:

test.zip

npm i && npm t

Meine aktuelle Knotenversion ist 6.3.0, die Redis-Version ist 3.2.1 ( docker run redis ), os x

Interessante Sache - jetzt, während ich Tests durchführe (ungefähr 50 Mal versucht), ist die fehlgeschlagene Iterationsnummer immer in diesem Satz 2479, 6260, 7520

Haben Sie das gleiche ohne Docker versucht?

Hm, jetzt ausprobiert und kann auch nicht reproduzieren :(
Kann aber auf Produktions-Redis-Server (mit erster Testiteration) reproduzieren, das ist nicht im Docker.

Wird versuchen, Unterschiede zu entdecken.

Kann nicht auf lokalen Redis reproduziert werden, kann aber reproduziert werden, während eine Verbindung zu einem anderen PC im Netzwerk hergestellt wird, wobei die Datenzeichenfolge an einem komplexeren Beispiel geändert wird.

test.zip

(Ersetzen Sie einfach den Host durch etwas anderes als Ihre IP, um über das Netzwerk zu arbeiten.)

fehlgeschlagen bei der ersten Iteration, in der nächsten finden Sie out of range index Fehler.

Ich habe gerade eine neue Parser-Version veröffentlicht, die das Problem behebt. Es tut mir leid, dass ich Multi-Byte-Zeichen vergessen habe.

Jetzt ist es in Ordnung, danke für die schnelle Lösung!

Danke für den sehr guten Fehlerbericht! : +1:

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen