简介: 短链服务介绍和应用场景讲解
简介: 需求出发带你详细一个短链的生命周期
简介: 短链URL生成服务里面的问题你能想到多少
简介: 短链服务问题解决方案讲解-业务关系+跳转问题
问题一:长链的关系和短链的关系是一对一还是一对多?
问题二:前端访问短链是如何跳转到对应的页面的?
服务端转发
request.getRequestDispatcher("/two").forward(request, response);
简介: 短链服务问题解决方案讲解-短链码生成解决方案《上》
问题三:短链码如何是如何生成的
短链码特点
方式
MD5内容压缩
43E08496,9E5CF455,E6D2D2B3,3407A6D2
简介: 敏感数据讲解+自增ID暴露的商业秘密
什么是数据脱敏
手机号
、身份证
等信息,进行转换或者修改的一种技术手段,防止敏感数据直接在不可靠的环境下使用和泄露、撞库等
数据库业务规则安全:自增ID暴露的商业秘密
背景
作为后端开发人员肯定离不开数据库设计,尽管你知道数据安全、接口安全、网络安全,但你也很大可能不小心暴露的公司的核心机密。
【做空上市公司的股票】如果你有炒股,那你知道如果这个数据库设计漏洞被他人知道,就可以做空一个上司公司的股票的不?
【摧毁对手的利器】如果一个公司在是靠业务数据来说话的,如果被他人知道,在核心的时间点,被披露出来,那融资可能凉凉,企业可能面临倒闭。
在某天一个竞争对手 老王 做竞品调研的时候,注册了你公司的应用
【暴露了总用户量】
通过业务接口抓包分析(假定数据没做加密或者加密被破解了),被他发现了自增id这个事情,他好几个号注
册了,编号都是一百多万,每次id都是自增1, 用户量最多100多万,就此暴雷了。
经过有经验的人知道不能对外暴露id这个事情,但是总有关联的业务,或者其他不知道的人员开发了对应
的功能,比如 订单表、记录表、收藏表或者其他和user_id有关联的,只要他操作业务,接口有返回user_id,就容易出问题了。
【暴露了每日拉新数据】
如果是用户自增id,老王 肯定不单停留这里这么简单,假如他想看这个产品每日新增的用户有多少。
毕竟拉新这个指标是很多公司都离不开的,比如通过投放广告、买量业务等等去获取新用户。
老王想看下这个公司每天新增用户量大不大,他就今天注册一个看id多少,明天再注册一个看id多少;
通过一段时间内去统计每天递增的值,老王就可以推断出平台新增用户大概是多少了,公司的拉新能力如何。
【暴露了平台商品数量-订单数量】
同样的思路,去爬取电商平台的商品,爬取平台最大的商品id, 第二天再次爬取,持续一段时间。就可以可以推断出新品发布数量。
同样的思路,去抓取订单接口,看最大id是多少, 第二天再次爬取,持续一段时间。就可以推断出这个公司的每天订单量有多大。
结语:
CREATE TABLE `USER` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`biz_id` varchar(64) DEFAULT NULL COMMENT '业务id',
`name` varchar(128) DEFAULT NULL COMMENT '昵称',
`pwd` varchar(124) DEFAULT NULL COMMENT '密码',
`head_img` varchar(524) DEFAULT NULL COMMENT '头像',
`phone` varchar(64) DEFAULT '' COMMENT '手机号',
`login_type` int(10) DEFAULT NULL COMMENT '登录类型',
`email` varchar(128) DEFAULT NULL COMMENT '邮箱',
`sex` tinyint(2) DEFAULT '1' COMMENT '0表示女,1表示男',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`roles` varchar(11) DEFAULT NULL COMMENT '1,2,3,数字权限,逗号分隔',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=100000 DEFAULT CHARSET=utf8;
增加了 biz_id,这个就是业务id, 如果有关联,则用 biz_id进行关联并返回,这个可以是varchar类型,long雪花算法.
其实最靠谱的就是,不要把有业务规则的id暴露给用户,不止id字段,类似的敏感字段都是
简介: 短链URL服务问题解决方案讲解-短链码生成解决方案《下》
哈希算法:将一个元素映射成另一个元素
MurMurHash
Murmur哈希是一种非加密散列函数,适用于一般的基于散列的查找。
它在2008年由Austin Appleby创建,在Github上托管,名为“SMHasher” 的测试套件。
它也存在许多变种,所有这些变种都已经被公开。
该名称来自两个基本操作,乘法(MU)和旋转(R)--来自百科
是一种【非加密型】哈希函数且【随机分布】特征表现更良好
由于是非加密的哈希函数,性能会比MD5强
再很多地方都用到比如Guava、Jedis、HBase、Lucence等
存在两个版本
数据量
首年日活用户: 10万
首年日新增短链数据:10万*50 = 500万
年新增短链数:500万 * 365天 = 18.2亿
年新增用户数:50万/1年
年营收目标: 10万付费用户 * 客单价200元 = 2千万
新增短链:50条/用户每日
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
6 位 62 进制数可表示 568 亿个短链(62的6次方,每位都有62个可能,如果扩大位数到7位,则可以支持3万5200亿)
简介: Guava框架里面的Murmur哈希算法测试
@Test
public void testMurmurHash() {
for (int i = 0; i < 50; i++) {
int num1 = random.nextInt(1000000);
int num2 = random.nextInt(1000000);
int num3 = random.nextInt(1000000);
String originalUrl = num1 + "xdclass+" + num2 + ".net" + num3;
long murmur3_32 = Hashing.murmur3_32().hashUnencodedChars(originalUrl).padToLong();
System.out.println("murmur3_32="+murmur3_32);
}
}
/**
* murmur hash算法
* @param param
* @return
*/
public static long murmurHash32(String param){
long murmur32 = Hashing.murmur3_32().hashUnencodedChars(param).padToLong();
return murmur32;
}
简介: 短链生成组件ShortLinkComponent封装
/**
* 创建短链
* @param originalUrl
* @return db编码+6位短链编码
*/
public String createShortLinkCode(String originalUrl){
long murmur32 = CommonUtil.murmurHash32(originalUrl);
//转62进制
String shortLinkCode = encodeToBase62(murmur32);
return code;
}
private static final String CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
/**
* 10进制转62进制
* @param num
* @return
*/
private static String encodeToBase62(long num) {
//StringBuffer:线程安全; StringBuilder:线程不安全
StringBuffer sb = new StringBuffer();
do {
int i = (int) (num % 62);
sb.append(CHARS.charAt(i));
num /= 62;
// num = num/ 62;
} while (num > 0);
String value = sb.reverse().toString();
return value;
}
简介: 组件ShortLinkComponent测试和疑惑解答
/**
* 测试短链平台
*/
@Test
public void testCreateShortLink() {
Random random = new Random();
for (int i = 0; i < 100; i++) {
int num1 = random.nextInt(10);
int num2 = random.nextInt(1000000);
int num3 = random.nextInt(1000000);
String originalUrl = num1 + "xdclass" + num2 + ".net" + num3;
String shortLinkCode = shortLinkComponent.createShortLinkCode(originalUrl);
log.info("originalUrl:" + originalUrl + ", shortLinkCode=" + shortLinkCode);
}
}
简介: 数据库表模型讲解-短链分组和短链
CREATE TABLE `link_group` (
`id` bigint unsigned NOT NULL,
`title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '组名',
`account_no` bigint DEFAULT NULL COMMENT '账号唯一编号',
`gmt_create` datetime DEFAULT CURRENT_TIMESTAMP,
`gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
CREATE TABLE `short_link` (
`id` bigint unsigned NOT NULL ,
`group_id` bigint DEFAULT NULL COMMENT '组',
`title` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '短链标题',
`original_url` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '原始url地址',
`domain` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '短链域名',
`code` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '短链压缩码',
`sign` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT '长链的md5码,方便查找',
`expired` datetime DEFAULT NULL COMMENT '过期时间,长久就是-1',
`account_no` bigint DEFAULT NULL COMMENT '账号唯一编号',
`gmt_create` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
`del` int unsigned NOT NULL COMMENT '0是默认,1是删除',
`state` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '状态,lock是锁定不可用,active是可用',
`link_type` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '链接产品层级:FIRST 免费青铜、SECOND黄金、THIRD钻石',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_code` (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
简介: MybatisPlus逆向工具生成短链服务相关java对象
public class MyBatisPlusGenerator {
public static void main(String[] args) {
//1. 全局配置
GlobalConfig config = new GlobalConfig();
// 是否支持AR模式
config.setActiveRecord(true)
// 作者
.setAuthor("二当家小D")
// 生成路径,最好使用绝对路径,window路径是不一样的
//TODO TODO TODO TODO
.setOutputDir("/Users/xdclass/Desktop/demo/src/main/java")
// 文件覆盖
.setFileOverride(true)
// 主键策略
.setIdType(IdType.AUTO)
.setDateType(DateType.ONLY_DATE)
// 设置生成的service接口的名字的首字母是否为I,默认Service是以I开头的
.setServiceName("%sService")
//实体类结尾名称
.setEntityName("%sDO")
//生成基本的resultMap
.setBaseResultMap(true)
//不使用AR模式
.setActiveRecord(false)
//生成基本的SQL片段
.setBaseColumnList(true);
//2. 数据源配置
DataSourceConfig dsConfig = new DataSourceConfig();
// 设置数据库类型
dsConfig.setDbType(DbType.MYSQL)
.setDriverName("com.mysql.cj.jdbc.Driver")
//TODO TODO TODO TODO
.setUrl("jdbc:mysql://120.79.150.146:3306/dcloud_link?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai")
.setUsername("root")
.setPassword("xdclass.net168");
//3. 策略配置globalConfiguration中
StrategyConfig stConfig = new StrategyConfig();
//全局大写命名
stConfig.setCapitalMode(true)
// 数据库表映射到实体的命名策略
.setNaming(NamingStrategy.underline_to_camel)
//使用lombok
.setEntityLombokModel(true)
//使用restcontroller注解
.setRestControllerStyle(true)
// 生成的表, 支持多表一起生成,以数组形式填写
//TODO TODO TODO TODO
.setInclude("link_group","short_link");
//4. 包名策略配置
PackageConfig pkConfig = new PackageConfig();
pkConfig.setParent("net.xdclass")
.setMapper("mapper")
.setService("service")
.setController("controller")
.setEntity("model")
.setXml("mapper");
//5. 整合配置
AutoGenerator ag = new AutoGenerator();
ag.setGlobalConfig(config)
.setDataSource(dsConfig)
.setStrategy(stConfig)
.setPackageInfo(pkConfig);
//6. 执行操作
ag.execute();
System.out.println("======= 小滴课堂 Done 相关代码生成完毕 ========");
}
}
简介: 配置文件修改-yml转properties
server.port=8001
spring.application.name=dcloud-account
#----------服务注册和发现--------------
spring.cloud.nacos.discovery.server-addr=120.79.150.146:8848
spring.cloud.nacos.discovery.username=nacos
spring.cloud.nacos.discovery.password=nacos
#-------redis连接配置-------
spring.redis.client-type=jedis
spring.redis.host=120.79.150.146
spring.redis.password=xdclass.net
spring.redis.port=6379
spring.redis.jedis.pool.max-active=100
spring.redis.jedis.pool.max-idle=100
spring.redis.jedis.pool.min-idle=100
spring.redis.jedis.pool.max-wait=60000
#-------分库分表数据源配置-------
spring.shardingsphere.datasource.names=ds0
spring.shardingsphere.datasource.ds0.connectionTimeoutMilliseconds=30000
spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds0.idleTimeoutMilliseconds=60000
spring.shardingsphere.datasource.ds0.jdbc-url=jdbc:mysql://120.79.150.146:3306/dcloud_account?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
spring.shardingsphere.datasource.ds0.maintenanceIntervalMilliseconds=30000
spring.shardingsphere.datasource.ds0.maxLifetimeMilliseconds=1800000
spring.shardingsphere.datasource.ds0.maxPoolSize=50
spring.shardingsphere.datasource.ds0.minPoolSize=50
spring.shardingsphere.datasource.ds0.password=xdclass.net168
spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds0.username=root
spring.shardingsphere.props.sql.show=true
# 指定traffic表的数据分布情况,配置数据节点,行表达式标识符使用 ${...} 或 $->{...},但前者与 Spring 本身的文件占位符冲突,所以在 Spring 环境中建议使用 $->{...}
spring.shardingsphere.sharding.tables.traffic.actual-data-nodes=ds0.traffic_$->{0..1}
#水平分表策略+行表达式分片
spring.shardingsphere.sharding.tables.traffic.table-strategy.inline.algorithm-expression=traffic_$->{ account_no % 2 }
spring.shardingsphere.sharding.tables.traffic.table-strategy.inline.sharding-column=account_no
#id生成策略
spring.shardingsphere.sharding.tables.traffic.key-generator.column=id
spring.shardingsphere.sharding.tables.traffic.key-generator.props.worker.id=${workId}
spring.shardingsphere.sharding.tables.traffic.key-generator.type=SNOWFLAKE
#----------sms短信配置--------------
sms.app-code=6999d4df3e7d48028470bbe517169a8d
sms.template-id=M72CB42894
#----------阿里云OSS配置--------------
aliyun.oss.endpoint=oss-cn-321.aliyuncs.com
aliyun.oss.access-key-id=312
aliyun.oss.access-key-secret=123
aliyun.oss.bucketname=dcloud-link
简介: 短链分组管理-CURD接口开发实战《上》
简介: 短链分组管理-CURD接口开发实战《下》
简介: 短链分组管理-水平分库分表配置实战
#----------短链组,策略:水平分库,不水平分表--------------
# 先进行水平分库, 水平分库策略,行表达式分片
spring.shardingsphere.sharding.tables.link_group.database-strategy.inline.sharding-column=account_no
spring.shardingsphere.sharding.tables.link_group.database-strategy.inline.algorithm-expression=ds$->{account_no % 2}
简介: 短链服务-ShortLink分库分表解决方案讲解
短链分库分表-小滴课堂老王 同学想到的
数据量预估
首年日活用户: 10万
首年日新增短链数据:10万*50 = 500万
年新增短链数:500万 * 365天 = 18.2亿
往高的算就是100亿,支撑3年
分库分表策略
分库分表
分片键:短链码 code
分库分表算法:短链码进行hash取模
库ID = 短链码hash值 % 库数量
表ID = 短链码hash值 / 库数量 % 表数量
优点
问题
简介: 短链服务-分库分表免迁移扩容解决方案讲解《黄金玩法》
简介: 短链服务-分库分表相关库表建立
spring.shardingsphere.datasource.names=ds0,ds1,dsa
#ds0配置
spring.shardingsphere.datasource.ds0.connectionTimeoutMilliseconds=30000
spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds0.idleTimeoutMilliseconds=60000
spring.shardingsphere.datasource.ds0.jdbc-url=jdbc:mysql://120.79.150.146:3306/dcloud_link_0?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds0.maintenanceIntervalMilliseconds=30000
spring.shardingsphere.datasource.ds0.maxLifetimeMilliseconds=1800000
spring.shardingsphere.datasource.ds0.maxPoolSize=50
spring.shardingsphere.datasource.ds0.minPoolSize=50
spring.shardingsphere.datasource.ds0.username=root
spring.shardingsphere.datasource.ds0.password=xdclass.net168
#ds1配置
spring.shardingsphere.datasource.ds1.connectionTimeoutMilliseconds=30000
spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds1.idleTimeoutMilliseconds=60000
spring.shardingsphere.datasource.ds1.jdbc-url=jdbc:mysql://120.79.150.146:3306/dcloud_link_1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
spring.shardingsphere.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds1.maintenanceIntervalMilliseconds=30000
spring.shardingsphere.datasource.ds1.maxLifetimeMilliseconds=1800000
spring.shardingsphere.datasource.ds1.maxPoolSize=50
spring.shardingsphere.datasource.ds1.minPoolSize=50
spring.shardingsphere.datasource.ds1.username=root
spring.shardingsphere.datasource.ds1.password=xdclass.net168
#dsa配置
spring.shardingsphere.datasource.dsa.connectionTimeoutMilliseconds=30000
spring.shardingsphere.datasource.dsa.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.dsa.idleTimeoutMilliseconds=60000
spring.shardingsphere.datasource.dsa.jdbc-url=jdbc:mysql://120.79.150.146:3306/dcloud_link_a?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
spring.shardingsphere.datasource.dsa.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.dsa.maintenanceIntervalMilliseconds=30000
spring.shardingsphere.datasource.dsa.maxLifetimeMilliseconds=1800000
spring.shardingsphere.datasource.dsa.maxPoolSize=50
spring.shardingsphere.datasource.dsa.minPoolSize=50
spring.shardingsphere.datasource.dsa.username=root
spring.shardingsphere.datasource.dsa.password=xdclass.net168
简介: 短链服务分库分表实战-标准分片策略-精准分片算法
public class CustomDBPreciseShardingAlgorithm implements PreciseShardingAlgorithm<String> {
/**
* @param availableTargetNames 数据源集合
* 在分库时值为所有分片库的集合 databaseNames
* 分表时为对应分片库中所有分片表的集合 tablesNames
* @param shardingValue 分片属性,包括
* logicTableName 为逻辑表,
* columnName 分片健(字段),
* value 为从 SQL 中解析出的分片健的值
* @return
*/
@Override
public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<String> shardingValue) {
//获取短链码第一位,即库位
String codePrefix = shardingValue.getValue().substring(0, 1);
for (String targetName : availableTargetNames) {
//获取库名的最后一位,真实配置的ds
String targetNameSuffix = targetName.substring(targetName.length() - 1);
//如果一致则返回
if (codePrefix.equals(targetNameSuffix)) {
return targetName;
}
}
//抛异常
throw new BizException(BizCodeEnum.DB_ROUTE_NOT_FOUND);
}
}
#----------短链,策略:分库+分表--------------
# 先进行水平分库,然后再水平分表
spring.shardingsphere.sharding.tables.short_link.database-strategy.standard.sharding-column=code
spring.shardingsphere.sharding.tables.short_link.database-strategy.standard.precise-algorithm-class-name=net.xdclass.strategy.CustomDBPreciseShardingAlgorithm
简介: 短链服务分库分表实战-标准分片策略-精准分片算法
public class CustomTablePreciseShardingAlgorithm implements PreciseShardingAlgorithm<String> {
/**
* @param availableTargetNames 数据源集合
* 在分库时值为所有分片库的集合 databaseNames
* 分表时为对应分片库中所有分片表的集合 tablesNames
* @param shardingValue 分片属性,包括
* logicTableName 为逻辑表,
* columnName 分片健(字段),
* value 为从 SQL 中解析出的分片健的值
* @return
*/
@Override
public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<String> shardingValue) {
//获取逻辑表名
String targetName = availableTargetNames.iterator().next();
String value = shardingValue.getValue();
//短链码最后一位
String codePrefix = value.substring(value.length()-1);
//拼装actual table
return targetName + "_" + codePrefix;
}
}
# 水平分表策略,自定义策略。 真实库.逻辑表
spring.shardingsphere.sharding.tables.short_link.actual-data-nodes=ds0.short_link,ds1.short_link,dsa.short_link
spring.shardingsphere.sharding.tables.short_link.table-strategy.standard.sharding-column=code
spring.shardingsphere.sharding.tables.short_link.table-strategy.standard.precise-algorithm-class-name=net.xdclass.strategy.CustomTablePreciseShardingAlgorithm
#id生成策略
spring.shardingsphere.sharding.tables.short_link.key-generator.column=id
spring.shardingsphere.sharding.tables.short_link.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.short_link.key-generator.props.worker.id=${workerId}
简介: 短链服务-短链码配置生成库表位实战
public class ShardingDBConfig {
/**
* 存储数据库位置编号
*/
private static final List<String> dbPrefixList = new ArrayList<>();
private static Random random = new Random();
//配置启用那些库的前缀
static {
dbPrefixList.add("0");
dbPrefixList.add("1");
dbPrefixList.add("a");
}
/**
* 获取随机的前缀
* @return
*/
public static String getRandomDBPrefix(){
int index = random.nextInt(dbPrefixList.size());
return dbPrefixList.get(index);
}
}
public class ShardingTableConfig {
/**
* 存储数据表位置编号
*/
private static final List<String> tableSuffixList = new ArrayList<>();
private static Random random = new Random();
//配置启用那些表的后缀
static {
tableSuffixList.add("0");
tableSuffixList.add("a");
}
/**
* 获取随机的后缀
* @return
*/
public static String getRandomTableSuffix(){
int index = random.nextInt(tableSuffixList.size());
return tableSuffixList.get(index);
}
}
String code = ShardingDBConfig.getRandomDBPrefix() + shortLinkCode + ShardingTableConfig.getRandomTablePrefix();
简介: 短链服务-Manager层模块CRUD开发
public interface ShortLinkManager {
/**
* 新增域名
*
* @param shortLinkDO
* @return
*/
int addShortLink(ShortLinkDO shortLinkDO);
/**
* 根据短链码找内容
*
* @param shortLinkCode
* @return
*/
ShortLinkDO findByShortLinkCode(String shortLinkCode);
/**
* 根据短链码和accountNo删除
*
* @param shortLinkCode
* @param accountNo
* @return
*/
int del(String shortLinkCode, Long accountNo);
}
@Component
@Slf4j
public class ShortLinkManagerImpl implements ShortLinkManager {
@Autowired
private ShortLinkMapper shortLinkMapper;
@Override
public int addShortLink(ShortLinkDO shortLinkDO) {
return shortLinkMapper.insert(shortLinkDO);
}
@Override
public ShortLinkDO findByShortLinkCode(String shortLinkCode) {
ShortLinkDO shortLinkDO = shortLinkMapper.selectOne(new QueryWrapper<ShortLinkDO>().eq("code", shortLinkCode).eq("del", 0));
return shortLinkDO;
}
/**
* 逻辑删除
*
* @param shortLinkCode
* @param accountNo
* @return
*/
@Override
public int del(String shortLinkCode, Long accountNo) {
ShortLinkDO shortLinkDO = new ShortLinkDO();
shortLinkDO.setDel(1);
int rows = shortLinkMapper.update(shortLinkDO, new QueryWrapper<ShortLinkDO>()
.eq("code", shortLinkCode).eq("account_no", accountNo));
return rows;
}
}
简介: 短链服务-自定义分库分表策略单元测试实战
单元测试
@Autowired
private ShortLinkManager shortLinkManager;
/**
* 保存
*/
@Test
public void testSaveShortLink() {
Random random = new Random();
//for (int i = 0; i < 10; i++) {
int num1 = random.nextInt(10);
int num2 = random.nextInt(10000000);
int num3 = random.nextInt(10000000);
String originalUrl = num1 + "xdclass" + num2 + ".net" + num3;
String shortLinkCode = shortLinkComponent.createShortLinkCode(originalUrl);
ShortLinkDO shortLinkDO = new ShortLinkDO();
shortLinkDO.setCode(shortLinkCode);
shortLinkDO.setAccountNo(Long.valueOf(num3));
shortLinkDO.setSign(originalUrl);
shortLinkDO.setDel(0);
shortLinkManager.addShortLink(shortLinkDO);
//}
}
@Test
public void testFind() {
ShortLinkDO shortLinkDO = shortLinkManager.findByShortLinkCode("03aAg0la");
log.info(shortLinkDO.toString());
}
简介: 加权负载均衡思想应用-数据库表扩容-数据不均匀问题解决方案
Nginx加权负载均衡的应用(架构大课)
不同的库表位分配的概率不一样,类似的中间件应用场景有nginx
Nginx常见的负载均衡策略
节点轮询(默认)
weight 权重配置
upstream lbs {
server 192.168.159.133:8080 weight=5;
server 192.168.159.133:8081 weight=10;
}