---
title: Day02
index: false
icon: laptop-code
category:
  - 开发笔记
  - 学习记录
---

## 任务

- [x] 表设计
- [x] 抽奖领域模块开发

## 学习过程

1. 查询分库分表相关知识点，了解到垂直和水平分库分表，主要是为了解决数据量过大导致 MySQL 查询慢、单体容量过大问题
2. 开始写代码
   1. 编写基础的持久化对象 (PO)
   2. 编写 Mapper 接口
   3. 编写对应的 Mapper.xml
   4. 设计抽奖策略顶级接口，主要是入参出参，如何封装，要封装哪些数据
   5. 编写顶级接口的基础实现，实现里面公用的方法，比如把初始化方法、哈希计算的方法以及判断是否初始化完成
   6. 编写两种算法的实现
   7. 算法单元测试

## 遇到的问题

1. 为什么在设计阶段就考虑分库分表等问题

   在之前的学习过程中，并没有项目环境的支撑，导致了这个问题，一个大的项目，如果要兼顾性能以及代码的可扩展性，那么在数据库设计阶段就应该想到这些，那些是热点数据，那些数据会进行大量的插入，没有全局把控的观念，只有了解这些，才能设计出一个性能良好且代码可维护性高的项目，这个需要项目积累，这是一个很重要的东西，以后在学习的时候一定要多注意这方面，多看看别人的数据库是怎么设计的，以及为什么要这么设计，要有全局把控的观念

2. 抽奖算法是怎么实现的呢

   首先这个初始化的时候，传入奖品和对应的概率，然后概率乘以 100，就是对应的下标范围，一个奖品一个范围，是不会重复的，然后经过斐波那契哈希散列算法，将这个对应的下标进行加工，使其均匀的分布在数组中，在对下标进行加工的过程中，确保了无论传入什么数字，都会在 0 ~ 128 的范围内

   1. SingleRateRandomDrawAlgorithm

      这种策略是生成一个 1 ~ 100 的随机数，然后经过 hashIdx 计算对应的下标，然后去上面初始化好的数组中去取奖品

   2. DefaultRateRandomDrawAlgorithm

      这是一种必中奖策略，先排除掉不在抽奖范围内的奖品ID，然后生成随机数，然后判断这个随机数是否在指定的范围内，如果不在，那么这个奖品就没中，然后看下一个奖品，重新生成随机数，然后看是否在指定的中奖概率内加上上次生成的随机数范围内

## 总结

今天主要把抽奖算法给搞定了，虽然代码不多，但是很难理解，最开始都搞不清楚为什么这样子就实现了抽奖算法，不懂这个概率是如何保证的，然后 debug 了好久，发现其实就是一个 128 长度的数组，然后经过哈希散列排列，保证随机的均匀性，其实这 128 长度的数组就已经保证了抽奖的概率，假设不经过哈希算法，直接放进去，假设两个的抽奖概率是 0.1 和 0.2，那么放进去的时候就是下标 1~10 全是第一个奖品，下标 11 ~ 30 全是第二个奖品，随机数生成的是 1 ~ 100，那么第一个奖品也就是有 10 个数字能中奖，那不就是 10% 的中奖概率了么，加哈希散列只是为了均匀分布，增加随机性和公平性

收获：

1. 对 DDD 有更深的了解，知道什么类该写在什么包下，比昨天更清楚代码该如何组织了
2. 了解了分库分表，虽然是第一次接触，但是至少知道了为什么要分库分表，随着项目的进行，就会学会如何分库分表了吧
3. 了解了 Hash 散列算法，后续看看源码，要搞清楚底层是如何运作的

