网站Logo 时光杂货铺

redis使用

admin
31
2025-06-23

RedisTemplate 完整常用 API 分类

  1. Spring‑data‑redis,RedisTemplate<String,Object>;推荐业务优先StringRedisTemplate

  2. opsForXxx 对应 Redis 五大数据结构;底层通用方法直接由 redisTemplate 调用

  3. Bitmap 属于opsForValue(),底层是 String

  4. executePipelined 中 RedisConnection 是底层原生连接,key 需要转 byte [],不走序列化

1、opsForValue() String字符串操作


java
ValueOperations<String,Object> ops = redisTemplate.opsForValue();

// 设置key-value
ops.set("key","value");
// 设置key-value,同时设置过期时间
ops.set("key","value",10, TimeUnit.SECONDS);
// setnx:key不存在才设置,存在不生效
ops.setIfAbsent("key","value");
// key存在才设置,不存在不生效
ops.setIfPresent("key","value");

// 根据key获取value
Object v = ops.get("key");
// 获取旧值,同时写入新值(getset命令)
Object oldVal = ops.getAndSet("key","newVal");
// 截取字符串,[start,end]下标
String subStr = ops.get("key",0,2);

// 数字+1,自增
ops.increment("num");
// 数字增加指定步长
ops.increment("num",5L);
// 数字-1,自减
ops.decrement("num");
// 数字减去指定步长
ops.decrement("num",2L);

// 批量设置多个key-value
ops.multiSet(Map);
// 批量获取多个key的值
List<Object> list = ops.multiGet(Collection<String> keys);

// ========= bitmap 位图API,属于ValueOperations =========
// 设置指定offset的bit位,true=1 false=0
ops.setBit(key,offset,true);
// 获取指定offset的bit位,返回true/false
ops.getBit(key,offset);
// 统计bitmap中bit=1的总数量(bitcount)
ops.bitCount(key);
// 查找第一个bit=1的offset位置(bitpos)
ops.bitPos(key,true);
// bit位运算 AND/OR/XOR/NOT,运算结果存入dest目标key
ops.bitOp(BitOperations.BitOp.AND,"dest",k1,k2);

// 获取字符串占用字节大小,字节数*8=总bit位数
Long byteSize = ops.size("key");

2、opsForHash () Hash 哈希

HashOperations<String,Object,Object> hashOps = redisTemplate.opsForHash();

// hset:给hash的field设置value
hashOps.put("hKey","field","val");
// hsetnx:field不存在才赋值
hashOps.putIfAbsent("hKey","field","val");
// hmset:批量写入多个field-value
hashOps.putAll("hKey",Map);

// hget 获取hash中某个field的值
Object val = hashOps.get("hKey","field");
// hmget:批量获取多个field
List<Object> vals = hashOps.multiGet("hKey",List.of("f1","f2"));

// 判断hash内某个field是否存在
boolean exist = hashOps.hasKey("hKey","field");
// hincrby:hash内部字段数值自增
hashOps.increment("hKey","count",1);

// 获取hash全部field字段
Set<Object> fields = hashOps.keys("hKey");
// 获取hash全部value
List<Object> values = hashOps.values("hKey");
// 获取hash全部键值对,返回Map
Map<Object,Object> entries = hashOps.entries("hKey");

// hdel 删除hash中一个或多个field
hashOps.delete("hKey","f1","f2");
// hlen 获取hash里面field总个数
Long len = hashOps.size("hKey");

3、opsForList () List 列表

ListOperations<String,Object> listOps = redisTemplate.opsForList();

// ========= 入队 =========
// lpush:链表左侧头部插入元素
listOps.leftPush("lKey","a");
// lpush批量插入多个元素到头部
listOps.leftPushAll("lKey","a","b");
// rpush:链表尾部右侧插入元素
listOps.rightPush("lKey","x");
// rpush批量插入多个元素到尾部
listOps.rightPushAll("lKey","x","y");

// ========= 出队 =========
// lpop:头部弹出一个元素
Object lpop = listOps.leftPop("lKey");
// blpop:阻塞式头部弹出,超时时间内等待有数据返回
Object blpop = listOps.leftPop("lKey",10,TimeUnit.SECONDS);
// rpop:尾部弹出一个元素
Object rpop = listOps.rightPop("lKey");

// lindex 根据下标获取list元素
Object idxVal = listOps.index("lKey",0);
// lrange 获取区间元素,-1代表末尾
List<Object> range = listOps.range("lKey",0,-1);
// lset 根据下标修改指定位置元素
listOps.set("lKey",1,"newVal");
// lrem 删除list中指定value,count代表删除个数
listOps.remove("lKey",1,"val");
// ltrim 裁剪list,只保留[start,end]区间元素,其余全部删除
listOps.trim("lKey",0,10);

// llen 获取list总长度
Long size = listOps.size("lKey");

4、opsForSet () Set 无序集合

SetOperations<String,Object> setOps = redisTemplate.opsForSet();

// sadd 添加一个/多个元素到集合
setOps.add("sKey","v1","v2");
// smembers 获取集合全部元素
Set<Object> members = setOps.members("sKey");
// sismember 判断值是否存在集合中
boolean isIn = setOps.isMember("sKey","v1");

// srem 删除集合中的指定元素
setOps.remove("sKey","v1");
// spop 随机弹出集合内一个元素
Object pop = setOps.pop("sKey");
// srandmember 随机获取N个元素,不删除原集合数据
List<Object> rand = setOps.randomMembers("sKey",2);

// ========= 集合运算 =========
// sdiff 差集,返回key1有key2没有的数据
Set<Object> diff = setOps.difference("k1","k2");
// sinter 交集,两边都存在的数据
Set<Object> inter = setOps.intersect("k1","k2");
// sunion 并集,两边所有去重数据
Set<Object> union = setOps.union("k1","k2");

// scard 获取集合元素总数
Long card = setOps.size("sKey");

5、opsForZSet () ZSet 有序集合

ZSetOperations<String,Object> zsetOps = redisTemplate.opsForZSet();

// zadd 添加member,绑定score分数
zsetOps.add("zKey","member",10.0);

// zrange 按score从小到大获取区间元素
Set<Object> range = zsetOps.range("zKey",0,-1);
// zrange同时带出每条member对应的score
Set<ZSetOperations.TypedTuple<Object>> rangeScore = zsetOps.rangeWithScores("zKey",0,-1);
// zrevrange 按score从大到小获取区间元素
Set<Object> revRange = zsetOps.reverseRange("zKey",0,-1);
// zrangebyscore 根据分数区间过滤查询
Set<Object> rangeScoreFilter = zsetOps.rangeByScore("zKey",0,100);

// zrem 删除zset中的member成员
zsetOps.remove("zKey","member");
// zincrby 给member的score增加指定数值
Double newScore = zsetOps.incrementScore("zKey","member",5);

// zrank 获取member从小到大排名下标,从0开始
Long rank = zsetOps.rank("zKey","member");
// zrevrank 获取member从大到小排名下标
Long revRank = zsetOps.reverseRank("zKey","member");

// zcard 获取zset总元素数量
Long zSize = zsetOps.size("zKey");
// zcount 获取指定score分数区间内元素个数
Long countScore = zsetOps.count("zKey",0,100);

6、opsForHyperLogLog 基数统计

HyperLogLogOperations<String,Object> hllOps = redisTemplate.opsForHyperLogLog();
// 添加元素,做去重基数统计
hllOps.add("hllKey","v1","v2");
// 获取估算的去重总数
Long total = hllOps.size("hllKey");
// 多个hll合并,结果存入destKey
hllOps.union("destKey","src1","src2");

7、opsForGeo 地理位置

GeoOperations<String,Object> geoOps = redisTemplate.opsForGeo();
// 添加地点经纬度
geoOps.add("geoKey",new Point(116.40,39.90,"beijing"));
// 计算两个地点之间距离,指定单位KM/M
Distance dis = geoOps.distance("geoKey","p1","p2", Metrics.KILOMETERS);

顶层通用方法(直接 redisTemplate 调用)

// ========= key基础操作 =========
// 删除单个key
redisTemplate.delete("key1");
// 批量删除多个key
redisTemplate.delete(List.of("k1","k2"));
// 判断key是否存在
boolean hasKey = redisTemplate.hasKey("key");

// ========= 过期时间 =========
// 设置key多少时间后过期
redisTemplate.expire("key",30,TimeUnit.SECONDS);
// 设置key在某个具体时间点过期
redisTemplate.expireAt("key",new Date());
// 获取key剩余过期时间;-1永不过期,-2key不存在
Long ttl = redisTemplate.getExpire("key",TimeUnit.SECONDS);

// 修改key名称
redisTemplate.rename("old","new");
// 获取key对应的数据类型
DataType type = redisTemplate.type("key");

// ========= Pipeline管道,批量命令一次网络往返(签到项目用到) =========
List<Object> res = redisTemplate.executePipelined((RedisCallback<Object>)conn->{
    // conn.getBit(bytes,offset) ... 底层连接,key需要转byte[]
    return null;
});

// ========= Redis事务 multi / exec / discard =========
redisTemplate.multi(); //开启事务
redisTemplate.exec();  //提交事务
redisTemplate.discard();//放弃事务回滚

// ========= Lua脚本执行,原子操作 =========
DefaultRedisScript<Long> script = new DefaultRedisScript<>();
script.setScriptText("return redis.call('get',KEYS[1])");
script.setResultType(Long.class);
Long ret = redisTemplate.execute(script,List.of("key1"));

踩坑备忘

  1. RedisTemplate 默认 JDK 序列化,key 带 \xac\xed;业务优先使用 StringRedisTemplate

  2. executePipelined 内部 RedisConnection 不做序列化,key 要转 byte []

  3. BITCOUNT start/end 单位是字节,不是 bit

  4. Bitmap offset 最大 4294967295,超出报错

  5. opsForXXX 获取的操作对象线程安全,可以复用