1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
| import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisConnectionUtils; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional;
import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit;
/** * Redis处理器 * * @author Arber * @version 1.0 * @date 2019年5月21日 下午4:52:06 */ @Slf4j @Component public class RedisCacheClient { private static final int MAX_REPLAY = 3; private static final String UPDATE_COLUMN_NAME = "Update";
@Autowired private RedisTemplate<String, Object> redisTemplate;
/** * 得到缓存值,直接得到缓存值(不逆序列化),不存在则返回空字符串 * * @param tableName 表名 * @param columnName 列名 * @param primary 主健 * @param clazz 返回结果类 * @param <T> 泛型 * @return 缓存值 */ public <T> T get(String tableName, String columnName, String primary, Class<? extends T> clazz) { Map<Object, Object> values = redisTemplate.opsForHash().entries(createKey(tableName, columnName, primary)); return values.containsKey(columnName) ? AirJsonUtil.parseObject(values.get(columnName).toString(), clazz) : null; }
/** * 解压缩并转换对象 * 得到缓存值,直接得到缓存值(不逆序列化),不存在则返回空字符串 * * @param tableName * @param columnName * @param primary * @param clazz * @return */ public <T> T getUnzip(String tableName, String columnName, String primary, Class<? extends T> clazz) { Map<Object, Object> values = redisTemplate.opsForHash().entries(createKey(tableName, columnName, primary)); if (!values.containsKey(columnName)) { return null; } String value = values.get(columnName).toString(); //解压缩并转换对象 return AirJsonUtil.parseObject(AirStringUtil.uncompress(value), clazz); }
/** * 得到缓存值,直接得到缓存值(不逆序列化),不存在则返回空字符串 * * @param tableName 表名 * @param columnName 列名 * @param primary 主健 * @return 缓存值 */ public String get(String tableName, String columnName, String primary) { Map<Object, Object> values = redisTemplate.opsForHash().entries(createKey(tableName, columnName, primary)); return values.containsKey(columnName) ? values.get(columnName).toString() : null; }
/** * 删除键 * * @param tableName 表名 * @param columnName 列名 * @param primary 主健 * @return 缓存值 */ public Boolean remove(String tableName, String columnName, String primary) { return redisTemplate.delete(createKey(tableName, columnName, primary)); }
/** * 更新缓存值 * * @param tableName 表名 * @param columnName 列名 * @param primary 主健 * @param value 缓存值 * @param updateDateTime 更新时间 * @param expireTime 过期时间 * @param replay 重试次数 * @return 更新结果 */ public Boolean updateValueMulti(String tableName, String columnName, String primary, String value, Date updateDateTime, Date expireTime, int replay) { if (replay >= MAX_REPLAY) { return false; } String key = createKey(tableName, columnName, primary); Map<Object, Object> valuesMap = redisTemplate.opsForHash().entries(key); if (valuesMap.containsKey(UPDATE_COLUMN_NAME)) { if (Long.parseLong((String) valuesMap.get(UPDATE_COLUMN_NAME)) >= updateDateTime.getTime()) { return true; } redisTemplate.watch(key); } if (valuesMap.isEmpty()) { valuesMap = new HashMap<>(); } valuesMap.put(columnName, value); valuesMap.put(UPDATE_COLUMN_NAME, String.valueOf(updateDateTime.getTime()));
// 增加事务支持(在RedisSentinelConfig里有事务支持配置) redisTemplate.setEnableTransactionSupport(true); redisTemplate.multi(); redisTemplate.opsForHash().putAll(key, valuesMap); redisTemplate.expireAt(key, expireTime); List<Object> rs = redisTemplate.exec(); RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory()); if (rs == null) { return updateValueMulti(tableName, columnName, primary, value, updateDateTime, expireTime, ++replay); } return true; }
/** * 更新缓存值 * * @param tableName 表名 * @param columnName 列名 * @param primary 主健 * @param value 缓存值 * @param updateDateTime 更新时间 * @param expireTime 过期时间 * @param replay 重试次数 * @return 更新结果 */ @Transactional(rollbackFor = Exception.class) public Boolean updateValue(String tableName, String columnName, String primary, String value, Date updateDateTime, Date expireTime, int replay) {
// 增加事务支持(在RedisSentinelConfig里有事务支持配置) redisTemplate.setEnableTransactionSupport(true); if (replay >= MAX_REPLAY) { return false; } String key = createKey(tableName, columnName, primary); Map<Object, Object> valuesMap = redisTemplate.opsForHash().entries(key); if (valuesMap.containsKey(UPDATE_COLUMN_NAME)) { if (Long.parseLong((String) valuesMap.get(UPDATE_COLUMN_NAME)) >= updateDateTime.getTime()) { return true; } } if (valuesMap.isEmpty()) { valuesMap = new HashMap<>(); } valuesMap.put(columnName, value); valuesMap.put(UPDATE_COLUMN_NAME, String.valueOf(updateDateTime.getTime()));
// 更新数据 redisTemplate.opsForHash().putAll(key, valuesMap); return redisTemplate.expireAt(key, expireTime); }
/** * 创建Key关键表列关键字 * * @param tableName 表名 * @param columnName 列名 * @param primary 主健 * @return 关键字 */ private String createKey(String tableName, String columnName, String primary) { return tableName + ":" + primary + ":" + columnName; }
/** * 替换方法 setEntryIfNotExists(); * Only set the key if it does not already exist * * @param key * @param ticketNo NX -- Only set the key if it does not already exist. * XX -- Only set the key if it already exist * @param expx EX|PX, expire time units, EX=seconds; PX = milliseconds * @param time 过期时间 * @return */ @Deprecated public boolean setEntryIfNotExists(String key, String ticketNo, String expx, int time) {
TimeUnit unit = null;
switch (expx) { case "EX": unit = TimeUnit.SECONDS; break; case "PX": unit = TimeUnit.MILLISECONDS; break; default: unit = TimeUnit.SECONDS; }
return redisTemplate.opsForValue().setIfAbsent(key, ticketNo, time, unit); }
/** * 通过redis过期时间实现限制QPS * * @param key 主键 * @param ticketNo 票号 * @param time 过期时间 * @param expx 时间单位 TimeUnit * @return */ public boolean setEntryIfNotExists(String key, String ticketNo, int time, TimeUnit expx) {
return redisTemplate.opsForValue().setIfAbsent(key, ticketNo, time, expx); }
/** * 释放redis链接 */ public void unbindConnection() {
RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory()); }
|