分布式分段锁解决数据竞争问题

一、介绍

分布式分段锁是在分布式环境下,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。

在数据存储层面对单表订单分片,集群中使用分段锁技术路由至指定订单分片,各线程按顺序轮询负载均衡策略获取分段锁,

支持集群,多线程,各台机器可以在各分片获取订单,以达到数据被公平性竞争,重量级锁,集群机器数<=分片数,以免造成一直获取不到数据的极端情况

二、具体方案

分段锁集群架构图

锁获取流程图

锁和数据分片简单映射关系

1.锁中心

这里使用redis中的命令set(key,value,‘NX‘,‘EX‘,seconds)实现锁机制,用来在分布式环境中获取锁

key:唯一对应db中一区间,分段锁

value:分片编号,例如shard=1

NX:setnx命令

EX:单位秒

seconds:秒数值

2.集群

应用服务器(rpmatch)集群,集群数量<=provider中分区数量,可以暂时定为2台机器

  • 缓存

在配置中的信息使用CopyOnWriteArrayList集合,存储各分片的分段锁,

分段锁,即segment,例如:rpmatch:cluster:order:segment:0表示订单表中分片shard=0的订单锁,rpmatch:cluster:order:segment:1表示订单表中区间shard=1的订单锁,共计两把锁

缓存数据:分片是否有数据,所有分片是否有数据,

偏移量:本地缓存保存上一次竞争锁的偏移量,

  • 获取锁

rpmatch循环获取集合的分段锁信息, 从本地拿到锁令牌,按次序去锁中心获取锁,默认从偏移量0开始

情况一:假如未获取到锁,则判断下一把锁,redis命令rt为0.02ms左右,自旋1ms,假如都没有获取到数据和锁则进入休眠,休眠2s,

在过程中记录线程上次获取锁偏移量和锁对应的分片是否有数据,假如不存在数据则标记为false,那么线程循环时要先判断它是否为false,假如为false则不需要轮询它,false过期时间为2s

情况二:假如获取锁异常或者锁中心(redis)宕机,则把债权抛入等待队列,此时源队列也无法消费新标或者债转,此情况需要做异常监控

3.provider

订单提供者,订单表增加shard字段,把订单数据切8个分片,分片编号0,1...8;

  • 先手工初始化分片数据
  • 在插入源头需要孙伟那边把shard值插入
  • 可以动态调整shard值

4.配置中心

目前使用fiona来做配置,存储着锁等信息,shard数量发生变化,则可以通过配置来修改

原有代码需要改造的有,等待队列需要全局控制消费,避免数据竞争

问题:

1:对债转而言,在区间数据内,获取到的订单并非是最精准的,后续通过改进匹配规则可以避免

发布

1.fiona配置

[{
"segmentLock": "rpmatch:cluster:order:segment:0",
"shardIdList": [0, 1, 2, 3]
}, {
"segmentLock": "rpmatch:cluster:order:segment:1",
"shardIdList": [4, 5, 6, 7]
}]

2.db

db数据统计

总数:2719749

Mod%8=1   339975

Mod%8=2.  339978

Mod%8=3   339977

Mod%8=4   339985

Mod%8=5   339978

Mod%8=6   339979

Mod%8=7   339983

Mod%8=0   339977

增加字段

alter table T_RpPlan_OrderAccount add COLUMN ShardId int not null default 0 comment ‘单表逻辑分片id‘;

更新表数据

update T_RpPlan_OrderAccount set shardid=1 where autoid%8=1;
update T_RpPlan_OrderAccount set shardid=2 where autoid%8=2;
update T_RpPlan_OrderAccount set shardid=3 where autoid%8=3;
update T_RpPlan_OrderAccount set shardid=4 where autoid%8=4;
update T_RpPlan_OrderAccount set shardid=5 where autoid%8=5;
update T_RpPlan_OrderAccount set shardid=6 where autoid%8=6;
update T_RpPlan_OrderAccount set shardid=7 where autoid%8=7;

原文地址:https://www.cnblogs.com/javaConcurrent/p/9195938.html

时间: 2024-11-11 13:10:54

分布式分段锁解决数据竞争问题的相关文章

python-多线程同步中创建互斥锁解决资源竞争的问题

import threadingimport time # 定义一个全局变量g_num = 0 def test1(num): global g_num for i in range(num): g_num += 1 print('-------in test1 g_num={}'.format(g_num)) def test2(num): global g_num for i in range(num): g_num += 1 print('-------in test1 g_num={}'

JVM+分布式+算法+锁+MQ+微服务+数据库 面试题

JAVA基础 1.JAVA中的几种基本数据类型是什么,各自占用多少字节 Java基本数据类型有8种: 名词解释: bit:位,计算机存储数据的最小单位,二进制数中的一个 位数. byte:字节,计算机存储数据的基本单位,一个字节由8位二进制数组成.通常一个汉字占两个字节. 2.String类能被继承吗,为什么. 不可以,因为String类有final修饰符,而final修饰的类是不能被继承的,实现细节不允许改变. 关于final修饰符,介绍如下: 根据程序上下文环境,Java关键字final有“

Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等(转)

Java 中15种锁的介绍 在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容如下: 公平锁 / 非公平锁 可重入锁 / 不可重入锁 独享锁 / 共享锁 互斥锁 / 读写锁 乐观锁 / 悲观锁 分段锁 偏向锁 / 轻量级锁 / 重量级锁 自旋锁 上面是很多锁的名词,这些分类并不是全是指锁的状态,有的指锁的特性,有的指锁的设计,下面总结的内容是对每个锁的名词进行一定的解释. 公平锁 / 非公平锁 公平锁 公平锁是指多个线程按照申请锁的顺序来获取锁. 非公

基于(Redis | Memcache)实现分布式互斥锁

设计一个缓存系统,不得不要考虑的问题就是:缓存穿透.缓存击穿与失效时的雪崩效应. 缓存击穿 缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义.在流量大时,可能DB就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞. 解决方案 有很多种方法可以有效地解决缓存穿透问题,最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap

基于Zookeeper实现的分布式互斥锁 - InterProcessMutex

Curator是ZooKeeper的一个客户端框架,其中封装了分布式互斥锁的实现,最为常用的是InterProcessMutex,本文将对其进行代码剖析 简介 InterProcessMutex基于Zookeeper实现了分布式的公平可重入互斥锁,类似于单个JVM进程内的ReentrantLock(fair=true) 构造函数 1234567891011121314151617 // 最常用public InterProcessMutex(CuratorFramework client, St

【教程分享】基于Greenplum Hadoop分布式平台的大数据解决方案及商业应用案例剖析

基于Greenplum Hadoop分布式平台的大数据解决方案及商业应用案例剖析 课程讲师:迪伦 课程分类:Java 适合人群:高级 课时数量:96课时 用到技术:MapReduce.HDFS.Map-Reduce.Hive.Sqoop 涉及项目:Greenplum Hadoop大数据分析平台 更新程度:完毕 对这个课程有兴趣的朋友可以加我的QQ2059055336和我联系 下载地址:链接:   pan.baidu.com/s/1nthYpKH 密码: niyi 随着云计算.大数据迅速发展,亟需

乐观锁与悲观锁——解决并发问题(转)

引言 为什么需要锁(并发控制)? 在多用户环境中,在同一时间可能会有多个用户更新相同的记录,这会产生冲突.这就是著名的并发性问题. 典型的冲突有: 丢失更新:一个事务的更新覆盖了其它事务的更新结果,就是所谓的更新丢失.例如:用户A把值从6改为2,用户B把值从2改为6,则用户A丢失了他的更新. 脏读:当一个事务读取其它完成一半事务的记录时,就会发生脏读取.例如:用户A,B看到的值都是6,用户B把值改为2,用户A读到的值仍为6. 为了解决这些并发带来的问题. 我们需要引入并发控制机制. 并发控制机制

Hadoop分布式平台的大数据解决方案

讲师:迪伦 对这个课程有兴趣的可以加我qq2059055336联系我 1 课程背景 GREENPLUM适用场景 Greenplum的架构采用了MPP(大规模并行处理).在 MPP 系统中,每个 SMP 节点也可以运行自己的操作系统.数据库等,它的特点主要就是查询速度快,数据装载速度快,批量DML处理快.而且性能可以随着硬件的添加,呈线性增加,拥有非常良好的可扩展性.因此,它主要适用于面向分析的应用.比如构建企业级ODS/EDW,或者数据集市等等. GREENPLUM运行的平台 GREENPLUM

乐观锁与悲观锁——解决并发问题

悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁.传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁. 乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制.乐观锁适用于