第一题: Redis数据
1.1 基础数据类型
public class RedisDataTypes {
@Test
public void stringOperations ( ) {
jedis. set ( "user:name" , "张三" ) ;
jedis. incr ( "page:views" ) ;
jedis. set ( "price" , "99.99" ) ;
jedis. setbit ( "online:users" , 100 , true ) ;
}
@Test
public void hashOperations ( ) {
jedis. hset ( "user:1001" , "name" , "李四" ) ;
jedis. hset ( "user:1001" , "age" , "25" ) ;
jedis. hset ( "user:1001" , "email" , "lisi@example.com" ) ;
Map < String , String > user = jedis. hgetAll ( "user:1001" ) ;
}
@Test
public void listOperations ( ) {
jedis. lpush ( "queue:email" , "email1@test.com" ) ;
jedis. rpush ( "queue:email" , "email2@test.com" ) ;
List < String > result = jedis. blpop ( 5 , "queue:email" ) ;
}
@Test
public void setOperations ( ) {
jedis. sadd ( "tags:java" , "spring" , "mybatis" , "redis" ) ;
jedis. sadd ( "tags:python" , "django" , "flask" , "redis" ) ;
Set < String > common = jedis. sinter ( "tags:java" , "tags:python" ) ;
}
@Test
public void zsetOperations ( ) {
jedis. zadd ( "leaderboard" , 1500 , "player1" ) ;
jedis. zadd ( "leaderboard" , 1200 , "player2" ) ;
jedis. zadd ( "leaderboard" , 1800 , "player3" ) ;
Set < String > top3 = jedis. zrevrange ( "leaderboard" , 0 , 2 ) ;
}
}
1.2 特殊数据类型
类型 基于类型 特点 典型场景 Bitmap String 位操作,节省内存 签到统计、在线用户、布隆过滤器 HyperLogLog String 基数估算,标准误差0.81% UV统计、独立用户计数 GEO Sorted Set 地理位置索引 LBS服务、附近的人 Stream 专用结构 消息流,支持消费组 消息队列、事件溯源
public class RedisSpecialTypes {
@Test
public void bitmapOperations ( ) {
jedis. setbit ( "signin:20240301" , 1001 , true ) ;
jedis. setbit ( "signin:20240301" , 1002 , true ) ;
long count = jedis. bitcount ( "signin:20240301" ) ;
long firstUser = jedis. bitpos ( "signin:20240301" , true ) ;
}
@Test
public void hyperLogLogOperations ( ) {
jedis. pfadd ( "uv:20240301" , "user1" , "user2" , "user3" ) ;
jedis. pfadd ( "uv:20240302" , "user2" , "user4" , "user5" ) ;
long uv = jedis. pfcount ( "uv:20240301" ) ;
jedis. pfmerge ( "uv:march" , "uv:20240301" , "uv:20240302" ) ;
}
@Test
public void geoOperations ( ) {
jedis. geoadd ( "restaurants" , 116.397128 , 39.916527 , "全聚德" ) ;
jedis. geoadd ( "restaurants" , 116.405285 , 39.904989 , "东来顺" ) ;
List < GeoRadiusResponse > nearby = jedis. georadius (
"restaurants" , 116.400000 , 39.910000 , 5 , GeoUnit . KM) ;
Double distance = jedis. geodist ( "restaurants" , "全聚德" , "东来顺" , GeoUnit . KM) ;
}
@Test
public void streamOperations ( ) {
StreamEntryID msgId = jedis. xadd ( "order:stream" ,
StreamEntryID . NEW_ENTRY,
Map . of ( "orderId" , "12345" , "status" , "created" , "amount" , "99.99" ) ) ;
jedis. xgroupCreate ( "order:stream" , "payment-group" , StreamEntryID . LAST_ENTRY, false ) ;
Map < String , StreamEntryID > streams = Map . of ( "order:stream" , StreamEntryID . UNRECEIVED_ENTRY) ;
List < Map. Entry < String , List < StreamEntry > > > result =
jedis. xreadGroup ( "payment-group" , "consumer1" , 1 , 1000 , false , streams) ;
}
}
二、内部编码结构(底层实现)
2.1 核心数据结构
public class SDS {
private int len;
private int alloc;
private byte flags;
private char [ ] buf;
}
public class Dict {
private DictHashTable [ ] ht = new DictHashTable [ 2 ] ;
private long rehashIndex = - 1 ;
public void rehash ( int n) {
while ( n-- > 0 && ht[ 0 ] . used != 0 ) {
migrateBucket ( ) ;
}
if ( ht[ 0 ] . used == 0 ) {
ht[ 0 ] = ht[ 1 ] ;
ht[ 1 ] = new DictHashTable ( ) ;
rehashIndex = - 1 ;
}
}
}
public class IntSet {
private int encoding;
private int length;
private byte [ ] contents;
public void upgrade ( long value) {
int oldEncoding = encoding;
encoding = getEncodingForValue ( value) ;
resizeAndCopy ( oldEncoding, encoding) ;
}
}
2.2 压缩数据结构
public class ZipList {
public static class ZipListEntry {
private int prevLen;
private int encoding;
private byte [ ] data;
}
}
public class ListPack {
public static class ListPackEntry {
private int encoding;
private byte [ ] data;
private int backLen;
}
}
public class QuickList {
private QuickListNode head, tail;
private int count;
private int len;
private int compressDepth;
public static class QuickListNode {
private QuickListNode prev, next;
private byte [ ] ziplist;
private int count;
private boolean compressed;
}
}
public class SkipList {
private static final int MAX_LEVEL = 32 ;
private static final double PROBABILITY = 0.25 ;
private SkipListNode header;
private SkipListNode tail;
private int level;
private long length;
public static class SkipListNode {
private String member;
private double score;
private SkipListNode backward;
private SkipListLevel [ ] levels;
}
private int randomLevel ( ) {
int level = 1 ;
while ( Math . random ( ) < PROBABILITY && level < MAX_LEVEL) {
level++ ;
}
return level;
}
}
三、编码选择策略
3.1 自动编码转换机制
public class RedisEncodingStrategy {
public void stringEncoding ( ) {
jedis. set ( "int_key" , "12345" ) ;
jedis. set ( "short_key" , "hello" ) ;
jedis. set ( "long_key" , "very long string over 44 bytes..." ) ;
String encoding = jedis. objectEncoding ( "int_key" ) ;
}
public void hashEncoding ( ) {
Map < String , String > smallHash = new HashMap < > ( ) ;
smallHash. put ( "name" , "张三" ) ;
smallHash. put ( "age" , "25" ) ;
jedis. hmset ( "user:small" , smallHash) ;
for ( int i = 0 ; i < 1000 ; i++ ) {
jedis. hset ( "user:large" , "field" + i, "value" + i) ;
}
}
public void listEncoding ( ) {
jedis. lpush ( "mylist" , "item1" , "item2" , "item3" ) ;
String encoding = jedis. objectEncoding ( "mylist" ) ;
}
public void setEncoding ( ) {
jedis. sadd ( "numbers" , "1" , "2" , "3" , "100" , "200" ) ;
System . out. println ( jedis. objectEncoding ( "numbers" ) ) ;
jedis. sadd ( "mixed" , "1" , "hello" , "3" ) ;
System . out. println ( jedis. objectEncoding ( "mixed" ) ) ;
}
public void zsetEncoding ( ) {
jedis. zadd ( "small_rank" , 100 , "user1" ) ;
jedis. zadd ( "small_rank" , 200 , "user2" ) ;
System . out. println ( jedis. objectEncoding ( "small_rank" ) ) ;
for ( int i = 0 ; i < 200 ; i++ ) {
jedis. zadd ( "large_rank" , i, "user" + i) ;
}
System . out. println ( jedis. objectEncoding ( "large_rank" ) ) ;
}
}
3.2 配置优化建议
# redis.conf 关键配置
# Hash类型优化
hash-max-ziplist-entries 512 # ziplist最大元素数
hash-max-ziplist-value 64 # ziplist最大value长度
# List类型优化
list-max-ziplist-size -2 # 每个quicklist节点最大8KB
list-compress-depth 0 # 不压缩头尾节点(0=不压缩)
# Set类型优化
set-max-intset-entries 512 # intset最大元素数
# ZSet类型优化
zset-max-ziplist-entries 128 # ziplist最大元素数
zset-max-ziplist-value 64 # ziplist最大member长度
# HyperLogLog优化
hll-sparse-max-bytes 3000 # 稀疏表示最大字节数
四、场景选型策略
4.1 实战选择指南
public class RedisTypeSelector {
public String selectDataType ( String scenario) {
if ( scenario. contains ( "缓存" ) ) {
if ( scenario. contains ( "对象" ) ) return "Hash" ;
if ( scenario. contains ( "计数" ) ) return "String" ;
return "String" ;
}
if ( scenario. contains ( "排行" ) || scenario. contains ( "排序" ) ) {
return "ZSet" ;
}
if ( scenario. contains ( "队列" ) || scenario. contains ( "消息" ) ) {
if ( scenario. contains ( "延迟" ) ) return "ZSet" ;
if ( scenario. contains ( "持久" ) ) return "Stream" ;
return "List" ;
}
if ( scenario. contains ( "去重" ) || scenario. contains ( "唯一" ) ) {
if ( scenario. contains ( "计数" ) ) return "HyperLogLog" ;
return "Set" ;
}
if ( scenario. contains ( "统计" ) ) {
if ( scenario. contains ( "签到" ) || scenario. contains ( "状态" ) ) return "Bitmap" ;
if ( scenario. contains ( "UV" ) || scenario. contains ( "基数" ) ) return "HyperLogLog" ;
return "String" ;
}
if ( scenario. contains ( "位置" ) || scenario. contains ( "地理" ) ) {
return "GEO" ;
}
return "String" ;
}
@Test
public void performanceComparison ( ) {
long start = System . currentTimeMillis ( ) ;
for ( int i = 0 ; i < 100000 ; i++ ) {
jedis. set ( "key" + i, "value" + i) ;
}
long stringTime = System . currentTimeMillis ( ) - start;
start = System . currentTimeMillis ( ) ;
for ( int i = 0 ; i < 10000 ; i++ ) {
jedis. hmset ( "hash" + i, Map . of (
"field1" , "value1" ,
"field2" , "value2" ,
"field3" , "value3"
) ) ;
}
long hashTime = System . currentTimeMillis ( ) - start;
System . out. printf ( "String操作: %dms, Hash操作: %dms\n" , stringTime, hashTime) ;
}
}
4.2 内存优化策略
public class RedisMemoryOptimization {
@Test
public void memoryOptimizationDemo ( ) {
for ( int i = 1 ; i <= 1000 ; i++ ) {
jedis. set ( "user:" + i + ":name" , "user" + i) ;
jedis. set ( "user:" + i + ":age" , String . valueOf ( 20 + i % 50 ) ) ;
jedis. set ( "user:" + i + ":email" , "user" + i + "@example.com" ) ;
}
for ( int i = 1 ; i <= 1000 ; i++ ) {
Map < String , String > user = Map . of (
"name" , "user" + i,
"age" , String . valueOf ( 20 + i % 50 ) ,
"email" , "user" + i + "@example.com"
) ;
jedis. hmset ( "user:" + i, user) ;
}
for ( int userId = 1 ; userId <= 100000 ; userId++ ) {
if ( userId % 3 == 0 ) {
jedis. setbit ( "online:users" , userId, true ) ;
}
}
long onlineCount = jedis. bitcount ( "online:users" ) ;
System . out. println ( "在线用户数: " + onlineCount) ;
}
}
第二题: Redis为什么快
一、内存存储 + 合理的线程模型
1.1 纯内存操作优势
public class StoragePerformance {
private static final long CPU_CACHE_ACCESS = 1 ;
private static final long MEMORY_ACCESS = 100 ;
private static final long SSD_ACCESS = 100_000 ;
private static final long DISK_ACCESS = 10_000_000 ;
public void performanceComparison ( ) {
System . out. println ( "内存 vs SSD: " + ( SSD_ACCESS / MEMORY_ACCESS) + "倍" ) ;
System . out. println ( "内存 vs 机械硬盘: " + ( DISK_ACCESS / MEMORY_ACCESS) + "倍" ) ;
}
}
1.2 单线程模型优势(Redis 6.0之前)
public class RedisEventLoop {
public void eventLoop ( ) {
while ( running) {
List < Event > events = epoll. wait ( timeout) ;
for ( Event event : events) {
if ( event. isReadable ( ) ) {
handleRead ( event. getClient ( ) ) ;
} else if ( event. isWritable ( ) ) {
handleWrite ( event. getClient ( ) ) ;
}
}
processTimeEvents ( ) ;
processBlockedClients ( ) ;
}
}
private void handleRead ( RedisClient client) {
String command = client. readCommand ( ) ;
Object result = executeCommand ( command) ;
client. writeResponse ( result) ;
}
}
单线程优势 :
避免线程切换开销(每次切换约1-10μs) 无需复杂的锁机制 指令执行顺序可预测 简化内存模型,避免缓存一致性问题
二、高效数据结构实现
2.1 核心数据结构优化
public class SDS {
private int len;
private int alloc;
private byte flags;
private char [ ] buf;
public int length ( ) {
return len;
}
public void append ( String str) {
if ( len + str. length ( ) > alloc) {
int newSize = len < 1024 * 1024 ?
( len + str. length ( ) ) * 2 :
len + str. length ( ) + 1024 * 1024 ;
resize ( newSize) ;
}
}
}
2.2 压缩数据结构
public class ZipList {
public static class ZipListEntry {
private int prevLen;
private int encoding;
private byte [ ] data;
}
public Object get ( int index) {
return decodeEntry ( findEntry ( index) ) ;
}
}
public class QuickList {
private QuickListNode head;
private QuickListNode tail;
private int count;
private int len;
public static class QuickListNode {
private QuickListNode prev, next;
private byte [ ] ziplist;
private int count;
private boolean compressed;
}
}
2.3 数据结构选择策略
数据类型 小数据量结构 大数据量结构 切换阈值配置 String embstr raw 44字节Hash ziplist hashtable hash-max-ziplist-entries 512hash-max-ziplist-value 64List quicklist quicklist list-max-ziplist-size -2list-compress-depth 0Set intset hashtable set-max-intset-entries 512ZSet ziplist skiplist+hashtable zset-max-ziplist-entries 128zset-max-ziplist-value 64
三、I/O多路复用机制
3.1 事件驱动模型
public class RedisServer {
private EventLoop eventLoop;
private Map < Integer , RedisClient > clients;
public void initServer ( ) {
if ( isLinux ( ) ) {
eventLoop = new EpollEventLoop ( ) ;
} else if ( isMacOS ( ) ) {
eventLoop = new KqueueEventLoop ( ) ;
} else {
eventLoop = new SelectEventLoop ( ) ;
}
}
public void serverMain ( ) {
while ( running) {
long timeout = getTimeToNextTimeout ( ) ;
List < Event > events = eventLoop. poll ( timeout) ;
for ( Event event : events) {
processEvent ( event) ;
}
processTimeEvents ( ) ;
}
}
}
3.2 非阻塞网络处理
public class RedisNetworking {
public void readFromClient ( RedisClient client) {
try {
ByteBuffer buffer = client. getInputBuffer ( ) ;
int bytesRead = client. getChannel ( ) . read ( buffer) ;
if ( bytesRead > 0 ) {
List < String [ ] > commands = parseRedisProtocol ( buffer) ;
for ( String [ ] cmd : commands) {
processCommand ( client, cmd) ;
}
} else if ( bytesRead == 0 ) {
return ;
} else {
closeClient ( client) ;
}
} catch ( IOException e) {
closeClient ( client) ;
}
}
private List < String [ ] > parseRedisProtocol ( ByteBuffer buffer) {
return protocolParser. parse ( buffer) ;
}
}
四、Redis 6.0+ I/O多线程优化
4.1 多线程架构设计
public class RedisIOThreads {
private final int ioThreadsNum;
private final ExecutorService ioThreadPool;
private final BlockingQueue < IOTask > taskQueue;
public RedisIOThreads ( int threadNum) {
this . ioThreadsNum = threadNum;
this . ioThreadPool = Executors . newFixedThreadPool ( threadNum) ;
this . taskQueue = new LinkedBlockingQueue < > ( ) ;
}
public void distributeIOTasks ( List < RedisClient > clients) {
for ( RedisClient client : clients) {
if ( client. hasPendingRead ( ) ) {
taskQueue. offer ( new ReadTask ( client) ) ;
}
if ( client. hasPendingWrite ( ) ) {
taskQueue. offer ( new WriteTask ( client) ) ;
}
}
waitForIOCompletion ( ) ;
for ( RedisClient client : clients) {
processCommands ( client) ;
}
}
private class IOWorker implements Runnable {
@Override
public void run ( ) {
while ( running) {
try {
IOTask task = taskQueue. take ( ) ;
task. execute ( ) ;
} catch ( InterruptedException e) {
Thread . currentThread ( ) . interrupt ( ) ;
break ;
}
}
}
}
}
4.2 多线程配置优化
io-threads 4
io-threads-do-reads yes
public class RedisPerformanceTest {
@Test
public void compareIOThreadsPerformance ( ) {
RedisConfig singleThread = new RedisConfig ( ) ;
singleThread. setIOThreads ( 1 ) ;
RedisConfig multiThread = new RedisConfig ( ) ;
multiThread. setIOThreads ( 4 ) ;
multiThread. setIOThreadsDoReads ( true ) ;
}
}
五、内存管理优化
5.1 内存分配器优化
public class RedisMemoryManager {
static {
System . loadLibrary ( "jemalloc" ) ;
}
private static final RedisObject [ ] SHARED_INTEGERS =
new RedisObject [ 10000 ] ;
static {
for ( int i = 0 ; i < SHARED_INTEGERS. length; i++ ) {
SHARED_INTEGERS[ i] = new RedisObject ( REDIS_STRING, i) ;
}
}
public RedisObject getSharedInteger ( int value) {
if ( value >= 0 && value < SHARED_INTEGERS. length) {
return SHARED_INTEGERS[ value] ;
}
return new RedisObject ( REDIS_STRING, value) ;
}
public void evictMemory ( ) {
while ( getCurrentMemoryUsage ( ) > maxMemory) {
switch ( maxMemoryPolicy) {
case "allkeys-lru" :
evictLRU ( getAllKeys ( ) ) ;
break ;
case "volatile-lru" :
evictLRU ( getVolatileKeys ( ) ) ;
break ;
case "allkeys-lfu" :
evictLFU ( getAllKeys ( ) ) ;
break ;
}
}
}
}
5.2 编码优化
public class RedisObject {
private int type;
private int encoding;
private Object ptr;
private int lru;
public static final int OBJ_ENCODING_RAW = 0 ;
public static final int OBJ_ENCODING_INT = 1 ;
public static final int OBJ_ENCODING_HT = 2 ;
public static final int OBJ_ENCODING_ZIPMAP = 3 ;
public static final int OBJ_ENCODING_LINKEDLIST = 4 ;
public static final int OBJ_ENCODING_ZIPLIST = 5 ;
public static final int OBJ_ENCODING_INTSET = 6 ;
public static final int OBJ_ENCODING_SKIPLIST = 7 ;
public static final int OBJ_ENCODING_EMBSTR = 8 ;
public static final int OBJ_ENCODING_QUICKLIST = 9 ;
public void tryObjectEncoding ( ) {
if ( type == REDIS_STRING && encoding == OBJ_ENCODING_RAW) {
String str = ( String ) ptr;
try {
long value = Long . parseLong ( str) ;
if ( value >= Integer . MIN_VALUE && value <= Integer . MAX_VALUE) {
this . encoding = OBJ_ENCODING_INT;
this . ptr = ( int ) value;
return ;
}
} catch ( NumberFormatException e) {
}
if ( str. length ( ) <= 44 ) {
this . encoding = OBJ_ENCODING_EMBSTR;
}
}
}
}
六、持久化性能优化
6.1 RDB快照优化
public class RDBPersistence {
public void saveRDB ( ) {
int childPid = fork ( ) ;
if ( childPid == 0 ) {
try {
saveRDBFile ( ) ;
System . exit ( 0 ) ;
} catch ( Exception e) {
System . exit ( 1 ) ;
}
} else if ( childPid > 0 ) {
waitForChild ( childPid) ;
} else {
throw new RuntimeException ( "Failed to fork child process" ) ;
}
}
private void copyOnWrite ( ) {
}
}
6.2 AOF优化
public class AOFPersistence {
private BufferedWriter aofWriter;
private final String AOF_FSYNC_NO = "no" ;
private final String AOF_FSYNC_ALWAYS = "always" ;
private final String AOF_FSYNC_EVERYSEC = "everysec" ;
public void writeAOF ( String command) {
try {
aofWriter. write ( command) ;
switch ( aofFsyncPolicy) {
case AOF_FSYNC_ALWAYS:
aofWriter. flush ( ) ;
break ;
case AOF_FSYNC_EVERYSEC:
scheduleFlush ( ) ;
break ;
case AOF_FSYNC_NO:
break ;
}
} catch ( IOException e) {
handleAOFError ( e) ;
}
}
@Async
public void rewriteAOF ( ) {
}
}
七、网络协议优化
7.1 Pipeline批处理
public class RedisPipeline {
@Test
public void pipelinePerformanceTest ( ) {
Jedis jedis = new Jedis ( "localhost" , 6379 ) ;
long start = System . currentTimeMillis ( ) ;
for ( int i = 0 ; i < 10000 ; i++ ) {
jedis. set ( "key" + i, "value" + i) ;
}
long normalTime = System . currentTimeMillis ( ) - start;
start = System . currentTimeMillis ( ) ;
Pipeline pipeline = jedis. pipelined ( ) ;
for ( int i = 0 ; i < 10000 ; i++ ) {
pipeline. set ( "key" + i, "value" + i) ;
}
pipeline. sync ( ) ;
long pipelineTime = System . currentTimeMillis ( ) - start;
System . out. printf ( "普通模式: %dms, Pipeline模式: %dms, 提升: %.2fx\n" ,
normalTime, pipelineTime, ( double ) normalTime / pipelineTime) ;
}
}
7.2 Lua脚本优化
public class RedisLuaScript {
private static final String INCR_WITH_LIMIT_SCRIPT =
"local current = redis.call('GET', KEYS[1]) or '0' " +
"if tonumber(current) < tonumber(ARGV[1]) then " +
" return redis.call('INCR', KEYS[1]) " +
"else " +
" return nil " +
"end" ;
public Long incrWithLimit ( String key, int limit) {
Jedis jedis = new Jedis ( ) ;
Object result = jedis. eval ( INCR_WITH_LIMIT_SCRIPT,
Collections . singletonList ( key) ,
Collections . singletonList ( String . valueOf ( limit) ) ) ;
return ( Long ) result;
}
private final Map < String , String > scriptShaCache = new ConcurrentHashMap < > ( ) ;
public Object evalOptimized ( String script) {
String sha = scriptShaCache. computeIfAbsent ( script, this :: loadScript ) ;
try {
return jedis. evalsha ( sha) ;
} catch ( JedisDataException e) {
sha = loadScript ( script) ;
return jedis. evalsha ( sha) ;
}
}
}
八、性能监控与调优
8.1 性能指标监控
@Component
public class RedisPerformanceMonitor {
@Scheduled ( fixedDelay = 5000 )
public void monitorRedisPerformance ( ) {
try ( Jedis jedis = new Jedis ( "localhost" , 6379 ) ) {
String info = jedis. info ( ) ;
Map < String , String > metrics = parseInfo ( info) ;
long instantaneousOpsPerSec = Long . parseLong (
metrics. getOrDefault ( "instantaneous_ops_per_sec" , "0" ) ) ;
long usedMemory = Long . parseLong (
metrics. getOrDefault ( "used_memory" , "0" ) ) ;
long maxMemory = Long . parseLong (
metrics. getOrDefault ( "maxmemory" , "0" ) ) ;
double memoryUsageRatio = maxMemory > 0 ?
( double ) usedMemory / maxMemory : 0 ;
int connectedClients = Integer . parseInt (
metrics. getOrDefault ( "connected_clients" , "0" ) ) ;
long keyspaceHits = Long . parseLong (
metrics. getOrDefault ( "keyspace_hits" , "0" ) ) ;
long keyspaceMisses = Long . parseLong (
metrics. getOrDefault ( "keyspace_misses" , "0" ) ) ;
double hitRatio = ( keyspaceHits + keyspaceMisses) > 0 ?
( double ) keyspaceHits / ( keyspaceHits + keyspaceMisses) : 0 ;
if ( memoryUsageRatio > 0.8 ) {
alertService. sendAlert ( "Redis内存使用率过高: " + memoryUsageRatio) ;
}
if ( hitRatio < 0.9 ) {
alertService. sendAlert ( "Redis缓存命中率过低: " + hitRatio) ;
}
}
}
public void monitorSlowQueries ( ) {
try ( Jedis jedis = new Jedis ( ) ) {
List < Slowlog > slowlogs = jedis. slowlogGet ( ) ;
for ( Slowlog log : slowlogs) {
if ( log. getExecutionTime ( ) > 1000 ) {
logger. warn ( "慢查询检测: 命令={}, 耗时={}μs, 时间={}" ,
log. getArgs ( ) , log. getExecutionTime ( ) ,
new Date ( log. getTimeStamp ( ) * 1000 ) ) ;
}
}
}
}
}
8.2 性能调优建议
public class RedisOptimizationGuide {
public void optimizeDataStructure ( ) {
}
public void optimizeMemory ( ) {
}
public void optimizeNetwork ( ) {
}
}