我开始使用Redis,我遇到了以下问题。
我有一堆对象,比如我的系统中的Messages
。每次新的User
连接时,我都会执行以下操作:
INCR
一些全局变量,假设为g_message_id
,并保存INCR的返回值(g_message_id
的当前值)。
LPUSH
将新邮件(包括id
和实际邮件)放入列表中。
其他客户端使用g_message_id
的值来检查是否有任何新消息要获取。
问题是,假设有新消息,一个客户端可以INCR
g_message_id
,但在另一个客户端尝试读取消息之前没有时间LPUSH
消息。< / p>
换句话说,我正在寻找一种方法来相当于在SQL中添加行,并使用自动递增的索引来处理。
备注:
我无法使用列表索引,因为我经常要删除列表中的部分内容,使其无效。
我的实际情况有点复杂,这是一个更简单的版本。
当前解决方案:
我提出的最佳解决方案以及我打算做的是使用WATCH
和Transactions
来尝试自己执行“自动增量”。
但是在Redis中这是一个常见的用例,我很惊讶它没有现成的答案,所以我担心我做错了。
答案 0 :(得分:7)
如果我正确阅读,您使用 g_message_id 作为id序列和标志来指示新消息可用。一种选择是将其拆分为两个变量:一个用于分配消息标识符,另一个用于向客户端发信号通知新消息可用。
客户可以比较 g_new_message_flag 的当前/先前值,以了解新消息何时可用:
> INCR g_message_id
(integer) 123
# construct the message with id=123 in code
> MULTI
OK
> INCR g_new_message_flag
QUEUED
> LPUSH g_msg_queue "{\"id\": 123, \"msg\": \"hey\"}"
QUEUED
> EXEC
可能的替代方案,如果您的客户可以支持:您可能需要查看 Redis publish/subscribe个命令,例如客户可以发布新消息的通知并订阅一个或多个消息通道以接收通知。如有必要,您可以保留 g_msg_queue 以维护新客户的N条消息积压。
根据评论更新:如果您希望每个客户端检测到可用消息,请弹出所有可用消息,并将列表清零,一个选项是使用事务来读取列表:
# assuming the message queue contains "123", "456", "789"..
# a client detects there are new messages, then runs this:
> WATCH g_msg_queue
OK
> LRANGE g_msg_queue 0 100000
QUEUED
> DEL g_msg_queue
QUEUED
> EXEC
1) 1) "789"
2) "456"
3) "123"
2) (integer) 1
更新2 :鉴于新信息,我将采取以下措施:
答案 1 :(得分:5)
您真的需要唯一的顺序ID吗?您可以使用UUIDs获取唯一性和时间戳来检查新邮件。如果您使所有服务器上的时钟保持正确同步,那么具有一秒分辨率的时间戳应该可以正常工作。
如果您确实需要唯一的顺序ID,那么您可能需要设置Flickr style ticket server来正确管理ID的中央列表。实质上,这会将您的g_message_id
移动到具有正确事务处理的数据库中。
答案 2 :(得分:0)
您可以模拟自动递增新行的唯一键。只需使用DBSIZE即可获取当前行数,然后在代码中将该数字递增1,然后将该数字用作新行的键。简单而原子。