26 changed files with 330 additions and 57 deletions
@ -0,0 +1,35 @@
|
||||
package nets.sopod.soim.das.user.service; |
||||
|
||||
import net.sopod.soim.common.util.ImClock; |
||||
import net.sopod.soim.das.user.DasUserApplication; |
||||
import net.sopod.soim.logic.api.segmentid.core.SegmentIdGenerator; |
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
import org.springframework.boot.test.context.SpringBootTest; |
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; |
||||
|
||||
import javax.annotation.Resource; |
||||
|
||||
/** |
||||
* SegmentIdGeneratorTest |
||||
* |
||||
* @author tmy |
||||
* @date 2022-04-04 09:34 |
||||
*/ |
||||
@RunWith(SpringJUnit4ClassRunner.class) |
||||
@SpringBootTest(classes = DasUserApplication.class) |
||||
public class SegmentIdGeneratorTest { |
||||
|
||||
@Resource |
||||
private SegmentIdGenerator segmentIdGenerator; |
||||
|
||||
@Test |
||||
public void test() { |
||||
long begin = ImClock.millis(); |
||||
for (int i = 0; i < 100000; i++) { |
||||
System.out.println(segmentIdGenerator.nextId("im_user")); |
||||
} |
||||
System.out.println(ImClock.millis() - begin + "ms"); |
||||
} |
||||
|
||||
} |
||||
@ -1,4 +1,4 @@
|
||||
package net.sopod.soim.logic.api.auth.model; |
||||
package net.sopod.soim.logic.user.auth.model; |
||||
|
||||
/** |
||||
* LoginParam |
||||
@ -1,6 +1,6 @@
|
||||
package net.sopod.soim.logic.api.auth.service; |
||||
package net.sopod.soim.logic.user.auth.service; |
||||
|
||||
import net.sopod.soim.logic.api.auth.model.ReqLogin; |
||||
import net.sopod.soim.logic.user.auth.model.ReqLogin; |
||||
|
||||
/** |
||||
* AuthService |
||||
@ -1,4 +1,4 @@
|
||||
package net.sopod.soim.logic.api.user.service; |
||||
package net.sopod.soim.logic.user.service; |
||||
|
||||
/** |
||||
* UserService |
||||
@ -0,0 +1,37 @@
|
||||
package net.sopod.soim.logic.api.segmentid.config; |
||||
|
||||
import net.sopod.soim.logic.api.segmentid.core.SegmentIdGenerator; |
||||
import net.sopod.soim.logic.api.segmentid.service.SegmentIdService; |
||||
import org.apache.dubbo.config.annotation.DubboReference; |
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
|
||||
/** |
||||
* SegmentIdAutoConfiguration |
||||
* o( ̄ヘ ̄o#) |
||||
* |
||||
* @author tmy |
||||
* @date 2022-04-05 21:02 |
||||
*/ |
||||
@ConditionalOnProperty( |
||||
prefix = "im-segment-id", |
||||
name = {"enabled"}, |
||||
matchIfMissing = true |
||||
) |
||||
@Configuration |
||||
public class SegmentIdAutoConfiguration { |
||||
|
||||
@DubboReference |
||||
private SegmentIdService segmentIdService; |
||||
|
||||
@Bean |
||||
public SegmentIdGenerator segmentIdGenerator() { |
||||
if (segmentIdService == null) { |
||||
throw new NullPointerException("segmentIdService bean not exists!"); |
||||
} |
||||
return new SegmentIdGenerator(segmentIdService); |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,34 @@
|
||||
package net.sopod.soim.logic.api.segmentid.core; |
||||
|
||||
import java.util.concurrent.atomic.AtomicLong; |
||||
|
||||
/** |
||||
* Segment |
||||
* |
||||
* @author tmy |
||||
* @date 2022-04-03 23:12 |
||||
*/ |
||||
public class Segment { |
||||
|
||||
private final AtomicLong atomicId; |
||||
|
||||
private final long end; |
||||
|
||||
public Segment(long begin, long end) { |
||||
atomicId = new AtomicLong(begin); |
||||
this.end = end; |
||||
} |
||||
|
||||
public boolean hasNext() { |
||||
return this.atomicId.get() <= this.end; |
||||
} |
||||
|
||||
public long next() { |
||||
long id = this.atomicId.getAndIncrement(); |
||||
if (id > this.end) { |
||||
throw new IllegalStateException("id最大值超过范围"); |
||||
} |
||||
return id; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,56 @@
|
||||
package net.sopod.soim.logic.api.segmentid.core; |
||||
|
||||
import net.sopod.soim.logic.api.segmentid.model.SegmentRange; |
||||
import net.sopod.soim.logic.api.segmentid.service.SegmentIdService; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.LinkedList; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* SegmentGenerator |
||||
* |
||||
* @author tmy |
||||
* @date 2022-04-03 23:21 |
||||
*/ |
||||
public class SegmentIdGenerator { |
||||
|
||||
private final SegmentIdService segmentIdService; |
||||
|
||||
private final Map<String, LinkedList<Segment>> segmentsMap; |
||||
|
||||
public SegmentIdGenerator(SegmentIdService segmentIdService) { |
||||
this.segmentIdService = segmentIdService; |
||||
segmentsMap = new HashMap<>(); |
||||
} |
||||
|
||||
/** |
||||
* TODO 动态增加步长 |
||||
* TODO 剩余数一半时, 异步更新 segment |
||||
* @param bizTag 业务标签,同一业务标签生成id唯一 |
||||
* @return id |
||||
*/ |
||||
public long nextId(String bizTag) { |
||||
if (bizTag == null || bizTag.isEmpty()) { |
||||
throw new IllegalStateException("bizTag can not be empty!"); |
||||
} |
||||
synchronized (bizTag.intern()) { |
||||
LinkedList<Segment> segments = segmentsMap.computeIfAbsent(bizTag, tag -> { |
||||
LinkedList<Segment> nextSegments = new LinkedList<>(); |
||||
SegmentRange range = segmentIdService.nextSegmentId(bizTag); |
||||
Segment segment = new Segment(range.getBeginId(), range.getEndId()); |
||||
nextSegments.add(segment); |
||||
return nextSegments; |
||||
}); |
||||
Segment segment = segments.getFirst(); |
||||
if (!segment.hasNext()) { |
||||
SegmentRange nextRange = segmentIdService.nextSegmentId(bizTag); |
||||
segment = new Segment(nextRange.getBeginId(), nextRange.getEndId()); |
||||
segments.removeFirst(); |
||||
segments.add(segment); |
||||
} |
||||
return segment.next(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -1,4 +1,4 @@
|
||||
package net.sopod.soim.logic.segmentid.api.model.dto; |
||||
package net.sopod.soim.logic.api.segmentid.model; |
||||
|
||||
import lombok.Data; |
||||
|
||||
@ -0,0 +1,17 @@
|
||||
package net.sopod.soim.logic.api.segmentid.service; |
||||
|
||||
import net.sopod.soim.logic.api.segmentid.model.SegmentRange; |
||||
|
||||
/** |
||||
* SegmentIdService |
||||
* |
||||
* @author tmy |
||||
* @date 2022-04-02 23:07 |
||||
*/ |
||||
public interface SegmentIdService { |
||||
|
||||
SegmentRange nextSegmentId(String bizTag); |
||||
|
||||
SegmentRange nextSegmentId(String bizTag, Long step); |
||||
|
||||
} |
||||
@ -1,13 +0,0 @@
|
||||
package net.sopod.soim.logic.segmentid.api.model; |
||||
|
||||
/** |
||||
* Segment |
||||
* |
||||
* @author tmy |
||||
* @date 2022-04-02 11:58 |
||||
*/ |
||||
public class Segment { |
||||
|
||||
|
||||
|
||||
} |
||||
@ -1,18 +0,0 @@
|
||||
package net.sopod.soim.logic.segmentid.api.service; |
||||
|
||||
import net.sopod.soim.logic.segmentid.api.model.dto.NextSegmentParam; |
||||
import net.sopod.soim.logic.segmentid.api.model.dto.SegmentDTO; |
||||
|
||||
/** |
||||
* SegmentIdService |
||||
* |
||||
* @author tmy |
||||
* @date 2022-04-02 23:07 |
||||
*/ |
||||
public interface SegmentIdService { |
||||
|
||||
SegmentDTO nextSegmentId(String bizTag); |
||||
|
||||
SegmentDTO nextSegmentId(String bizTag, Long step); |
||||
|
||||
} |
||||
@ -0,0 +1 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=net.sopod.soim.logic.api.segmentid.config.SegmentIdAutoConfiguration |
||||
@ -0,0 +1,10 @@
|
||||
package net.sopod.soim.logic.user.service; |
||||
|
||||
/** |
||||
* UserServiceImpl |
||||
* |
||||
* @author tmy |
||||
* @date 2022-04-04 10:03 |
||||
*/ |
||||
public class UserServiceImpl { |
||||
} |
||||
Loading…
Reference in new issue