redis是基于键值对来存储一系列信息的非关系型数据库,也就是说每条信息都一定有一个key。
使用的工具是StringRedisTemplate
一、基本数据类型
1.String(字符串):应用:计数器、分布式锁、共享session、缓存预热
SET key value
:设置指定键的值。GET key
:获取指定键的值。INCR key
:将键的值增加1,如果键不存在则创建并设为0后再加1。DECR key
:将键的值减少1,如果键不存在则创建并设为0后再减1。INCRBY key increment
:将键的值增加指定的增量。DECRBY key decrement
:将键的值减少指定的减量。
设置和获取键值
@Service
public class RedisService {@Autowiredprivate StringRedisTemplate stringRedisTemplate;public void setKeyValue(String key, String value) {stringRedisTemplate.opsForValue().set(key, value);}public String getKeyValue(String key) {return stringRedisTemplate.opsForValue().get(key);}
}
增加和减少数值
public void incrementKey(String key, long increment) {stringRedisTemplate.opsForValue().increment(key, increment);
}public void decrementKey(String key, long decrement) {stringRedisTemplate.opsForValue().decrement(key, decrement);
}
追加值
public void appendValue(String key, String value) {stringRedisTemplate.opsForValue().append(key, value);
}
2.Hash(哈希):结构是key:(key:value);应用:缓存用户信息
HSET key field value
:设置哈希表中字段的值。HGET key field
:获取哈希表中字段的值。HMSET key field1 value1 [field2 value2 ...]
:同时设置哈希表中多个字段的值。HMGET key field1 [field2 ...]
:获取哈希表中多个字段的值。HGETALL key
:获取哈希表中所有字段和值。HDEL key field1 [field2 ...]
:删除哈希表中的一个或多个字段。HEXISTS key field
:检查哈希表中是否存在指定字段。HLEN key
:获取哈希表中字段的数量。HKEYS key
:获取哈希表中所有的字段。HVALS key
:获取哈希表中所有的值。
设置和获取哈希表字段
public void setHashField(String key, String field, String value) {stringRedisTemplate.opsForHash().put(key, field, value);
}public String getHashField(String key, String field) {return (String) stringRedisTemplate.opsForHash().get(key, field);
}
获取哈希表所有字段和值
public Map<Object, Object> getAllHashFields(String key) {
return stringRedisTemplate.opsForHash().entries(key);
}
删除哈希表字段
public void deleteHashField(String key, String field) {stringRedisTemplate.opsForHash().delete(key, field);
}
3.List(列表):有序可重复;应用:消息队列,文章列表
LPUSH key value1 [value2 ...]
:将一个或多个值插入列表的头部。RPUSH key value1 [value2 ...]
:将一个或多个值插入列表的尾部。LPOP key
:移除并返回列表的第一个元素。RPOP key
:移除并返回列表的最后一个元素。LRANGE key start stop
:获取列表中指定范围的元素。LLEN key
:获取列表的长度。LINDEX key index
:获取列表中指定位置的元素。LSET key index value
:设置列表中指定位置的元素值。LREM key count value
:从列表中移除指定数量的值。
插入值到列表头部和尾部
public void pushToListHead(String key, String value) {stringRedisTemplate.opsForList().leftPush(key, value);
}public void pushToListTail(String key, String value) {stringRedisTemplate.opsForList().rightPush(key, value);
}
移除并返回列表的第一个和最后一个元素
public String popFromListHead(String key) {return stringRedisTemplate.opsForList().leftPop(key);
}public String popFromListTail(String key) {
return stringRedisTemplate.opsForList().rightPop(key);
}
获取列表中指定范围的元素
public List<String> getListRange(String key, long start, long end) {return stringRedisTemplate.opsForList().range(key, start, end);
}
4.集合(Set):无序且不重复;应用:关注列表,共同关注,生成随机数抽奖
SADD key member1 [member2 ...]
:将一个或多个成员添加到集合中。SMEMBERS key
:获取集合中的所有成员。SISMEMBER key member
:检查成员是否存在于集合中。SREM key member1 [member2 ...]
:从集合中移除一个或多个成员。SCARD key
:获取集合中成员的数量。SINTER key1 [key2 ...]
:获取多个集合的交集。SUNION key1 [key2 ...]
:获取多个集合的并集。SDIFF key1 [key2 ...]
:获取多个集合的差集。SRANDMEMBER key [count]
:随机返回集合中的一个或多个成员。
添加和移除集合成员
public void addSetMember(String key, String member) {stringRedisTemplate.opsForSet().add(key, member);
}public void removeSetMember(String key, String member) {stringRedisTemplate.opsForSet().remove(key, member);
}
获取集合中的所有成员
public Set<String> getSetMembers(String key) {
return stringRedisTemplate.opsForSet().members(key);
}
检查成员是否存在于集合中
public boolean isSetMember(String key, String member) {return stringRedisTemplate.opsForSet().isMember(key, member);
}
5.有序集合(Sorted Set):有序且不重复,分数可以相同。点赞排行榜()
ZADD key score1 member1 [score2 member2 ...]
:将一个或多个成员及其分数添加到有序集合中。ZRANGE key start stop [WITHSCORES]
:按分数从小到大返回有序集合中指定范围的成员。ZREVRANGE key start stop [WITHSCORES]
:按分数从大到小返回有序集合中指定范围的成员。ZRANK key member
:返回成员在有序集合中的排名,分数从小到大。ZREVRANK key member
:返回成员在有序集合中的排名,分数从大到小。ZREM key member1 [member2 ...]
:从有序集合中移除一个或多个成员。ZCARD key
:获取有序集合中成员的数量。ZCOUNT key min max
:统计有序集合中分数在指定范围内的成员数量。ZSCORE key member
:获取成员在有序集合中的分数。ZINCRBY key increment member
:将成员的分数增加指定的增量。ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
:计算多个有序集合的交集,并将结果存储在新的有序集合中。ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
:计算多个有序集合的并集,并将结果存储在新的有序集合中。
添加和移除有序集合成员
public void addSortedSetMember(String key, String member, double score) {stringRedisTemplate.opsForZSet().add(key, member, score);
}public void removeSortedSetMember(String key, String member) {stringRedisTemplate.opsForZSet().remove(key, member);
}
获取有序集合中指定范围的成员
public Set<String> getSortedSetRange(String key, long start, long end) {return stringRedisTemplate.opsForZSet().range(key, start, end);
}public Set<String> getSortedSetReverseRange(String key, long start, long end) {return stringRedisTemplate.opsForZSet().reverseRange(key, start, end);
}
获取成员的排名
public Long getSortedSetRank(String key, String member) {return stringRedisTemplate.opsForZSet().rank(key, member);
}public Long getSortedSetReverseRank(String key, String member) {return stringRedisTemplate.opsForZSet().reverseRank(key, member);
}
6.通用命令
DEL key
:删除键。EXISTS key
:检查键是否存在。EXPIRE key seconds
:设置键的过期时间(秒)。TTL key
:获取键的剩余生存时间(秒)。TYPE key
:获取键的类型。KEYS pattern
:查找符合给定模式的键。FLUSHDB
:清空当前数据库中的所有键。FLUSHALL
:清空所有数据库中的所有键。
删除键
public void deleteKey(String key) {
stringRedisTemplate.delete(key);
}
检查键是否存在
public boolean existsKey(String key) {
return stringRedisTemplate.hasKey(key);
}
设置键的过期时间
public void expireKey(String key, long timeout, TimeUnit unit) {stringRedisTemplate.expire(key, timeout, unit);
}
获取键的剩余生存时间
public Long getKeyTTL(String key) {
return stringRedisTemplate.getExpire(key);
}
清空当前数据库
public void flushDatabase() {stringRedisTemplate.getConnectionFactory().getConnection().flushDb();
}
清空所有数据库
public void flushAllDatabases() {stringRedisTemplate.getConnectionFactory().getConnection().flushAll();
}
二、高级数据类型
1. Bitmaps(位图)
特点:
- 位图是一种特殊的字符串类型,每个位可以存储 0 或 1。
- 位图操作可以用于高效地存储和检索二进制数据。
应用场景:
- 用户签到:记录用户每天是否签到,每个位表示一天,1 表示签到,0 表示未签到。
- 统计分析:记录某个时间段内用户的活跃情况,如每日登录用户数。
- 权限控制:记录用户的权限,每个位表示一种权限。
常用命令:
SETBIT key offset value
:设置指定偏移量上的位值。GETBIT key offset
:获取指定偏移量上的位值。BITCOUNT key [start] [end]
:统计指定键中 1 的数量。BITOP operation destkey key [key ...]
:对多个位图进行按位操作(AND、OR、NOT、XOR)。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;@Service
public class RedisBitMapService {@Autowiredprivate StringRedisTemplate stringRedisTemplate;/*** 设置位图中的某一位** @param key 键* @param offset 位偏移量* @param value 位值(true 或 false)*/public void setBit(String key, long offset, boolean value) {stringRedisTemplate.getConnectionFactory().getConnection().setBit(key.getBytes(), offset, value);}/*** 获取位图中的某一位** @param key 键* @param offset 位偏移量* @return 位值(true 或 false)*/public boolean getBit(String key, long offset) {return stringRedisTemplate.getConnectionFactory().getConnection().getBit(key.getBytes(), offset);}/*** 计算位图中 1 的数量** @param key 键* @return 1 的数量*/public long bitCount(String key) {return stringRedisTemplate.execute((RedisConnection connection) -> connection.bitCount(key.getBytes()));}/*** 对多个位图进行按位操作并将结果存储到目标位图中** @param destKey 目标键* @param keys 源键数组* @return 结果位图中 1 的数量*/public long bitOpAndStore(String destKey, String... keys) {return stringRedisTemplate.execute((RedisConnection connection) -> connection.bitOp(RedisConnection.BitOperation.AND, destKey.getBytes(), toByteArrays(keys)));}/*** 将字符串数组转换为字节数组** @param keys 字符串数组* @return 字节数组*/private byte[][] toByteArrays(String[] keys) {byte[][] byteKeys = new byte[keys.length][];for (int i = 0; i < keys.length; i++) {byteKeys[i] = keys[i].getBytes();}return byteKeys;}
}
2. HyperLogLog
特点:
- 用于估计集合的基数(即集合中不重复元素的数量)。
- 占用空间极小,每个 HyperLogLog 只占用 12 KB 内存。
- 有一定的误差率,但误差率通常在 0.81% 以内。
应用场景:
- 独立访客统计:统计网站的独立访客数。
- 日活用户:统计应用的每日活跃用户数。
- 去重统计:统计某一时间段内的不重复事件数。
常用命令:
PFADD key element [element ...]
:添加一个或多个元素到 HyperLogLog。PFCOUNT key [key ...]
:返回一个或多个 HyperLogLog 的近似基数。PFMERGE destkey sourcekey [sourcekey ...]
:将多个 HyperLogLog 合并到一个新的 HyperLogLog 中。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;@Service
public class RedisHyperLogLogService {@Autowiredprivate StringRedisTemplate stringRedisTemplate;/*** 向 HyperLogLog 中添加一个或多个元素** @param key 键* @param elements 元素数组*/public void addElementToHyperLogLog(String key, String... elements) {stringRedisTemplate.execute((RedisConnection connection) -> {connection.pfAdd(key.getBytes(), toByteArrays(elements));return null;});}/*** 获取 HyperLogLog 的近似基数** @param key 键* @return 近似基数*/public long getApproximateCount(String key) {return stringRedisTemplate.execute((RedisConnection connection) -> connection.pfCount(key.getBytes()));}/*** 合并多个 HyperLogLog 并将结果存储到目标 HyperLogLog 中** @param destKey 目标键* @param sourceKeys 源键数组* @return 合并后的近似基数*/public long mergeHyperLogLogs(String destKey, String... sourceKeys) {return stringRedisTemplate.execute((RedisConnection connection) -> connection.pfMerge(destKey.getBytes(), toByteArrays(sourceKeys)));}/*** 将字符串数组转换为字节数组** @param elements 字符串数组* @return 字节数组*/private byte[][] toByteArrays(String[] elements) {byte[][] byteElements = new byte[elements.length][];for (int i = 0; i < elements.length; i++) {byteElements[i] = elements[i].getBytes();}return byteElements;}
}
3. GEO(地理信息)
特点:
- 用于存储和查询地理位置信息。
- 支持基于经纬度的地理位置操作,如距离计算、半径查询等。
应用场景:
- 附近的人:查找附近的用户或地点。
- 位置服务:提供基于地理位置的服务,如地图标注、导航等。
- 物流配送:优化配送路径,计算配送距离。
常用命令:
GEOADD key longitude latitude member [longitude latitude member ...]
:添加一个或多个地理空间元素。
// 添加几个城市的地理位置信息
geoService.addGeoLocation("cities", 116.4074, 39.9042, "北京");
geoService.addGeoLocation("cities", 121.4737, 31.2304, "上海");
geoService.addGeoLocation("cities", 113.2644, 23.1291, "广州");
GEOPOS key member [member ...]
:获取一个或多个地理空间元素的经纬度。GEODIST key member1 member2 [unit]
:计算两个地理空间元素之间的距离。GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]
:查找指定半径内的地理空间元素。GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]
:查找指定元素周围的地理空间元素。GEOHASH key member [member ...]
:获取一个或多个地理空间元素的 Geohash 编码。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.GeoOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;@Service
public class RedisGeoService {@Autowiredprivate StringRedisTemplate stringRedisTemplate;/*** 向 GEO 数据集中添加地理位置信息** @param key 键* @param longitude 经度* @param latitude 纬度* @param member 成员*/public void addGeoLocation(String key, double longitude, double latitude, String member) {stringRedisTemplate.opsForGeo().add(key, new Point(longitude, latitude), member);}/*** 获取指定半径内的地理位置信息** @param key 键* @param longitude 经度* @param latitude 纬度* @param radius 半径* @param unit 单位* @return 地理位置信息*/public GeoResults<RedisGeoCommands.GeoLocation<String>> getGeoLocationsWithinRadius(String key, double longitude, double latitude, double radius, RedisGeoCommands.DistanceUnit unit) {RedisGeoCommands.Circle circle = new RedisGeoCommands.Circle(new Point(longitude, latitude), new RedisGeoCommands.Distance(radius, unit));RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().includeCoordinates();return stringRedisTemplate.opsForGeo().radius(key, circle, args);}/*** 获取两个地理位置之间的距离** @param key 键* @param member1 成员1* @param member2 成员2* @param unit 单位* @return 距离*/public Double getDistanceBetweenGeoLocations(String key, String member1, String member2, RedisGeoCommands.DistanceUnit unit) {return stringRedisTemplate.opsForGeo().distance(key, member1, member2, unit);}/*** 获取指定成员周围的地理位置信息** @param key 键* @param member 成员* @param radius 半径* @param unit 单位* @return 地理位置信息*/public GeoResults<RedisGeoCommands.GeoLocation<String>> getGeoLocationsByMember(String key, String member, double radius, RedisGeoCommands.DistanceUnit unit) {RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().includeCoordinates();return stringRedisTemplate.opsForGeo().radius(key, member, new RedisGeoCommands.Distance(radius, unit), args);}
}
4. Bloom Filter(布隆过滤器)
特点:
- 用于高效地判断某个元素是否在一个集合中。
- 占用空间小,查询速度快,但有一定的误判率。
应用场景:
- 网页爬虫:判断某个 URL 是否已经被抓取过。
- 黑名单:判断某个 IP 地址是否在黑名单中。
- 缓存穿透:防止缓存穿透,判断某个键是否存在于缓存中。
注意:
- Redis 本身并不直接支持 Bloom Filter,但可以通过 Redis 模块(如 RedisBloom)来实现。
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class RedisBloomFilterService {@Autowiredprivate RedissonClient redissonClient;/*** 创建一个 Bloom Filter** @param name 布隆过滤器的名称* @param expectedInsertions 预期插入的元素数量* @param probabilityOfFalsePositives 误判概率* @return 布隆过滤器*/public RBloomFilter<String> createBloomFilter(String name, long expectedInsertions, double probabilityOfFalsePositives) {RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter(name);bloomFilter.tryInit(expectedInsertions, probabilityOfFalsePositives);return bloomFilter;}/*** 向布隆过滤器中添加元素** @param name 布隆过滤器的名称* @param element 元素*/public void addElementToBloomFilter(String name, String element) {RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter(name);bloomFilter.add(element);}/*** 检查元素是否可能存在于布隆过滤器中** @param name 布隆过滤器的名称* @param element 元素* @return 是否可能存在*/public boolean mightContain(String name, String element) {RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter(name);return bloomFilter.contains(element);}
}