@@ -23,16 +23,23 @@ public RedisDao(String ip, int port) {
23
23
24
24
private RuntimeSchema <Seckill > schema = RuntimeSchema .createFrom (Seckill .class );
25
25
26
+ public Seckill getSeckill (long seckillId ) {
27
+ return getSeckill (seckillId , null );
28
+ }
29
+
26
30
/**
27
31
* 从redis获取信息
28
32
*
29
33
* @param seckillId id
30
34
* @return 如果不存在,则返回null
31
35
*/
32
- public Seckill getSeckill (long seckillId ) {
36
+ public Seckill getSeckill (long seckillId , Jedis jedis ) {
37
+ boolean hasJedis = jedis != null ;
33
38
//redis操作逻辑
34
39
try {
35
- Jedis jedis = jedisPool .getResource ();
40
+ if (!hasJedis ) {
41
+ jedis = jedisPool .getResource ();
42
+ }
36
43
try {
37
44
String key = getSeckillRedisKey (seckillId );
38
45
//并没有实现哪部序列化操作
@@ -48,7 +55,9 @@ public Seckill getSeckill(long seckillId) {
48
55
return seckill ;
49
56
}
50
57
} finally {
51
- jedis .close ();
58
+ if (!hasJedis ) {
59
+ jedis .close ();
60
+ }
52
61
}
53
62
} catch (Exception e ) {
54
63
@@ -65,38 +74,41 @@ public Seckill getSeckill(long seckillId) {
65
74
* @return 返回商品信息
66
75
*/
67
76
public Seckill getOrPutSeckill (long seckillId , Function <Long , Seckill > getDataFromDb ) {
68
- Seckill seckill = getSeckill (seckillId );
69
- if (seckill != null ) {
70
- return seckill ;
71
- }
72
77
73
78
String lockKey = "seckill:locks:getSeckill:" + seckillId ;
74
79
String lockRequestId = UUID .randomUUID ().toString ();
75
80
Jedis jedis = jedisPool .getResource ();
76
- // 尝试获取锁。
77
- // 锁过期时间是防止程序突然崩溃来不及解锁,而造成其他线程不能获取锁的问题。过期时间是业务容忍最长时间。
78
- boolean getLock = JedisUtils .tryGetDistributedLock (jedis , lockKey , lockRequestId , 1000 );
79
- if (getLock ) {
80
- // 获取到锁,从数据库拿数据, 然后存redis
81
- try {
82
- seckill = getDataFromDb .apply (seckillId );
83
- putSeckill (seckill );
84
- } catch (Exception ignored ) {
85
- } finally {
86
- // 无论如何,最后要去解锁
87
- JedisUtils .releaseDistributedLock (jedis , lockKey , lockRequestId );
88
- }
89
- return seckill ;
90
- }
91
81
92
- // 获取不到锁,睡一下,等会再出发。sleep的时间需要斟酌,主要看业务处理速度
93
82
try {
94
- Thread .sleep (100 );
95
- } catch (InterruptedException e ) {
96
- e .printStackTrace ();
97
- }
98
- return getOrPutSeckill (seckillId , getDataFromDb );
83
+ // 循环直到获取到数据
84
+ while (true ) {
85
+ Seckill seckill = getSeckill (seckillId , jedis );
86
+ if (seckill != null ) {
87
+ return seckill ;
88
+ }
89
+ // 尝试获取锁。
90
+ // 锁过期时间是防止程序突然崩溃来不及解锁,而造成其他线程不能获取锁的问题。过期时间是业务容忍最长时间。
91
+ boolean getLock = JedisUtils .tryGetDistributedLock (jedis , lockKey , lockRequestId , 1000 );
92
+ if (getLock ) {
93
+ // 获取到锁,从数据库拿数据, 然后存redis
94
+ seckill = getDataFromDb .apply (seckillId );
95
+ putSeckill (seckill , jedis );
96
+ return seckill ;
97
+ }
99
98
99
+ // 获取不到锁,睡一下,等会再出发。sleep的时间需要斟酌,主要看业务处理速度
100
+ try {
101
+ Thread .sleep (100 );
102
+ } catch (InterruptedException ignored ) {
103
+ }
104
+ }
105
+ } catch (Exception ignored ) {
106
+ } finally {
107
+ // 无论如何,最后要去解锁
108
+ JedisUtils .releaseDistributedLock (jedis , lockKey , lockRequestId );
109
+ jedis .close ();
110
+ }
111
+ return null ;
100
112
}
101
113
102
114
/**
@@ -110,8 +122,15 @@ private String getSeckillRedisKey(long seckillId) {
110
122
}
111
123
112
124
public String putSeckill (Seckill seckill ) {
125
+ return putSeckill (seckill , null );
126
+ }
127
+
128
+ public String putSeckill (Seckill seckill , Jedis jedis ) {
129
+ boolean hasJedis = jedis != null ;
113
130
try {
114
- Jedis jedis = jedisPool .getResource ();
131
+ if (!hasJedis ) {
132
+ jedis = jedisPool .getResource ();
133
+ }
115
134
try {
116
135
String key = getSeckillRedisKey (seckill .getSeckillId ());
117
136
byte [] bytes = ProtostuffIOUtil .toByteArray (seckill , schema ,
@@ -122,7 +141,9 @@ public String putSeckill(Seckill seckill) {
122
141
123
142
return result ;
124
143
} finally {
125
- jedis .close ();
144
+ if (!hasJedis ) {
145
+ jedis .close ();
146
+ }
126
147
}
127
148
} catch (Exception e ) {
128
149
0 commit comments