第十二章 海量数据下的分库分表技术栈讲解
第1集 大话业界常见数据库分库分表中间件介绍
简介: 大话业界常见分库分表中间件介绍
- 业界常见分库分表中间件
- Cobar(已经被淘汰没使用了)
- TDDL
- 淘宝根据自己的业务特点开发了 TDDL (Taobao Distributed Data Layer)
- 基于JDBC规范,没有server,以client-jar的形式存在,引入项目即可使用
- 开源功能比较少,阿里内部使用为主
- Mycat
- 地址 http://www.mycat.org.cn/
- Java语言编写的MySQL数据库网络协议的开源中间件,前身 Cobar
- 遵守Mysql原生协议,跨语言,跨平台,跨数据库的通用中间件代理
- 是基于 Proxy,它复写了 MySQL 协议,将 Mycat Server 伪装成一个 MySQL 数据库
- 和ShardingShere下的Sharding-Proxy作用类似,需要单独部署
ShardingSphere 下的Sharding-JDBC
- 地址:https://shardingsphere.apache.org/
- Apache ShardingSphere 是一套开源的分布式数据库中间件解决方案组成的生态圈
- 它由 Sharding-JDBC、Sharding-Proxy 和 Sharding-Sidecar 3个独立产品组合
- Sharding-JDBC
- 基于jdbc驱动,不用额外的proxy,支持任意实现 JDBC 规范的数据库
- 它使用客户端直连数据库,以 jar 包形式提供服务,无需额外部署和依赖
- 可理解为加强版的 JDBC 驱动,兼容 JDBC 和各类 ORM 框架
- 面试官最喜欢问的,是Mycat和ShardingJdbc区别
- 两者设计理念相同,主流程都是SQL解析–>SQL路由–>SQL改写–>结果归并
- sharding-jdbc
- 基于jdbc驱动,不用额外的proxy,在本地应用层重写Jdbc原生的方法,实现数据库分片形式
- 是基于 JDBC 接口的扩展,是以 jar 包的形式提供轻量级服务的,性能高
- 代码有侵入性
- Mycat
- 是基于 Proxy,它复写了 MySQL 协议,将 Mycat Server 伪装成一个 MySQL 数据库
- 客户端所有的jdbc请求都必须要先交给MyCat,再有MyCat转发到具体的真实服务器
- 缺点是效率偏低,中间包装了一层
- 代码无侵入性
第2集 分库分表中间件Apache ShardingSphere急速认知
简介: 分库分表中间件Apache ShardingSphere急速认知
-
什么是ShardingSphere
- 已于2020年4月16日成为 Apache 软件基金会的顶级项目
- 是一套开源的分布式数据库解决方案组成的生态圈,定位为
Database Plus
- 它由 JDBC、Proxy 和 Sidecar这 3 款既能够独立部署,又支持混合部署配合使用的产品组成
-
三大构成(下面图片素材来源 sharding-sphere官网)
-
ShardingSphere-Sidecar(规划中,简单知道就行)
- 定位为 Kubernetes 的云原生数据库代理,以 Sidecar(边车) 的形式代理所有对数据库的访问
- 通过无中心、零侵入的方案提供与数据库交互的啮合层,即
Database Mesh
,又可称数据库网格
-
ShardingSphere-JDBC
- 它使用客户端直连数据库,以 jar 包形式提供服务
- 无需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC 和各种 ORM 框架
- 适用于任何基于 JDBC 的 ORM 框架,如:JPA, Hibernate, Mybatis,或直接使用 JDBC
- 支持任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, HikariCP 等;
- 支持任意实现 JDBC 规范的数据库,目前支持 MySQL,PostgreSQL,Oracle,SQLServer 以及任何可使用 JDBC 访问的数据库
- 采用无中心化架构,与应用程序共享资源,适用于 Java 开发的高性能的轻量级 OLTP 应用
-
- ShardingSphere-Proxy
- 数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持
- 向应用程序完全透明,可直接当做 MySQL/PostgreSQL
- 它可以使用任何兼容 MySQL/PostgreSQL 协议的访问客户端(如:MySQL Command Client, MySQL Workbench, Navicat 等)操作数据
第3集 分库分表和Sharding-Jdbc常见概念术语讲解
简介: 分库分表和Sharding-Jdbc常见概念术语讲解
-
站着统一水平线上,沟通无障碍,统一下专业术语
-
数据节点Node
- 数据分片的最小单元,由数据源名称和数据表组成
- 比如:ds_0.product_order_0
-
真实表
- 在分片的数据库中真实存在的物理表
- 比如订单表 product_order_0、product_order_1、product_order_2
-
逻辑表
- 水平拆分的数据库(表)的相同逻辑和数据结构表的总称
- 比如订单表 product_order_0、product_order_1、product_order_2,逻辑表就是product_order
-
绑定表
- 指分片规则一致的主表和子表
- 比如product_order表和product_order_item表,均按照order_id分片,则此两张表互为绑定表关系
- 绑定表之间的多表关联查询不会出现笛卡尔积关联,关联查询效率将大大提升
- 广播表
- 指所有的分片数据源中都存在的表,表结构和表中的数据在每个数据库中均完全一致
- 适用于数据量不大且需要与海量数据的表进行关联查询的场景
- 例如:字典表、配置表
第4集 分库分表和Sharding-Jdbc常见分片算法讲解
简介: 分库分表和Sharding-Jdbc常见分片算法讲解
-
数据库表分片(水平库、表)
- 包含分片键和分片策略
-
分片键 (PartitionKey)
- 用于分片的数据库字段,是将数据库(表)水平拆分的关键字段
- 比如prouduct_order订单表,根据订单号 out_trade_no做哈希取模,则out_trade_no是分片键
- 除了对单分片字段的支持,ShardingSphere也支持根据多个字段进行分片
-
分片策略
-
行表达式分片策略 InlineShardingStrategy
-
只支持【单分片键】使用Groovy的表达式,提供对SQL语句中的 =和IN 的分片操作支持
-
可以通过简单的配置使用,无需自定义分片算法,从而避免繁琐的Java代码开发
-
prouduct_order_$->{user_id % 8}` 表示订单表根据user_id模8,而分成8张表,表名称为`prouduct_order_0`到`prouduct_order_7
-
-
标准分片策略StandardShardingStrategy
- 只支持【单分片键】,提供PreciseShardingAlgorithm和RangeShardingAlgorithm两个分片算法
- PreciseShardingAlgorithm 精准分片 是必选的,用于处理=和IN的分片
- RangeShardingAlgorithm 范围分配 是可选的,用于处理BETWEEN AND分片
- 如果不配置RangeShardingAlgorithm,如果SQL中用了BETWEEN AND语法,则将按照全库路由处理,性能下降
-
复合分片策略ComplexShardingStrategy
- 支持【多分片键】,多分片键之间的关系复杂,由开发者自己实现,提供最大的灵活度
- 提供对SQL语句中的=, IN和BETWEEN AND的分片操作支持
- prouduct_order_0_0、prouduct_order_0_1、prouduct_order_1_0、prouduct_order_1_1
-
Hint分片策略HintShardingStrategy
-
这种分片策略无需配置分片健,分片健值也不再从 SQL中解析,外部手动指定分片健或分片库,让 SQL在指定的分库、分表中执行
-
用于处理使用Hint行分片的场景,通过Hint而非SQL解析的方式分片的策略
-
Hint策略会绕过SQL解析的,对于这些比较复杂的需要分片的查询,Hint分片策略性能可能会更好
-
-
不分片策略 NoneShardingStrategy
- 不分片的策略。
-
-
自己实现分片策略的优缺点
- 优点:可以根据分片策略代码里面自己拼装 真实的数据库、真实的表,灵活控制分片规则
- 缺点:增加了编码,不规范的sql容易造成全库表扫描,部分sql语法支持不友好
第十三章 流量包模块-海量数据下的分库分表《青铜玩法》
第1集 账号微服务-流量包模块水平分表需求讲解和开发
简介: 账号微服务-流量包模块水平分表需求讲解和开发
-
需求
- 未来2年,短链平台累计5百万用户
- 付费流量包记录:一个用户10条/年,总量就是5千万条
- 单表不超过1千万数据,需要分5张表
- 进一步延伸,进行水平分表,比如 2张表、4张表、8张表、16张表
- 流量包traffic表数据太多,选取可用流量包 会影响性能,需要降低单表数据量,进行水平分表
- 分表数量:线上分8张表,本地分2张表即可
- 分片key: account_no,查询维度都是根据account_no进行查询
- 分片策略:行表达式分片策略 InlineShardingStrategy
- 未来2年,短链平台累计5百万用户
-
新建表
- traffic_0
- traffic_1
CREATE TABLE `traffic_0` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT, `day_limit` int DEFAULT NULL COMMENT '每天限制多少条,短链', `day_used` int DEFAULT NULL COMMENT '当天用了多少条,短链', `total_limit` int DEFAULT NULL COMMENT '总次数,活码才用', `account_no` bigint DEFAULT NULL COMMENT '账号', `out_trade_no` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '订单号', `level` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '产品层级:FIRST青铜、SECOND黄金、THIRD钻石', `expired_date` date DEFAULT NULL COMMENT '过期日期', `plugin_type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '插件类型', `product_id` bigint DEFAULT NULL COMMENT '商品主键', `gmt_create` datetime DEFAULT CURRENT_TIMESTAMP, `gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_trade_no` (`out_trade_no`,`account_no`) USING BTREE, KEY `idx_account_no` (`account_no`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
-
配置
- 加入 sharding-jdbc依赖包,account项目注释下面的依赖排查
<exclusions> <exclusion> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> </exclusion> </exclusions>
- 配置文件 (注释之前jdbc单库配置)
# 数据源 ds0 第一个数据库 shardingsphere: datasource: ds0: connectionTimeoutMilliseconds: 30000 driver-class-name: com.mysql.cj.jdbc.Driver idleTimeoutMilliseconds: 60000 jdbc-url: jdbc:mysql://120.79.150.146:3306/dcloud_account?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true maintenanceIntervalMilliseconds: 30000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 50 minPoolSize: 50 password: xdclass.net168 type: com.zaxxer.hikari.HikariDataSource username: root names: ds0 props: # 打印执行的数据库以及语句 sql: show: true sharding: tables: traffic: # 指定traffic表的数据分布情况,配置数据节点,行表达式标识符使用 ${...} 或 $->{...},但前者与 Spring 本身的文件占位符冲突,所以在 Spring 环境中建议使用 $->{...} actual-data-nodes: ds0.traffic_$->{0..1}
第2集 账号微服务-流量包模块水平分表策略配置和测试实战
简介: 账号微服务-流量包模块水平分表策略配置和测试实战
- 水平分表策略配置
# 水平分表策略+行表达式分片
table-strategy:
inline:
algorithm-expression: traffic_$->{account_no % 2}
sharding-column: account_no
- 单元测试
@Autowired
private TrafficMapper trafficMapper;
@Test
public void testSaveTraffic(){
Random random = new Random();
for(int i=0;i<3;i++) {
TrafficDO trafficDO = new TrafficDO();
trafficDO.setAccountNo(Long.valueOf(random.nextInt(1000)));
trafficMapper.insert(trafficDO);
}
}
- 问题
- 主键id重复
第3集 分库分表暴露的问题-ID冲突和分布式id生成介绍
简介: 分库分表暴露的问题-ID冲突和分布式id生成
-
单库下一般使用Mysql自增ID, 但是分库分表后,会造成不同分片上的数据表主键会重复。
-
需求
- 性能强劲
- 全局唯一
- 防止恶意用户根据id的规则来获取数据
-
业界常用ID解决方案
-
数据库自增ID
- 利用自增id, 设置不同的自增步长,auto_increment_offset、auto-increment-increment
DB1: 单数 //从1开始、每次加2 DB2: 偶数 //从2开始,每次加2
- 缺点
- 依靠数据库系统的功能实现,但是未来扩容麻烦
- 主从切换时的不一致可能会导致重复发号
- 性能瓶颈存在单台sql上
-
UUID
- 性能非常高,没有网络消耗
- 缺点
- 无序的字符串,不具备趋势自增特性
- UUID太长,不易于存储,浪费存储空间,很多场景不适用
-
Redis发号器
- 利用Redis的INCR和INCRBY来实现,原子操作,线程安全,性能比Mysql强劲
- 缺点
- 需要占用网络资源,增加系统复杂度
-
Snowflake雪花算法
- twitter 开源的分布式 ID 生成算法,代码实现简单、不占用宽带、数据迁移不受影响
- 生成的 id 中包含有时间戳,所以生成的 id 按照时间递增
- 部署了多台服务器,需要保证系统时间一样,机器编号不一样
- 缺点
- 依赖系统时钟(多台服务器时间一定要一样)
-
第4集 带你彻底掌握分布式 ID 生成算法Snowflake原理
简介: 小D-带你彻底掌握分布式 ID 生成算法Snowflake原理
-
什么是雪花算法Snowflake
-
twitter用scala语言编写的高效生成唯一ID的算法
-
优点
- 生成的ID不重复
- 算法性能高
- 基于时间戳,基本保证有序递增
-
-
计算机的基础知识回顾
-
bit与byte
- bit(位):电脑中存储的最小单位,可以存储二进制中的0或1
- byte(字节):一个byte由8个bit组成
-
常规64位系统里面java数据类型存储字节大小
- int:4 个字节
- short:2 个字节
- long:8 个字节
- byte:1 个字节
- float:4 个字节
- double:8 个字节
- char:2 个字节
-
科普:数据类型在不同位数机器的平台下长度不同(怼面试官的严谨性)
- 16位平台 int 2个字节16位
- 32位平台 int 4个字节32位
- 64位平台 int 4个字节32位
-
-
雪花算法生成的数字,long类,所以就是8个byte,64bit
- 表示的值 -9223372036854775808(-2的63次方) ~ 9223372036854775807(2的63次方-1)
- 生成的唯一值用于数据库主键,不能是负数,所以值为0~9223372036854775807(2的63次方-1)
第5集 分布式ID生成器Snowflake里面的坑你是否知道
简介: 分布式ID生成器Snowflake里面的坑你是否知道
-
分布式ID生成器需求
- 性能强劲
- 全局唯一不能重复
- 防止恶意用户根据id的规则来获取数据
-
全局唯一不能重复-坑
-
坑一
- 分布式部署就需要分配不同的workId, 如果workId相同,可能会导致生成的id相同
-
坑二:
- 分布式情况下,需要保证各个系统时间一致,如果服务器的时钟回拨,就会导致生成的 id 重复
-
- 分布式情况下,需要保证各个系统时间一致,如果服务器的时钟回拨,就会导致生成的 id 重复
-
-
配置实操
-
spring.shardingsphere.sharding.tables.traffic.key-generator.props.worker.id=1
-
方式一
-
订单id使用MybatisPlus的配置,TrafficDO类配置
@TableId(value = "id", type = IdType.ASSIGN_ID) 默认实现类为DefaultIdentifierGenerator雪花算法
-
-
方式二
- 使用Sharding-Jdbc配置文件,注释DO类里面的id分配策略
#id生成策略 key-generator: column: id props: worker: id: 0 #id生成策略 type: SNOWFLAKE
-
第6集 分布式ID生成器Snowflake自定义wrokId实战
简介: 分布式ID生成器Snowflake自定义wrokId实战
- 进阶:动态指定sharding jdbc 的雪花算法中的属性work.id属性
- 使用sharding-jdbc中的使用IP后几位来做workId, 但在某些情况下会出现生成重复ID的情况
- 解决办法时
- 在启动时给每个服务分配不同的workId, 引入redis/zk都行,缺点就是多了依赖
- 启动程序的时候,通过JVM参数去控制,覆盖变量
- 解决办法时
- 使用sharding-jdbc中的使用IP后几位来做workId, 但在某些情况下会出现生成重复ID的情况
@Configuration
public class SnowFlakeWordIdConfig {
/**
* 动态指定sharding jdbc 的雪花算法中的属性work.id属性
* 通过调用System.setProperty()的方式实现,可用容器的 id 或者机器标识位
* workId最大值 1L << 100,就是1024,即 0<= workId < 1024
* {@link SnowflakeShardingKeyGenerator#getWorkerId()}
*
*/
static {
try {
InetAddress ip4 = Inet4Address.getLocalHost();
String addressIp = ip4.getHostAddress();
System.setProperty("workerId", (Math.abs(addressIp.hashCode())%1024)+"");
} catch (UnknownHostException e) {
throw new BizException(BizCodeEnum.OPS_NETWORK_ADDRESS_ERROR);
}
}
}
- 配置
#id生成策略
key-generator:
column: id
props:
worker:
id: ${workerId}
#id生成策略
type: SNOWFLAKE
第7集 shardingjdbc-Snowflake时间回拨问题解决和封装ID生成器
简介: shardingjdbc-Snowflake时间回拨问题解决和封装ID生成器
- shardingjdbc-Snowflake里面解决时间回拨问题
- 需求
- 用户注册-生成的account_no需要是long类型,且全局唯一
- 利用Sharding-Jdbc封装id生成器
public class IDUtil {
private static SnowflakeShardingKeyGenerator shardingKeyGenerator = new SnowflakeShardingKeyGenerator();
/**
* 雪花算法生成器,配置workId,避免重复
*
* 10进制 654334919987691526
* 64位 0000100100010100101010100010010010010110000000000000000000000110
*
* {@link SnowFlakeWordIdConfig}
*
* @return
*/
public static Comparable<?> geneSnowFlakeID(){
return shardingKeyGenerator.generateKey();
}
}
- 修改注册时账号生成策略
第十四章 短链服务-业务需求和短链码解决方案讲解
第1集 短链服务介绍和应用场景讲解
简介: 短链服务介绍和应用场景讲解
- 什么是短链服务
-
业务背景:为啥需要短链
- 公司电商产品推广、业务活动页、广告落地页 缺少实时【数据反馈和渠道效果分析】
- 老项目业务推广【没人维护,无法做埋点】需要统计效果
- 例子 https://tongji.baidu.com/web/demo/overview/index?siteId=16847648
- APP和营销活动发送营销短信链接过长,【浪费短信发送费用】
- 国内【反垄断后】微信、抖音、淘宝 流量互通,很多知识付费公司需要做 私域流量、社群运营
- 可以对外做产品输出,实现商业化能力增加公司营收
- 积累终端数据和人群数据,为公司未来产品人群做策略助力
- 更多。。。。
-
短链组成
- 协议://短链域名/短链码
-
最简单的方式
- 一个短链编码,去数据库select * from table where code =XXX,返回给用户就行
第2集 需求出发-带你详细一个短链的生命周期
简介: 需求出发带你详细一个短链的生命周期
- 创建者和访问者
创建者
- 流量包管理
- 免费流量包
- 付费流量包
分组管理
- 新增分组
- 删除分组
- 修改分组
- 查看分组下的短链
短链管理
- 创建短链
- 目标地址
- 短链标题
- 短链域名
- 所属分组
- 有效期
-
-
- 删除短链
- 修改短链
- 查看短链
- 访问PV、UV
- 地域分布
- 时间分布
- 来源分布
- …
-
- 访问者
- 访问短链
- 跳转目标站点
第3集 短链服务生成短链URL的问题你能想到多少
简介: 短链URL生成服务里面的问题你能想到多少
- 短链码如何生成
需要解决的问题(自己是技术Leader,能否想到这些问题,并解决。做架构设计之前,要想清楚)
- 问题一:长链的关系和短链的关系
- 一对一?
- 一对多?
- 多对多?
- 问题二:前端访问短链是如何跳转到对应的页面的?
- 问题三:短链码是如何生成的
- 知道几种方式?
- 问题四:SaaS类型业务,数据量有多大,是否要分库分表
- 问题五:如果分库分表,PartitionKey是哪个?使用怎样的策略
- 问题六:如果分库分表,访问短链怎么知道具体是哪个库哪个表?
- 问题七:如果分库分表,怎么查看某个账号创建的全部短链?
第4集 短链服务问题解决方案讲解-业务关系+跳转问题
简介: 短链服务问题解决方案讲解-业务关系+跳转问题
-
问题一:长链的关系和短链的关系是一对一还是一对多?
- 一个长链,在不同情况下,生成的短网址应该不一样,才不会造成冲突
- 多渠道推广下,也可以区分统计不同渠道的效果质量
- 所以是 一个短链接只能对应一个长链接,当然一个长链接可以对应多个短链接
-
问题二:前端访问短链是如何跳转到对应的页面的?
-
服务端转发
- 由服务器端进行的页面跳转,刚学Servlet时, 从OneServlet中转发到TwoServlet
- 地址栏不发生变化,显示的是上一个页面的地址
- 请求次数:只有1次请求
- 转发只能在同一个应用的组件之间进行,不可以转发给其他应用的地址
request.getRequestDispatcher("/two").forward(request, response);
-
页面的跳转-重定向
- 由浏览器端进行的页面跳转
- 重定向涉及到3xx状态码,访问跳转是301还是302,301和302代表啥意思?
- 301 是永久重定向
- 会被浏览器硬缓存,第一次会经过短链服务,后续再访问直接从浏览器缓存中获取目标地址
- 302 是临时重定向
- 不会被浏览器硬缓存,每次都是会访问短链服务
- 短地址一经生成就不会变化,所以用 301 是同时对服务器压力也会有一定减少
- 但是如果使用了 301,无法统计到短地址被点击的次数
- 所以选择302虽然会增加服务器压力,但是有很多数据可以获取进行分析
- 选择使用302,这个也可以对违规推广的链接进行实时封禁
- 301 是永久重定向
第5集 短链服务问题解决方案讲解-短链码生成解决方案《上》
简介: 短链服务问题解决方案讲解-短链码生成解决方案《上》
- 问题三:短链码如何是如何生成的
- 短链码特点
- 生成性能强劲
- 碰撞概率低
- 避免重复
- 恶意猜测
- 业务规则安全
方式
-
自增ID
- 利用插入数据库,利用数据库自增id
- 把自增id转成62进制作为短链码
- 短链码的长度不固定,随着 id 变大,短链码长度也增长
- 可以指定从某个长度开始增长,到百亿、千亿数量
- 转换工具:https://tool.lu/hexconvert/
- 是否存在重复: 不重复
- 但短链码是有序的递增,存在【业务数据安全】问题
-
-
MD5内容压缩
- 长链接做md5加密
43E08496,9E5CF455,E6D2D2B3,3407A6D2
- 加密串查询是否已经生成过短链接
- 如果已经存在,则拼接时间戳再MD5加密,插入数据库
- 如果不存在则把长链接、长链接加密串插入数据库
- 取MD5后 最后1 个 8 位字符串作为短链码
- 是否存在重复: 存在碰撞(重复)可能
- 是有损压缩算法,数据量超大情况碰撞概念越大
- 比如 老王的女友有300多个,每再多1个,再同一天生日的概率越大,就更加复杂
-
第6集 【重要】敏感数据+自增ID暴露的商业秘密
简介: 敏感数据讲解+自增ID暴露的商业秘密
-
什么是数据脱敏
-
也叫数据的去隐私化,在给定脱敏规则和策略的情况下,对敏感数据比如
手机号
、身份证
等信息,进行转换或者修改的一种技术手段,防止敏感数据直接在不可靠的环境下使用和泄露、撞库等 -
技术分两类
- 静态数据脱敏
- 将生产数据导出,进行对外发送或者给开发、测试人员等
- 动态数据脱敏
- 程序直接连接生产数据的场景,如运维人员在运维的工作中直接连接生产数据库进行运维
- 客服人员在生产中通过后台查询的个人信息
- 静态数据脱敏
-
-
数据库业务规则安全:自增ID暴露的商业秘密
-
背景
作为后端开发人员肯定离不开数据库设计,尽管你知道数据安全、接口安全、网络安全,但你也很大可能不小心暴露的公司的核心机密。 【做空上市公司的股票】如果你有炒股,那你知道如果这个数据库设计漏洞被他人知道,就可以做空一个上司公司的股票的不? 【摧毁对手的利器】如果一个公司在是靠业务数据来说话的,如果被他人知道,在核心的时间点,被披露出来,那融资可能凉凉,企业可能面临倒闭。
-
在某天一个竞争对手 老王 做竞品调研的时候,注册了你公司的应用
【暴露了总用户量】 通过业务接口抓包分析(假定数据没做加密或者加密被破解了),被他发现了自增id这个事情,他好几个号注 册了,编号都是一百多万,每次id都是自增1, 用户量最多100多万,就此暴雷了。 经过有经验的人知道不能对外暴露id这个事情,但是总有关联的业务,或者其他不知道的人员开发了对应 的功能,比如 订单表、记录表、收藏表或者其他和user_id有关联的,只要他操作业务,接口有返回user_id,就容易出问题了。
【暴露了每日拉新数据】 如果是用户自增id,老王 肯定不单停留这里这么简单,假如他想看这个产品每日新增的用户有多少。 毕竟拉新这个指标是很多公司都离不开的,比如通过投放广告、买量业务等等去获取新用户。 老王想看下这个公司每天新增用户量大不大,他就今天注册一个看id多少,明天再注册一个看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字段,类似的敏感字段都是
第7集 短链服务问题解决方案讲解-短链码生成解决方案《下》
简介: 短链URL服务问题解决方案讲解-短链码生成解决方案《下》
-
哈希算法:将一个元素映射成另一个元素
-
加密哈希,如SHA256、MD5(上集讲了)
-
非加密哈希,如MurMurHash,CRC32
-
-
MurMurHash
Murmur哈希是一种非加密散列函数,适用于一般的基于散列的查找。 它在2008年由Austin Appleby创建,在Github上托管,名为“SMHasher” 的测试套件。 它也存在许多变种,所有这些变种都已经被公开。 该名称来自两个基本操作,乘法(MU)和旋转(R)--来自百科
-
是一种【非加密型】哈希函数且【随机分布】特征表现更良好
-
由于是非加密的哈希函数,性能会比MD5强
-
再很多地方都用到比如Guava、Jedis、HBase、Lucence等
-
存在两个版本
- MurmurHash2(产生32位或64位值)
- MurmurHash3(产生32位或128位值)
-
数据量
- MurmurHash的 32 bit 能表示的最大值近 43 亿的10进制
- 满足多数业务,如果接近43亿则冲突概率大
- 产品目标【超理想情况】
首年日活用户: 10万 首年日新增短链数据:10万*50 = 500万 年新增短链数:500万 * 365天 = 18.2亿 年新增用户数:50万/1年 年营收目标: 10万付费用户 * 客单价200元 = 2千万 新增短链:50条/用户每日
- MurMurHash得到的数值是10进制,一般会转化为62进制进行缩短
- 例子
- 10进制:1813342104
- 转62进制:1YIB7i
- https://tool.lu/hexconvert/
- 例子
- 常规短链码是6~8位数字+大小写字母组合
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 6 位 62 进制数可表示 568 亿个短链(62的6次方,每位都有62个可能,如果扩大位数到7位,则可以支持3万5200亿)
- MurmurHash的 32 bit 满足多数业务 43亿
- 拼接上库-表位则可以表示更多数据(后续会讲分库分表的,库表位)
- 7位则可以到到 43亿 * 62 = 2666亿
- 8位则可以到到 2666亿 * 62 = 1.65万亿条数据
- 结合短链过期数据归档,理论上满足未来全部需求了
- 数据库存储
- 单表1千万 * 62个库 * 62表 = 384亿数据
- MurmurHash的 32 bit 能表示的最大值近 43 亿的10进制
-
h3(产生32位或128位值)
-
数据量
- MurmurHash的 32 bit 能表示的最大值近 43 亿的10进制
- 满足多数业务,如果接近43亿则冲突概率大
- 产品目标【超理想情况】
首年日活用户: 10万 首年日新增短链数据:10万*50 = 500万 年新增短链数:500万 * 365天 = 18.2亿 年新增用户数:50万/1年 年营收目标: 10万付费用户 * 客单价200元 = 2千万 新增短链:50条/用户每日
- MurMurHash得到的数值是10进制,一般会转化为62进制进行缩短
- 例子
- 10进制:1813342104
- 转62进制:1YIB7i
- https://tool.lu/hexconvert/
- 例子
- 常规短链码是6~8位数字+大小写字母组合
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 6 位 62 进制数可表示 568 亿个短链(62的6次方,每位都有62个可能,如果扩大位数到7位,则可以支持3万5200亿)
- MurmurHash的 32 bit 满足多数业务 43亿
- 拼接上库-表位则可以表示更多数据(后续会讲分库分表的,库表位)
- 7位则可以到到 43亿 * 62 = 2666亿
- 8位则可以到到 2666亿 * 62 = 1.65万亿条数据
- 结合短链过期数据归档,理论上满足未来全部需求了
- 数据库存储
- 单表1千万 * 62个库 * 62表 = 384亿数据
- MurmurHash的 32 bit 能表示的最大值近 43 亿的10进制