Search code examples
sortingluaredislocale

Sorting with underscore in Lua Redis


I have a problem with tables being sorted in a different ways on my two ubuntu servers. I'm executing the following command in the redis-cli tool. This is the server 1:

127.0.0.1:6379> eval "local a = {'_mcat:banner','for_meta:1','_size:300x250','_mtype:html', 'axx:1'};table.sort(a);return a;" 0
1) "_mcat:banner"
2) "_mtype:html"
3) "_size:300x250"
4) "axx:1"
5) "for_meta:1"

And the server 2:

127.0.0.1:6379> eval "local a = {'_mcat:banner','for_meta:1','_size:300x250','_mtype:html', 'axx:1'};table.sort(a);return a;" 0
1) "axx:1"
2) "for_meta:1"
3) "_mcat:banner"
4) "_mtype:html"
5) "_size:300x250"

As you can see the problem lays in how the sort is treating the '_' character. I have tried to upgrade versions of redis & gcc and the behavior is not changed between the servers. Redis versions tested: 2.8.4, 2.8.19, 4.0.2, gcc version: 4.8.2. Running locale returns the same values on both servers:

LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=

Executing the same code in Python, works the same on both machines:

>>> sorted(['_mcat:banner','for_meta:1','_size:300x250','_mtype:html', 'axx:1'])
['_mcat:banner', '_mtype:html', '_size:300x250', 'axx:1', 'for_meta:1']

Maybe somebody has a suggestion on what to try next? Thanks.

EDITED:

On both servers running:

eval "local a = {'_mcat:banner','for_meta:1','_size:300x250','_mtype:html', 'axxx:2'};table.sort(a, function(a,b) return a<b end);return a;" 0

Produces results consistent with the table.sort(a) (so different between servers), but take a look at this:

On server 1:

127.0.0.1:6379> eval "local a;if 'axxx:2'>'_mcat:banner' then a=1 else a=0 end;return a;" 0
(integer) 1

127.0.0.1:6379> eval "local a;if 'a'>'_' then a=1 else a=0 end;return a;" 0
(integer) 1

On server 2:

127.0.0.1:6379> eval "local a;if 'axxx:2'>'_mcat:banner' then a=1 else a=0 end;return a;" 0
(integer) 0
127.0.0.1:6379> eval "local a;if 'a'>'_' then a=1 else a=0 end;return a;" 0
(integer) 1

Solution

  • Thanks for all the comments and suggestions, I still don't know what exactly happened but rebuilding the server worked.