public Boolean set(final byte[] key, final byte[] value, final long liveTime) {
return redisTemplate.execute(new RedisCallback() {
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
connection.set(key, value);
if (liveTime > 0) {
connection.expire(key, liveTime);
}
return Boolean.TRUE;
}
});
}
对于大文本【超过500字节】写入到Redis时,一定要压缩后存储!大文本数据存入Redis,除了带来极大的内存占用外,在访问量高时,很容易就会将网卡流量占满,进而造成整个服务器上的所有服务不可用,并引发雪崩效应,造成各个系统瘫痪!
public Boolean setBigValue(final byte[] key, final byte[] value, final long liveTime){
return redisTemplate.execute(new RedisCallback() {
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
byte[] compressedBytes = CompressUtil.compress(value);
connection.set(key, compressedBytes);
if (liveTime > 0) {
connection.expire(key, liveTime);
}
return Boolean.TRUE;
}
});
}
压缩可参考:
public class CompressUtil {
private static final Inflater infl = new Inflater();
private static final Deflater defl = new Deflater();
private CompressUtil(){
}
public static byte[] uncompress(byte[] inputByte) throws IOException {
int len = 0;
infl.setInput(inputByte);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] outByte = new byte[1024];
try {
while (!infl.finished()) {
len = infl.inflate(outByte);
if (len == 0) {
break;
}
bos.write(outByte, 0, len);
}
infl.end();
} catch (Exception e) {
} finally {
bos.close();
}
return bos.toByteArray();
}
public static byte[] compress(byte[] inputByte) throws IOException {
int len = 0;
defl.setInput(inputByte);
defl.finish();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] outputByte = new byte[1024];
try {
while (!defl.finished()) {
len = defl.deflate(outputByte);
bos.write(outputByte, 0, len);
}
defl.end();
} finally {
bos.close();
}
return bos.toByteArray();
}
}
Redis是单线程处理,在线上KEY数量较多时,操作效率极低【时间复杂度为O(N)】,该命令一旦执行会严重阻塞线上其它命令的正常请求,而且在高QPS情况下会直接造成Redis服务崩溃!如果有类似需求,请使用scan命令代替!
//此操作禁止
public Set<byte[]> get(final byte[] pattern){
return redisTemplate.execute(new RedisCallback<Set<byte[]>>() {
@Override
public Set<byte[]> doInRedis(RedisConnection connection) throws DataAccessException {
return connection.keys(pattern);
}
});
}
Redis List经常被用于消息队列服务。假设消费者程序在从队列中取出消息
《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》
【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享
后立刻崩溃,但由于该消息已经被取出且没有被正常处理,那么可以认为该消息已经丢失,由此可能会导致业务数据丢失,或业务状态不一致等现象发生。为了避免这种情况,Redis提供了RPOPLPUSH命令,消费者程序会原子性的从主消息队列中取出消息并将其插入到备份队列中,直到消费者程序完成正常的处理逻辑后再将该消息从备份队列中删除。同时还可以提供一个守护进程,当发现备份队列中的消息过期时,可以重新将其再放回到主消息队列中,以便其它的消费者程序继续处理。