docker的使用技巧
基本概念镜像镜像是容器的静态形式,它打包了应用程序的所有运行依赖项,方便保存和传输。使用容器技术运行镜像,就形成了动态的容器,由于镜像只读不可修改,所以应用程序的运行环境总是一致的。 容器 容器就是操作系统里一个特殊的“沙盒”环境,里面运行的进程只能看到受限的信息,与外部系统实现了隔离。 容器隔离的目的是为了系统安全,限制了进程能够访问的各种资源。 相比虚拟机技术,容器更加轻巧、更加高效,消耗的系统资源非常少,在云计算时代极具优势。 进入容器命令 1docker exec -it 062 sh Docker DesktopDocker Desktop 是容器化应用开发与部署的一体化工具,支持在本地环境创建、管理和运行Docker容器。 很多人以为,只要换了新电脑或者格式化电脑后,在docker desktop拉取的镜像、容器都会消失,现在我就来介绍一下将 Docker Desktop 的容器打包成镜像,上传到 docker hub 的方法,以后就可以像代码一样管理维护自己的docker镜像。 Docker Hub在使用 docker pull 获取镜像的时候,我们并没有明确地指 ...
Redis实战:场景设计
Redis 热升级对于线上较大流量的业务,单个 Redis 实例的内存占用很容易达到数 G 的容量,对应的 aof 会占用数十 G 的空间。即便每天流量低峰时间,对 Redis 进行 rewriteaof,减少数据冗余,但由于业务数据多,写操作多,aof 文件仍然会达到 10G 以上。 此时,在 Redis 需要升级版本或修复 bug 时,如果直接重启变更,由于需要数据恢复,这个过程需要近 10 分钟的时间,时间过长,会严重影响系统的可用性。 首先构建一个 Redis 壳程序,将 redisServer 的所有属性(包括redisDb、client等)保存为全局变量。然后将 Redis 的处理逻辑代码全部封装到动态连接库 so 文件中。Redis 第一次启动,从磁盘加载恢复数据,在后续升级时,通过指令,壳程序重新加载 Redis 新的 so 文件,即可完成功能升级,毫秒级完成 Redis 的版本升级。而且整个过程中,所有 Client 连接仍然保留,在升级成功后,原有 Client 可以继续进行读写操作,整个过程对业务完全透明。 Redis 功能扩展在 Redis 使用中,也经常会遇到 ...
Spring循环依赖及解决原理
什么是循环依赖字面上理解就是A依赖B的同时,B也依赖了A。 体现在启动控制台就是以下的日志: 12345┌─────┐| asyncServiceImpl defined in file [D:\Download\GitLabProject\uhr\jr-uhr-provider\jr-uhr-attendance\target\classes\com\jr\uhr\gtd\service\impl\AsyncServiceImpl.class]↑ ↓| gtdClassServiceImpl defined in file [D:\Download\GitLabProject\uhr\jr-uhr-provider\jr-uhr-attendance\target\classes\com\jr\uhr\gtd\service\impl\GtdClassServiceImpl.class]└─────┘ 体现在代码层次就是这个样子: 12345678910111213@Componentpublic class A { // A中注入了B @Autowir ...
销售提成计算引擎实现
销售提成计算引擎实现1. 模块概述该模块是销售提成计算系统的具体实现层,基于模板方法模式设计,实现了不同业务线(BPO、HRO)的提成计算逻辑。 2. 目录结构12345CopyInsertcalculation/engine/├── AbstractCalculationEngine.java # 抽象计算引擎基类├── CalculationEngine.java # 计算引擎接口├── BpoCalculationEngine.java # BPO业务线计算引擎实现└── HroCalculationEngine.java # HRO业务线计算引擎实现 3. 核心组件说明3.1 计算引擎接口CalculationEngine 定义了计算引擎的基本契约 核心方法: calculation(CalculationDto): 执行业务数据核算 supportedProductLine(): 声明支持的产品线类型 3.2 抽象计算引擎AbstractCalculationEngine 实现了计算引擎的通用逻辑 核 ...
销售提成合并滚动明细逻辑
销售提成合并滚动明细逻辑滚动明细回款金额暂未发完的账单,会滚动到下一个工资月继续发放 同步底表增量同步BI底表数据,系统自动给本次拉取的数据打上“工资月份”的标识,BPO(T+2),HRO(T+1)。 合并明细合并时注意需保留用户编辑后的数据,部分字段需延用(自动带出)上个账单月的数值。
常用的缓存组件Redis是如何运行的
Redis简介Redis 是一款基于 ANSI C 语言编写的,BSD 许可的,日志型 key-value 存储组件,它的所有数据结构都存在内存中,可以用作缓存、数据库和消息中间件。 Redis 是 Remote dictionary server 即远程字典服务的缩写,一个 Redis 实例可以有多个存储数据的字典,客户端可以通过 select 来选择字典即 DB 进行数据存储。 Redis核心数据类型同为 key-value 存储组件,Memcached 只能支持二进制字节块这一种数据类型。而 Redis 的数据类型却丰富的多,它具有 8 种核心数据类型,每种数据类型都有一系列操作指令对应。 首先,来看一下 Redis 的核心数据类型。Redis 有 8 种核心数据类型,分别是 : string 字符串类型; list 列表类型; set 集合类型; sorted set 有序集合类型; hash 类型; bitmap 位图类型; geo 地理位置类型; HyperLogLog 基数统计类型。 string 字符串string 是 Redis 的最基本数据类型。可以把它理解为 ...
缓存的基本思想
缓存的基本思想空间换时间。 缓存中的数据通常存储于内存中,因此访问速度非常快。为了避免内存中的数据在重启或者宕机之后丢失,很多缓存中间件会利用磁盘做持久化。 缓存相比较于我们常用的关系型数据库来说访问速度要快非常多,为了避免用户请求数据库中的数据速度过于缓慢,我们可以在数据库之上增加一层缓存。 除了能提高访问速度之外,缓存支持的并发量也要大。有了缓存后,数据库的压力也会随之变小。 缓存的分类本地缓存本地缓存的方案 JDK 自带的 HashMap 和 ConcurrentHashMap ConcurrentHashMap 是线程安全版本的 HashMap,大部分场景不会使用这两者做缓存,因为只提供了缓存的功能,并没有提供其他诸如过期时间之类的功能。 Ehcache、Guava Cache、Spring Cache 比较常用的本地缓存框架 Ehcache 比其他两者更重量。Ehcache 可以嵌入到 Hibernate 和 MyBatis 作为多级缓存,并且可以将缓存的数据持久化到本地磁盘中 Guava Cache 和 Spring Cache 两者比较像。Guava 使用更 ...
Java业务开发常见问题
Spring 框架:IoC 和 AOP 是扩展的核心 当 Bean 产生循环依赖时,比如 BeanA 的构造方法依赖 BeanB 作为成员需要注入,BeanB 也依赖 BeanA,你觉得会出现什么问题呢?又有哪些解决方式呢? 答:Bean 产生循环依赖,主要包括两种情况:一种是注入属性或字段涉及循环依赖,另一种是构造方法注入涉及循环依赖。接下来,我分别和你讲一讲。 第一种,注入属性或字段涉及循环依赖,比如 TestA 和 TestB 相互依赖: 1234567891011121314151617181920212223@Componentpublic class TestA { @Autowired @Getter private TestB testB;}@Componentpublic class TestB { @Autowired @Getter private TestA testA;} 针对这个问题,Spring 内部通过三个 Map 的方式解决了这个问题,不会出错。基本原理是,因为循环依赖,所 ...
Java程序从虚拟机迁移到Kubernetes的一些坑
在大多数的公司中,Kubernetes 集群由运维来搭建,而程序的发布一般也是由 CI/CD 平台完成。从虚拟机到 Kubernetes 的整个迁移过程,基本不需要修改任何代码,可能只是重新发布一次而已。所以,我们 Java 开发人员可能对迁移这个事情本身感知不强烈,认为 Kubernetes 只是运维需要知道的事情。但是程序一旦部署到了 Kubernetes 集群中,在容器环境中运行,总是会出现各种各样之前没有的奇怪的问题。 Pod IP 不固定带来的坑Pod 是 Kubernetes 中能够创建和部署应用的最小单元,我们可以通过 Pod IP 来访问到某一个应用实例,但需要注意的是,如果没有经过特殊配置,Pod IP 并不是固定不变的,会在 Pod 重启后会发生变化。 不过好在,通常我们的 Java 微服务都是没有状态的,我们并不需要通过 Pod IP 来访问到某一个特定的 Java 服务实例。通常来说,要访问到部署在 Kubernetes 中的微服务集群,有两种服务发现和访问的方式: 通过 Kubernetes 来实现。也就是通过 Service 进行内部服务的互访,通 ...
漫谈RocketMQ消息发送
topic路由机制消息发送者向某一个topic发送消息时,需要查询topic的路由信息。初次发送时会根据topic的名称向NameServer集群查询topic的路由信息,然后将其缓存在本地内存中,并且每隔30s依次遍历缓存中的topic,向NameServer查询最新的路由信息。如果成功查询到路由信息,会将这些信息更新到本地缓存,实现topic路由信息的动态感知。 RocketMQ提供了自动创建主题的机制,消息发送者向一个不存在的主题发送消息时,向NameServer查询该主题的路由信息会先返回空,如果开启了自动创建主题机制,会使用一个默认的主题名再次从NameServer查询路由信息,然后消息发送者会使用默认主题的路由信息进行负载均衡,但不会直接使用默认路由信息为新主题创建对应的路由信息。 生产环境中,为何不建议自动创建topic原因分析因为生产环境一般是集群部署多台broker服务器,autoCreateTopicEnable设置为true,表示开启topic自动创建,但新创建的topic的路由信息只包含在其中一台broker服务器上。 期望回答:为了消息发送的高可用,希望新创 ...
线程安全小妙招
TreadLocal的正确打开方式我们知道,ThreadLocal 适用于变量在线程间隔离,而在方法或类间共享的场景。如果用户信息的获取比较昂贵(比如从数据库查询用户信息),那么在 ThreadLocal 中缓存数据是比较合适的做法。 但是如果错误地使用了ThreadLocal,可能会导致有时获取到的用户信息是别人的。为什么会出现用户信息错乱的 Bug 呢? 我们来复现一下这个场景。 使用 Spring Boot 创建一个 Web 应用程序,使用 ThreadLocal 存放一个 Integer 的值,来暂且代表需要在线程中保存的用户信息,这个值初始是 null。在业务逻辑中,我先从 ThreadLocal 获取一次值,然后把外部传入的参数设置到 ThreadLocal 中,来模拟从当前上下文获取到用户信息的逻辑,随后再获取一次值,最后输出两次获得的值和线程名称。 12345678910111213141516private static final ThreadLocal<Integer> currentUser = ThreadLocal.withInitial(() ...
RocketMQ集群性能调优及运维
系统参数调优在解压 RocketMQ 安装包后,在 bin 目录中有个 os.sh 的文件,该文件由 RocketMQ 官方推荐系统参数配置。通常这些参数可以满足系统需求,也可以根据情况进行调整。 最大文件数设置用户的打开的最多文件数: 123456vim /etc/security/limits.conf# End of filebaseuser soft nofile 655360baseuser hard nofile 655360* soft nofile 655360* hard nofile 655360 系统参数设置系统参数的调整以官方给出的为主,下面对各个参数做个说明。设置时可以直接执行 sh os.sh 完成系统参数设定,也可以编辑 vim /etc/sysctl.conf 文件手动添加如下内容,添加后执行 sysctl -p 让其生效。 123456789vm.overcommit_memory=1vm.drop_caches=1vm.zone_reclaim_mode=0vm.max_map_count=655360vm.dirty_background_rat ...
avatar
Palette
这是一个终身学习的时代
Follow Me
公告

欢迎来到「Palette」个人技术博客!🎉

本平台专注于:

  • > JAVA后端技术笔记
  • > 场景设计解决方案
  • > AI应用实践

🌟 一起钻研技术,共同进步!