Preamble:
I have a legacy memcached instance running which interacts with Perl Modules to manage keys.
I can telnet to the server to manually get and set keys.
Problem:
I'm trying to connect to this instance using Ruby/Rails.
Using the Dalli Gem, I've successfully connected to the memcached instance.
I've faced two problems. One using the :meta
protocol. One using the :binary
protocol.
Meta Protocol:
Code:
dc = Dalli::Client.new("<address>:11211", socket_timeout: 2.0, protocol: :meta, namespace: 'ws')
dc.get('item_679')
Output:
Traceback (most recent call last):
1: from (irb):2
Dalli::DalliError (Response error: ERROR)
Log output from Memcached:
<32 new auto-negotiating client connection
32: Client using the ascii protocol
<32 version
>32 VERSION 1.4.4
<32 mg ws:item_679 v f
>32 ERROR
Binary Protocol
Code:
dc = Dalli::Client.new("<address>:11211", socket_timeout: 2.0, protocol: :binary, namespace: 'ws')
dc.get('item_679')
Output:
Traceback (most recent call last):
1: from (irb):5
Dalli::UnmarshalError (Unable to unmarshal value: incompatible marshal file format (can't be read))
format version 4.8 required; 5.9 given
Log output from Memcached:
<38 Read binary protocol data:
<38 0x80 0x00 0x00 0x0b
<38 0x00 0x00 0x00 0x00
<38 0x00 0x00 0x00 0x0b
<38 0x00 0x00 0x00 0x00
<38 0x00 0x00 0x00 0x00
<38 0x00 0x00 0x00 0x00
<38 GET ws:item_679
>38 Writing bin response:
>38 0x81 0x00 0x00 0x00
>38 0x04 0x00 0x00 0x00
>38 0x00 0x00 0x06 0x5f
>38 0x00 0x00 0x00 0x00
>38 0x00 0x00 0x00 0x00
>38 0x00 0x00 0x00 0x00
Versions
- Memcached 1.4.4
- Ruby 2.7
- Dalli 3.2.2
Any ideas on why my requests are coming through strangely?
CodePudding user response:
It appears you are using a Memcached server in version 1.4.4. The server in this version does not support the meta protocol yet. It was only introduced in Memcached 1.6.
As such, you will only be able to use the meta protocol after you have upgraded the server to at least Memcached 1.6.0.
When using the binary protocol, it appears you are able to read the data from the Memcached server. However, data written by Dalli (and ActiveSupport::Cache
) is by default serialized to a binary format using Ruby's Marshal
library.
When reading, Dalli tries to be smart to detect if the data read from Memcached is marshaled or not and tries to unmarshal if it thinks it is marshaled. If you are reading binary data, this heuristic might fail however. In that case (or if you know that the data is not marshaled), you can instruct Dalli to return the raw data:
dc.get('item_679', raw: true)
You can than handle any required conversation / unserialization yourself.