Implement a simplified memcached server
Company: Reddit
Role: Machine Learning Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
Quick Answer: This question evaluates a candidate's ability to implement a TCP-based in-memory key-value store, exercising skills in network I/O, protocol parsing, byte-level data handling, and state management.
Part 1: Single-Key Memcached Protocol Simulator
Constraints
- 0 <= len(requests) <= 200000
- All command lines are well-formed and end with `\n`.
- Keys contain one or more characters matching `[A-Za-z0-9_-]+`.
- For Part 1, each `get` command has exactly one key.
- For each `set`, `0 <= byte_count`, and exactly `byte_count` raw value bytes are followed by one newline byte.
- The key-value store starts empty for each call to `solution`.
Examples
Input: (b'',)
Expected Output: b''
Explanation: empty stream returns empty response
Input: (b'get does_not_exist\n',)
Expected Output: b'END\n'
Explanation: get on a missing key returns END
Input: (b'set greeting 5\nhello\nget greeting\n',)
Expected Output: b'STORED\nVALUE greeting 5\nhello\nEND\n'
Explanation: store then retrieve a 5-byte value
Input: (b'set empty 0\n\nget empty\n',)
Expected Output: b'STORED\nVALUE empty 0\n\nEND\n'
Explanation: store a zero-length value then retrieve it
Input: (b'set bin 3\na\nb\nget bin\n',)
Expected Output: b'STORED\nVALUE bin 3\na\nb\nEND\n'
Explanation: value containing a newline byte is parsed by byte_count, not by scanning for the next newline
Input: (b'set k 1\nA\nset k 1\nB\nget k\n',)
Expected Output: b'STORED\nSTORED\nVALUE k 1\nB\nEND\n'
Explanation: overwriting a key keeps only the latest value
Input: (b'set blob 5\nx\ny\nz\nget blob\nget missing\n',)
Expected Output: b'STORED\nVALUE blob 5\nx\ny\nz\nEND\nEND\n'
Explanation: multi-newline value, then a hit followed by a miss
Input: (b'set big 1000\nqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\nget big\n',)
Expected Output: b'STORED\nVALUE big 1000\nqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\nEND\n'
Explanation: large 1000-byte value round-trips through set/get
Input: (b'set a 1\n1\nset b 2\n22\nget a\nget b\nget c\n',)
Expected Output: b'STORED\nSTORED\nVALUE a 1\n1\nEND\nVALUE b 2\n22\nEND\nEND\n'
Explanation: multiple interleaved keys, two hits and one miss
Hints
- Maintain an index into the byte stream. Use newline search only for command lines, not for value bodies.
- After a `set` line, slice exactly `byte_count` bytes for the value, then advance one more byte for the required trailing newline.
Part 2: Multi-Key Memcached Protocol Simulator
Constraints
- 0 <= len(requests) <= 200000
- All command lines are well-formed and end with `\n`.
- Keys contain one or more characters matching `[A-Za-z0-9_-]+`.
- Each `get` command contains at least one key and may contain multiple keys.
- For each `set`, `0 <= byte_count`, and exactly `byte_count` raw value bytes are followed by one newline byte.
- The key-value store starts empty for each call to `solution`.
Examples
Input: (b'',)
Expected Output: b''
Explanation: Empty input: empty store, no commands -> empty output.
Input: (b'set a 1\nA\nset b 2\nBB\nget b missing a\n',)
Expected Output: b'STORED\nSTORED\nVALUE b 2\nBB\nVALUE a 1\nA\nEND\n'
Explanation: Multi-key get: existing keys emitted in request order, missing omitted, single END.
Input: (b'get x y z\n',)
Expected Output: b'END\n'
Explanation: Get on empty store: all keys missing, only END.
Input: (b'set x 1\nZ\nget x x\n',)
Expected Output: b'STORED\nVALUE x 1\nZ\nVALUE x 1\nZ\nEND\n'
Explanation: Repeated existing key in one get emits its VALUE block each time.
Input: (b'set empty 0\n\nset c 1\nC\nget empty c nope\n',)
Expected Output: b'STORED\nSTORED\nVALUE empty 0\n\nVALUE c 1\nC\nEND\n'
Explanation: Zero-length value read correctly; missing key omitted.
Input: (b'set k 5\nab\ncd\nget k\n',)
Expected Output: b'STORED\nVALUE k 5\nab\ncd\nEND\n'
Explanation: Value contains a newline byte; set must read exactly byte_count bytes across the embedded newline.
Input: (b'get only\n',)
Expected Output: b'END\n'
Explanation: Single get on empty store with one missing key -> just END.
Input: (b'set key0 3\nv00\nset key1 3\nv01\nset key2 3\nv02\nset key3 3\nv03\nset key4 3\nv04\nset key5 3\nv05\nset key6 3\nv06\nset key7 3\nv07\nset key8 3\nv08\nset key9 3\nv09\nset key10 3\nv10\nset key11 3\nv11\nset key12 3\nv12\nset key13 3\nv13\nset key14 3\nv14\nset key15 3\nv15\nset key16 3\nv16\nset key17 3\nv17\nset key18 3\nv18\nset key19 3\nv19\nset key20 3\nv20\nset key21 3\nv21\nset key22 3\nv22\nset key23 3\nv23\nset key24 3\nv24\nset key25 3\nv25\nset key26 3\nv26\nset key27 3\nv27\nset key28 3\nv28\nset key29 3\nv29\nset key30 3\nv30\nset key31 3\nv31\nset key32 3\nv32\nset key33 3\nv33\nset key34 3\nv34\nset key35 3\nv35\nset key36 3\nv36\nset key37 3\nv37\nset key38 3\nv38\nset key39 3\nv39\nset key40 3\nv40\nset key41 3\nv41\nset key42 3\nv42\nset key43 3\nv43\nset key44 3\nv44\nset key45 3\nv45\nset key46 3\nv46\nset key47 3\nv47\nset key48 3\nv48\nset key49 3\nv49\nget key0 key1 key2 key3 key4 key5 key6 key7 key8 key9 key10 key11 key12 key13 key14 key15 key16 key17 key18 key19 key20 key21 key22 key23 key24 key25 key26 key27 key28 key29 key30 key31 key32 key33 key34 key35 key36 key37 key38 key39 key40 key41 key42 key43 key44 key45 key46 key47 key48 key49 missing key0 key2 key4 key6 key8 key10 key12 key14 key16 key18 key20 key22 key24 key26 key28 key30 key32 key34 key36 key38 key40 key42 key44 key46 key48\n',)
Expected Output: b'STORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nSTORED\nVALUE key0 3\nv00\nVALUE key1 3\nv01\nVALUE key2 3\nv02\nVALUE key3 3\nv03\nVALUE key4 3\nv04\nVALUE key5 3\nv05\nVALUE key6 3\nv06\nVALUE key7 3\nv07\nVALUE key8 3\nv08\nVALUE key9 3\nv09\nVALUE key10 3\nv10\nVALUE key11 3\nv11\nVALUE key12 3\nv12\nVALUE key13 3\nv13\nVALUE key14 3\nv14\nVALUE key15 3\nv15\nVALUE key16 3\nv16\nVALUE key17 3\nv17\nVALUE key18 3\nv18\nVALUE key19 3\nv19\nVALUE key20 3\nv20\nVALUE key21 3\nv21\nVALUE key22 3\nv22\nVALUE key23 3\nv23\nVALUE key24 3\nv24\nVALUE key25 3\nv25\nVALUE key26 3\nv26\nVALUE key27 3\nv27\nVALUE key28 3\nv28\nVALUE key29 3\nv29\nVALUE key30 3\nv30\nVALUE key31 3\nv31\nVALUE key32 3\nv32\nVALUE key33 3\nv33\nVALUE key34 3\nv34\nVALUE key35 3\nv35\nVALUE key36 3\nv36\nVALUE key37 3\nv37\nVALUE key38 3\nv38\nVALUE key39 3\nv39\nVALUE key40 3\nv40\nVALUE key41 3\nv41\nVALUE key42 3\nv42\nVALUE key43 3\nv43\nVALUE key44 3\nv44\nVALUE key45 3\nv45\nVALUE key46 3\nv46\nVALUE key47 3\nv47\nVALUE key48 3\nv48\nVALUE key49 3\nv49\nVALUE key0 3\nv00\nVALUE key2 3\nv02\nVALUE key4 3\nv04\nVALUE key6 3\nv06\nVALUE key8 3\nv08\nVALUE key10 3\nv10\nVALUE key12 3\nv12\nVALUE key14 3\nv14\nVALUE key16 3\nv16\nVALUE key18 3\nv18\nVALUE key20 3\nv20\nVALUE key22 3\nv22\nVALUE key24 3\nv24\nVALUE key26 3\nv26\nVALUE key28 3\nv28\nVALUE key30 3\nv30\nVALUE key32 3\nv32\nVALUE key34 3\nv34\nVALUE key36 3\nv36\nVALUE key38 3\nv38\nVALUE key40 3\nv40\nVALUE key42 3\nv42\nVALUE key44 3\nv44\nVALUE key46 3\nv46\nVALUE key48 3\nv48\nEND\n'
Explanation: Large input: 50 sets then a multi-key get of all keys plus a missing key plus repeats, preserving request order and duplicates.
Input: (b'set d 2\n\nX\nset d 1\nQ\nget d\n',)
Expected Output: b'STORED\nSTORED\nVALUE d 1\nQ\nEND\n'
Explanation: Overwrite: re-setting an existing key replaces the value (value also starts with a newline byte).
Hints
- The single-key `get` logic becomes a loop over all key tokens after the command name.
- Append `END\n` once per `get` command, after all existing keys have been emitted.