Alive Note - 中间件
type: channel
link: https://www.vae.li/tag/middleware/
items: Sharding-JDBC学习记录
items: Spring Data Jpa 分表处理
items: 周会-Redis简介
items: Web基础之Dubbo

Sharding-JDBC学习记录
type: item
date: 2022-09-20T02:55:00+00:00
description: 最近学习了 sharding sphere 中的jdbc组件，此文作为学习记录方便以后复习。中间件官网：Apache Sharding Sphere学习准备快速开始分表创建库表：CREATE DATABASE `db_device_0` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE TABLE `tb_device_0` ( `device_id` BIGINT NOT NULL AUTO_INCREMENT, `device_type` INT DEFAULT NULL, PRIMARY KEY ( `device_id` ) ) AUTO_INCREMENT = 9 DEFAULT CHARSET = utf8mb4; CREATE TABLE `tb_device_1` ( `device_id` BIGINT NOT NULL AUTO_INCREMENT, `device_type` INT DEFAULT NULL, PRIMARY KEY ( `device_id` ) ) AUTO_INCREMENT = 10 DEFAULT CHARSET = utf8mb4;引入依赖：因为是demo项目，所以直接使用了JDK17pom.xml<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.1</version> </parent> <groupId>fun.psgame</groupId> <artifactId>sharding-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>sharding-demo</name> <description>sharding-demo</description> <properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.24</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.2</version> </dependency> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-st…

Spring Data Jpa 分表处理
type: item
date: 2022-07-19T02:53:00+00:00
description: Spring Data Jpa 动态表处理Jpa 分表问题现在有一张学生表t_stu按年份进行了处理，物理表分别是t_stu_2020、t_stu_2021、t_stu_2022这样 如果是mybatis，可以直接把表后缀传入sql，然后使用t_stu_${year}对表名进行拼接 但是对于Jpa这个全自动化ORM框架来说不太好处理，因为Jpa的表名是写在实体类的注解上的，在运行时不能修改：// 实体类 @Entity @Table(name = "t_stu") // 这里的表名定义是无法在运行时修改的 @Getter @Setter public class TVisionStu { private static final long serialVersionUID = 1L; @Id @Column(name = "id") private String id; @Column(name = "name") private String name; } // dao 层 @Repository public interface TVisionStuDao extends JpaRepository<TVisionStu, String>, JpaSpecificationExecutor<TVisionStu> {}解决方案Hibernate 插件方式Hibernate 插件可以在sql执行前对sql进行修改，从而达到动态表的功能import org.apache.commons.lang3.StringUtils; import org.hibernate.EmptyInterceptor; import org.springframework.stereotype.Component; @Component public class HibernateInterceptor extends EmptyInterceptor { @Override public String onPrepareStatement(String sql) { String schoolYear = ReqContextHolder.getSchoolYear(); // 这里对表名进行替换 if (StringUtils.isNotBlank(schoolYear)) { return sql.replaceAll("t_stu", "t_stu_" + schoolYear); } return super.onPrepareStatement(sql); } }其中的ReqContextHolder是一个线程安全的类，用来保存要查找的实际年份public class ReqContextHolder { private ReqContextHolder() { } protected static ThreadLocal<String> schoolYearThreadLocal = new ThreadLocal<>(); public static void setSchoolYear(String schoolYear) { schoolYearThreadLocal.set(schoolYear); } public static String getSchoolYear() { return schoolYearThreadLocal.get(); } public static void remove() { schoolYearThreadLocal.remove(); } }然后在application.yml中对插件进行配置：spring: # 设置jpa插件，可以实现分表 jpa: properties: hibernate: ejb: # 注册自定义的插件类 interceptor: com.power.aop.HibernateInterceptor实际使用的话就像这样： @RestController @RequestMapping("/stu") public class StuController{ @GetMapping("/query") public List<TVisionStu> query(@RequestParam("schoolYear") String schoolYear) { ReqContextHolder.setSchoolYear(schoolYear); List<TVisionStu> list = this.stuDao.findAll(); ReqContextHolder.remove(); return list; } }然后就可以到sql可以正常执行了。如果觉…

周会-Redis简介
type: item
date: 2021-03-12T01:00:00+00:00
description: *为什么提本话题：Maps优化的时候，大部分时间都花在数据库查询上，并且不是某一个SQL执行时间特别长，而是很多小SQL总体时间很长。 当时就在想有没有那么些数据，特别是不经常变动的数据，但是经常查询，把它们保存起来，做一个中央缓存。然后就想到Redis，一个比较流行的缓存应用。*Redis简介关系型数据库 与 非关系型数据库 （SQL 与 NoSQL）关系型数据库最典型的数据结构是表，由二维表及其之间的联系所组成的一个数据组织 优点： 1、易于维护：都是使用表结构，格式一致； 2、使用方便：SQL语言通用，可用于复杂查询； 3、复杂操作：支持SQL，可用于一个表以及多个表之间非常复杂的查询。 缺点： 1、读写性能比较差，尤其是海量数据的高效率读写； 2、固定的表结构，灵活度稍欠；（对比MongoDB） 3、高并发读写需求，传统关系型数据库来说，硬盘I/O是一个很大的瓶颈 非关系型数据库严格上不是一种数据库，应该是一种数据结构化存储方法的集合，可以是键值对或者文档等。 优点： 1、格式灵活：存储数据的格式可以是key,value形式、文档形式、图片形式等等，文档形式、图片形式等等，使用灵活，应用场景广泛，而关系型数据库则只支持基础类型。 2、速度快：nosql可以使用硬盘或者随机存储器（内存）作为载体，而关系型数据库只能使用硬盘； 3、高扩展性； 缺点： 1、不提供sql支持，学习和使用成本较高； 2、无事务处理；（Redis可以保证单个客户端执行的多条命令是原子性的，类似于事务） 3、数据结构相对复杂，复杂查询方面稍欠。为什么Maps中没有使用RedisRedis一般是作为缓存使用，解决的是高并发下数据库IO瓶颈的问题（主要是查询）。 Maps是客户端应用，用户少，并发不高，与Web项目不同。并且Maps系统中有分库的机能，数据库一般不会达到瓶颈（缺点就是系统变复杂）。 但是Maps中有一部分数据也是可以使用Redis的，在调用一个接口前，查询的数据库对应信息、用户认证信息等等（日志中体现的），就可以使用Redis做一个中央缓存。Redis为什么快主要原因有两个： 1、数据在内存中（但是有持久化机制） 2、采用的是IO多路复用机制（也就是NIO） 关于NIO和阻塞式IO可以看这个：浅析NIO https://www.cnblogs.com/lixin-link/p/11279448.htmlRedis数据类型Redis本身是key-value形式的数据库，这里说的数据类型指的是value中的类型。 Redis支持五种数据类型：string（字符串），hash（哈希），list（列表），set（集合）及zset(sorted set：有序集合)。Redis常见应用场景Redis常见的应用场景有1、会话缓存（最常用） 2、消息队列（支付）3、活动排行榜或计数4、发布，订阅消息（消息通知）Redis过期时间有时候放在Redis中的数据，想让它时间到了自动消失，比如缓存、手机验证码这样的数据，可以设置过期时间。Redis淘汰策略Redis可设置的内存空间是512G，物理内存不够的时候： 1、volatile-lru：从已设置过期时间的数据集中挑选最近最少使用的数据淘汰 2、volatile-ttl：从已设置过期时间的数据集中挑选将要过期的数据淘汰 3、volatile-random：从已设置过期时间的数据集中任意选择数据淘汰 4、allkeys-lru：从数据集中挑选最近最少使用的数据淘汰 5、allkeys-random：从数据集中任意选择数据淘汰 6、no-enviction（驱逐）：禁止驱逐数据 默认设置是6：禁止驱逐数据，也就是说内存满了后再添加值会出错。 常用设置是4：淘汰最少使用。Redis持久化两种持久化方式： RDB：定期将内存中的信息写成文件 AOF：定期将执行的写删更新命令记录成文件 有了持久化之后，服务重启之后Redis可以快速回复数据，不用重新添加缓存。扩展Redis与服务器数据的一致性、缓存穿透、缓存击穿、缓存雪崩等问题、小结“如无必要，勿增实体” Redis可以解决一些问题，但是也会让系统更加复杂。

Web基础之Dubbo
type: item
date: 2019-09-18T03:45:00+00:00
description: DubboRPC即Remote Procedure Call，即为远程调用。这和Java的远程代理RMI有点类似，不过RMI只能在Java系统之间进行调用，并且是使用序列化对象的方式进行通信。相比之下，RPC模式的Dubbo性能更高一些，由于使用HTTP进行通信，因此可以在不同语言的服务之间进行调用。快速入门首先导入Spring以及Dubbo相关依赖： maven依赖<properties> <spring.version>5.0.5.RELEASE</spring.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.6.0</version> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.7</version> </dependency> <dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> <version>0.1</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.47</version> </dependency> </dependencies> 创建公共接口并安装到maven仓库：公共接口单独打包package cn.bilibili.dubbo.service; public interface HellobilibiliService { String sayHello(String name); }服务方开发：打包为war包，并在web.xml中配置监听器：web.xml <web-app> <display-name>Archetype Created Web Application</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext-service.xml</param…