基于Redisson实现任务的多实例竞争控制与重试机制
在分布式系统中,多个实例可能会同时尝试执行某些任务,例如监听数据库变更、执行定时任务等。为了避免任务的重复执行,我们通常需要一种竞争控制机制,以确保只有一个实例能够执行任务,同时在失败时支持自动重试。本文介绍一种基于 Redis 分布式锁的解决方案,结合 Redisson 和 MongoDB Change Streams,实现任务的多实例竞争控制与自动重试。
方案背景在 矿小圈 中,需要从 MongoDB 同步数据到 Elasticsearch,以实现高效的搜索功能。由于该项目是 微服务架构,但 MongoDB Change Streams 监听只能由一个实例执行,因此需要一种机制来确保在多个实例部署的情况下,只有一个实例 监听 MongoDB 的变更,同时为了 避免单实例负载过高,需要 定期释放锁,让其他实例有机会获取锁并执行任务。这就形成了 多实例竞争唯一任务的机制。
方案概述本方案基于 Redis 的分布式锁来确保 多个实例竞争一个任务,即 MongoDB Change Streams 监听。
单实例监听:同一时间只能有一个实例在监听 MongoDB。
定期释放锁:避免某个实例 ...
SpringBoot多种配置导入方式
在 Spring Boot 应用开发中,合理管理和加载配置是非常重要的。以往,我们通常使用 bootstrap.yaml/properties 方式来提前导入外部配置。但在 Spring Boot 2.4 及以上版本中,引入了 spring.config.import 机制,提供了更灵活的配置加载方式。
1. 传统的 bootstrap.yaml/properties 方式(Spring Boot 2.3 及以下)在 Spring Boot 2.3 及以下版本,bootstrap.yaml(或 bootstrap.properties)主要用于加载外部配置,例如 Nacos。这种方式通常用于 Spring Cloud 组件初始化阶段。
示例:
1234567891011121314# bootstrap.yamlspring: cloud: nacos: config: name: test.yml group: DEFAULT_GROUP server-addr: 127.0.0.1:8848 extensio ...
基于Redis分布式锁实现分布式定时任务调度
前情提要众所不周知:矿小圈使用Sa-Token进行鉴权服务,为了防止”黑客”绕过Gateway网关直接访问内部微服务,使用Same-Token进行网关请求鉴定,拿到相同的Same-Token才能请求非网关服务
为了保证Same-Token不被”非法分子”破解,Same-Token采用定时刷新策略,每隔10分钟就会更新一次,因此,想要获取Same-Token并不是一件容易的事情
BUG现形单例模式下,使用SpringBoot的@Scheduled是一件非常”爽”的事情,如下很容易定义了一个定时任务每隔10分钟刷新一次Same-Token
1234@Scheduled(cron = "0 0/10 * * * ?")public void refreshToken() { SaSameUtil.refreshToken();}
但是,在分布式、微服务场景下,同一个类型的服务可能会部署多个实例以达到高可用,于此情景下,再直接使用@Scheduled会导致同一个任务被重复多次调用
解决方案如果我们不希望同一任务重复调用,就要用到分布式任务调度技术,市面 ...
MongoDB踩坑日志
搞了老长时间,MongoDB真的我哭死🥹
前言想着MongoDB不是支持事务了嘛,我就想在服务里面加上MongoDB的事务功能,然后百度到使用MongoDB事务,必须要开启副本集才行,然后顺藤摸瓜,就跑去弄了三个副本集,以下主要是配置副本集的踩坑日志
踩坑一:副本集鉴权MongoDB如果配置用户名密码鉴权,就必须要在各个服务之间加上公用的keyfile
自己生成一个随机的keyfile
12openssl rand -base64 756 > <path-to-keyfile>chmod 400 <path-to-keyfile>
在conf中加入如下配置
123security: authorization: enabled # 启用身份验证 keyFile: <path-to-keyfile>
踩坑二:不能获取密钥文件报错如下:
1{"error":"Location5579201: Unable to acquire security key[s]"}
这是因为 ...
音乐专赏 - Let Her Go
Let Her Go - Passenger
单曲「Let Her Go」
MV | Youtube
window.onload = function() {
var articleContainer = document.getElementById('article-container');
var iframeContainer = document.getElementById('iframe-container');
var containerWidth = articleContainer.offsetWidth;
var aspectRatio = 16 / 9;
var iframe = document.createElement('iframe');
iframe.src = "https://www.youtube.com/embed/HTcL9WkB_wg?si=NB0m78Q2D-VF1WwE";
iframe.setAttribute("frameborder ...
数据结构作业3
此作业为某大学数据结构作业3,点击下方按钮,输入密码后可查看答案
问题 A: 无向图的深度优先搜索题目描述已知一个无向图G的顶点和边,顶点从0依次编号,现在需要深度优先搜索,访问任一邻接顶点时编号小的顶点优先,请编程输出图G的深度优先搜索序列。
输入第一行是整数m和n(1<m,n<100),分别代表顶点数和边数。后边n行,每行2个数,分别表示一个边的两个顶点。
输出该图从0号顶点开始的深度优先搜索序列。
样例输入1234565 50 12 01 31 44 2
样例输出10 1 3 4 2
参考答案查看答案
问题 B: 最小堆的形成题目描述现在给你n个结点的完全二叉树数组存储序列,请编程调整为最小堆,并输出相应最小堆的存储序列。
输入第一行是n,第二行是n个结点的完全二叉树数组存储序列。
输出输出相应最小堆的存储序列。
样例输入12853 17 78 23 45 65 87 9
样例输出19 17 65 23 45 78 87 53
参考答案查看答案
问题 C: 折半查找的次数题目描述给你一个无重复数的有序序列,如果采用折半查找的方式,对于给定的数,需要比较 ...
数据结构作业2
此作业为某大学数据结构作业2,答案为我当时所写,仅供学习和参考
问题 A: 统计回文子串题目描述现在给你一个字符串S,请你计算S中有多少连续子串是回文串。
输入输入包含多组测试数据。每组输入是一个非空字符串,长度不超过5000。
输出对于每组输入,输出回文子串的个数。
样例输入12abaaa
样例输出1243
参考答案查看答案
123456789101112131415161718192021222324252627282930313233#include <iostream>#include <bits/stdc++.h>using namespace std;int main() { string s; while (getline(cin, s)) { int ans=0; for (int i = 0; i < s.length(); ++i) { int j=i,k=i; while (j>=0 &&am ...
数据结构作业1
此作业为某大学数据结构作业1,答案为我当时所写,仅供学习和参考
问题 A: 查成绩题目描述期末考试结束后,数学老师给出了班里同学们的数学成绩,为了快速查成绩,请编程帮助查成绩。
输入第一行为N(N<1000)表示班级人数,第一行后N行,每行两个部分,一个是学号(符号最多8个),一个是成绩(整数)。最后一行是要查找成绩同学的学号。
输出输出要查找同学的学号。
样例输入12342001 90002 95002
样例输出195
参考答案查看答案
12345678910111213141516171819202122#include <iostream>using namespace std;int main() { int n; cin >> n; int num[n]; int score[n]; for (int i = 0; i < n; ++i) { cin >> num[i] >> score[i]; } int find ...
一款完备的SpringBoot博客平台
一. 功能
用户注册与登录(JWT令牌单点登录)、注销
修改用户信息(管理员有更多权限)
发表文章(有点踩)
发表评论(可回复)
上传文件
二. 使用工具
Springboot
Mybatis
Redis
Mysql
Leancloud
Postman(其他亦可)
三. Mysql数据库表结构如下:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283create table user( id varchar(255) comment '用户的唯一标识ID' primary key, username varchar(20) unique not n ...
Java多线程补充(转)
1 线程状态1.1 状态介绍当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。线程对象在不同的时期有不同的状态。那么Java中的线程存在哪几种状态呢?Java中的线程
状态被定义在了java.lang.Thread.State枚举类中,State枚举类的源码如下:
123456789101112131415161718192021222324252627282930public class Thread { public enum State { /* 新建 */ NEW , /* 可运行状态 */ RUNNABLE , /* 阻塞状态 */ BLOCKED , /* 无限等待状态 */ WAITING , /* 计时等待 */ TIMED_WAITING , /* 终止 */ TERMINATED; } / ...