1、UUID
UUID可以应用在Token生成和数据库主键生成上
2、数据库自增方式
如果数据库是集群的时候会出现问题:
可以应用读写分离,可是这样在数据库写的效率会降低;
可以应用设置步长的方式来解决;可是这样也有缺点,就是一旦设定步长,后期无法再扩展;(ElasticSearch)
3、基于Redis实现
当前日期 + 5位自增id(根据一毫秒中的订单数最大值来确定)
redis先天性高并发安全,因为单线程
一般来说都是先生成订单号存放子redis中,用的时候直接去取就好了(当redis中的订单号少去某个阈值的时候就开始再次生成定量订单号放置于redis中)
考虑在应用主从复制的redis集群中,应该考虑到唯一ID的问题,也应该应用设置步长来解决
考虑失效时间问题 建议设置为24h
package com.mayikt;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
@Autowired
private RedisTemplate redisTemplate;
@RequestMapping("/order")
public String order(String key, Long timeOut) {
RedisAtomicLong redisAtomicLong = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
redisAtomicLong.set(1);
// 设置redis步长增长为2
redisAtomicLong.addAndGet(1);
// for (int i = 0; i < 100; i++) {
long andIncrement = redisAtomicLong.getAndIncrement();
String orderId = prefix() + String.format("%1$05d", andIncrement);
String insertSQL = "insert into orderNumber value('" + orderId + "');";
// System.out.println(Thread.currentThread().getName() +
// ",insertSQL:" + insertSQL);
System.out.println(insertSQL);
if ((null == redisAtomicLong || redisAtomicLong.longValue() == 0) && timeOut > 0) {// 初始设置过期时间
redisAtomicLong.expire(timeOut, TimeUnit.SECONDS);
}
// }
return "success";
}
public static String prefix() {
String temp_str = "";
Date dt = new Date();
// 最后的aa表示“上午”或“下午” HH表示24小时制 如果换成hh表示12小时制
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
temp_str = sdf.format(dt);
return temp_str;
}
public static void main(String[] args) {
System.out.println(prefix());
}
}
4、基于雪花算法
UUID与雪花算法都是不占用宽带的;而数据库自增与redis实现都是需要占用宽带的;