mysql实现分布式锁

1 篇文章 0 订阅

利用数据库的悲观锁实现分布式锁,实际应用中要考虑mysql的高可用。

DistributedLock.h

#ifndef DistributedLock_H_
#define DistributedLock_H_

//
// DistributedLock.h: 
//
#include "base/MySQLDriver.h"
class CDistributedLock
{
public:
	//
	// Construction/Destruction
	//
	CDistributedLock(server::mysqldb::MySQLConnection* c, const std::string& path, uint64_t key, uint16_t partitions = 16);
	~CDistributedLock();

	operator bool()
	{
		return m_bLocked;
	}

	bool getLocked()
	{
		return m_bLocked;
	}

	bool getDbDeaded()
	{
		return m_bDbDead;
	}

private:
	server::mysqldb::MySQLConnection* con_;
	bool		m_bLocked; //获取分布式锁是否成功
	bool		m_bDbDead;  //数据库是否是否宕机
};
#endif

DistributedLock.cpp

//
// DistributedLock.cpp: 
//

#include "DistributedLock.h"
#include "logger.h"
#include "base/common.h"
#include <string>
#include <sys/timeb.h>
#include <time.h>

//
// Construction/Destruction
//

char*   log_Time(void)
{
	struct  tm      *ptm;
	struct  timeb   stTimeb;
	static  char    szTime[19];

	ftime(&stTimeb);
	ptm = localtime(&stTimeb.time);
	sprintf(szTime, "%02d-%02d %02d:%02d:%02d.%03d",
		ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec, stTimeb.millitm);
	szTime[18] = 0;
	return szTime;
}

CDistributedLock::CDistributedLock(server::mysqldb::MySQLConnection* c,const std::string& path,uint64_t key,uint16_t partitions) 
{
	m_bLocked = false ;
	m_bDbDead = false;

	con_ = c ;
	if ( c )
	{
		server::mysqldb::Statement st = c->createStatement() ;
		char szSQL[256] ;

		sprintf(szSQL,"insert into %s_%d (lock_key,lock_ts) values (" UINT64FORMAT ",now()) on duplicate key update lock_ts=now()",path.c_str(),uint16_t(key % partitions), key) ;
		
		st.prepare(szSQL) ;
        int errcode = 0;
        std::string errwhat;
        for(int i = 0; i < 3; ++i) {
            try {
                server::mysqldb::ResultSet result = st.execute();
				if (result.getAffectedRows() > 0)
				{
					LogTrace(Info, "Distributed lock get succeed , affectedRows %d tms %s", result.getAffectedRows(), log_Time());
					m_bLocked = true;
				}
				else{
					LogTrace(Warn, "Distributed lock get failed , affectedRows %d tms %s", result.getAffectedRows(), log_Time());
				}
                break;
            } catch (server::mysqldb::Exception &e) {
                c->reconnect();
                errcode = e.code();
                errwhat = e.what();
				LogTrace(Error, "statemt error, %d %s try again !", errcode, errwhat.c_str());
            }
        }
        if(!m_bLocked) {
            LogTrace(Error, "sql execute error, code:%d, reason:%s", errcode, errwhat.c_str());
        }
	}else
	{
		LogTrace(Error, "get distributed lock failed, lock db is gone !");
		m_bDbDead = true;
	}
}


CDistributedLock::~CDistributedLock()
{	
	if ( con_ ) 
	{
		try {
			m_bLocked ? con_->commit() : con_->rollback() ;
		} catch (server::mysqldb::Exception &e) {	
			LogTrace(Error, "commit execute error, code:%d, reason:%s", e.code(), e.what());	
			con_->close() ;
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值