DAS SEMQ优化

1.tb_0030增加在f003v_0030上的唯一索引

           

a.目的:

关于发送端消息记录的Ack记录可能在目标接收方因多次传输可能出现多条记录。

这种重复是不必要,而且导致在故障检查时双方消息数的不一致而不利于排查问题。


SQL Server脚本            

CREATE UNIQUE NONCLUSTERED INDEX [ui_0030_2] ON [dbo].[tb_0030]
(
    [f003v_0030] ASC
)WITH (STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = OFF) ON [PRIMARY]


b.代码修改: 

修改semq.cpp文件的内容.        


int QueryValue(CDbAccessor *pdbor,const char *sql,_variant_t *v) {
    AUTO_QUERY_RECORDSET(CRecordset,prs,pdbor);
    prs = pdbor->Query(adCmdText,sql);
    if (prs==0) {
        return -1;
    }
    if (prs->IsEof()) {
        return -2;
    }
    int fld_cnt = prs->GetFieldCount();
    for (int i=0;i<fld_cnt;i++) {
        _variant_t vtVal;
        if (!prs->GetFieldValue(i,vtVal))
            return -3;
        v[i] = vtVal;
    }
    return 0;
}

int CSEMQ::SaveAck(SEMQ_ACK_HELPER *ak) {
    USEDBC(pdbor,ack_queue_dbc_.c_str());

    ITableHandler *th = CBasePlugInModule::db_helper_->NewTableHandler(pdbor,"tb_0030");
    AUTO_POINTER_NODECLARE(ITableHandler,th);

    pdbor->BeginTrans();
    unsigned short num = ak->loc_keys_.size();
    for (unsigned short i=0;i<num;i++) {
        MQ_LOC_KEY *lk = ak->loc_keys_[i];
        char key[128];
        sprintf(key,"%d,%d,%d,%d,%I64d",lk->node_type_,lk->node_id_,lk->mq_id_,lk->mq_db_id_,lk->record_id_);
        th->BindField("f003v_0030",key);
        char date[32];
        CDateTime::GetDateTime(date);
        th->BindField("src_type",(char**)&ak->src_.type_,sizeof(ak->src_.type_));
        th->BindField("src_id",(char**)&ak->src_.id_,sizeof(ak->src_.id_));
        th->BindField("dest_type",(char**)&ak->dest_.type_,sizeof(ak->dest_.type_));
        th->BindField("dest_id",(char**)&ak->dest_.id_,sizeof(ak->dest_.id_));
        th->BindField("f005d_0030",date);
        bool dup_key_error = false;
        if (th->Insert()) {
            dup_key_error = pdbor->GetDBExt()->IsDuplicateKeyError(pdbor->GetLastErrorCode());
            if (!dup_key_error) {
                return -1;
            }
        }
        unsigned __int64 record_id;
        if (!dup_key_error) {
            if (pdbor->GetDBExt()->GetLastID(record_id,1,"tb_0030")) {
                return -2;
            }
        }
        else {
            string sql = LogMsg("select object_id from tb_0030 where f003v_0030='%s'",key);
            _variant_t v;
            if (QueryValue(pdbor,sql.c_str(),&v)) {
                return -3;
            }
            string sVal = ExVariantToString(v);
            record_id = a2Li(sVal.c_str());
        }
        ak->src_record_ids_.push_back(record_id); ///< 保存写入的待确认记录的记录编号
    }
    FAIL_RETURN(pdbor->CommitTrans(),,-1);

    return 0;
}


2.多内部服务器时异步处理模式的实现


a.背景

之前的版本引入了对dxi_change_log同步方式的支持.见http://blog.csdn.net/wherwh/article/details/26482279

目的是在多个内部服务器时避免对异步任务的分配.带来好处的同时,存在一个缺陷:由于接收消息时立即处理,如果数据库处理效率低下或者开销大,可能导致通信接收的堵塞现象。
另外,系统还遗留一个失败重做时任务由谁承担的问题,当时的计划是配置一个服务器可以执行失败重做任务,这引入了单点问题。

鉴于测试的效果,需要对于异步任务方式的完全支持。
实现策略为:
在异步模式下,谁接收谁负责处理.接收者写入tb_change_log时记录处理者ID.即服务器ID.
失败重做也采用同样机制.
 

b.脚本    

以下为前置机和内部服务器数据库的SQL Server升级脚本:
.tb_0033增加处理者ID字段

alter table tb_0033 add f016n_0033 int; 
.tb_change_log增加处理者ID字段:
alter table tb_jxj_job add handler int;
***表名对应具体的配置

c.代码修改

.dxi_change_log默认采用异步方式:

    <handle_mode>3</handle_mode> <!-- 处理模式: bit0-1:同步 0-异步 bit1-同步模式下是否写变更日志表.默认:1 -->  

.bbox
int CRedoar::Save(CMsg *msg,const char *text,const char *seq_ctrl_key,const char *app_key);
int CRedoar::RedoProc();

.dxi_change_log
ACE_THR_FUNC_RETURN ChangeLogScanProc(void *arg);
int CDxkChangeLog::HandleBillAccept(CBillAcceptEvent *e) 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值