我正在学习Redis,而且我正在使用一个简单的users
表。我通过node_redis
与Redis进行了互动。
我将每个新用户存储为:
client = redis.createClient();
client.incr('user_count', function (err, reply) {
var new_user_id = reply;
client.lpush('user_ids', new_user_id);
client.hset('user:' + new_user_id, 'username', req.param('username'), redis.print);
client.quit();
res.redirect('/');
});
所以在这一点上,我希望我的数据库看起来像:
user_ids
1
2
和
user:1 username 'Guy One'
user:2 username 'Guy Two'
这很好用。但我现在坚持的是生成完整的用户表。我遍历user_ids
,并为每一个提取相应的user
哈希条目。
这种方法除了看起来非常低效(每个用户密钥的单独查询)之外,由于node_redis
异步执行getter调用,因此也存在问题。因此,每个getter必须在其成功回调中调用下一个getter等。非常长嵌套回调getter。
这是我最初尝试过的:
var usernamesList = new Array();
client.lrange('user_ids', 0, -1, function (err, reply) {
var userIdsList = (reply == null || reply == undefined) ? new Array() : reply;
for (var userId in userIdsList) {
usernamesList.push(client.hget('user:' + userId, 'username'));
}
res.render('users', { usernames: usernamesList });
});
但如上所述,它不仅效率低下,而且无法正常工作,因为hget()
方法的第三个参数(目前不存在)实际上应该是是一个回调,然后应该hget()
调用userIdsList
中的下一个项目等。
hget()
的返回值是一个布尔值。因此,我上面编写的方法只返回一个数组:[true, true]
所以我的问题:
这是执行/构建完整用户列表和查找的正确方法吗?
如何处理每个hget()
需要回调的事实?
答案 0 :(得分:1)
以这种方式迭代所有用户将需要与user_ids
的长度一样多的往返行程。如果您不打算使用Redis群集,则可以使用MULTI/EXEC
一次性发送所有这些命令,并将结果发回一次。
client.lrange('user_ids', 0, -1, function (err, users) {
var userIds = users || [],
pipeline = [];
userIds.forEach(function (userId) {
pipeline.hget('user:' + userId, 'username');
});
pipeline.exec(function (err, users) {
res.render('users', { usernames: users);
});
});
如果您的users表包含单个字段(用户名),则可以使用单个哈希来存储所有用户。
集:
client.incr('users_count', function (err, count) {
client.hset('users', count, req.param('username'));
});
向上看:
client.hgetall('users', function (err, users) {
res.render('users', users);
});
另一种方法是使用lua脚本,但由于要查找的用户密钥是动态生成的,因此无法与redis群集很好地协同工作,并且群集要求服务器访问的所有密钥都在同一个redis实例。