+-------------------+ | "Hello World" | +-------------------+
String是Redis最基本的数据类型,一个key对应一个value。String类型是二进制安全的,意味着Redis的String可以包含任何数据,比如jpg图片或者序列化的对象。String类型的值最大能存储512MB。
java@Service
public class StringCacheService {
@Autowired
private StringRedisTemplate redisTemplate;
// 缓存用户信息
public void cacheUser(String userId, String userInfo) {
String key = "user:info:" + userId;
redisTemplate.opsForValue().set(key, userInfo, Duration.ofHours(1));
}
// 获取用户信息
public String getUserInfo(String userId) {
String key = "user:info:" + userId;
return redisTemplate.opsForValue().get(key);
}
// 计数器功能
public Long incrementCounter(String counterKey) {
return redisTemplate.opsForValue().increment(counterKey);
}
// 分布式锁
public boolean tryLock(String lockKey, String lockValue, Duration expireTime) {
return Boolean.TRUE.equals(
redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, expireTime)
);
}
}
+-------+-------+-------+-------+ | "A" | "B" | "C" | "D" | +-------+-------+-------+-------+ 0 1 2 3 索引
List是简单的字符串列表,按照插入顺序排序。可以添加一个元素到列表的头部(左边)或者尾部(右边)。List的底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差。
java@Service
public class ListQueueService {
@Autowired
private StringRedisTemplate redisTemplate;
// 添加消息到队列
public void pushMessage(String queueKey, String message) {
redisTemplate.opsForList().leftPush(queueKey, message);
}
// 从队列获取消息
public String popMessage(String queueKey) {
return redisTemplate.opsForList().rightPop(queueKey);
}
// 获取最新动态列表
public List<String> getLatestFeeds(String userId, int count) {
String key = "user:feeds:" + userId;
return redisTemplate.opsForList().range(key, 0, count - 1);
}
// 添加用户动态
public void addUserFeed(String userId, String feed) {
String key = "user:feeds:" + userId;
redisTemplate.opsForList().leftPush(key, feed);
// 保持列表长度不超过100
redisTemplate.opsForList().trim(key, 0, 99);
}
}
+----------+----------+ | Field | Value | +----------+----------+ | name | "张三" | | age | "25" | | city | "北京" | +----------+----------+
Hash是一个键值对集合,是一个String类型的field和value的映射表。Hash特别适合用于存储对象。每个Hash可以存储2^32-1键值对(40多亿)。
java@Service
public class HashUserService {
@Autowired
private StringRedisTemplate redisTemplate;
// 存储用户信息
public void saveUserInfo(String userId, Map<String, String> userInfo) {
String key = "user:profile:" + userId;
redisTemplate.opsForHash().putAll(key, userInfo);
}
// 获取用户信息
public Map<Object, Object> getUserInfo(String userId) {
String key = "user:profile:" + userId;
return redisTemplate.opsForHash().entries(key);
}
// 更新用户单个字段
public void updateUserField(String userId, String field, String value) {
String key = "user:profile:" + userId;
redisTemplate.opsForHash().put(key, field, value);
}
// 购物车操作
public void addToCart(String userId, String productId, String quantity) {
String key = "cart:" + userId;
redisTemplate.opsForHash().put(key, productId, quantity);
}
// 获取购物车内容
public Map<Object, Object> getCartItems(String userId) {
String key = "cart:" + userId;
return redisTemplate.opsForHash().entries(key);
}
}
+-------------------+ | { "A", "B", "C" } | +-------------------+
Set是String类型的无序集合。集合是通过哈希表实现的,所以添加、删除、查找的复杂度都是O(1)。Set中的元素是唯一的,不允许重复。
java@Service
public class SetTagService {
@Autowired
private StringRedisTemplate redisTemplate;
// 为文章添加标签
public void addArticleTags(String articleId, String... tags) {
String key = "article:tags:" + articleId;
redisTemplate.opsForSet().add(key, tags);
}
// 获取文章标签
public Set<String> getArticleTags(String articleId) {
String key = "article:tags:" + articleId;
return redisTemplate.opsForSet().members(key);
}
// 添加好友关系
public void addFriend(String userId, String friendId) {
String key = "user:friends:" + userId;
redisTemplate.opsForSet().add(key, friendId);
}
// 获取共同好友
public Set<String> getCommonFriends(String userId1, String userId2) {
String key1 = "user:friends:" + userId1;
String key2 = "user:friends:" + userId2;
return redisTemplate.opsForSet().intersect(key1, key2);
}
// 数据去重
public void addUniqueVisitor(String pageId, String visitorId) {
String key = "page:visitors:" + pageId;
redisTemplate.opsForSet().add(key, visitorId);
}
}
+-------+-------+ | Score | Value | +-------+-------+ | 100 | "张三" | | 95 | "李四" | | 90 | "王五" | +-------+-------+
Sorted Set是Set的一个升级版本,它在Set的基础上增加了一个顺序属性score,这一属性在添加修改元素的时候可以指定。每次指定后,Sorted Set会自动重新按新的值调整顺序。
java@Service
public class SortedSetRankService {
@Autowired
private StringRedisTemplate redisTemplate;
// 更新用户积分
public void updateUserScore(String userId, double score) {
String key = "game:leaderboard";
redisTemplate.opsForZSet().add(key, userId, score);
}
// 获取排行榜前N名
public Set<ZSetOperations.TypedTuple<String>> getTopPlayers(int count) {
String key = "game:leaderboard";
return redisTemplate.opsForZSet().reverseRangeWithScores(key, 0, count - 1);
}
// 获取用户排名
public Long getUserRank(String userId) {
String key = "game:leaderboard";
return redisTemplate.opsForZSet().reverseRank(key, userId);
}
// 延时任务队列
public void addDelayedTask(String taskId, long executeTime) {
String key = "delayed:tasks";
redisTemplate.opsForZSet().add(key, taskId, executeTime);
}
// 获取到期任务
public Set<String> getExpiredTasks(long currentTime) {
String key = "delayed:tasks";
return redisTemplate.opsForZSet().rangeByScore(key, 0, currentTime);
}
}
+---+---+---+---+---+---+---+---+ | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | +---+---+---+---+---+---+---+---+ 0 1 2 3 4 5 6 7 位置
Bitmap不是一个实际的数据类型,而是基于String类型的位操作。在Redis中,String类型的值最大可以是512MB,即可以存储多达2^32个不同的位。每个位只能存储0或1两种状态,非常适合存储布尔类型的数据。
java@Service
public class UserSignService {
@Autowired
private StringRedisTemplate redisTemplate;
// 用户签到
public void userSign(String userId, LocalDate date) {
String key = "user:sign:" + userId + ":" + date.getYear() + ":" + date.getMonthValue();
redisTemplate.opsForValue().setBit(key, date.getDayOfMonth() - 1, true);
}
// 检查用户是否签到
public boolean checkSign(String userId, LocalDate date) {
String key = "user:sign:" + userId + ":" + date.getYear() + ":" + date.getMonthValue();
return Boolean.TRUE.equals(redisTemplate.opsForValue().getBit(key, date.getDayOfMonth() - 1));
}
}
+----------------+ | Register 1 | +----------------+ | Register 2 | +----------------+ | ... | +----------------+ | Register 16384| +----------------+
HyperLogLog是一种用于基数统计的概率性数据结构,可以在使用固定且很小的内存空间(每个HyperLogLog键只需要花费12KB内存)的情况下,计算集合中不重复元素的数量。其原理基于概率学中的伯努利试验,通过观察集合元素的二进制表示中前导零的数量来估算基数。
java@Service
public class UVCountService {
@Autowired
private StringRedisTemplate redisTemplate;
// 记录用户访问
public void recordUserVisit(String userId, LocalDate date) {
String key = "uv:" + date;
redisTemplate.opsForHyperLogLog().add(key, userId);
}
// 获取当日UV
public long getUVCount(LocalDate date) {
String key = "uv:" + date;
return redisTemplate.opsForHyperLogLog().size(key);
}
// 获取指定时间范围内的UV
public long getUVCountInRange(LocalDate startDate, LocalDate endDate) {
String destKey = "uv:range:" + startDate + ":" + endDate;
String[] keys = new String[(int) ChronoUnit.DAYS.between(startDate, endDate) + 1];
int index = 0;
for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
keys[index++] = "uv:" + date;
}
redisTemplate.opsForHyperLogLog().union(destKey, keys);
return redisTemplate.opsForHyperLogLog().size(destKey);
}
}
+-------------+-------------+----------+ | 经度 | 纬度 | 成员 | +-------------+-------------+----------+ | 116.397128 | 39.916527 | 商家A | | 116.321429 | 39.897308 | 商家B | | 116.380338 | 39.913527 | 商家C | +-------------+-------------+----------+
GEO(Geospatial)是Redis用于存储地理位置信息的数据类型,其底层实际上是基于Sorted Set实现的。Redis会将二维的经纬度转换成一维的52位整数(GeoHash编码),并将这个整数作为Sorted Set的score值。这种设计让我们可以方便地进行范围查找和距离计算。
java@Service
public class LocationService {
@Autowired
private StringRedisTemplate redisTemplate;
// 添加商家位置
public void addShopLocation(String shopId, double longitude, double latitude) {
String key = "shop:locations";
redisTemplate.opsForGeo().add(key, new Point(longitude, latitude), shopId);
}
// 查找附近的商家
public List<GeoResult<RedisGeoCommands.GeoLocation<String>>> findNearbyShops(
double longitude, double latitude, double radius) {
String key = "shop:locations";
Circle circle = new Circle(new Point(longitude, latitude), new Distance(radius, Metrics.KILOMETERS));
GeoResults<RedisGeoCommands.GeoLocation<String>> results = redisTemplate.opsForGeo()
.search(key, circle);
return results.getContent();
}
// 计算两个商家之间的距离
public Distance getDistance(String shopId1, String shopId2) {
String key = "shop:locations";
return redisTemplate.opsForGeo()
.distance(key, shopId1, shopId2, Metrics.KILOMETERS);
}
}
本文详细介绍了Redis中八种重要的数据类型,包括五种基本数据类型和三种高级数据类型。每种数据类型都有其独特的特性和适用场景:
基本数据类型:
高级数据类型:
在实际应用中,合理选择和使用这些数据类型不仅能提高系统性能,还能大大降低内存使用量和开发复杂度。通过SpringBoot的集成示例,我们可以看到这些数据类型在实际项目中的应用方式都相对简单直观。掌握这些数据类型的特性和使用场景,对于构建高性能、可扩展的Redis应用至关重要。
本文作者:大哥吕
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!