Best way to store arrays of integers, lincrby?

1,095 views
Skip to first unread message

Alberto Gimeno Brieba

unread,
Dec 27, 2010, 6:10:42 AM12/27/10
to redi...@googlegroups.com
Hi,

First of all: thank you, you are doing a great job with redis!

Now, my questiong. I'm developing a webpage using redis. I need to
store fixed-length arrays (I need to store an integer value for each
day in a month). And I just need to increment the values from time to
time. I'm thinking about which is the best way to implement this in
redis. My thoughts are:

- Using a string with a specific format. For example a basic example
would be: "1,2,3,4,...". This is the option I have already
implemented. The problem is that I need to do a few steps: read,
parse, write. This option could be improved using different ways to
encode the integers.
- Using a list.
- Using a key-value for each integer value. I don't like it: too many
keys. But is good because I could use incrby.

I think using a list would be the best option, but it would be great
to be able to:
- incr an element in the list, so there is not need to read it from
the code. Maybe a "lincrby" command?
- create a list with a number of elements all having the same value.
For example I would create a list of 30 elements having "0" as value.
Well, I can just call rpush several times.

In the other hand I don't know if using a list adds too much overhead
than using a simple encoded string value.

Any suggestion? Thank you very much.

---
Alberto Gimeno Brieba
http://www.google.com/profiles/gimenete

Dvir Volk

unread,
Dec 27, 2010, 7:56:36 AM12/27/10
to redi...@googlegroups.com
Hi Alberto. There are many ways to do that...

Using strings would make you miss out on one of redis' coolest features IMHO which is atomicity.
You could use a list but then you'd have to first read the element, then write it back, which is faster than using an encoded string but still misses the point.

I would have chosen to implemnt this using a HASH with sub keys for each day, and then increment them atomically and get the result at once:
#first seed the values:
HSET december 1 1
HSET december 2 1
HSET december 3 1
....

HINCRBY december 3 1 #increase day 3 by 1
....

HGETALL december
will return something like:
{ 1: 20, 2: 15, 3: 6 .... }

And you could use multiple keys for each day, that's not a problem at all, and then use SORT to get all the values at once. It's less memory efficient than using a single HASH

You can of course use a sorted set to store this, where each day is an entry, and the score is incremented.
But AFAIK and someone correct me if I'm wrong, there's no way of getting the whole sorted set, sorted by the days and not the scores, in one go.
But then again, using a HASH achieves the same thing and is efficient in memory and execution time, as you can get the entire result in one go.




--
You received this message because you are subscribed to the Google Groups "Redis DB" group.
To post to this group, send email to redi...@googlegroups.com.
To unsubscribe from this group, send email to redis-db+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/redis-db?hl=en.


Damian Janowski

unread,
Dec 27, 2010, 8:24:36 AM12/27/10
to redi...@googlegroups.com
On Mon, Dec 27, 2010 at 8:10 AM, Alberto Gimeno Brieba
<gime...@gmail.com> wrote:
> Now, my questiong. I'm developing a webpage using redis. I need to
> store fixed-length arrays (I need to store an integer value for each
> day in a month). And I just need to increment the values from time to
> time. I'm thinking about which is the best way to implement this in
> redis. My thoughts are:
>
> - Using a string with a specific format. For example a basic example
> would be: "1,2,3,4,...". This is the option I have already
> implemented. The problem is that I need to do a few steps: read,
> parse, write. This option could be improved using different ways to
> encode the integers.

If you're using 2.2, then you can use WATCH together with GETRANGE and
SETRANGE to store everything in a single key:

WATCH foo
value = GETRANGE foo, 0, 0
value = value + increment
MULTI
SETRANGE foo, 0, value
EXEC

An implementation in Ruby: https://gist.github.com/756126

Alberto Gimeno Brieba

unread,
Dec 27, 2010, 9:32:00 AM12/27/10
to redi...@googlegroups.com
Great. Many thanks. I didn't know about the hash types, and the
commands with ranges of strings. I have just figured out that I have a
command cheatsheet of redis v1.

Nevertheless having a command like HINCRBY, I wonder if it is possible
to have a similar command for lists in a future release of redis. I
think this would be the best approach in this case.

Thanks again!

Pieter Noordhuis

unread,
Dec 28, 2010, 2:20:14 AM12/28/10
to redi...@googlegroups.com
Follow-up for this thread, I've posted my take on this here:

Cheers,
Pieter
Reply all
Reply to author
Forward
0 new messages