分布式锁,是控制分布式系统之间同步访问共享资源的一种方式。在分布式系统中,常常需要协调他们的动作。如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰来保证一致性,在这种情况下,便需要使用到分布式锁。
分布式锁的本质可以看作是特殊的普通锁,它的竞争者不是普通的进程和线程,它的竞争者分布在不同的主机上,需要通过网络来相互通信,不同的主机分布和网络的不确定性给分布式锁的实现和普通锁有着很大的不同。
什么是分布式锁极速飞艇平台开发,需要请搜索【大神源码论坛】dsluntan.com 客服企娥3393756370 V信17061863513,
目前常见的分布式锁的实现有基于数据库,基于缓存(redis等缓存数据库),基于zoonkeeper三种:
基于redis实现分布式锁很简单,通过一个命令setnx(set if no exist).只有在key不存在的时候才set成功返回1,否则返回失败0,但是要考虑到一些意外情况还是需要一个很严谨的逻辑。
//
// Created by dguco on 18-9-9.
//
#ifndef SERVER_REDI_LOCK_H
#define SERVER_REDI_LOCK_H
#include <iostream>
#include <redis_client.h>
#include <future>
using namespace std;
// 获取当前秒数
int GetSecond()
{
struct timeval tmval = {0};
int nRetCode = gettimeofday(&tmval, NULL);
if (nRetCode != 0) {
return 0;
}
return (int) (tmval.tv_sec);
}
#define LOCK_TIME_OUT 1 //1s
CRedisClient g_RedisCli;
class CRedisLock
{
public:
/*
- @param lockKey
- @param isBlock 司机阻塞
- @return 是否锁成功
*/
bool Lock(std::string &lockKey, bool isBlock = false);
template<class F, class... Args>
void DoWithLock(std::string &lockKey, F &&f, Args &&... args);
template<class F, class... Args>
void TryDoWithLock(std::string &lockKey, F &&f, Args &&... args);
private:
int m_iLockTimeOut;
};
template<class F, class... Args>
void CRedisLock::TryDoWithLock(std::string &lockKey, F &&f, Args &&... args)
{
bool isLock = Lock(lockKey, false);
if (isLock) {
using return_type = typename std::result_of<F(Args...)>::type;
auto task = std::make_shared<std::packaged_task<return_type()> >(
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
);
(*task)( );
int now = GetSecond( );
if (now < m_iLockTimeOut) {
g_RedisCli.Del(lockKey);
}
}
}
template<class F, class... Args>
inline void CRedisLock::DoWithLock(std::string &lockKey, F &&f, Args &&... args)
{
bool isLock = Lock(lockKey, true);
if (isLock) {
using return_type = typename std::result_of<F(Args...)>::type;
auto task = std::make_shared<std::packaged_task<return_type()> >(
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
);
(*task)( );
int now = GetSecond( );
if (now < m_iLockTimeOut) {
g_RedisCli.Del(lockKey);
}
}
}
bool CRedisLock::Lock(std::string &lockKey, bool isBlock)
{
int lock = 0;
m_iLockTimeOut = 0;
bool isLock = false;
while (lock != 1) {
int now = GetSecond( );
m_iLockTimeOut = now + LOCK_TIME_OUT + 1;
lock = g_RedisCli.Setnx(lockKey, to_string(m_iLockTimeOut));
//是否获取成功
if (lock == 1) {
isLock = true;
}
//判断是否超时,并设置新的超时时间
if (!isLock) {
string res = "";
g_RedisCli.Get(lockKey, &res);
//如果没有被其他竞争者
if (res != "") {
int out1 = atoi(res.c_str( ));
string res1 = "";
g_RedisCli.Getset(lockKey, &res1);
//如果更新超时之前没有被其他竞争者抢先且超时
if (now > out1 && res == res1) {
isLock = true;
}
}
}
if (isLock or !isBlock) {
break;
}
else {
usleep(1000);
}
}
return isLock;
}
#endif //SERVER_REDI_LOCK_H
原文地址:http://blog.51cto.com/13970120/2175198