nodejs之連接redis以及事務封裝與使用

簡介

本文章主要針對nodejs中redis數據庫模塊事務的封裝,此文章只涉及本人個人見解和使用習慣,如果你還有更好的方法,歡迎提出一起交流。

所需模塊

目前redis模塊是使用回調函數的形式來接受返回的數據,這樣無疑會導致多種嵌套的使用,所以我們利用bluebird模塊進行加工變成promise,來美觀代碼:

  1. redis :V^2.8.0;
  2. bluebird:V^3.5.2;

文件結構

  1. config:redis.json(redis的連接參數)
  2. db:redis.js(連接redis)
  3. 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,一起進步。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章