自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(134)
  • 收藏
  • 关注

原创 全量数据同步:多线程性能优化

公司在做客服迁移迁移系统,下来的需求就是将公司的用户信息全量同步到那边的数据库,总数据量大概300w+,将无效数据过滤掉以及不需要进行同步的用户(手机号码不存在),剩下大概200w。开始采用的方案就是单线程分页查询,每批100条的数据量,定时任务写好放到测试环境里面跑了一下,预估大概每天能跑50w的数据量(两天反正很难完成任务)。另外就是核心线程数的设置,我在我自己机器上测,核心数是4,我设置线程数10速度是比较快的,和单线程相比较,大概能提升2.5倍,查询大概10分钟(仅仅是查询)。

2024-07-22 10:10:18 181

原创 测试数据生成:MySQL存储过程快速添加300w条数据

需要自己搞测试数据做测试,我测试总共用了不到两个小时,如果快的话,可能一个多小时就搞定了。表名和插入格式根据自己的稍微改动一下。

2024-07-22 09:23:06 26

原创 实际业务场景中大量if..else的优化:ApplicationContextAware的应用

如果操作的表不再改变这样,好像也不是不行,但是如果突然有其他表也需要做数据同步到BI库了,那么代码每次都需要改变,就会有大量的if…而这样的代码也不符合公司开发规范。在公司做一个Canal数据同步的时候,我们需要根据CanalEntry中传过来的表名,获取到相应的实例,然后调用相应的新增,更新删除数据的方法,如果能在spring初始化好Bean之后提前把表名和实例的映射放到map中,然后用到的时候直接get,就避免了大量if…比较直观的是通过if…当前的问题是如何根据表名获取到相应的实例呢?

2024-07-21 18:45:46 406

原创 [收件箱功能]如何使用Zset实现滚动分页?

假设在t1 时刻,我们去读取第一页,此时page = 1 ,size = 5 ,那么我们拿到的就是10~6 这几条记录,假设现在t2时候又发布了一条记录,此时t3 时刻,我们来读取第二页,读取第二页传入的参数是page=2 ,size=5 ,那么此时读取到的第二页实际上是从6 开始,然后是6~2 ,那么我们就读取到了重复的数据,所以feed流的分页,不能采用原始方案来做。2、我们需要找到与上一次查询相同的查询个数作为偏移量,下次查询时,跳过这些查询过的数据,拿到我们需要的数据。

2024-07-21 08:28:49 226

原创 [用户签到]如何使用BitMap实现签到功能?

我们只需要让得到的10进制数字和1做与运算就可以了,因为1只有遇见1 才是1,其他数字都是0 ,我们把签到结果和1进行与操作,每与一次,就把签到结果向右移动一位,依次内推,我们就能完成逐个遍历的效果了。假设今天是10号,那么我们就可以从当前月的第一天开始,获得到当前这一天的位数,是10号,那么就是10位,去拿这段时间的数据,就能拿到所有的数据了,那么这10天里边签到了多少次呢?用户一次签到,就是一条记录,假如有1000万用户,平均每人每年签到次数为10次,则这张表一年的数据量为 1亿条。

2024-07-20 21:06:16 1097

原创 [点赞排行榜]关于IN字段不按照顺序返回问题

无论因为何种问题,导致我们无法按照有规则的字段进行排序返回结果,只能通过in中顺序来返回的结果,我们只能使用自定义排序,MySQL中ORDER BY的field()函数,可以用来对SQL中查询结果集进行指定顺序排序。子句中指定的顺序不同的顺序返回。

2024-07-20 17:51:12 515

原创 分布式锁-redisson锁重试和WatchDog机制

接下来会有一个条件分支,因为lock方法有重载方法,一个是带参数,一个是不带参数,如果带带参数传入的值是-1,如果传入参数,则leaseTime是他本身,所以如果传入了参数,此时leaseTime!因为锁的失效时间是30s,当10s之后,此时这个timeTask 就触发了,他就去进行续约,把当前这把锁续约成30s,如果操作成功,那么此时就会递归调用自己,再重新设置一个timeTask(),于是再过10s后又再设置一个timerTask,完成不停的续约。TimerTask() {},参数2 ,参数3 )

2024-07-19 20:00:49 346

原创 Redis之五种数据类型

对⼀个内部表示成long型的string执行append, setbit, getrange这些命令,针对的仍然是string的值(即⼗进制表示的字符串),而不是针对内部表⽰的long型进⾏操作。因此,在这些命令的实现中,会把long型先转成字符串再进行相应的操作。String的内部存储结构⼀般是sds(Simple Dynamic String,可以动态扩展内存),但是如果⼀个String类型的value的值是数字,那么Redis内部会把它转成long类型来存储,从⽽减少内存的使用。

2024-07-18 08:26:28 921

原创 Redis数据结构-Dict

类似java的HashTable,底层是数组加链表来解决哈希冲突Dict包含两个哈希表,ht[0]平常用,ht[1]用来rehash当LoadFactor大于5或者LoadFactor大于1并且没有子进程任务时,Dict扩容当LoadFactor小于0.1时,Dict收缩扩容大小为第一个大于等于used + 1的2^n收缩大小为第一个大于等于used 的2^nDict采用渐进式rehash,每次访问Dict时执行一次rehash。

2024-07-18 08:12:11 667

原创 Redis数据结构-ZipList

ZipList中所有存储长度的数值均采用小端字节序,即低位字节在前,高位字节在后。如果前一节点的长度大于等于254字节,则采用5个字节来保存这个长度值,第一个字节为0xfe,后四个字节才是真实长度数据。如果前一节点的长度大于254字节,则采用5个字节来保存这个长度值,第一个字节为0xfe,后四个字节才是真实长度数据。encoding:编码属性,记录content的数据类型(字符串还是整数)以及长度,占用1个、2个或5个字节。previous_entry_length:前一节点的长度,占1个或5个字节。

2024-07-17 21:51:59 551

原创 Redis数据结构-SDS

(1)获取长度的时候需要运算(strlen函数的底层实现通常是通过遍历字符串,直到遇到空字符(null terminator,即 ‘\0’)为止来计算字符串的长度的。时间复杂度是O(n))相较于C中的字符串,(1)可以直接从len字段中直接得到他的长度 (2)可以动态扩容 (3)是二进制安全的,SDS并没有用’\0’作为结束符,而是看的len,即使中间出现了’\0’,也会继续往后找。在redis当中,key都是字符串类型,value要么是字符串要么是字符串的集合,所以字符串类型是redis中最常用的类型。

2024-07-17 19:28:07 391

原创 一条SQL查询语句是如何执行的?

以我们的查询语句为例,因为没索引,就从第一条记录开始遍历,如果发现c=10,就把他存在结果集里面,如果不是10,就接着往下依次判断,直到最后一条记录,最后把结果集返回给客户端。这个值就是在执行器每次调用引擎获取数据行的时候累加的。以上面这条SQL为例,一种方案是先到t1里面查c=10的,然后再去t2里面查,另一种方案是先到t2里面查d=20的再到t1里面查c=10的。Server层包含连接器,分析器,优化器,执行器等,这和数据库使用的是哪种存储引擎没关系,是跨存储引擎的,核心功能都包含在这一层了。

2024-07-10 21:02:50 281

原创 kafka.common.KafkaException: Socket server failed to bind to xx:9092

然后重新启动,检查进程是否存在ps -aux | grep kafka。修改config下的server.properties,添加。部署分布式集群的时候遇到的错误。

2024-07-10 08:50:15 426

原创 主线程结束子线程不再执行

起因是在做分布式锁的时候,我在单元测试里面创建了10个线程,然后启动。每个线程都会在run方法打印内容,但是测试结果居然什么都没输出。就很纳闷,然后推测可能是主线程执行完了子线程直接结束了,果不其然,在加上thread.join()得到了预期结果。thread.join()是当前线程,也就是main线程要等到thread线程执行完成才能继续往后执行。如果是写在main方法是不存在这个问题的,但是单测的确存在这个问题。

2024-07-07 23:43:46 282 3

原创 canal数据增量同步解决方案

待填坑。

2024-06-20 18:58:33 115

原创 git生成密钥(免密)

当系统提示你“Enter a file in which to save the key”,直接按回车键接受默认位置。将生成的密钥放到github/gitee/gitlab,以后git push代码的时候不再需要每次都输入密码了。在提示你输入密码的时候,直接按回车键,生成没有密码的SSH密钥。参数后面跟的是你的邮箱地址,通常用于标识这个密钥。打开Git Bash。

2024-05-29 16:55:53 441

原创 Redis指令汇总(二)

第一行可以看到redis版本信息,后面还有操作系统(我这里用的是windows,所以是os:Windows),进程id,执行程序的位置,配置文件的位置。当 key 存在但没有设置剩余生存时间时,返回 -1。否则,以秒为单位,返回 key 的剩余生存时间。在 Redis 2.8 以前,当 key 不存在,或者 key 没有设置剩余生存时间时,命令都返回 -1。在本例中,我们移除了key的过期时间,使其永久有效(ttl返回-1代表这个key永久有效)7.randomkey随机返回key空间的一个key。

2024-05-19 10:37:29 161

原创 一条sql语句在mysql中是怎么执行的

连接器主要和身份认证和权限相关的功能相关,就好比一个级别很高的门卫一样。主要负责用户登录数据库,进行用户的身份认证,包括校验账户密码,权限等操作,如果用户账户密码已通过,连接器会到权限表中查询该用户的所有权限,之后在这个连接里的权限逻辑判断都是会依赖此时读取到的权限数据,也就是说,后续只要这个连接不断开,即时管理员修改了该用户的权限,该用户也是不受影响的。

2024-05-17 14:10:29 695

原创 BM11 链表相加(二)

例如:链表 1 为 9->3->7,链表 2 为 6->3,最后生成新的结果链表为 1->0->0->0。数据范围:0≤𝑛,𝑚≤10000000≤n,m≤1000000,链表任意值 0≤𝑣𝑎𝑙≤90≤val≤9。假设链表中每一个节点的值都在 0 - 9 之间,那么链表整体就可以代表一个整数。要求:空间复杂度 𝑂(𝑛)O(n),时间复杂度 𝑂(𝑛)O(n)给定两个这种链表,请生成代表两个整数相加值的结果链表。输入:[9,3,7],[6,3]返回值:{1,0,0,0}输入:[0],[6,3]

2024-05-14 14:53:53 380

原创 BM10 两个链表的第一个公共结点

输入分为是3段,第一段是第一个链表的非公共部分,第二段是第二个链表的非公共部分,第三段是第一个链表和第二个链表的公共部分。后台会将这3个参数组装为两个链表,并将这两个链表对应的头节点传入到函数FindFirstCommonNode里面,用户得到的输入只有pHead1和pHead2。第一个参数{1,2,3}代表是第一个链表非公共部分,第二个参数{4,5}代表是第二个链表非公共部分,最后的{6,7}表示的是2个链表的公共部分。输入:{1,2,3},{4,5},{6,7}输入:{1},{2,3},{}

2024-05-14 14:21:39 450

原创 BM8 链表中倒数最后k个结点

过于简单,不再赘述。

2024-05-12 22:59:18 255

原创 BM7 链表中环的入口结点(快慢指针模板题)

输入分为2段,第一段是入环前的链表部分,第二段是链表环的部分,后台会根据第二段是否为空将这两段组装成一个无环或者有环单链表。思路:建立在上一道基础上,如果已知成环,慢指针移动到链表头部,快慢指针以1的步长去移动,直到两者相遇,有环必相遇。数据范围: 𝑛≤10000n≤10000,1<=结点值<=100001<=结点值<=10000。给一个长度为n链表,若其中包含环,请找出该链表的环的入口结点,否则,返回null。可以看到环的入口结点的结点值为3,所以返回结点值为3的结点。

2024-05-12 22:20:34 321

原创 BM6 判断链表中是否有环(快慢指针模板题)

输入分为两部分,第一部分为链表,第二部分代表是否有环,然后将组成的head头结点传入到函数里面。-1代表无环,其它的数字代表有环,这些参数解释仅仅是为了方便读者自测调试。实际在编程时读入的是链表的头节点。数据范围:链表长度 0≤𝑛≤100000≤n≤10000,链表中任意节点的值满足 ∣𝑣𝑎𝑙∣<=100000∣val∣<=100000。可以看出环的入口结点为从头结点开始的第1个结点(注:头结点为第0个结点),所以输出true。要求:空间复杂度 𝑂(1)O(1),时间复杂度 𝑂(𝑛)O(n)

2024-05-12 21:10:25 152

原创 BM5 合并k个已排序的链表

数据范围:节点总数 0≤𝑛≤50000≤n≤5000,每个节点的val满足 ∣𝑣𝑎𝑙∣<=1000∣val∣<=1000。需要借助BM4写的代码,看我上一篇博客。然后从左向右每两个链表之间一一合并,得到最终结果。合并 k 个升序的链表并将结果作为一个升序的链表返回其头节点。要求:时间复杂度 𝑂(𝑛𝑙𝑜𝑔𝑛)O(nlogn)

2024-05-12 20:39:31 175

原创 BM4 合并两个排序的链表

【代码】BM4 合并两个排序的链表。

2024-05-12 17:12:55 194

原创 手写阻塞队列(Condition)

自己实现阻塞队列的话可以采用Object下的wait和notify方法,也可以使用Lock锁提供的Condition来实现,本文就是自己手撸的一个简单的阻塞队列,部分借鉴了JDK的源码ArrayBlockingQueue类。1.BlockingQueue接口。2.数组方式实现阻塞队列。

2024-05-12 12:05:46 737

原创 责任链模式案例

请你设计一个员工休假审批流程,当员工的休假天数

2024-05-09 17:55:59 270

原创 LCR 062. 实现 Trie (前缀树)

更具体地说,如果我们在前缀树中插入一个字符串 S,我们要从根节点开始。我们将根据 S[0](S中的第一个字符),选择一个子节点或添加一个新的子节点。末端节点将是表示字符串 S 的节点。当我们在二叉搜索树中插入目标值时,在每个节点中,我们都需要根据 节点值 和 目标值 之间的关系,来确定目标值需要去往哪个子节点。同样地,当我们向前缀树中插入一个目标值时,我们也需要根据插入的 目标值 来决定我们的路径。每一个节点会有多个子节点,通往不同子节点的路径上有着不同的字符。子节点代表的字符串是由节点本身的。

2024-05-09 16:07:34 236

原创 Mapper代理逻辑模拟(自己留存)

【代码】Mapper代理逻辑模拟(自己留存)

2024-05-09 12:07:30 264

原创 多线程交替打印ABC(共享变量)

注意如果不满足条件要及时让出CPU,防止陷入死循环。

2024-05-09 09:46:22 223

原创 Countdown控制线程同时开始执行

不是同时启动的,但是线程都会阻塞在latch.await这里,直到最后一层循环,latch.countdown所有的线程被唤醒开始执行。

2024-05-09 09:11:47 116

原创 Future计算某盘符文件夹数量

------------------------------------------手动分割线-------------------------------------------------任务没有执行完,会阻塞到get方法,只有执行完返回结果,才会解除阻塞往下执行。计算前20个文件夹中文件数量。

2024-05-08 23:40:19 204

原创 场景:因异常未正确处理导致OOM内存泄漏

本文模拟一个项目调优的场景,topic如标题所言,异常处理不当导致OOM内存泄漏。

2024-05-05 20:56:46 183

原创 线程池和CountDownLatch搭配使用

在本人所从事的项目中就有类似的情况,因为我们使用的图片服务只提供了获取单个图片的功能,而每次获取图片的时间不等,一般都需要1.5s~2s。场景一:CountDownLatch 非常适合于对任务进行拆分,使其并行执行,比如某个任务执行2s,其对数据的请求可以分为五个部分,那么就可以将这个任务拆分为5个子任务,分别交由五个线程执行,执行完成之后再由主线程进行汇总,此时,总的执行时间将决定于执行最慢的任务,平均来看,还是大大减少了总的执行时间。的计数值,当计数值减到0时,所有等待的线程都会被唤醒。

2024-05-05 20:01:32 658 1

原创 任务调度梳理合集-分布式任务调度解决方案

通常任务调度的程序是集成在应用中的,比如:优惠卷服务中包括了定时发放优惠卷的的调度程序,结算服务中包括了定期生成报表的任务调度程序,由于采用分布式架构,一个服务往往会部署多个冗余实例来运行我们的业务,在这种分布式系统环境下运行任务调度,我们称之为。执行器接收调度请求去执行任务,要有办法去判断该任务是否处理完成,如果处理完则不再处理,即使重复调度处理相同的任务也不能重复处理相同的视频。任务添加成功后,对于要处理的任务会添加到待处理任务表中,现在启动多个执行器实例去查询这些待处理任务,

2024-05-05 19:53:18 920

原创 任务调度梳理合集-解决方案

Java 5 推出了基于线程池设计的 ScheduledExecutor,其设计思想是,每一个被调度的任务都会由线程池中一个线程去执行,因此任务是并发执行的,相互之间不会受到干扰。Timer 的优点在于简单易用,每个Timer对应一个线程,因此可以同时启动多个Timer并行执行多个任务,同一个Timer中的任务是串行执行。任务调度顾名思义,就是对任务的调度,它是指系统为了完成特定业务,基于给定时间点,给定时间间隔或者给定执行次数自动执行任务。每隔1s执行一次,在一分钟之后结束。2.基本定时器Timer。

2024-05-05 16:08:59 193

原创 深入理解Java泛型

max = e;return max;泛型为Java语言提供了强大的类型安全支持,使得集合操作更加安全和灵活。理解泛型的使用和原理,对于编写高质量的Java代码至关重要。这篇文章深入探讨了Java泛型的使用、类型推断、通配符、类型擦除、局限性和高级应用,适合那些希望提高自己泛型使用技巧的Java开发者。

2024-05-04 17:51:18 708

原创 Java中的异常处理机制详解

在Java中,异常是Throwable类的子类,表示程序运行时发生的不正常情况。所有的异常都是从Error:由Java虚拟机抛出,表示严重的错误,如等。通常不会尝试捕获这些异常。Exception:应用程序可以抛出和捕获的异常,又分为:未检查异常(Unchecked Exceptions):继承自,如等。检查异常(Checked Exceptions):继承自Exception类,但不是的子类,如等。异常处理是Java编程中不可或缺的一部分,正确使用异常处理机制可以提高程序的健壮性和可维护性。

2024-05-04 17:49:16 473

原创 Redis-三主三从高可用集群搭建

redis集群需要至少要三个master节点,我们这里搭建三个master节点,并且给每个master再搭建一个slave节点,总共6个redis节点,由于节点数较多,这里采用在一台机器上创建6个redis实例,并将这6个redis实例配置成集群模式,所以这里搭建的是伪集群模式,当然真正的分布式集群的配置方法几乎一样。PS:当出现集群无法启动时,删除临时的数据文件,再次重新启动每一个redis服务,然后重新构造集群环境。在redis3的安装目录下执行 redis-trib.rb命令创建整个redis集群。

2024-05-04 09:53:09 987

原创 SQL-索引篇整理

聚簇索引就是按照每张表的主键构造一颗B+树,同时叶子节点中存放的就是整张表的行记录数据,也将聚集索引的叶子节点称为数据页。索引需要额外的磁盘空间,并降低写操作的性能。3.使用短索引,如果对长字符串列进行索引,应该指定一个前缀长度,这样能够节省大量索引空间,如果搜索词超过索引前缀长度,则使用索引排除不匹配的行,然后检查其余行是否可能匹配。红黑树,1.每个节点都是红or黑 2.根节点是黑 3.每个叶子节点都是黑色 4.红色节点的父子节点都必须是黑的 5.从任一个节点到叶子节点的所有路径都包含相同的黑色结点。

2024-05-03 12:26:24 1494

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除