嗯,实现自己的存储可能是您的选择。该文件显示,所有你需要做的是实现三个方法:
.get,
.set和
.destroy(参见最后一段)。就像这样(使用node-
redis库并修改原始的connect-
redis存储有点):
var redis = require("redis"), redis_client = redis.createClient(), session_prefix = 'session::', lock_suffix = '::lock', threshold = 5000, wait_time = 250, oneDay = 86400;function CustomSessionStore(opts) { opts = opts || {}; var self = this; self.ttl = opts.ttl; // <---- used for setting timeout on session self.lock = function(sid, callback) { callback = callback || function(){}; var key = session_prefix + sid + lock_suffix; // try setting the lock with current Date redis_client.setnx(key, Date.now( ), function(err, res) { // some error handling? if (res) { // Everything's fine, call callback. callback(); return; } // setnx failed, look at timeout redis_client.get(key, function(err, res) { // some error handling? if (parseInt(res) + threshold > Date.now( )) { // timeout, release the old lock and lock it redis_client.getset(key, Date.now( ), function(err, date) { if (parseInt(date) + threshold > Date.now()) { // ups, some one else was faster in acquiring lock setTimeout(function() { self.lock(sid, callback); }, wait_time); return; } callback(); }); return; } // it is not time yet, wait and try again later setTimeout(function() { self.lock(sid, callback); }, wait_time); }); }); }; self.unlock = function(sid, callback) { callback = callback || function(){}; var key = session_prefix + sid + lock_suffix; redis_client.del(key, function(err) { // some error handling? callback(); }); }; self.get = function(sid, callback) { callback = callback || function(){}; var key = session_prefix + sid; // lock the session self.lock(sid, function() { redis_client.get(key, function(err, data) { if (err) { callback(err); return; } try { callback(null, JSON.parse(data)); } catch(e) { callback(e); } }); }); }; self.set = function(sid, data, callback) { callback = callback || function(){}; try { // ttl used for expiration of session var maxAge = sess.cookie.maxAge , ttl = self.ttl , sess = JSON.stringify(sess); ttl = ttl || ('number' == typeof maxAge ? maxAge / 1000 | 0 : oneDay); } catch(e) { callback(e); return; } var key = session_prefix + sid; redis_client.setex(key, ttl, data, function(err) { // unlock the session self.unlock(sid, function(_err) { callback(err || _err); }); }); }; self.destroy = function(sid, callback) { var key = session_prefix + sid; redis_client.del(key, function(err) { redis_client.unlock(sid, function(_err) { callback(err || _err); }); }); };}旁注
:我没有为
.lock和实现错误处理
.unlock。我把这个留给你!:)可能会有一些小错误(目前我没有NodeJS,我正在从我的记忆中写它:D),但是您应该理解这个想法。这是包含有关如何用于锁定/解锁Redis
的讨论的链接
setnx。
另一个注意事项
:您可能想对路由进行一些自定义错误处理,因为如果任何路由引发异常,则Redis会话将不会被解锁。该
.set方法始终被称为路线中的最后一件事-与
.getExpress
在路线的最开始处调用的方法相反(这就是为什么我在处锁定
.get并在处解锁
.set)。仍然您只会被锁定5秒钟,因此虽然不必担心。请记住,它调整到您的需求(尤其是
threshold和
wait_time变量)。
最后说明 :使用这种机制,您的请求处理程序将仅对每个用户一个接一个地触发。这意味着您将 无法为
每个用户运行并发处理程序。这可能是一个问题,因此另一个想法是将数据保留在会话外部并手动处理锁定/解锁。毕竟,有些事情必须手动处理。
希望对您有所帮助!祝好运!



