打算用nodejs+redis+sqlserver做站点,.Net开发的伤不起啊。 打算用nodejs到redis里面取静态页上的一些动态数据,取不到则走sqlserver数据库查询。 谁能给一个简单的搭建示例,重赏啊,有北京的朋友我请大餐。
@perfectnode YY.get_cache = function( self, tablename, where, row, cb ) { redis.get( key, function( err, res ) { if( err ) { cb( err ); } else { if( res === null ) { //console.log( ‘no cache’ ); var sql = YY.selectSQL( tablename, where, row ); self.query( sql, function( err, res ) { if( err ) { args( err ); } else { cb( null, res ); if( res.length !== 0 ) { redis.set( key, JSON.stringify( res ), 'NX’, 'EX’, 43200, function( err, res ) { if( err ) { console.error( err ); } }); } } }); } else { //console.log( ‘data from cache’ ); cb( null, JSON.parse( res ) ); } } });
};
@perfectnode 我们封装的与业务关系比较大,贴出来完整的估计也看不了明白,思路就是:1.redis缓存我们业务需要的数据(有生命周期),以减轻数据库的压力,当查询数据时,先走redis,redis没有数据走数据库,同时把得到的数据存入redis;2.当数据发生delete或者update操作时,删掉redis中的数据,同时更改数据库。
注意的地方:第一步中,从数据库中取数据存入redis,redis存储失败成功不重要。第二步中,必须等redis中清楚数据成功以后才能更改数据库,不然下次取数据就会有问题。
@perfectnode
//存储缓存
YY.get_cache = function( self, tablename, where, row, args ) {
if( tablename === ‘card’ ) {
//卡组查询
if( where.indexOf( ‘card_group’ ) !== -1 ) {
var groupid = where.match( new RegExp('card_group=([^ ])') )[ 1 ];
var key = ‘group_id=’ + groupid;
var redis = pomelo.app.get( ‘redis’);
redis.get( key, function( err, mres ) {
if( err ) {
args( err );
}
else {
//卡组信息缓存存在
if( mres ) {
//console.log( ‘card_group from cache’ );
res = JSON.parse( mres );
YY.get_multi_card( self, res, args );
}
//卡组缓存不存在
else {
//console.log( ‘card_group no cache’ );
var tmp_reg = where.match( new RegExp('role_id=([^ ])') );
if( tmp_reg ) {
var roleid = tmp_reg[ 1 ];
var sql = YY.selectSQL( ‘card_group’, ‘group_id=’ + groupid + ' AND role_id=’ + roleid, ‘*’ );
self.query( sql, function( err, res ) {
YY.get_multi_card( self, res[ 0 ], args );
redis.set( key , JSON.stringify( res[ 0 ] ), 'NX’, 'EX’, 43200, function( err, mres ) {
if( err ) {
console.error( err );
}
});
});
}
else {
console.error( ‘select card_group, role_id is required’ );
}
}
}
});
}
//通过card_id来查询
else if( where.indexOf( ‘card_id’ ) !== -1 ) {
var card_id_arr = where.match(/card_id=(\d+)/g).map(function(n){return n.match(/\d+/)[0]});
var redis = pomelo.app.get( ‘redis’);
//多张卡片的查询
if( card_id_arr.length > 1 ) {
YY.get_multi_card( self, card_id_arr, args );
}
//单张卡片的查询
else {
var key = ‘card_id=’ + card_id_arr[ 0 ];
redis.get( key, function( err, res ) {
if( err ) {
args( err );
}
else {
//单张卡片没有缓存
if( res === null ) {
//console.log( ‘card no cache’ );
var sql = YY.selectSQL( 'card’, where, row );
self.query( sql, function( err, res ) {
if( err ) {
args( err );
}
else {
args( null, res );
if( res.length !== 0 ) {
redis.set( key, JSON.stringify( res ), 'NX’, 'EX’, 43200, function( err, res ) {
if( err ) {
console.error( err );
}
});
}
}
});
}
//读取缓存
else {
//console.log( ‘card from cache’ );
args( null, JSON.parse( res ) );
}
}
});
}
}
//通过role_id来查询
else if( where.indexOf( ‘role_id’ ) !== -1 ) {
var sql = YY.selectSQL( 'card’, where, row );
self.query( sql, function( err, res ) {
if( err ) {
args( err );
}
else {
args( null, res );
if( res.length !== 0 ) {
var redis = pomelo.app.get( ‘redis’);
res.forEach(function( card ) {
//判断key是否存在,如果不存在,就缓存
var key = ‘card_id=’ + card.card_id;
redis.exists( key, function( err, res ) {
if( err ) {
console.error( err );
}
else {
if( res === 0 ) {
redis.set( key, JSON.stringify( [ card ] ), 'NX’, 'EX’, 43200, function( err, res ) {
if( err ) {
console.error( err );
}
});
}
}
});
});
}
}
});
}
else {
console.log( ‘no such condition is found’ );
}
}
};
//删除缓存 YY.del_cache = function( self, tablename, data, where, args, memc ) { var async = require( ‘async’ ); var redis = pomelo.app.get( ‘redis’ ); /* 删除key / function removekey( keys ) { var fun_arr = []; keys.forEach( function( key, idx ) { if( idx === 0 ) { fun_arr.push( function( cb ) { redis.exists( key, cb ); } ); } else { fun_arr.push( function( res, cb ) { redis.exists( key, cb ); } ); } fun_arr.push( function( res, cb ) { //没有缓存 if( res === 0 ) { cb( null, null ); } else { redis.del( key, function( err, res ) { //删除成功 if( res ) { cb( null, null ); } //删除失败 else { cb( ‘mysql cahce del failed’ ); } }); } } ); }); fun_arr.push( function( res, cb ) { if( memc.sql == ‘update’ ) { //console.log( ‘update cache success’ ); self[ memc.sql ]( tablename, data, where, args, true ); } else if( memc.sql == ‘delete’ ) { //console.log( ‘delete cache success’ ); self[ memc.sql ]( tablename, where, args, true ); } } ); async.waterfall( fun_arr, function( err ) { args( err ); }); } //卡组逻辑 if( tablename == ‘card_group’ ) { var groupid = where.match( new RegExp('group_id=([^ ])') )[ 1 ]; var keys = [ ‘group_id=’ + groupid ]; removekey( keys ); } else if( tablename == ‘card’ ) { var card_id_arr = where.match(/card_id=(\d+)/g).map(function(n){return n.match(/\d+/)[0]}); var keys = []; for( var i = 0; i < card_id_arr.length; i++ ) { keys.push( ‘card_id=’ + card_id_arr[ i ] ); } removekey( keys ); } else{ console.error( ‘mysql delete cache error, no such options’ ); } };
对于直接贴代码的做法我是不太赞成的,在这上面一般都是提供思路,剩下的自己去做。 我们代码和业务关系比较大,而且我们用的是mysql,能不能看懂就看你自己了。