您的位置:首页 > 汽车 > 新车 > 图片制作网页_沧州疫情风险区域_搜索引擎seo关键词优化方法_网推获客平台

图片制作网页_沧州疫情风险区域_搜索引擎seo关键词优化方法_网推获客平台

2024/11/18 13:41:43 来源:https://blog.csdn.net/yqq962464/article/details/143334238  浏览:    关键词:图片制作网页_沧州疫情风险区域_搜索引擎seo关键词优化方法_网推获客平台
图片制作网页_沧州疫情风险区域_搜索引擎seo关键词优化方法_网推获客平台

在上一篇文章,分布式 ID 生成策略(一),我们讨论了基于数据库的 ID 池策略,今天来看另一种实现,基于雪花算法的分布式 ID 生成策略。

在这里插入图片描述
如图所示,我们用 41 位时间戳 + 12 位机器 ID + 10 位序列号,来表示一个 64 位的分布式 ID。

基于这样的雪花算法来保证 ID 的唯一性

  • 时间戳是递增的,不同时刻产生的 ID 肯定是不同的;
  • 机器 ID 是不同的,同一时刻不同机器产生的 ID 肯定也是不同的;
  • 同一时刻同一机器上,可以轻易控制序列号。
CREATE TABLE `global_sequence_time` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',`node_name` varchar(32) NOT NULL DEFAULT '' COMMENT '机器名称,通常为内网IP',`node_id` smallint(6) NOT NULL COMMENT '机器ID,数字,最大1023',`sn` varchar(128) NOT NULL DEFAULT '' COMMENT '业务字段名称',`version` bigint(20) NOT NULL DEFAULT '1' COMMENT '乐观锁版本',`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`),UNIQUE KEY `uk_name` (`sn`,`node_name`) USING BTREE,UNIQUE KEY `uk_id` (`sn`,`node_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='全局ID生成表';
  • node_name:节点名称,默认为节点的内网IP。所以,同一个机器上,部署多个应用,他们的 node_name 是一样的;

  • sn:业务名称,根据此值分类ID的生成;

  • node_id:数字类型,最大值不能超过1024,即此算法最多支持1024个节点。

还有两个唯一约束

  • 同一个业务sn值,在一个机器上不能部署2个;
  • 同一个业务sn值,node_id不能重复。
package idgenerator;/*** Description* 基于SnowFlake算法实现* 将node_id保存在数据库中,根据本机IP地址作为标识.每个机器对应一个node_id.*/
public class TimeBasedIDGenerator extends IDGenerator {protected static final int DEFAULT_RETRY = 6;public static final int NODE_SHIFT = 10;public static final int SEQ_SHIFT = 12;public static final short MAX_NODE = 1024;//最大node 个数,public static final short MAX_SEQUENCE = 4096;//每秒最大ID个数private short sequence;private long referenceTime;private DataSource dataSource;private Map<String, Integer> cachedNodeId = new HashMap<>();private String nodeName;public void setDataSource(DataSource dataSource) {this.dataSource = dataSource;}/****/public TimeBasedIDGenerator() {nodeName = getLocalAddress();}private synchronized Integer getNodeId(String sn) {Integer nodeId = cachedNodeId.get(sn);//正常,返回if (nodeId != null) {return nodeId;}int i = 0;while (i < DEFAULT_RETRY) {nodeId = fetch(sn);if (nodeId > MAX_NODE) {throw new IllegalStateException("node_id is greater than " + MAX_NODE + ",please check sn=" + sn);}if (nodeId > 0) {cachedNodeId.put(sn, nodeId);break;}i++;}return nodeId;}/*** @return The next 64-bit integer.*/public synchronized long next(String sn) {Integer nodeId = getNodeId(sn);if (nodeId == null || nodeId < 0) {throw new IllegalStateException("无法获取nodeId,sn=" + sn);}long currentTime = System.currentTimeMillis();long counter;if (currentTime < referenceTime) {throw new RuntimeException(String.format("Last referenceTime %s is after reference time %s", referenceTime, currentTime));} else if (currentTime > referenceTime) {this.sequence = 0;} else {if (this.sequence < MAX_SEQUENCE) {this.sequence++;} else {throw new RuntimeException("Sequence exhausted at " + this.sequence);}}counter = this.sequence;referenceTime = currentTime;return currentTime << NODE_SHIFT << SEQ_SHIFT | nodeId << SEQ_SHIFT | counter;}/*** 获取nodeId.* @param sn* @return*/private int fetch(String sn) {Connection connection = null;PreparedStatement ps = null;try {connection = dataSource.getConnection();connection.setAutoCommit(true);//普通操作connection.setReadOnly(false);ps = connection.prepareStatement("select node_id from `global_sequence_time` where `sn` = ? and node_name = ? limit 1");ps.setString(1, sn);ps.setString(2, nodeName);ResultSet rs = ps.executeQuery();//已有数据,则直接返回if (rs.next()) {return rs.getInt(1);}ps.close();//如果没有数据,则首先获得已有的最大node_id,然后自增//查询已知最大idps = connection.prepareStatement("select MAX(node_id) AS m_id from `global_sequence_time` where `sn` = ?");ps.setString(1, sn);rs = ps.executeQuery();int id = 1;if (rs.next()) {id = rs.getInt(1) + 1;}ps.close();//新建记录ps = connection.prepareStatement("insert into global_sequence_time(node_name,node_id,sn,create_time,update_time) VALUE (?,?,?,NOW(),NOW())");ps.setString(1, nodeName);ps.setInt(2, id);ps.setString(3, sn);int row = ps.executeUpdate();if (row > 0) {return id;}} catch (Exception e) {throw new RuntimeException(e);} finally {try {if (ps != null) {ps.close();}if (connection != null) {connection.close();}} catch (Exception ex) {//}}return -1;}private String getLocalAddress() {try {Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();//一个主机有多个网络接口while (netInterfaces.hasMoreElements()) {NetworkInterface netInterface = netInterfaces.nextElement();Enumeration<InetAddress> addresses = netInterface.getInetAddresses();while (addresses.hasMoreElements()) {InetAddress address = addresses.nextElement();if (address.isSiteLocalAddress() && !address.isLoopbackAddress()) {return address.getHostAddress();}}}} catch (Exception e) {throw new RuntimeException("无法获取本地IP地址", e);}return null;}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com