[REDIS] 연결은 - 레디 스 - 경쟁 조건에 대한 세션 개체를 보호하는 방법
REDIS연결은 - 레디 스 - 경쟁 조건에 대한 세션 개체를 보호하는 방법
나는 세션 데이터를 저장하는 연결 - 레디 스에 nodejs를 사용하고 있습니다.
나는 세션에서 사용자 데이터를 저장하고, 세션 일생을 위해 사용하고있다.
나는 그것이 세션 데이터를 변경 두 요청 사이의 경쟁 조건을 가질 수 있다고 나타났습니다.
나는 세션을 잠그는 레디 스 잠금을 사용하려했지만, 나를 위해 약간의 문제가 있습니다.
나는 전체 세션을 잠 그려, 대신 특정 세션 변수를 고정하지 않습니다.
나는 그것이 불가능 발견, 나는 그것을 해결하는 방향에 대해 생각 :
사용자 데이터를 저장하는 세션 객체를 사용을 중지하고, 레디 스에서 직접 변수를 저장하고 잠금을 사용하기 전에.
나는 그것이 일 수 있다는 것을 알고 있지만, 그것은 나를 그냥 세션 객체를 통해 레디 스에 접근하는 대신 수동으로 모든 개체를 관리 할 필요합니다.
당신은 나와 함께 모범 사례 및 제안을 공유하시기 바랍니다 수 있습니까?
감사, 리 오르
해결법
-
==============================
1.글쎄, 당신의 자신의 스토리지를 구현하는 당신을위한 옵션이 될 수 있습니다. 당신이 할 필요가 세 가지 방법을 구현하는 것입니다이 문서 쇼 : 갔지,은 .set 및 .destroy는 (마지막 단락 참조). 그것은이 같은 (노드 - 레디 스 라이브러리를 사용하여 원래의 연결 - 레디 스 조금을 저장 수정)을 것입니다 :
글쎄, 당신의 자신의 스토리지를 구현하는 당신을위한 옵션이 될 수 있습니다. 당신이 할 필요가 세 가지 방법을 구현하는 것입니다이 문서 쇼 : 갔지,은 .set 및 .destroy는 (마지막 단락 참조). 그것은이 같은 (노드 - 레디 스 라이브러리를 사용하여 원래의 연결 - 레디 스 조금을 저장 수정)을 것입니다 :
var redis = require("redis"), redis_client = redis.createClient(), session_prefix = 'session::', lock_suffix = '::lock', threshold = 5000, wait_time = 250, oneDay = 86400; /* If timeout is greater then threshold, then we assume that one of the Redis Clients is dead and he cannot realese the lock. */ 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에 대한 오류 처리를 구현하지 않았다. 난 당신이 최대 떠날거야! : 약간의 실수가있을 수 있습니다 (I 순간에 NodeJS가없는 나는 내 기억에서 이것을 쓰고 있어요 : D),하지만 당신은 아이디어를 이해해야합니다. 여기 레디 스 잠금 해제 / 잠금에 대한 setnx을 사용하는 방법에 대한 논의를 포함하는 링크입니다.
다른 참고 : 당신은 아마 어떤 경로 예외가 발생하는 경우, 다음 레디 스 세션 잠금이 해제되지 않기 때문에, 루트에 대한 처리를 일부 사용자 지정 오류를 해보고 싶어요. 은 .set 방법은 항상 마지막 경로에서 일이라고한다 - 익스프레스는 매우 경로의 시작에서 호출 갔지 방법과 반대 (즉, 내가은 .set에 갔지 및 해제에 잠금 이유의). 그것이 비록 문제가 될 필요가 없습니다, 그래서 아직 당신은 5 초 동안 만 잠 깁니다. 사용자의 요구 (특히 임계 값 및 WAIT_TIME 변수)에 조정을해야합니다.
최종 참고 사항 :이 메커니즘을 요청 처리기는 사용자 당 잇달아 발사됩니다. 이 방법, 당신은 사용자 당 동시 핸들러를 실행할 수 없게됩니다. 다른 아이디어가 수동으로 잠금 해제 / 세션 및 핸들 잠금 외부 데이터를 개최하기 때문에 이러한 현상이 문제가 될 수 있습니다. 결국, 수동으로 처리해야 할 몇 가지가있다.
나는 그것이 도움이되기를 바랍니다! 행운을 빕니다!
from https://stackoverflow.com/questions/11420982/connect-redis-how-to-protect-the-session-object-against-race-condition by cc-by-sa and MIT license
'REDIS' 카테고리의 다른 글
[REDIS] 어떻게 CodeIgniter의에서 레디 스를 구현하는 방법? (0) | 2020.01.17 |
---|---|
[REDIS] 각종되는 NoSQL 데이터베이스에 대한 빠른 참조 안내서 (0) | 2020.01.17 |
[REDIS] 어떻게 레디 스 높은 처리량과 성능을 달성 하는가? (0) | 2020.01.17 |
[REDIS] 여러 클라이언트가 레디 스에서 차단받지 않고 동시에 동일한 목록에 액세스 할 수 있습니다? (0) | 2020.01.17 |
[REDIS] 스프링 데이터의 2.0.x에서 RedisCacheManager을 만드는 방법 (0) | 2020.01.17 |