nodejs之連線redis以及事務封裝與使用
阿新 • • 發佈:2018-12-12
nodejs之連線redis以及事務封裝
簡介
本文章主要針對nodejs中redis資料庫模組事務的封裝,此文章只涉及本人個人見解和使用習慣,如果你還有更好的方法,歡迎提出一起交流。
所需模組
目前redis模組是使用回撥函式的形式來接受返回的資料,這樣無疑會導致多種巢狀的使用,所以我們利用bluebird模組進行加工變成promise,來美觀程式碼:
- redis :V^2.8.0;
- bluebird:V^3.5.2;
檔案結構
- config:redis.json(redis的連線引數)
- db:redis.js(連線redis)
- model:RedisModel.js(對於redis的一些操作的封裝)
4.cache:CacheOrders.js(針對訂單相關操作的封裝,其中使用redismodel.js的方法)
乾貨部分
話不多少,只有程式碼才能說明一切。
1 此部分為redis初始化配置資訊:
// config檔案下的redis.json
{
"host":"127.0.0.1",
"port":6379,
"db":0,
"password":"*******"
}
2 資料庫連線
//db檔案下的redis.js
var redis=require('redis');
var redisConfig=require('../config/redis');
const utils=require('../utils/index')();
const logger=utils. logger;
redisConfig.retry_strategy= function (options) {
if (options.error && options.error.code === 'ECONNREFUSED') {
// End reconnecting on a specific error and flush all commands with
// a individual error
return new Error('The server refused the connection');
}
if (options.total_retry_time > 1000 * 60 * 60) {
// End reconnecting after a specific timeout and flush all commands
// with a individual error
return new Error('Retry time exhausted');
}
if (options.attempt > 10) {
// End reconnecting with built in error
return undefined;
}
// reconnect after
return Math.min(options.attempt * 100, 3000);
};
//在redis中的操作為原子操作,就算是非同步操作,他也是按照程式碼順序一條一條執行
//建立一個client連線到redis server資料庫
function startRedis(){
var client=redis.createClient(redisConfig);
//事件
client.on("ready",function(){
logger.info("redis opened success");
});
//監聽error事件,可以是redis客戶端自動連線資料庫
client.on("error", function (err) {
logger.error("資料庫斷開",err);
});
//伺服器與資料庫斷開連線
client.on("end", function () {
logger.warn("與資料開斷開連線");
});
return client;
}
module.exports={
startRedisDb:startRedis
};
3 RedisModel的封裝和對資料庫的使用
//因為專案需要,選擇redis中的List表結構儲存資料
const redis=require('../db/redis');
const client=redis.startRedisDb();
const Promise = require('bluebird');
//列表
//向redis中插入整個陣列,其陣列中為多條string型別的json資料
function setList(listId,list){//新增整個陣列
for(let i=0;i<list.length;i++){
if((typeof list[i])==="object"){
list[i]=JSON.stringify(list[i]);
}
}
client.lpush(listId,list[0]);
for(let i=1;i<list.length;i++){
client.rpush(listId,list[i]);
}
//cb(null,"set success");
return true;
}
//向表中插入單條資料
function pushList(listId,value,cb){//新增單個數據
client.rpush(listId,value,function(err,replay){
if(err){
cb(err,null);
}else {
cb(null,replay);
}
});
}
//刪除指定的元素
function removeListByValue(listId,value,cb){
client.lrem(listId,1,value,function(err,data){
if(data){
cb(null,data);
}else{
cb(err,null)
}
});
}
//更新redis中的指定元素
function updateListValueByIndex(listId,index,newValue,cb){
newValue=JSON.stringify(newValue);
client.lset(listId,index,newValue,function(err,data){
if(err){
cb(err,null);
}else{
cb(null,data);
}
})
}
//向指定位置插入元素
function insertValueByIndex(listId,value,index,cb){
index=Number(index);
if(index===0){
client.lindex(listId,index,function(err,result){
client.linsert(listId,"BEFORE",result,value,function(err,replay){
if(err){
cb(err,null);
}else {
cb(null,replay);
}
})
});
}else{
client.lindex(listId,index-1,function(err,result){
client.linsert(listId,"AFTER",result,value,function(err,replay){
if(err){
cb(err,null);
}else {
cb(null,replay);
}
})
});
}
}
//根據下標獲取表中的指定資料
function getValueByIndex(listId,index,cb){
client.lindex(listId,index,function(err,data){
if(err){
cb(err,null);
}else{
cb(null,data);
}
})
}
//查詢指定範圍的資料
function getListByRange(listId,begin,end,cb){
client.lrange(listId,begin,end, function (err,data) {
if(err){
cb(err,null);
}else {
cb(null,data);
}
});
}
//刪除整個表
function deleteKey(key,cb){
client.del(key, function (err,data) {
if(err){
cb(err,null);
}else {
cb(null,data);
}
})
}
//使用redis事務
function insertListTransaction(functions,cb){
//functions=[client.multi(),rpush(),rpush(),rpush()]//為多條redis的執行語句,其中multi和exec為事務的開啟和結束標誌。
client.multi(functions).exec(function(err,replies){
if(err){
cb(err,null);
}else{
cb(null,replies);
}
})
}
module.exports={
setList:setList,
pushList:pushList,
removeListByValue:removeListByValue,
updateListValueByIndex:updateListValueByIndex,
insertValueByIndex:insertValueByIndex,
getValueByIndex:getValueByIndex,
getListByRange:getListByRange,
deleteKey:deleteKey,
insertListTransaction:insertListTransaction
};
4 模型的封裝
//cache檔案下CacheOrders.js
class CacheOrders{
constructor(){
this.orders={};//根據使用者分類的訂單
this.ordersList=[];
}
//同時插入訂單和訂單項,當有一步操作失敗時,撤銷所有操作即使用了redis的事務機制
async insertCacheOrderAndOrderItem(order,orderItem){
var insertListTransaction=Promise.promisify(RedisModel.insertListTransaction,{context:RedisModel});
order=JSON.stringify(order);
orderItem=JSON.stringify(orderItem);
let addOrder_result;
try{
addOrder_result=await insertListTransaction("orders","orderItems",order,orderItem);
await this.refreshCache();
}catch(e){
console.log(e);
addOrder_result=null;
}
return addOrder_result;
}
}
具體使用
let CacheOrders=require(../cache/CacheOrders.js)
let orderJson={
oid:orderInfo.oid,
onumber:orderInfo.onumber,
oaccount:orderInfo.oaccount,
recipient:orderInfo.recipient,
district:orderInfo.district,
phone:orderInfo.phone,
express:orderInfo.express,
ordertime:orderInfo.ordertime,
paytime:orderInfo.paytime,
state:orderInfo.state,
uid:orderInfo.uid,
detaildistrict:orderInfo.detaildistrict
}
let orderItemJson={
oitemid:orderInfo.oitemid,
oid:orderInfo.oid,
pcount:orderInfo.pcount,
pid:orderInfo.pid,
sid:orderInfo.sid,
buysource:orderInfo.buysource,
fromuid:orderInfo.fromuid,
essayuid:orderInfo.essayuid,
standard:orderInfo.standard,
phy_number:"null"
phy_state:-1
}
let insert_result=await cacheOrders.insertCacheOrderAndOrderItem(orderJson,orderItemJson);
if(insert_result==null){
logger.info("新增訂單失敗");
res.send({encode:-1,msg:"新增訂單失敗"});
}else{
res.send({encode:0,msg:"新增訂單成功"});
}
到這裡我們就結束了,如果你喜歡,那謝謝你的瀏覽,如果不喜歡,那請留下你的建議。
如果有nodejs志同道合的人,歡迎加q:823522370,一起進步。