Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Administrator
mall4cloud-new
Commits
7abfefba
Commit
7abfefba
authored
Dec 21, 2023
by
shengnan hu
Browse files
init
parents
Pipeline
#281
passed with stage
in 1 minute and 55 seconds
Changes
678
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
1065 additions
and
0 deletions
+1065
-0
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/LeafServerApplication.java
...ain/java/com/mall4j/cloud/leaf/LeafServerApplication.java
+18
-0
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/common/Result.java
...af/src/main/java/com/mall4j/cloud/leaf/common/Result.java
+44
-0
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/common/Status.java
...af/src/main/java/com/mall4j/cloud/leaf/common/Status.java
+18
-0
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/common/ZeroIDGen.java
...src/main/java/com/mall4j/cloud/leaf/common/ZeroIDGen.java
+20
-0
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/exception/InitException.java
...n/java/com/mall4j/cloud/leaf/exception/InitException.java
+12
-0
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/exception/LeafServerException.java
.../com/mall4j/cloud/leaf/exception/LeafServerException.java
+16
-0
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/exception/NoKeyException.java
.../java/com/mall4j/cloud/leaf/exception/NoKeyException.java
+12
-0
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/feign/SegmentFeignController.java
...a/com/mall4j/cloud/leaf/feign/SegmentFeignController.java
+48
-0
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/segment/SegmentIDGenImpl.java
.../java/com/mall4j/cloud/leaf/segment/SegmentIDGenImpl.java
+336
-0
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/segment/dao/IDAllocDao.java
...in/java/com/mall4j/cloud/leaf/segment/dao/IDAllocDao.java
+38
-0
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/segment/dao/IDAllocMapper.java
...java/com/mall4j/cloud/leaf/segment/dao/IDAllocMapper.java
+53
-0
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/segment/dao/impl/IDAllocDaoImpl.java
...om/mall4j/cloud/leaf/segment/dao/impl/IDAllocDaoImpl.java
+67
-0
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/segment/model/LeafAlloc.java
...n/java/com/mall4j/cloud/leaf/segment/model/LeafAlloc.java
+58
-0
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/segment/model/Segment.java
...ain/java/com/mall4j/cloud/leaf/segment/model/Segment.java
+75
-0
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/segment/model/SegmentBuffer.java
...va/com/mall4j/cloud/leaf/segment/model/SegmentBuffer.java
+156
-0
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/service/SegmentService.java
...in/java/com/mall4j/cloud/leaf/service/SegmentService.java
+52
-0
mall4cloud-leaf/src/main/resources/bootstrap.yml
mall4cloud-leaf/src/main/resources/bootstrap.yml
+21
-0
mall4cloud-leaf/target/classes/bootstrap.yml
mall4cloud-leaf/target/classes/bootstrap.yml
+21
-0
mall4cloud-leaf/target/classes/com/mall4j/cloud/leaf/IDGen.class
...oud-leaf/target/classes/com/mall4j/cloud/leaf/IDGen.class
+0
-0
mall4cloud-leaf/target/classes/com/mall4j/cloud/leaf/LeafServerApplication.class
...classes/com/mall4j/cloud/leaf/LeafServerApplication.class
+0
-0
No files found.
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/LeafServerApplication.java
0 → 100644
View file @
7abfefba
package
com.mall4j.cloud.leaf
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.cloud.openfeign.EnableFeignClients
;
/**
* @author leaf
*/
@SpringBootApplication
(
scanBasePackages
=
{
"com.mall4j.cloud"
})
@EnableFeignClients
(
basePackages
=
{
"com.mall4j.cloud.api.**.feign"
})
public
class
LeafServerApplication
{
public
static
void
main
(
String
[]
args
)
{
SpringApplication
.
run
(
LeafServerApplication
.
class
,
args
);
}
}
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/common/Result.java
0 → 100644
View file @
7abfefba
package
com.mall4j.cloud.leaf.common
;
/**
* @author leaf
*/
public
class
Result
{
private
long
id
;
private
Status
status
;
public
Result
()
{
}
public
Result
(
long
id
,
Status
status
)
{
this
.
id
=
id
;
this
.
status
=
status
;
}
public
long
getId
()
{
return
id
;
}
public
void
setId
(
long
id
)
{
this
.
id
=
id
;
}
public
Status
getStatus
()
{
return
status
;
}
public
void
setStatus
(
Status
status
)
{
this
.
status
=
status
;
}
@Override
public
String
toString
()
{
return
"Result{"
+
"id="
+
id
+
", status="
+
status
+
'}'
;
}
}
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/common/Status.java
0 → 100644
View file @
7abfefba
package
com.mall4j.cloud.leaf.common
;
/**
* @author leaf
*/
public
enum
Status
{
/**
* success
*/
SUCCESS
,
/**
* exception
*/
EXCEPTION
}
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/common/ZeroIDGen.java
0 → 100644
View file @
7abfefba
package
com.mall4j.cloud.leaf.common
;
import
com.mall4j.cloud.leaf.IDGen
;
/**
* @author left
*/
public
class
ZeroIDGen
implements
IDGen
{
@Override
public
Result
get
(
String
key
)
{
return
new
Result
(
0
,
Status
.
SUCCESS
);
}
@Override
public
boolean
init
()
{
return
true
;
}
}
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/exception/InitException.java
0 → 100644
View file @
7abfefba
package
com.mall4j.cloud.leaf.exception
;
/**
* @author leaf
*/
public
class
InitException
extends
Exception
{
public
InitException
(
String
msg
)
{
super
(
msg
);
}
}
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/exception/LeafServerException.java
0 → 100644
View file @
7abfefba
package
com.mall4j.cloud.leaf.exception
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.web.bind.annotation.ResponseStatus
;
/**
* @author leaf
*/
@ResponseStatus
(
code
=
HttpStatus
.
INTERNAL_SERVER_ERROR
)
public
class
LeafServerException
extends
RuntimeException
{
public
LeafServerException
(
String
msg
)
{
super
(
msg
);
}
}
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/exception/NoKeyException.java
0 → 100644
View file @
7abfefba
package
com.mall4j.cloud.leaf.exception
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.web.bind.annotation.ResponseStatus
;
/**
* @author leaf
*/
@ResponseStatus
(
code
=
HttpStatus
.
INTERNAL_SERVER_ERROR
,
reason
=
"Key is none"
)
public
class
NoKeyException
extends
RuntimeException
{
}
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/feign/SegmentFeignController.java
0 → 100644
View file @
7abfefba
package
com.mall4j.cloud.leaf.feign
;
import
com.mall4j.cloud.api.leaf.feign.SegmentFeignClient
;
import
com.mall4j.cloud.common.response.ServerResponseEntity
;
import
com.mall4j.cloud.leaf.common.Result
;
import
com.mall4j.cloud.leaf.common.Status
;
import
com.mall4j.cloud.leaf.exception.LeafServerException
;
import
com.mall4j.cloud.leaf.exception.NoKeyException
;
import
com.mall4j.cloud.leaf.service.SegmentService
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.RestController
;
import
java.util.Objects
;
/**
* @author FrozenWatermelon
* @date 2020/7/15
*/
@RestController
public
class
SegmentFeignController
implements
SegmentFeignClient
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
SegmentFeignController
.
class
);
@Autowired
private
SegmentService
segmentService
;
@Override
public
ServerResponseEntity
<
Long
>
getSegmentId
(
String
key
)
{
return
ServerResponseEntity
.
success
(
get
(
key
,
segmentService
.
getId
(
key
)));
}
private
Long
get
(
String
key
,
Result
id
)
{
Result
result
;
if
(
key
==
null
||
key
.
isEmpty
())
{
throw
new
NoKeyException
();
}
result
=
id
;
if
(
Objects
.
equals
(
result
.
getStatus
(),
Status
.
EXCEPTION
))
{
throw
new
LeafServerException
(
result
.
toString
());
}
return
result
.
getId
();
}
}
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/segment/SegmentIDGenImpl.java
0 → 100644
View file @
7abfefba
package
com.mall4j.cloud.leaf.segment
;
import
com.mall4j.cloud.leaf.IDGen
;
import
com.mall4j.cloud.leaf.common.Result
;
import
com.mall4j.cloud.leaf.common.Status
;
import
com.mall4j.cloud.leaf.segment.dao.IDAllocDao
;
import
com.mall4j.cloud.leaf.segment.model.LeafAlloc
;
import
com.mall4j.cloud.leaf.segment.model.Segment
;
import
com.mall4j.cloud.leaf.segment.model.SegmentBuffer
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.security.SecureRandom
;
import
java.util.*
;
import
java.util.concurrent.*
;
import
java.util.concurrent.atomic.AtomicLong
;
/**
* @author leaf
*/
public
class
SegmentIDGenImpl
implements
IDGen
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
SegmentIDGenImpl
.
class
);
/**
* IDCache未初始化成功时的异常码
*/
private
static
final
long
EXCEPTION_ID_IDCACHE_INIT_FALSE
=
-
1
;
/**
* key不存在时的异常码
*/
private
static
final
long
EXCEPTION_ID_KEY_NOT_EXISTS
=
-
2
;
/**
* SegmentBuffer中的两个Segment均未从DB中装载时的异常码
*/
private
static
final
long
EXCEPTION_ID_TWO_SEGMENTS_ARE_NULL
=
-
3
;
/**
* 最大步长不超过100,0000
*/
private
static
final
int
MAX_STEP
=
1000000
;
/**
* 一个Segment维持时间为15分钟
*/
private
static
final
long
SEGMENT_DURATION
=
15
*
60
*
1000L
;
private
final
ExecutorService
service
=
new
ThreadPoolExecutor
(
5
,
Integer
.
MAX_VALUE
,
60L
,
TimeUnit
.
SECONDS
,
new
SynchronousQueue
<>(),
new
UpdateThreadFactory
());
private
volatile
boolean
initOk
=
false
;
private
final
Map
<
String
,
SegmentBuffer
>
cache
=
new
ConcurrentHashMap
<>();
private
IDAllocDao
dao
;
private
static
final
SecureRandom
RANDOM
=
new
SecureRandom
();
private
static
final
int
DEFAULT_LOAD_FACTOR
=
2
;
public
static
class
UpdateThreadFactory
implements
ThreadFactory
{
private
static
int
threadInitNumber
=
0
;
private
static
synchronized
int
nextThreadNum
()
{
return
threadInitNumber
++;
}
@Override
public
Thread
newThread
(
Runnable
r
)
{
return
new
Thread
(
r
,
"Thread-Segment-Update-"
+
nextThreadNum
());
}
}
@Override
public
boolean
init
()
{
logger
.
info
(
"Init ..."
);
// 确保加载到kv后才初始化成功
updateCacheFromDb
();
initOk
=
true
;
updateCacheFromDbAtEveryMinute
();
return
initOk
;
}
private
void
updateCacheFromDbAtEveryMinute
()
{
ScheduledExecutorService
service
=
Executors
.
newSingleThreadScheduledExecutor
(
new
ThreadFactory
()
{
@Override
public
Thread
newThread
(
Runnable
r
)
{
Thread
t
=
new
Thread
(
r
);
t
.
setName
(
"check-idCache-thread"
);
t
.
setDaemon
(
true
);
return
t
;
}
});
service
.
scheduleWithFixedDelay
(
new
Runnable
()
{
@Override
public
void
run
()
{
updateCacheFromDb
();
}
},
60
,
60
,
TimeUnit
.
SECONDS
);
}
private
void
updateCacheFromDb
()
{
logger
.
info
(
"update cache from db"
);
try
{
List
<
String
>
dbTags
=
dao
.
getAllTags
();
if
(
dbTags
==
null
||
dbTags
.
isEmpty
())
{
return
;
}
List
<
String
>
cacheTags
=
new
ArrayList
<
String
>(
cache
.
keySet
());
Set
<
String
>
insertTagsSet
=
new
HashSet
<>(
dbTags
);
Set
<
String
>
removeTagsSet
=
new
HashSet
<>(
cacheTags
);
// db中新加的tags灌进cache
for
(
int
i
=
0
;
i
<
cacheTags
.
size
();
i
++)
{
String
tmp
=
cacheTags
.
get
(
i
);
insertTagsSet
.
remove
(
tmp
);
}
for
(
String
tag
:
insertTagsSet
)
{
SegmentBuffer
buffer
=
new
SegmentBuffer
();
buffer
.
setKey
(
tag
);
Segment
segment
=
buffer
.
getCurrent
();
segment
.
setValue
(
new
AtomicLong
(
0
));
segment
.
setMax
(
0
);
segment
.
setStep
(
0
);
cache
.
put
(
tag
,
buffer
);
logger
.
info
(
"Add tag {} from db to IdCache, SegmentBuffer {}"
,
tag
,
buffer
);
}
// cache中已失效的tags从cache删除
for
(
int
i
=
0
;
i
<
dbTags
.
size
();
i
++)
{
String
tmp
=
dbTags
.
get
(
i
);
removeTagsSet
.
remove
(
tmp
);
}
for
(
String
tag
:
removeTagsSet
)
{
cache
.
remove
(
tag
);
logger
.
info
(
"Remove tag {} from IdCache"
,
tag
);
}
}
catch
(
Exception
e
)
{
logger
.
warn
(
"update cache from db exception"
,
e
);
}
}
@Override
public
Result
get
(
final
String
key
)
{
if
(!
initOk
)
{
return
new
Result
(
EXCEPTION_ID_IDCACHE_INIT_FALSE
,
Status
.
EXCEPTION
);
}
SegmentBuffer
buffer
=
cache
.
get
(
key
);
if
(
buffer
!=
null
)
{
if
(
buffer
.
isInitOk
())
{
synchronized
(
buffer
)
{
if
(
buffer
.
isInitOk
())
{
try
{
updateSegmentFromDb
(
key
,
buffer
.
getCurrent
());
logger
.
info
(
"Init buffer. Update leafkey {} {} from db"
,
key
,
buffer
.
getCurrent
());
buffer
.
setInitOk
(
true
);
}
catch
(
Exception
e
)
{
logger
.
warn
(
"Init buffer {} exception"
,
buffer
.
getCurrent
(),
e
);
}
}
}
}
return
getIdFromSegmentBuffer
(
cache
.
get
(
key
));
}
return
new
Result
(
EXCEPTION_ID_KEY_NOT_EXISTS
,
Status
.
EXCEPTION
);
}
public
void
updateSegmentFromDb
(
String
key
,
Segment
segment
)
{
SegmentBuffer
buffer
=
segment
.
getBuffer
();
LeafAlloc
leafAlloc
;
if
(
buffer
.
isInitOk
())
{
leafAlloc
=
dao
.
updateMaxIdAndGetLeafAlloc
(
key
);
buffer
.
setStep
(
leafAlloc
.
getStep
());
// leafAlloc中的step为DB中的step
buffer
.
setMinStep
(
leafAlloc
.
getStep
());
}
else
if
(
buffer
.
getUpdateTimestamp
()
==
0
)
{
leafAlloc
=
dao
.
updateMaxIdAndGetLeafAlloc
(
key
);
buffer
.
setUpdateTimestamp
(
System
.
currentTimeMillis
());
buffer
.
setStep
(
leafAlloc
.
getStep
());
// leafAlloc中的step为DB中的step
buffer
.
setMinStep
(
leafAlloc
.
getStep
());
}
else
{
long
duration
=
System
.
currentTimeMillis
()
-
buffer
.
getUpdateTimestamp
();
int
nextStep
=
buffer
.
getStep
();
if
(
duration
<
SEGMENT_DURATION
)
{
if
(
nextStep
*
DEFAULT_LOAD_FACTOR
>
MAX_STEP
)
{
// do nothing
}
else
{
nextStep
=
nextStep
*
DEFAULT_LOAD_FACTOR
;
}
}
else
if
(
duration
<
SEGMENT_DURATION
*
DEFAULT_LOAD_FACTOR
)
{
// do nothing with nextStep
}
else
{
nextStep
=
nextStep
/
DEFAULT_LOAD_FACTOR
>=
buffer
.
getMinStep
()
?
nextStep
/
DEFAULT_LOAD_FACTOR
:
nextStep
;
}
logger
.
info
(
"leafKey[{}], step[{}], duration[{}mins], nextStep[{}]"
,
key
,
buffer
.
getStep
(),
String
.
format
(
"%.2f"
,
((
double
)
duration
/
(
1000
*
60
))),
nextStep
);
LeafAlloc
temp
=
new
LeafAlloc
();
temp
.
setKey
(
key
);
temp
.
setStep
(
nextStep
);
leafAlloc
=
dao
.
updateMaxIdByCustomStepAndGetLeafAlloc
(
temp
);
buffer
.
setUpdateTimestamp
(
System
.
currentTimeMillis
());
buffer
.
setStep
(
nextStep
);
// leafAlloc的step为DB中的step
buffer
.
setMinStep
(
leafAlloc
.
getStep
());
}
// must set value before set max
long
value
=
leafAlloc
.
getMaxId
()
-
buffer
.
getStep
();
segment
.
getValue
().
set
(
value
);
segment
.
setMax
(
leafAlloc
.
getMaxId
());
segment
.
setStep
(
buffer
.
getStep
());
segment
.
setRandomStep
(
leafAlloc
.
getRandomStep
());
}
public
Result
getIdFromSegmentBuffer
(
final
SegmentBuffer
buffer
)
{
while
(
true
)
{
buffer
.
rLock
().
lock
();
try
{
final
Segment
segment
=
buffer
.
getCurrent
();
if
(!
buffer
.
isNextReady
()
&&
(
segment
.
getIdle
()
<
0.9
*
segment
.
getStep
())
&&
buffer
.
getThreadRunning
().
compareAndSet
(
false
,
true
))
{
service
.
execute
(
new
Runnable
()
{
@Override
public
void
run
()
{
Segment
next
=
buffer
.
getSegments
()[
buffer
.
nextPos
()];
boolean
updateOk
=
false
;
try
{
updateSegmentFromDb
(
buffer
.
getKey
(),
next
);
updateOk
=
true
;
logger
.
info
(
"update segment {} from db {}"
,
buffer
.
getKey
(),
next
);
}
catch
(
Exception
e
)
{
logger
.
warn
(
buffer
.
getKey
()
+
" updateSegmentFromDb exception"
,
e
);
}
finally
{
if
(
updateOk
)
{
buffer
.
wLock
().
lock
();
buffer
.
setNextReady
(
true
);
buffer
.
getThreadRunning
().
set
(
false
);
buffer
.
wLock
().
unlock
();
}
else
{
buffer
.
getThreadRunning
().
set
(
false
);
}
}
}
});
}
long
value
;
if
(
segment
.
getRandomStep
()
>
1
)
{
// 随机从1-10里面增加
value
=
segment
.
getValue
().
getAndAdd
(
randomAdd
(
segment
.
getRandomStep
()));
}
else
{
value
=
segment
.
getValue
().
getAndIncrement
();
}
if
(
value
<
segment
.
getMax
())
{
return
new
Result
(
value
,
Status
.
SUCCESS
);
}
}
finally
{
buffer
.
rLock
().
unlock
();
}
waitAndSleep
(
buffer
);
buffer
.
wLock
().
lock
();
try
{
final
Segment
segment
=
buffer
.
getCurrent
();
long
value
=
segment
.
getValue
().
getAndIncrement
();
if
(
value
<
segment
.
getMax
())
{
return
new
Result
(
value
,
Status
.
SUCCESS
);
}
if
(
buffer
.
isNextReady
())
{
buffer
.
switchPos
();
buffer
.
setNextReady
(
false
);
}
else
{
logger
.
error
(
"Both two segments in {} are not ready!"
,
buffer
);
return
new
Result
(
EXCEPTION_ID_TWO_SEGMENTS_ARE_NULL
,
Status
.
EXCEPTION
);
}
}
finally
{
buffer
.
wLock
().
unlock
();
}
}
}
private
int
randomAdd
(
int
randomStep
)
{
return
RANDOM
.
nextInt
(
randomStep
-
1
)
+
1
;
}
private
void
waitAndSleep
(
SegmentBuffer
buffer
)
{
int
roll
=
0
;
while
(
buffer
.
getThreadRunning
().
get
())
{
roll
+=
1
;
if
(
roll
>
10000
)
{
try
{
TimeUnit
.
MILLISECONDS
.
sleep
(
10
);
break
;
}
catch
(
InterruptedException
e
)
{
logger
.
warn
(
"Thread {} Interrupted, Exception: {}"
,
Thread
.
currentThread
().
getName
(),
e
);
break
;
}
}
}
}
public
List
<
LeafAlloc
>
getAllLeafAllocs
()
{
return
dao
.
getAllLeafAllocs
();
}
public
Map
<
String
,
SegmentBuffer
>
getCache
()
{
return
cache
;
}
public
IDAllocDao
getDao
()
{
return
dao
;
}
public
void
setDao
(
IDAllocDao
dao
)
{
this
.
dao
=
dao
;
}
}
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/segment/dao/IDAllocDao.java
0 → 100644
View file @
7abfefba
package
com.mall4j.cloud.leaf.segment.dao
;
import
com.mall4j.cloud.leaf.segment.model.LeafAlloc
;
import
java.util.List
;
/**
* @author leaf
*/
public
interface
IDAllocDao
{
/**
* com.mall4j.cloud.leaf.segment.dao.IDAllocMapper.getAllLeafAllocs
* @return List<LeafAlloc>
*/
List
<
LeafAlloc
>
getAllLeafAllocs
();
/**
* updateMaxIdAndGetLeafAlloc
* @param tag tag
* @return LeafAlloc
*/
LeafAlloc
updateMaxIdAndGetLeafAlloc
(
String
tag
);
/**
* updateMaxIdByCustomStepAndGetLeafAlloc
* @param leafAlloc leafAlloc
* @return LeafAlloc
*/
LeafAlloc
updateMaxIdByCustomStepAndGetLeafAlloc
(
LeafAlloc
leafAlloc
);
/**
* getAllTags
* @return List<String>
*/
List
<
String
>
getAllTags
();
}
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/segment/dao/IDAllocMapper.java
0 → 100644
View file @
7abfefba
package
com.mall4j.cloud.leaf.segment.dao
;
import
com.mall4j.cloud.leaf.segment.model.LeafAlloc
;
import
org.apache.ibatis.annotations.*
;
import
java.util.List
;
/**
* @author leaf
*/
public
interface
IDAllocMapper
{
/**
* getAllLeafAllocs
* @return List<LeafAlloc>
*/
@Select
(
"SELECT biz_tag, max_id, step, update_time FROM leaf_alloc"
)
@Results
(
value
=
{
@Result
(
column
=
"biz_tag"
,
property
=
"key"
),
@Result
(
column
=
"max_id"
,
property
=
"maxId"
),
@Result
(
column
=
"step"
,
property
=
"step"
),
@Result
(
column
=
"update_time"
,
property
=
"updateTime"
)
})
List
<
LeafAlloc
>
getAllLeafAllocs
();
/**
* getLeafAlloc
* @param tag tag
* @return LeafAlloc
*/
@Select
(
"SELECT biz_tag, max_id, step, random_step FROM leaf_alloc WHERE biz_tag = #{tag}"
)
@Results
(
value
=
{
@Result
(
column
=
"biz_tag"
,
property
=
"key"
),
@Result
(
column
=
"max_id"
,
property
=
"maxId"
),
@Result
(
column
=
"step"
,
property
=
"step"
),
@Result
(
column
=
"random_step"
,
property
=
"randomStep"
)
})
LeafAlloc
getLeafAlloc
(
@Param
(
"tag"
)
String
tag
);
/**
* updateMaxId
* @param tag tag
*/
@Update
(
"UPDATE leaf_alloc SET max_id = max_id + step WHERE biz_tag = #{tag}"
)
void
updateMaxId
(
@Param
(
"tag"
)
String
tag
);
/**
* updateMaxIdByCustomStep
* @param leafAlloc leafAlloc
*/
@Update
(
"UPDATE leaf_alloc SET max_id = max_id + #{step} WHERE biz_tag = #{key}"
)
void
updateMaxIdByCustomStep
(
@Param
(
"leafAlloc"
)
LeafAlloc
leafAlloc
);
/**
* getAllTags
* @return List<String>
*/
@Select
(
"SELECT biz_tag FROM leaf_alloc"
)
List
<
String
>
getAllTags
();
}
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/segment/dao/impl/IDAllocDaoImpl.java
0 → 100644
View file @
7abfefba
package
com.mall4j.cloud.leaf.segment.dao.impl
;
import
com.mall4j.cloud.leaf.segment.dao.IDAllocDao
;
import
com.mall4j.cloud.leaf.segment.dao.IDAllocMapper
;
import
com.mall4j.cloud.leaf.segment.model.LeafAlloc
;
import
org.apache.ibatis.mapping.Environment
;
import
org.apache.ibatis.session.Configuration
;
import
org.apache.ibatis.session.SqlSession
;
import
org.apache.ibatis.session.SqlSessionFactory
;
import
org.apache.ibatis.session.SqlSessionFactoryBuilder
;
import
org.apache.ibatis.transaction.TransactionFactory
;
import
org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory
;
import
javax.sql.DataSource
;
import
java.util.List
;
/**
* @author leaf
*/
public
class
IDAllocDaoImpl
implements
IDAllocDao
{
final
SqlSessionFactory
sqlSessionFactory
;
public
IDAllocDaoImpl
(
DataSource
dataSource
)
{
TransactionFactory
transactionFactory
=
new
JdbcTransactionFactory
();
Environment
environment
=
new
Environment
(
"development"
,
transactionFactory
,
dataSource
);
Configuration
configuration
=
new
Configuration
(
environment
);
configuration
.
addMapper
(
IDAllocMapper
.
class
);
sqlSessionFactory
=
new
SqlSessionFactoryBuilder
().
build
(
configuration
);
}
@Override
public
List
<
LeafAlloc
>
getAllLeafAllocs
()
{
try
(
SqlSession
sqlSession
=
sqlSessionFactory
.
openSession
(
false
))
{
return
sqlSession
.
selectList
(
"com.mall4j.cloud.leaf.segment.dao.IDAllocMapper.getAllLeafAllocs"
);
}
}
@Override
public
LeafAlloc
updateMaxIdAndGetLeafAlloc
(
String
tag
)
{
try
(
SqlSession
sqlSession
=
sqlSessionFactory
.
openSession
())
{
sqlSession
.
update
(
"com.mall4j.cloud.leaf.segment.dao.IDAllocMapper.updateMaxId"
,
tag
);
LeafAlloc
result
=
sqlSession
.
selectOne
(
"com.mall4j.cloud.leaf.segment.dao.IDAllocMapper.getLeafAlloc"
,
tag
);
sqlSession
.
commit
();
return
result
;
}
}
@Override
public
LeafAlloc
updateMaxIdByCustomStepAndGetLeafAlloc
(
LeafAlloc
leafAlloc
)
{
try
(
SqlSession
sqlSession
=
sqlSessionFactory
.
openSession
())
{
sqlSession
.
update
(
"com.mall4j.cloud.leaf.segment.dao.IDAllocMapper.updateMaxIdByCustomStep"
,
leafAlloc
);
LeafAlloc
result
=
sqlSession
.
selectOne
(
"com.mall4j.cloud.leaf.segment.dao.IDAllocMapper.getLeafAlloc"
,
leafAlloc
.
getKey
());
sqlSession
.
commit
();
return
result
;
}
}
@Override
public
List
<
String
>
getAllTags
()
{
try
(
SqlSession
sqlSession
=
sqlSessionFactory
.
openSession
(
false
))
{
return
sqlSession
.
selectList
(
"com.mall4j.cloud.leaf.segment.dao.IDAllocMapper.getAllTags"
);
}
}
}
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/segment/model/LeafAlloc.java
0 → 100644
View file @
7abfefba
package
com.mall4j.cloud.leaf.segment.model
;
/**
* @author leaf
*/
public
class
LeafAlloc
{
private
String
key
;
private
long
maxId
;
private
int
step
;
private
String
updateTime
;
private
int
randomStep
;
public
String
getKey
()
{
return
key
;
}
public
void
setKey
(
String
key
)
{
this
.
key
=
key
;
}
public
long
getMaxId
()
{
return
maxId
;
}
public
void
setMaxId
(
long
maxId
)
{
this
.
maxId
=
maxId
;
}
public
int
getStep
()
{
return
step
;
}
public
void
setStep
(
int
step
)
{
this
.
step
=
step
;
}
public
String
getUpdateTime
()
{
return
updateTime
;
}
public
void
setUpdateTime
(
String
updateTime
)
{
this
.
updateTime
=
updateTime
;
}
public
int
getRandomStep
()
{
return
randomStep
;
}
public
void
setRandomStep
(
int
randomStep
)
{
this
.
randomStep
=
randomStep
;
}
}
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/segment/model/Segment.java
0 → 100644
View file @
7abfefba
package
com.mall4j.cloud.leaf.segment.model
;
import
java.util.concurrent.atomic.AtomicLong
;
/**
* @author left
*/
public
class
Segment
{
private
AtomicLong
value
=
new
AtomicLong
(
0
);
private
volatile
long
max
;
private
volatile
int
step
;
private
volatile
int
randomStep
;
private
final
SegmentBuffer
buffer
;
public
Segment
(
SegmentBuffer
buffer
)
{
this
.
buffer
=
buffer
;
}
public
AtomicLong
getValue
()
{
return
value
;
}
public
void
setValue
(
AtomicLong
value
)
{
this
.
value
=
value
;
}
public
long
getMax
()
{
return
max
;
}
public
void
setMax
(
long
max
)
{
this
.
max
=
max
;
}
public
int
getStep
()
{
return
step
;
}
public
void
setStep
(
int
step
)
{
this
.
step
=
step
;
}
public
SegmentBuffer
getBuffer
()
{
return
buffer
;
}
public
long
getIdle
()
{
return
this
.
getMax
()
-
getValue
().
get
();
}
@Override
public
String
toString
()
{
return
"Segment("
+
"value:"
+
value
+
",max:"
+
max
+
",step:"
+
step
+
")"
;
}
public
int
getRandomStep
()
{
return
randomStep
;
}
public
void
setRandomStep
(
int
randomStep
)
{
this
.
randomStep
=
randomStep
;
}
}
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/segment/model/SegmentBuffer.java
0 → 100644
View file @
7abfefba
package
com.mall4j.cloud.leaf.segment.model
;
import
java.util.Arrays
;
import
java.util.concurrent.atomic.AtomicBoolean
;
import
java.util.concurrent.locks.Lock
;
import
java.util.concurrent.locks.ReadWriteLock
;
import
java.util.concurrent.locks.ReentrantReadWriteLock
;
/**
* 双buffer
*
* @author left
*/
public
class
SegmentBuffer
{
private
String
key
;
/**
* 双buffer
*/
private
final
Segment
[]
segments
;
/**
* 当前的使用的segment的index
*/
private
volatile
int
currentPos
;
/**
* 下一个segment是否处于可切换状态
*/
private
volatile
boolean
nextReady
;
/**
* 是否初始化完成
*/
private
volatile
boolean
initOk
;
/**
* 线程是否在运行中
*/
private
final
AtomicBoolean
threadRunning
;
private
final
ReadWriteLock
lock
;
private
volatile
int
step
;
private
volatile
int
minStep
;
private
volatile
long
updateTimestamp
;
public
SegmentBuffer
()
{
segments
=
new
Segment
[]
{
new
Segment
(
this
),
new
Segment
(
this
)
};
currentPos
=
0
;
nextReady
=
false
;
initOk
=
false
;
threadRunning
=
new
AtomicBoolean
(
false
);
lock
=
new
ReentrantReadWriteLock
();
}
public
String
getKey
()
{
return
key
;
}
public
void
setKey
(
String
key
)
{
this
.
key
=
key
;
}
public
Segment
[]
getSegments
()
{
return
segments
;
}
public
Segment
getCurrent
()
{
return
segments
[
currentPos
];
}
public
int
getCurrentPos
()
{
return
currentPos
;
}
public
int
nextPos
()
{
return
(
currentPos
+
1
)
%
2
;
}
public
void
switchPos
()
{
currentPos
=
nextPos
();
}
public
boolean
isInitOk
()
{
return
!
initOk
;
}
public
void
setInitOk
(
boolean
initOk
)
{
this
.
initOk
=
initOk
;
}
public
boolean
isNextReady
()
{
return
nextReady
;
}
public
void
setNextReady
(
boolean
nextReady
)
{
this
.
nextReady
=
nextReady
;
}
public
AtomicBoolean
getThreadRunning
()
{
return
threadRunning
;
}
public
Lock
rLock
()
{
return
lock
.
readLock
();
}
public
Lock
wLock
()
{
return
lock
.
writeLock
();
}
public
int
getStep
()
{
return
step
;
}
public
void
setStep
(
int
step
)
{
this
.
step
=
step
;
}
public
int
getMinStep
()
{
return
minStep
;
}
public
void
setMinStep
(
int
minStep
)
{
this
.
minStep
=
minStep
;
}
public
long
getUpdateTimestamp
()
{
return
updateTimestamp
;
}
public
void
setUpdateTimestamp
(
long
updateTimestamp
)
{
this
.
updateTimestamp
=
updateTimestamp
;
}
@Override
public
String
toString
()
{
final
StringBuilder
sb
=
new
StringBuilder
(
"SegmentBuffer{"
);
sb
.
append
(
"key='"
).
append
(
key
).
append
(
'\''
);
sb
.
append
(
", segments="
).
append
(
Arrays
.
toString
(
segments
));
sb
.
append
(
", currentPos="
).
append
(
currentPos
);
sb
.
append
(
", nextReady="
).
append
(
nextReady
);
sb
.
append
(
", initOk="
).
append
(
initOk
);
sb
.
append
(
", threadRunning="
).
append
(
threadRunning
);
sb
.
append
(
", step="
).
append
(
step
);
sb
.
append
(
", minStep="
).
append
(
minStep
);
sb
.
append
(
", updateTimestamp="
).
append
(
updateTimestamp
);
sb
.
append
(
'}'
);
return
sb
.
toString
();
}
}
mall4cloud-leaf/src/main/java/com/mall4j/cloud/leaf/service/SegmentService.java
0 → 100644
View file @
7abfefba
package
com.mall4j.cloud.leaf.service
;
import
com.mall4j.cloud.leaf.IDGen
;
import
com.mall4j.cloud.leaf.common.Result
;
import
com.mall4j.cloud.leaf.exception.InitException
;
import
com.mall4j.cloud.leaf.segment.SegmentIDGenImpl
;
import
com.mall4j.cloud.leaf.segment.dao.IDAllocDao
;
import
com.mall4j.cloud.leaf.segment.dao.impl.IDAllocDaoImpl
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.stereotype.Service
;
import
javax.sql.DataSource
;
/**
* @author left
*/
@Service
(
"SegmentService"
)
public
class
SegmentService
{
private
final
Logger
logger
=
LoggerFactory
.
getLogger
(
SegmentService
.
class
);
private
final
IDGen
idGen
;
public
SegmentService
(
DataSource
dataSource
)
throws
InitException
{
// Config Dao
IDAllocDao
dao
=
new
IDAllocDaoImpl
(
dataSource
);
// Config ID Gen
idGen
=
new
SegmentIDGenImpl
();
((
SegmentIDGenImpl
)
idGen
).
setDao
(
dao
);
if
(
idGen
.
init
())
{
logger
.
info
(
"Segment Service Init Successfully"
);
}
else
{
throw
new
InitException
(
"Segment Service Init Fail"
);
}
}
public
Result
getId
(
String
key
)
{
return
idGen
.
get
(
key
);
}
public
SegmentIDGenImpl
getIdGen
()
{
if
(
idGen
instanceof
SegmentIDGenImpl
)
{
return
(
SegmentIDGenImpl
)
idGen
;
}
return
null
;
}
}
mall4cloud-leaf/src/main/resources/bootstrap.yml
0 → 100644
View file @
7abfefba
server
:
port
:
9100
spring
:
application
:
name
:
@
artifactId@
cloud
:
nacos
:
discovery
:
server-addr
:
${NACOS_HOST:192.168.1.46}:${NACOS_PORT:8848}
username
:
nacos
password
:
nacos
config
:
server-addr
:
${spring.cloud.nacos.discovery.server-addr}
file-extension
:
yml
namespace
:
@
nacos.namespace@
shared-configs
:
-
application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
username
:
${spring.cloud.nacos.discovery.username}
password
:
${spring.cloud.nacos.discovery.password}
profiles
:
active
:
@
profiles.active@
mall4cloud-leaf/target/classes/bootstrap.yml
0 → 100644
View file @
7abfefba
server
:
port
:
9100
spring
:
application
:
name
:
mall4cloud-leaf
cloud
:
nacos
:
discovery
:
server-addr
:
${NACOS_HOST:192.168.1.46}:${NACOS_PORT:8848}
username
:
nacos
password
:
nacos
config
:
server-addr
:
${spring.cloud.nacos.discovery.server-addr}
file-extension
:
yml
namespace
:
shared-configs
:
-
application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
username
:
${spring.cloud.nacos.discovery.username}
password
:
${spring.cloud.nacos.discovery.password}
profiles
:
active
:
dev
mall4cloud-leaf/target/classes/com/mall4j/cloud/leaf/IDGen.class
0 → 100644
View file @
7abfefba
File added
mall4cloud-leaf/target/classes/com/mall4j/cloud/leaf/LeafServerApplication.class
0 → 100644
View file @
7abfefba
File added
Prev
1
…
18
19
20
21
22
23
24
25
26
…
34
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment