分布式主键生成策略

在分布式系统中id需要满足一下条件

1、全局唯一性
2、信息安全:防止恶意用户通过id的规则来获取数据
3、数据递增:保证下一个id一定大于上一个id

业内解决方案

1、uuid通用唯一识别码
优点:代码实现简单,不占宽带,数据迁移不受影响。 缺点:无序不能保证递增,字符串存储传输查询慢不可读。

2、snowfiake雪花算法
高位随机码+毫秒数+机器码(数据中心+机器id)+IO流水号
优点:代码简单,不占宽带,数据迁移不受影响。 缺点:强依赖时钟后台服务器时间一样,无序。

SnowFlake算法优点:是全局唯一、自增、有序、纯数字组成查询效率高且不依赖于数据库。适合在分布式的场景中应用,可根据需求调整具体实现细节。

SnowFlake算法缺点:依赖于系统时间,雪花算法在单机系统上ID是递增的,但是在分布式系统多节点的情况下,所有节点的时钟改变或者其他情况,就有可能会出现不是全局递增的情况。

3、mysql主键生成策略
缺点:依赖数据库,存在单点故障问题

4、使用redis生成主键
优点:不依赖数据库,高可用
缺点:占用网络资源

使用redis实现

核心代码RedisServiceImpl.java

使用当前日期的年份的后两位+一年中的天数+一天中的小时数作为前缀,使用redis自增保持主键递增性,最后可以使用加密算法保证主键安全性。

@Service
public class RedisServiceImpl implements RedisService {

	@Autowired
	JedisPool jedisPool;

	public String getOrderID(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int year = calendar.get(Calendar.YEAR);
		int day = calendar.get(Calendar.DAY_OF_YEAR);
		int hour = calendar.get(Calendar.HOUR_OF_DAY);
		String dayFmt = String.format("%1$03d", day);
		String hourFmt = String.format("%1$02d", hour);
		return (year - 2000) + dayFmt + hourFmt;
	}

	public Long orderId(String prefix) {
		Jedis jedis = jedisPool.getResource();
		String key = "t1_order_id" + prefix;
		Long index = jedis.incr(key);
		String orderId = prefix + String.format("%1$05d", index);
		return Long.parseLong(orderId);
	}

	public Long id() {
		return orderId(getOrderID(new Date()));
	}
}

你可能感兴趣的:(#,分布式,分布式)