技术代码:分布式

1--BEGIN DISTRIBUTED TRANSACTION [transactionname]
2 --标志一个由分布式事务处理协调器MSDTC管理的TSQL分布式事务开始
3 --SERVER A服务器为主控服务器。当连接发出后续COMMIT TRANSACTION或
4 --ROLLBACK TRANSACTION语句时,主控服务器请求MSDTC在所涉及的服务器间管理
5 --分布式事务的完成
6 
7 --SQLSERVER使用链接服务器或者远程服务器作为分布式事务处理的平台,提供
8 --远程存储过程调用和分布式查询
9 --当使用分布式事务进行一个远程存储过程调用和一个分布式查询时,在SERVER A
10 --上发出BEGIN DISTRIBUTED TRANSACTION ,该连接调用SERVER B上的存储过程
11--和SERVER C上的另一个存储过程,并且SERVER C上的存储过程对SERVER D执行一个
12--分布式查询,则四个SQLSERVER服务器进入分布式事务中,SERVER A是该事务的创建者
13--和控制服务器
14--创建分布式事务,在本地和远程数据库同时删除一条记录,其中,远程SQLSERVER
15--的实例名称为RemoteServer。本地和远程数据库同时提交或同时回滚该事务。
16--注意,执行分布式查询或调用存储过程时,使用4部分名称限定规则
17--前提:本机的MSDTC和远程机器的MSDTC服务要打开
18--本机和远程机器能互相ping通
19--数据库端口能互相telnet通
20--创建一个链接服务器到远程机器WIN7U-20130414Z
21USE [GPOSDB]
22GO
23SELECT * FROM [SystemPara]WHERE [Name]='HDTPort'
24SELECT * FROM [WIN7U-20130414Z].[GPOSDB].dbo.[SystemPara]WHERE [Name]='HDTPort'
25
26USE [GPOSDB]
27GO
28BEGIN DISTRIBUTED TRANSACTION
29--从本地数据库删除一条记录
30DELETE FROM [JOE].[GPOSDB].[DBO].[SystemPara]
31WHERE [Name]='HDTPort'
32--从远程数据库中删除一条记录
33DELETE FROM [GPOSDB].[dbo].[SystemPara]
34WHERE [Name]='HDTPort'
35COMMIT TRAN
36GO
37
38
39
40--个人尝试了下是由于在双向的sql server访问中采用了链式方式访问(LinkedServer方式),
41--遇到这种情况只需要将原来访问对方数据库的语句:
42--select  *  from  linkedServerA.dbo.table1
43--修改为:
44--select  *  from  dbo.table1即可。
45--标记下,以便以后解决。
参考地址:SQLSERVER2008分布式事务配置实现
1@Component
2@Slf4j
3public class RedissonManager {
4
5    private Config config = new Config();
6
7    private Redisson redisson = null;
8
9    public Redisson getRedisson() {
10        return redisson;
11    }
12
13    private static String redis1Ip = PropertiesUtil.getProperty("redis1.ip");
14    private static Integer redis1Port = Integer.parseInt(PropertiesUtil.getProperty("redis1.port"));
15    private static String redis2Ip = PropertiesUtil.getProperty("redis2.ip");
16    private static Integer redis2Port = Integer.parseInt(PropertiesUtil.getProperty("redis2.port"));
17
18    @PostConstruct
19    private void init(){
20        try {
21            config.useSingleServer().setAddress(new StringBuilder().append(redis1Ip).append(":").append(redis1Port).toString());
22
23            redisson = (Redisson) Redisson.create(config);
24
25            log.info("初始化Redisson结束");
26        } catch (Exception e) {
27            log.error("redisson init error",e);
28        }
29    }
30}
参考地址:spring schedule + redisson实现分布式系统任务调度
1import java.util.Collections;
2
3import org.springframework.data.redis.core.RedisTemplate;
4import org.springframework.data.redis.core.script.DefaultRedisScript;
5
6
7/**
8 * 使用redis构建分布式锁(使用lun语言)
9 * @author fangyuan
10 *
11 */
12public class RedisLock {
13    
14    private static final Long RELEASE_SUCCESS = 1L;
15
16    /**
17     * 尝试获取分布式锁
18     * @param redisTemplate Redis客户端
19     * @param lockKey 锁 redis key
20     * @param requestId 请求标识 redis value
21     * @param expireTime lock超期时间
22     * @return 是否获取成功
23     */
24    public static boolean tryGetDistributedLock(RedisTemplate redisTemplate , String lockKey, String requestId, int expireTime) {
25
26        String scriptText = "if redis.call('setNx',KEYS[1],ARGV[1]) == 1 then if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('expire',KEYS[1],ARGV[2]) else return 0 end else return 0 end";
27
28        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
29
30        redisScript.setResultType(Long.class);
31        redisScript.setScriptText(scriptText);
32
33        Long result = redisTemplate.execute(redisScript, Collections.singletonList(lockKey),requestId,String.valueOf(expireTime));
34
35        if(RELEASE_SUCCESS.equals(result)){
36            return true;
37        }
38        return false;
39    }
40    
41
42    /**
43     * 释放分布式锁
44     * @param redisTemplate Redis客户端
45     * @param lockKey46     * @param requestId 请求标识
47     * @return 是否释放成功
48     */
49    public static boolean releaseDistributedLock(RedisTemplate redisTemplate, String lockKey, String requestId) {
50
51        String scriptText = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
52
53        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
54
55        redisScript.setResultType(Long.class);
56        redisScript.setScriptText(scriptText);
57
58
59        Long result = redisTemplate.execute(redisScript, Collections.singletonList(lockKey), requestId);
60
61        if (RELEASE_SUCCESS.equals(result)) {
62            return true;
63        }
64        return false;
65
66    }
参考地址:springboot 使用RedisTemplate构建分布式锁
1public class RedissonManager {
2
3    private Config config = new Config();
4    private Redisson redisson = null;
5
6    public Redisson getRedisson() {
7        return redisson;
8    }
9
10    private static String redis1Ip = PropertiesUtil.getProperty("redis1.ip");
11    private static Integer redis1Port = Integer.parseInt(PropertiesUtil.getProperty("redis1.port"));
12    private static String redis2Ip = PropertiesUtil.getProperty("redis2.ip");
13    private static Integer redis2Port = Integer.parseInt(PropertiesUtil.getProperty("redis2.port"));
14
15    //在构造器完成之后执行init方法
16    @PostConstruct
17    private void init() {
18        try {
19            config.useSingleServer().setAddress(new StringBuilder().append(redis1Ip).append(":").append(redis1Port).toString());
20            redisson = (Redisson) Redisson.create(config);
21            log.info("初始化Redisson结束");
22        } catch (Exception e) {
23            log.error("redisson init error", e);
24        }
25    }
26
27}
参考地址:Tomcat集群与Redis分布式(十三)——Redisson框架及项目集成
1package com.mmall.common;
2
3import com.mmall.util.PropertiesUtil;
4import lombok.extern.slf4j.Slf4j;
5import org.redisson.Redisson;
6import org.redisson.config.Config;
7import org.springframework.stereotype.Component;
8
9import javax.annotation.PostConstruct;
10
11/**
12 * Created by geely
13 */
14@Component
15@Slf4j
16public class RedissonManager {
17
18    private Config config = new Config();
19
20    private Redisson redisson = null;
21
22    public Redisson getRedisson() {
23        return redisson;
24    }
25
26    private static String redis1Ip = PropertiesUtil.getProperty("redis1.ip");
27    private static Integer redis1Port = Integer.parseInt(PropertiesUtil.getProperty("redis1.port"));
28    private static String redis2Ip = PropertiesUtil.getProperty("redis2.ip");
29    private static Integer redis2Port = Integer.parseInt(PropertiesUtil.getProperty("redis2.port"));
30
31    @PostConstruct
32    private void init(){
33        try {
34            config.useSingleServer().setAddress(new StringBuilder().append(redis1Ip).append(":").append(redis1Port).toString());
35
36            redisson = (Redisson) Redisson.create(config);
37
38            log.info("初始化Redisson结束");
39        } catch (Exception e) {
40            log.error("redisson init error",e);
41        }
42    }
43
44}
参考地址:2018.8.2 java电商从1到2--chapter15~16 SpringSchedule+Redission实现分布式任务调度
1// 1.分布式锁唯一标识,采用UUID
2String lockKeyId = UUID.randomUUID().toString();
3
4// 2.获取锁,设置锁标识
5long timeout = 5L;
6boolean flag = distributeLockUtils.lock(productId, lockKeyId, timeout);
7
8// 3.延长锁失效时间
9distributeLockUtils.extendExpTime(productId, timeout);
10
11// 4.判断锁是否有效
12distributeLockUtils.checkLock(flag);
13
14// 5.获取锁成功后,执行业务代码
15// 业务代码开始执行标志
16System.out.println("request start " + "[" + Thread.currentThread().getName() + "]");
17
18try { //业务代码
19	**************************
20	**************************
21	**************************
22    // 测试:
23    // 模拟业务代码处理时间为 10s,但是将锁超时时间设置为 5 秒,
24    // 即模拟在业务代码还没有执行完时锁失效,第二个请求线程进来时的场景
25    try {
26        Thread.sleep(10000);
27    } catch (InterruptedException e) {
28        e.printStackTrace();
29    }
30
31    // 业务代码运行结束标志
32    System.out.println("request end" + " [" + Thread.currentThread().getName() + "]");
33} finally {
34    // 6.释放锁
35    distributeLockUtils.unLock(productId, lockKeyId);
36}
参考地址:springboot分布式锁
1/**
2 * Description: 分布式事务执行模板
3 * <p>
4 *     1. 先执行各个服务块业务
5 *     2. 执行结束通过confirm判定执行结果, 如果失败则进行取消(回滚操作)
6 *     3. 如果执行服务模块发生异常,则判定后进行
7 * </p>
8 * User: zhouzhou
9 * Date: 2018-08-27
10 * Time: 10:27
11 */
12public class TccTemplate {
13
14    private static final Logger logger = LoggerFactory.getLogger(TccCallBack.class);
15
16    /**
17     *  分布式事务模板
18     * @param tccCallBack 分布式事务执行回调
19     * @param method 当前方法名(封装参数, 可方便捞取数据)
20     */
21    public static <T> TccResult process(TccCallBack tccCallBack, String method, T t) {
22        // 返回一个消息用于
23        TccResult tccResult = new TccResult();
24        String msg = "";
25        try {
26            // 执行主业务
27            tccCallBack.tryExecute();
28            // 进行确认执行结果,如果结果是false,则执行回滚操作
29            boolean judge = tccCallBack.judge();
30            if (judge) {
31                tccResult.setStatus(true);
32                msg = String.format("分布式事务{%s}执行成功", method);
33                logger.info(msg);
34                // 执行确认操作
35                tccCallBack.confirm();
36            } else {
37                tccResult.setStatus(false);
38                msg = String.format("分布式事务{%s}执行失败,进行回滚操作", method);
39                logger.warn(msg);
40                tccCallBack.cancel();
41            }
42        } catch (Exception e) {
43            // 主流程发生异常, 则直接执行回滚操作
44            tccResult.setStatus(false);
45            msg = String.format("分布式事务{%s}执行发生异常{%s},进行回滚操作", method,e.getMessage());
46            logger.warn(String.format("分布式事务{%s}执行发生异常,进行回滚操作", method), e);
47            tccCallBack.cancel();
48        }finally {
49            // 返回结果Result
50            tccResult.setMsg(msg);
51            return tccResult;
52        }
53
54
55    }
56}
参考地址:分布式事务之TCC模式实现 TCCJ 变种模式代码
1#生成分布式ID(按时间戳区分datacenterId和workerId)
2/service/id
3
4#生成分布式ID(按dwId[0-1023])
5/service/id/{dwId}
6
7#生成分布式ID(按datacenterId[0-31]和workerId[0-31])
8/service/id/{datacenterId}/{workerId}
9
10#批量生成分布式ID(按时间戳区分datacenterId和workerId)
11/service/id/batch/{count}
12
13#批量生成分布式ID(按dwId[0-1023])
14/service/id/batch/{dwId}/{count}
15
16#批量生成分布式ID(按datacenterId[0-31]和workerId[0-31])
17/service/id/batch/{datacenterId}/{workerId}/{count}
参考地址:spring boot - cloud (十六) 分布式ID生成服务
1/**
2	 * 尝试获取分布式锁
3	 * @param jedis Redis客户端
4	 * @param lockKey5	 * @param requestId 请求标识
6	 * @param expireTime 超期时间
7	 * @return 是否获取成功
8	 */
9	public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
10
11		String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
12
13		if (LOCK_SUCCESS.equals(result)) {
14			return true;
15		}
16		return false;
17	}
参考地址:分布式锁--Redis小试牛刀
1package io.github.hengyunabc.redis;
2
3import java.text.SimpleDateFormat;
4import java.util.Date;
5
6
7public class Test {
8
9	public static void main(String[] args) {
10		long buildId = buildId(1565165536640L, 53, 1);
11		System.out.println("分布式id是:"+buildId);
12		long buildIdLast = buildId(1565165536640L, 53, 1023);
13		System.out.println("分布式id是:"+buildIdLast);
14	}
15	
16	public static long buildId(long miliSecond, long shardId, long seq) {
17		return (miliSecond << (12 + 10)) + (shardId << 10) + seq;
18	}
19
20
21}
22public class Test {
23
24	public static void main(String[] args) {
25		long buildId = buildId(1565165536640L, 53, 1);
26		System.out.println("分布式id是:"+buildId);
27		long buildIdLast = buildId(1565165536640L, 53, 1023);
28		System.out.println("分布式id是:"+buildIdLast);
29	}
30	
31	public static long buildId(long miliSecond, long shardId, long seq) {
32		return (miliSecond << (12 + 10)) + (shardId << 10) + seq;
33	}
34
35
36}
参考地址:分布式唯一ID生成系列(4)——Redis集群实现的分布式ID适合做分布式ID吗

代码交流 2021