1. Redis INCR
分布式ID基于Redis其实就是基于命令 INCR 。作用:将存储在key处的数字加1。如果该键不存在,则在执行操作前将其设置为0。如果键包含错误类型的值或包含不能用整数表示的字符串,则返回错误。此操作仅限于64位有符号整数。同时 INCR 操作是原子操作 。 这个是保证多线程高并发下生成数据不重复的原因。
2. 如何利用INCR做分布式ID生成器
redis:6379> SET mykey "10"
"OK"
redis:6379> INCR mykey
(integer) 11
redis:6379> GET mykey
"11"
redis:6379>
- 确定一个KEY作为分布式ID的生成器
- 然后调用INCR命令获取对应KEY的返回的值,这个值就是全局ID的值
3. Java具体实现代码
@RestController
@RequestMapping("/generator/redis")
public class Generator4MysqlController {
@Autowired
private RedisTemplate redisTemplate;
@GetMapping("/id")
public Long getDistributedId() {
return redisTemplate.opsForValue().increment("KEY");
}
}
Tips:代码地址github.com/mxsm/distri…
4. 优缺点
优点:
- 不依赖于数据库,灵活方便,且性能优于数据库。
- 实现起来简单,并发的工作不需要实现者来考虑,
INCR命令本身就是原子操作 - 需要进行业务分类来获取全局的分布式ID而言,只需要增加KEY值就可以了,用MySQL实现简单很多。
缺点:
- 如果系统中没有Redis需要,需要为这个引入Redis增加了故障点和系统的复杂程度。
- 相比本地生成增加了网络的消耗
Tips:对于全局ID来说最重要的是不能出现重复,所以对于Redis就需要考虑持久化。Redis的持久化方式有两种
RDB和AOF
- RDB持久化方案是按照指定时间间隔对你的数据集生成的时间点快照, 将数据库的快照(snapshot)以二进制的方式保存到磁盘中。也就是定时快照,如果在连续自增但是Redis在下个快照生成之前发生了Redis宕机。那么在上一次快照生成到宕机生成的自增ID就没有被快照保存。重启Redis后就会出现ID重复的情况。
- AOF 则以协议文本的方式,将所有对数据库进行过写入的命令(及其参数)记录到 AOF 文件,以此达到记录数据库状态的目的。所以即即使
Redis挂掉了也不会出现ID重复的情况。但是 Redis 重启回复数据时间过长。建议分布式ID生成单独使用一套Redis所以对比以上两种持久化以及分布式全局ID的不能重复的特殊性AOF持久化是不二的选择。
5. 总结
用Redis作为分布式ID生成器总的来说由于MySQL来实现。同样实现方式简单也可以达到很高并发性能更好。
我是蚂蚁背大象,文章对你有帮助点赞关注我,文章有不正确的地方请您斧正留言评论~谢谢
参考资料: