gpt4 book ai didi

ruby-on-rails - 在 redis 中存储(唯一)键值数组

转载 作者:可可西里 更新时间:2023-11-01 11:35:37 26 4
gpt4 key购买 nike

应用程序中的用户在特定事件中获得奖励/惩罚积分。

我想为每个用户存储:

1- 奖励列表 [EventID,#points]

2- 惩罚列表[EventID,#points]

特点

  • 必须能够将新的 [EventID, #points] 对推送到列表。

  • 可以轻松检索 EventID 的列表。

  • #points 可以是小数,而不仅仅是整数。

例如

用户#10

  • 奖金:[ [122,10], [128,10], [133,5]]

  • 惩罚:[ [22,10], [28,5], [13,1]]

· 用户#1 余额:(10+10+5)-(10+5+1) = 9

到目前为止的选项

我正在使用 postgres + Redis。

1。 Postgres 的 HSTORE

例如User.find(10).bonus_events => {'122':'10','128':'10','133':'5'}

2。 Postgres 的 JSON 类型

例如User.find(10).bonus_events =>
[{id:'122',点数:'10'},
{id:'128',点数:'10'}
{id:'133',points:'5'}]

3。雷迪斯?

不相信...

最佳答案

ZSET案例

ZSET (Sorted Set) 可以这样使用。在您的问题中,eventId 和 points 是整数,因此 Redis 将以最大可能的有效性存储它们。

来自 datatypes intro :

Redis Sorted Sets are non repeating collections of Strings. The difference is that every member of a Sorted Set is associated with score, that is used in order to take the sorted set ordered, from the smallest to the greatest score. While members are unique, scores may be repeated.

With sorted sets you can add, remove, or update elements in a very fast way (in a time proportional to the logarithm of the number of elements). Since elements are taken in order and not ordered afterwards, you can also get ranges by score or by rank (position) in a very fast way. Accessing the middle of a sorted set is also very fast, so you can use Sorted Sets as a smart list of non repeating elements where you can quickly access everything you need: elements in order, fast existence test, fast access to elements in the middle!

解决方法:

  1. 每位用户使用 2 个 ZSET - 一个用于奖励,一个用于惩罚。
  2. EventID 是关键,#points 是 ZSET 的分数。

添加事件:

ZADD bonuses:1 10 122 
ZADD penalization:1 10 22
...

聚合它们(伪代码):

function getBalance(userId) {
bonusKey = "bonuses:" + userId;
penalizationKey = "penalization:" + userIdl

bonuses = redis.call("ZRANGE", bonusKey, 0 -1, "WITHSCORES")
penalization = redis.call("ZRANGE", penalizationKey, 0 -1, "WITHSCORES")

//`bonuses` and `penalization` are array of eventId->points,
// so use index 1 to aceess just points
return bonuses.reduse(acc, element => acc + element[1]) +
penalization.reduse(acc, element => acc + element[1]);
}

HSET案例

Use this case only if you have unique eventId in each list

Redis 哈希是字符串字段和字符串值之间的映射,因此它们是表示对象的完美数据类型(例如,具有姓名、姓氏、年龄等多个字段的用户)。具有几个字段的哈希以占用很少空间的方式存储,因此您可以在一个小型 Redis 实例中存储数百万个对象。

解决方法:

  1. 每个用户使用 2 个 HSET - 一个用于奖励,一个用于惩罚(使用可能会考虑用一组前缀存储两个列表,例如 bonus:eventId - 不要那样做。这不允许 redis 到 use RAM effecient ).
  2. EventID 是键,#points 是 HSET 的值。

添加事件:

HSET bonuses:1 122 10
HSET penalization:1 22 10
...

聚合它们(伪代码):

function getBalance(userId) {
bonusKey = "bonuses:" + userId;
penalizationKey = "penalization:" + userIdl

bonuses = redis.call("HGETALL", bonusKey)
penalization = redis.call("HGETALL", penalizationKey)

//`bonuses` and `penalization` are array of eventId->points,
// so use index 1 to aceess just points
return bonuses.reduse(acc, element => acc + element[1]) +
penalization.reduse(acc, element => acc + element[1]);
}

什么更好

HSET 案例更好更​​快地使用 RAM。如果您在每个列表中只有唯一的 eventId - 使用这种情况。

关于ruby-on-rails - 在 redis 中存储(唯一)键值数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34755998/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com