Redis 生成电商系统商品全局唯一 ID
业务场景
在互联网电商系统中通常有着千亿级别的商品数据,万亿级别的订单数据;而传统的单库单表是无法支撑这种级别的数据的,通常会采用分库分表。
但是一旦进行分库分表,数据库表中原先设计的自增 ID 就会失去意义,所以在分布式系统中通常需要一个全局唯一 ID 来标识每一条数据。
全局唯一 ID 生成的技术方案有很多,业界比较有名的有
UUID
Redis
Snowflake
Leaf
实战演练
这里我们使用 Redis INCR 命令来实现分布式系统全局唯一 ID
核心 Maven Dependency
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency>
核心 application.properties
spring.redis.host=localhostspring.redis.port=6379spring.redis.database=0spring.redis.password=spring.redis.timeout=2000spring.redis.lettuce.pool.max-active=50spring.redis.lettuce.pool.max-wait=2000spring.redis.lettuce.pool.max-idle=10spring.redis.lettuce.pool.min-idle=10
RedisConfiguration.java
package org.fool.springboot.config;import org.springframework.cache.CacheManager;import org.springframework.cache.annotation.EnableCaching;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.cache.RedisCacheConfiguration;import org.springframework.data.redis.cache.RedisCacheManager;import org.springframework.data.redis.cache.RedisCacheWriter;import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;import org.springframework.data.redis.serializer.RedisSerializationContext;import org.springframework.data.redis.serializer.StringRedisSerializer;import java.time.Duration;public class RedisConfiguration {public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory connectionFactory) {RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(connectionFactory);GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);redisTemplate.setKeySerializer(new StringRedisSerializer());redisTemplate.setHashKeySerializer(new StringRedisSerializer());redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);redisTemplate.afterPropertiesSet();return redisTemplate;}public CacheManager cacheManager(LettuceConnectionFactory connectionFactory) {RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(30L)).disableCachingNullValues().serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory)).cacheDefaults(redisCacheConfiguration).build();}}
IdGeneratorService.java
package org.fool.springboot.service;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.stereotype.Service;public class IdGeneratorService {private StringRedisTemplate stringRedisTemplate;private static final String CACHE_MERCHANDISE_ID_KEY = "MERCHANDISE::ID";public Long genId() {return stringRedisTemplate.opsForValue().increment(CACHE_MERCHANDISE_ID_KEY);}}
MerchandiseRequest.java
package org.fool.springboot.contract.request;import lombok.Data;public class MerchandiseRequest {private Long id;private String name;private Double price;private String desc;}
MerchandiseController.java
Test
多次执行以下 curl 命令
curl --location --request POST 'http://localhost:8080/merchandise/create' \--header 'Content-Type: application/json' \--data-raw '{"name": "Car","price": 300000.00,"detail": "Lexus"}'
泰克风格 只讲干货 不弄玄虚
