我在学习ID全局生成器的时候,想生成下图这样的id模板,但是最后return出现了一个或运算我不太理解,
而且 long count = stringRedisTemplate.opsForValue().increment("icr:"+keyPrefix+":"+date);这条语句的执行结果只有1或者0,为什么 return timestamp<< COUNT_BITS | count; 就可以实现下面这个模板呢?
//基于Redis的id生成器
@Component
public class RedisWorker {
// 开始的一个时间戳
// 时间戳 指的就是Unix时间戳(Unix timestamp)。
// 它也被称为Unix时间(Unix time)、POSIX时间(POSIX time),是一种时间表示方式,
// 定义为从格林威治时间1970年01月01日00时00分00秒起至现在的总秒数。
private static final long BEGIN_TIMESTAPMP=1640995200L;
// 序列号的位数
private static final int COUNT_BITS = 32;
@Resource
private StringRedisTemplate stringRedisTemplate;
/**
*
* @param keyPrefix 前缀
* @return
*/
public long nextId(String keyPrefix){
// 1.生成时间戳 当前时间
LocalDateTime now = LocalDateTime.now();
// 当前时间的秒数
long nowSecond = now.toEpochSecond(ZoneOffset.UTC);
// 计算一下时间戳
long timestamp = nowSecond-BEGIN_TIMESTAPMP;
// 2.生成序列号 我们用的Redis中的String数据结构 increment是自增,括号可以填一个参数key
// 2.1获取当前日期,精确到Tina
String date = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));
// 2.2 自增长 我们在后面添加一个日期还是有好处的,每一天都是不同的key,当我们获取某一天的订单的时候也好查询,
// 另外如果都是用同一个key的话,可能会超过2的32次方
long count = stringRedisTemplate.opsForValue().increment("icr:"+keyPrefix+":"+date);
// 3.拼接并返回
// 借助位运算进行拼接,如果直接拼接的话就成字符串了
// 时间戳移动32位(因为我们定义的就是32位,定义为了一个常量) 后面空出来的32位(序列号)就补零
// 序列号采用或运算填充 后面32为刚开始为0,count可能为0也可能为1,不管是0还是1 都填入进去
return timestamp<< COUNT_BITS | count;
}
// 用下面这个方法可以获取当前的时间戳
// public static void main(String[] args) {
//// 得到2022年一月一号0时0分0秒这个时间
// LocalDateTime time = LocalDateTime.of(2022, 1, 1, 0, 0, 0);
//// 得到一个秒数 ZoneOffset.UTC是一个时间戳
// long second =time.toEpochSecond(ZoneOffset.UTC);
// System.out.println(second);
// }
}