Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
S
spring-boot
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DEMO
spring-boot
Commits
b12d7c70
Commit
b12d7c70
authored
May 22, 2014
by
Dave Syer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve redis repository implementations
Storing values in zset makes them less prone to races. Fixes gh-929
parent
cf5c1d1b
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
36 additions
and
21 deletions
+36
-21
RedisMetricRepository.java
...tuate/metrics/repository/redis/RedisMetricRepository.java
+13
-17
RedisMultiMetricRepository.java
.../metrics/repository/redis/RedisMultiMetricRepository.java
+4
-4
RedisMetricRepositoryTests.java
.../metrics/repository/redis/RedisMetricRepositoryTests.java
+9
-0
RedisMultiMetricRepositoryTests.java
...ics/repository/redis/RedisMultiMetricRepositoryTests.java
+10
-0
No files found.
spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMetricRepository.java
View file @
b12d7c70
...
@@ -28,8 +28,6 @@ import org.springframework.boot.actuate.metrics.writer.Delta;
...
@@ -28,8 +28,6 @@ import org.springframework.boot.actuate.metrics.writer.Delta;
import
org.springframework.data.redis.connection.RedisConnectionFactory
;
import
org.springframework.data.redis.connection.RedisConnectionFactory
;
import
org.springframework.data.redis.core.BoundZSetOperations
;
import
org.springframework.data.redis.core.BoundZSetOperations
;
import
org.springframework.data.redis.core.RedisOperations
;
import
org.springframework.data.redis.core.RedisOperations
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.data.redis.core.ValueOperations
;
import
org.springframework.util.Assert
;
import
org.springframework.util.Assert
;
/**
/**
...
@@ -51,14 +49,9 @@ public class RedisMetricRepository implements MetricRepository {
...
@@ -51,14 +49,9 @@ public class RedisMetricRepository implements MetricRepository {
private
final
RedisOperations
<
String
,
String
>
redisOperations
;
private
final
RedisOperations
<
String
,
String
>
redisOperations
;
private
final
ValueOperations
<
String
,
Long
>
longOperations
;
public
RedisMetricRepository
(
RedisConnectionFactory
redisConnectionFactory
)
{
public
RedisMetricRepository
(
RedisConnectionFactory
redisConnectionFactory
)
{
Assert
.
notNull
(
redisConnectionFactory
,
"RedisConnectionFactory must not be null"
);
Assert
.
notNull
(
redisConnectionFactory
,
"RedisConnectionFactory must not be null"
);
this
.
redisOperations
=
RedisUtils
.
stringTemplate
(
redisConnectionFactory
);
this
.
redisOperations
=
RedisUtils
.
stringTemplate
(
redisConnectionFactory
);
RedisTemplate
<
String
,
Long
>
longRedisTemplate
=
RedisUtils
.
createRedisTemplate
(
redisConnectionFactory
,
Long
.
class
);
this
.
longOperations
=
longRedisTemplate
.
opsForValue
();
this
.
zSetOperations
=
this
.
redisOperations
.
boundZSetOps
(
this
.
key
);
this
.
zSetOperations
=
this
.
redisOperations
.
boundZSetOps
(
this
.
key
);
}
}
...
@@ -89,7 +82,7 @@ public class RedisMetricRepository implements MetricRepository {
...
@@ -89,7 +82,7 @@ public class RedisMetricRepository implements MetricRepository {
public
Metric
<?>
findOne
(
String
metricName
)
{
public
Metric
<?>
findOne
(
String
metricName
)
{
String
redisKey
=
keyFor
(
metricName
);
String
redisKey
=
keyFor
(
metricName
);
String
raw
=
this
.
redisOperations
.
opsForValue
().
get
(
redisKey
);
String
raw
=
this
.
redisOperations
.
opsForValue
().
get
(
redisKey
);
return
deserialize
(
redisKey
,
raw
);
return
deserialize
(
redisKey
,
raw
,
this
.
zSetOperations
.
score
(
redisKey
)
);
}
}
@Override
@Override
...
@@ -102,7 +95,8 @@ public class RedisMetricRepository implements MetricRepository {
...
@@ -102,7 +95,8 @@ public class RedisMetricRepository implements MetricRepository {
List
<
Metric
<?>>
result
=
new
ArrayList
<
Metric
<?>>(
keys
.
size
());
List
<
Metric
<?>>
result
=
new
ArrayList
<
Metric
<?>>(
keys
.
size
());
List
<
String
>
values
=
this
.
redisOperations
.
opsForValue
().
multiGet
(
keys
);
List
<
String
>
values
=
this
.
redisOperations
.
opsForValue
().
multiGet
(
keys
);
for
(
String
v
:
values
)
{
for
(
String
v
:
values
)
{
Metric
<?>
value
=
deserialize
(
keysIt
.
next
(),
v
);
String
key
=
keysIt
.
next
();
Metric
<?>
value
=
deserialize
(
key
,
v
,
this
.
zSetOperations
.
score
(
key
));
if
(
value
!=
null
)
{
if
(
value
!=
null
)
{
result
.
add
(
value
);
result
.
add
(
value
);
}
}
...
@@ -121,15 +115,19 @@ public class RedisMetricRepository implements MetricRepository {
...
@@ -121,15 +115,19 @@ public class RedisMetricRepository implements MetricRepository {
String
name
=
delta
.
getName
();
String
name
=
delta
.
getName
();
String
key
=
keyFor
(
name
);
String
key
=
keyFor
(
name
);
trackMembership
(
key
);
trackMembership
(
key
);
this
.
longOperations
.
increment
(
key
,
delta
.
getValue
().
longValue
());
double
value
=
this
.
zSetOperations
.
incrementScore
(
key
,
delta
.
getValue
()
.
doubleValue
());
String
raw
=
serialize
(
new
Metric
<
Double
>(
name
,
value
,
delta
.
getTimestamp
()));
this
.
redisOperations
.
opsForValue
().
set
(
key
,
raw
);
}
}
@Override
@Override
public
void
set
(
Metric
<?>
value
)
{
public
void
set
(
Metric
<?>
value
)
{
String
raw
=
serialize
(
value
);
String
name
=
value
.
getName
();
String
name
=
value
.
getName
();
String
key
=
keyFor
(
name
);
String
key
=
keyFor
(
name
);
trackMembership
(
key
);
trackMembership
(
key
);
this
.
zSetOperations
.
add
(
key
,
value
.
getValue
().
doubleValue
());
String
raw
=
serialize
(
value
);
this
.
redisOperations
.
opsForValue
().
set
(
key
,
raw
);
this
.
redisOperations
.
opsForValue
().
set
(
key
,
raw
);
}
}
...
@@ -141,18 +139,16 @@ public class RedisMetricRepository implements MetricRepository {
...
@@ -141,18 +139,16 @@ public class RedisMetricRepository implements MetricRepository {
}
}
}
}
private
Metric
<?>
deserialize
(
String
redisKey
,
String
v
)
{
private
Metric
<?>
deserialize
(
String
redisKey
,
String
v
,
Double
value
)
{
if
(
redisKey
==
null
||
v
==
null
||
!
redisKey
.
startsWith
(
this
.
prefix
))
{
if
(
redisKey
==
null
||
v
==
null
||
!
redisKey
.
startsWith
(
this
.
prefix
))
{
return
null
;
return
null
;
}
}
String
[]
vals
=
v
.
split
(
"@"
);
Date
timestamp
=
new
Date
(
Long
.
valueOf
(
v
));
Double
value
=
Double
.
valueOf
(
vals
[
0
]);
Date
timestamp
=
vals
.
length
>
1
?
new
Date
(
Long
.
valueOf
(
vals
[
1
]))
:
new
Date
();
return
new
Metric
<
Double
>(
nameFor
(
redisKey
),
value
,
timestamp
);
return
new
Metric
<
Double
>(
nameFor
(
redisKey
),
value
,
timestamp
);
}
}
private
String
serialize
(
Metric
<?>
entity
)
{
private
String
serialize
(
Metric
<?>
entity
)
{
return
String
.
valueOf
(
entity
.
get
Value
())
+
"@"
+
entity
.
getTimestamp
().
getTime
(
);
return
String
.
valueOf
(
entity
.
get
Timestamp
().
getTime
()
);
}
}
private
String
keyFor
(
String
name
)
{
private
String
keyFor
(
String
name
)
{
...
@@ -164,7 +160,7 @@ public class RedisMetricRepository implements MetricRepository {
...
@@ -164,7 +160,7 @@ public class RedisMetricRepository implements MetricRepository {
}
}
private
void
trackMembership
(
String
redisKey
)
{
private
void
trackMembership
(
String
redisKey
)
{
this
.
zSetOperations
.
add
(
redisKey
,
0.0
D
);
this
.
zSetOperations
.
incrementScore
(
redisKey
,
0.0
D
);
}
}
}
}
spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMultiMetricRepository.java
View file @
b12d7c70
...
@@ -33,9 +33,9 @@ import org.springframework.util.Assert;
...
@@ -33,9 +33,9 @@ import org.springframework.util.Assert;
/**
/**
* {@link MultiMetricRepository} implementation backed by a redis store. Metric values are
* {@link MultiMetricRepository} implementation backed by a redis store. Metric values are
* stored as
regular values against a key composed of the group name prefixed with a
* stored as
zset values and the timestamps as regular values, both against a key composed
*
constant prefix (default "spring.groups."). The group names are stored as a zset under
*
of the group name prefixed with a constant prefix (default "spring.groups."). The group
* "keys." + <code>[prefix]</code>.
*
names are stored as a zset under
"keys." + <code>[prefix]</code>.
*
*
* @author Dave Syer
* @author Dave Syer
*/
*/
...
@@ -167,7 +167,7 @@ public class RedisMultiMetricRepository implements MultiMetricRepository {
...
@@ -167,7 +167,7 @@ public class RedisMultiMetricRepository implements MultiMetricRepository {
}
}
private
void
trackMembership
(
String
redisKey
)
{
private
void
trackMembership
(
String
redisKey
)
{
this
.
zSetOperations
.
add
(
redisKey
,
0.0
D
);
this
.
zSetOperations
.
incrementScore
(
redisKey
,
0.0
D
);
}
}
}
}
spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMetricRepositoryTests.java
View file @
b12d7c70
...
@@ -70,6 +70,15 @@ public class RedisMetricRepositoryTests {
...
@@ -70,6 +70,15 @@ public class RedisMetricRepositoryTests {
assertEquals
(
3
,
this
.
repository
.
findOne
(
"foo"
).
getValue
().
longValue
());
assertEquals
(
3
,
this
.
repository
.
findOne
(
"foo"
).
getValue
().
longValue
());
}
}
@Test
public
void
setIncrementAndGet
()
{
this
.
repository
.
set
(
new
Metric
<
Number
>(
"foo"
,
12.3
));
this
.
repository
.
increment
(
new
Delta
<
Long
>(
"foo"
,
3L
));
Metric
<?>
metric
=
this
.
repository
.
findOne
(
"foo"
);
assertEquals
(
"foo"
,
metric
.
getName
());
assertEquals
(
15.3
,
metric
.
getValue
().
doubleValue
(),
0.01
);
}
@Test
@Test
public
void
findAll
()
{
public
void
findAll
()
{
this
.
repository
.
increment
(
new
Delta
<
Long
>(
"foo"
,
3L
));
this
.
repository
.
increment
(
new
Delta
<
Long
>(
"foo"
,
3L
));
...
...
spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/repository/redis/RedisMultiMetricRepositoryTests.java
View file @
b12d7c70
...
@@ -81,6 +81,16 @@ public class RedisMultiMetricRepositoryTests {
...
@@ -81,6 +81,16 @@ public class RedisMultiMetricRepositoryTests {
@Test
@Test
public
void
setAndGet
()
{
public
void
setAndGet
()
{
this
.
repository
.
set
(
"foo"
,
Arrays
.<
Metric
<?>>
asList
(
new
Metric
<
Number
>(
"foo.bar"
,
12.3
)));
this
.
repository
.
set
(
"foo"
,
Arrays
.<
Metric
<?>>
asList
(
new
Metric
<
Number
>(
"foo.bar"
,
15.3
)));
assertEquals
(
15.3
,
Iterables
.
collection
(
this
.
repository
.
findAll
(
"foo"
))
.
iterator
().
next
().
getValue
());
}
@Test
public
void
setAndGetMultiple
()
{
this
.
repository
.
set
(
"foo"
,
Arrays
.<
Metric
<?>>
asList
(
new
Metric
<
Number
>(
this
.
repository
.
set
(
"foo"
,
Arrays
.<
Metric
<?>>
asList
(
new
Metric
<
Number
>(
"foo.val"
,
12.3
),
new
Metric
<
Number
>(
"foo.bar"
,
11.3
)));
"foo.val"
,
12.3
),
new
Metric
<
Number
>(
"foo.bar"
,
11.3
)));
assertEquals
(
2
,
Iterables
.
collection
(
this
.
repository
.
findAll
(
"foo"
)).
size
());
assertEquals
(
2
,
Iterables
.
collection
(
this
.
repository
.
findAll
(
"foo"
)).
size
());
...
...
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