原創轉載請註明出處:http://www.javashuo.com/article/p-gueovgml-np.htmlhtml
在互聯網系統中,併發越大的系統,數據就越大,數據越大就越須要分佈式,而大量的分佈式數據就越須要惟一標識來識別它們。java
例如淘寶的商品系統有千億級別商品,訂單系統有萬億級別的訂單數據,這些數據都是日漸增加,傳統的單庫單表是沒法支撐這種級別的數據,必須對其進行分庫分表;一旦分庫分表,表的自增ID就失去了意義;故須要一個全局惟一的ID來標識每一條數據(商品、訂單)。web
e.g: 一張表1億條數據,被分庫分表10張表,原先的ID就失去意義,因此須要全局惟一ID來標識10張表的數據。redis
全局惟一的ID生成的技術方案有不少,業界比較有名的有 UUID、Redis、Twitter的snowflake算法、美團Leaf算法。 算法
INCR 命令主要有如下2個特徵:spring
基於以上2個特性,能夠採用INCR命令來實現分佈式全局ID生成。數據庫
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.8.RELEASE</version> <relativePath/> </parent> <modelVersion>4.0.0</modelVersion> <groupId>org.fool.redis</groupId> <artifactId>redis-string-id</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
spring.application.name=redis-spring-id server.port=8888 spring.redis.host=localhost spring.redis.port=6379 spring.redis.database=0 spring.redis.password= spring.redis.timeout=2000 spring.redis.pool.max-active=10 spring.redis.pool.max-wait=1000 spring.redis.pool.max-idle=10 spring.redis.pool.min-idle=5 spring.redis.pool.num-tests-per-eviction-run=1024 spring.redis.pool.time-between-eviction-runs-millis=30000 spring.redis.pool.min-evictable-idle-time-millis=60000 spring.redis.pool.soft-min-evictable-idle-time-millis=10000 spring.redis.pool.test-on-borrow=true spring.redis.pool.test-while-idle=true spring.redis.pool.block-when-exhausted=false
Application.javaapache
1 package org.fool.redis; 2 3 import org.springframework.boot.SpringApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication; 5 6 @SpringBootApplication 7 public class Application { 8 public static void main(String[] args) { 9 SpringApplication.run(Application.class, args); 10 } 11 }
Product.javajson
1 package org.fool.redis.model; 2 3 import lombok.Data; 4 5 import java.math.BigDecimal; 6 7 @Data 8 public class Product { 9 private Long id; 10 private String name; 11 private BigDecimal price; 12 private String detail; 13 }
IdGeneratorService.java架構
1 package org.fool.redis.service; 2 3 import org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.data.redis.core.StringRedisTemplate; 5 import org.springframework.stereotype.Service; 6 7 @Service 8 public class IdGeneratorService { 9 @Autowired 10 private StringRedisTemplate stringRedisTemplate; 11 12 private static final String ID_KEY = "id:generator:product"; 13 14 public Long incrementId() { 15 return stringRedisTemplate.opsForValue().increment(ID_KEY); 16 } 17 }
ProductController.java
1 package org.fool.redis.controller; 2 3 import lombok.extern.slf4j.Slf4j; 4 import org.fool.redis.model.Product; 5 import org.fool.redis.service.IdGeneratorService; 6 import org.springframework.beans.factory.annotation.Autowired; 7 import org.springframework.web.bind.annotation.PostMapping; 8 import org.springframework.web.bind.annotation.RequestBody; 9 import org.springframework.web.bind.annotation.RequestMapping; 10 import org.springframework.web.bind.annotation.RestController; 11 12 @RestController 13 @Slf4j 14 @RequestMapping(value = "/product") 15 public class ProductController { 16 @Autowired 17 private IdGeneratorService idGeneratorService; 18 19 @PostMapping(value = "/create") 20 public String create(@RequestBody Product obj) { 21 //生成分佈式id 22 long id = idGeneratorService.incrementId(); 23 24 //使用全局id 代替數據庫的自增id 25 obj.setId(id); 26 27 //取模(e.g: 這裏分爲8張表,海量數據能夠分爲1024張表),計算表名 28 int table = (int) id % 8; 29 String tableName = "product_" + table; 30 31 log.info("insert to table: {}, with content: {}", tableName, obj); 32 33 return "insert to table: " + tableName + " with content: " + obj; 34 } 35 }
curl --location --request POST 'http://localhost:8888/product/create' \ --header 'Content-Type: application/json' \ --data-raw '{ "name": "Car", "price": "300000.00", "detail": "Lexus Style" }'