一 字符串(String)
Redis 的字符串类型(String)是 Redis 中最基本的数据类型,它的使用非常广泛,几乎所有的应用场景都可以涉及到字符串的操作。下面,我们将通过一个虚拟电商平台的示例来展示 Redis 字符串类型的各种操作和应用场景。
应用场景
假设我们正在开发一个电商平台,需要管理以下几个方面:
-
商品库存管理:跟踪商品的库存数量。
-
用户积分管理:管理用户的积分余额。
-
用户登录状态:跟踪用户的登录状态(如活跃用户)。
-
缓存查询结果:缓存一些频繁查询的数据,如商品详情。
Java 代码示例
1. 商品库存管理
设置和获取库存数量
@Autowired private RedisTemplate<String, String> redisTemplate; // 设置商品库存 public void setProductStock(String productId, int stock) { redisTemplate.opsForValue().set("product:stock:" + productId, String.valueOf(stock)); } // 获取商品库存 public int getProductStock(String productId) { String stock = redisTemplate.opsForValue().get("product:stock:" + productId); return stock == null ? 0 : Integer.parseInt(stock); } // 扣减库存 public void decrementProductStock(String productId, int quantity) { redisTemplate.opsForValue().decrement("product:stock:" + productId, quantity); }
示例
// 设置商品 ID 为 100 的库存为 50 setProductStock("100", 50); // 获取商品 ID 为 100 的库存 int stock = getProductStock("100"); // 50 // 扣减库存 5 个 decrementProductStock("100", 5); // 剩余库存 45
2. 用户积分管理
设置和获取用户积分
// 设置用户积分 public void setUserPoints(String userId, int points) { redisTemplate.opsForValue().set("user:points:" + userId, String.valueOf(points)); } // 获取用户积分 public int getUserPoints(String userId) { String points = redisTemplate.opsForValue().get("user:points:" + userId); return points == null ? 0 : Integer.parseInt(points); } // 增加用户积分 public void addUserPoints(String userId, int points) { redisTemplate.opsForValue().increment("user:points:" + userId, points); }
示例
// 设置用户 ID 为 1 的积分为 100 setUserPoints("1", 100); // 获取用户 ID 为 1 的积分 int points = getUserPoints("1"); // 100 // 增加用户 ID 为 1 的积分 50 addUserPoints("1", 50); // 总积分 150
3. 用户登录状态
设置和检查用户登录状态
// 设置用户登录状态 public void setUserLoggedIn(String userId) { redisTemplate.opsForValue().set("user:login:" + userId, "true"); } // 检查用户是否在线 public boolean isUserLoggedIn(String userId) { String status = redisTemplate.opsForValue().get("user:login:" + userId); return "true".equals(status); } // 用户登出 public void setUserLoggedOut(String userId) { redisTemplate.opsForValue().set("user:login:" + userId, "false"); }
示例
// 用户 ID 为 1 登录 setUserLoggedIn("1"); // 检查用户 ID 为 1 是否在线 boolean isLoggedIn = isUserLoggedIn("1"); // true // 用户 ID 为 1 登出 setUserLoggedOut("1");
4. 缓存查询结果
缓存商品详情
// 设置商品详情缓存 public void cacheProductDetails(String productId, String details) { redisTemplate.opsForValue().set("product:details:" + productId, details); } // 获取商品详情缓存 public String getCachedProductDetails(String productId) { return redisTemplate.opsForValue().get("product:details:" + productId); }
示例
// 缓存商品 ID 为 100 的详情 cacheProductDetails("100", "{\"name\": \"Laptop\", \"price\": 1200}"); // 获取商品 ID 为 100 的缓存详情 String details = getCachedProductDetails("100"); // "{\"name\": \"Laptop\", \"price\": 1200}"
Redis 命令示例
-
设置商品库存
SET product:stock:100 50
-
获取商品库存
GET product:stock:100
-
扣减库存
DECRBY product:stock:100 5
-
设置用户积分
SET user:points:1 100
-
获取用户积分
GET user:points:1
-
增加用户积分
INCRBY user:points:1 50
-
设置用户登录状态
SET user:login:1 true
-
检查用户登录状态
GET user:login:1
-
用户登出
SET user:login:1 false
-
缓存商品详情
SET product:details:100 "{\"name\": \"Laptop\", \"price\": 1200}"
-
获取缓存商品详情
GET product:details:100
这些代码示例和 Redis 命令展示了 Redis 字符串类型的各种操作和应用场景,帮助你在实际应用中灵活使用 Redis 的字符串类型。
二 哈希(Hash)
Redis 哈希是一种键值对的集合,用于存储对象类型的数据。下面,我们将通过一个虚拟电商平台的示例来展示 Redis 哈希类型(Hash)的各种操作和应用场景。哈希类型特别适用于存储和操作与对象相关的数据。
应用场景
假设我们在开发一个电商平台,需要管理以下几个方面:
-
用户信息管理:存储和更新用户的个人信息。
-
商品信息管理:存储和更新商品的详细信息。
-
订单信息管理:存储和查询订单的详细信息。
Java 代码示例
1. 用户信息管理
设置和获取用户信息
@Autowired private RedisTemplate<String, Object> redisTemplate; // 设置用户信息 public void setUserInfo(String userId, Map<String, String> userInfo) { redisTemplate.opsForHash().putAll("user:" + userId, userInfo); } // 获取用户信息 public Map<Object, Object> getUserInfo(String userId) { return redisTemplate.opsForHash().entries("user:" + userId); } // 更新用户邮箱 public void updateUserEmail(String userId, String email) { redisTemplate.opsForHash().put("user:" + userId, "email", email); } // 获取用户的特定字段 public String getUserField(String userId, String field) { return (String) redisTemplate.opsForHash().get("user:" + userId, field); }
示例
// 设置用户 ID 为 1 的信息 Map<String, String> userInfo = new HashMap<>(); userInfo.put("username", "JohnDoe"); userInfo.put("email", "john@example.com"); userInfo.put("registered", "2024-08-04"); setUserInfo("1", userInfo); // 获取用户 ID 为 1 的信息 Map<Object, Object> userInfoMap = getUserInfo("1"); // 包含 "username", "email", "registered" // 更新用户 ID 为 1 的邮箱 updateUserEmail("1", "new_email@example.com"); // 获取用户 ID 为 1 的邮箱 String email = getUserField("1", "email"); // "new_email@example.com"
2. 商品信息管理
设置和获取商品信息
// 设置商品信息 public void setProductInfo(String productId, Map<String, String> productInfo) { redisTemplate.opsForHash().putAll("product:" + productId, productInfo); } // 获取商品信息 public Map<Object, Object> getProductInfo(String productId) { return redisTemplate.opsForHash().entries("product:" + productId); } // 更新商品价格 public void updateProductPrice(String productId, String price) { redisTemplate.opsForHash().put("product:" + productId, "price", price); } // 获取商品的特定字段 public String getProductField(String productId, String field) { return (String) redisTemplate.opsForHash().get("product:" + productId, field); }
示例
// 设置商品 ID 为 100 的信息 Map<String, String> productInfo = new HashMap<>(); productInfo.put("name", "Laptop"); productInfo.put("price", "1200"); productInfo.put("stock", "50"); setProductInfo("100", productInfo); // 获取商品 ID 为 100 的信息 Map<Object, Object> productInfoMap = getProductInfo("100"); // 包含 "name", "price", "stock" // 更新商品 ID 为 100 的价格 updateProductPrice("100", "1150"); // 获取商品 ID 为 100 的价格 String price = getProductField("100", "price"); // "1150"
3. 订单信息管理
设置和获取订单信息
// 设置订单信息 public void setOrderInfo(String orderId, Map<String, String> orderInfo) { redisTemplate.opsForHash().putAll("order:" + orderId, orderInfo); } // 获取订单信息 public Map<Object, Object> getOrderInfo(String orderId) { return redisTemplate.opsForHash().entries("order:" + orderId); } // 更新订单状态 public void updateOrderStatus(String orderId, String status) { redisTemplate.opsForHash().put("order:" + orderId, "status", status); } // 获取订单的特定字段 public String getOrderField(String orderId, String field) { return (String) redisTemplate.opsForHash().get("order:" + orderId, field); }
示例
// 设置订单 ID 为 500 的信息 Map<String, String> orderInfo = new HashMap<>(); orderInfo.put("userId", "1"); orderInfo.put("productId", "100"); orderInfo.put("quantity", "1"); orderInfo.put("status", "pending"); setOrderInfo("500", orderInfo); // 获取订单 ID 为 500 的信息 Map<Object, Object> orderInfoMap = getOrderInfo("500"); // 包含 "userId", "productId", "quantity", "status" // 更新订单 ID 为 500 的状态 updateOrderStatus("500", "shipped"); // 获取订单 ID 为 500 的状态 String status = getOrderField("500", "status"); // "shipped"
Redis 命令示例
-
用户信息管理
HSET user:1 username "JohnDoe" HSET user:1 email "john@example.com" HSET user:1 registered "2024-08-04" HGETALL user:1 HSET user:1 email "new_email@example.com" HGET user:1 email
-
商品信息管理
HSET product:100 name "Laptop" HSET product:100 price "1200" HSET product:100 stock "50" HGETALL product:100 HSET product:100 price "1150" HGET product:100 price
-
订单信息管理
HSET order:500 userId "1" HSET order:500 productId "100" HSET order:500 quantity "1" HSET order:500 status "pending" HGETALL order:500 HSET order:500 status "shipped" HGET order:500 status
这些代码示例和 Redis 命令展示了 Redis 哈希类型的各种操作和应用场景。哈希类型非常适合存储和管理具有多个字段的数据对象,并允许对字段进行高效的操作。
三 列表(List)
Redis 列表是一个按插入顺序排序的字符串列表,支持从两端推送和弹出元素。下面,我们将通过一个虚拟电商平台的示例来展示 Redis 列表类型(List)的各种操作和应用场景。Redis 列表类型适合于需要有序存储和操作数据的场景。
应用场景
假设我们在开发一个电商平台,需要管理以下几个方面:
-
用户购物车:管理用户的购物车,包括添加、查看和删除购物车中的商品。
-
订单历史记录:存储用户的订单历史,以便用户查看历史订单。
-
最近浏览的商品:记录用户最近浏览过的商品,用于推荐相关商品。
Java 代码示例
1. 用户购物车
添加、查看和删除购物车中的商品
@Autowired private RedisTemplate<String, String> redisTemplate; // 添加商品到购物车 public void addToCart(String userId, String product) { redisTemplate.opsForList().leftPush("cart:" + userId, product); } // 获取购物车中的商品列表 public List<String> getCartItems(String userId) { return redisTemplate.opsForList().range("cart:" + userId, 0, -1); } // 移除购物车中的商品 public void removeFromCart(String userId, String product) { redisTemplate.opsForList().remove("cart:" + userId, 1, product); }
示例
// 添加商品到用户 ID 为 1 的购物车 addToCart("1", "product:100"); addToCart("1", "product:200"); // 获取用户 ID 为 1 的购物车商品 List<String> cartItems = getCartItems("1"); // ["product:200", "product:100"] // 移除购物车中的商品 removeFromCart("1", "product:100");
2. 订单历史记录
添加和获取订单历史记录
// 添加订单到用户历史记录 public void addOrderToHistory(String userId, String orderId) { redisTemplate.opsForList().leftPush("orderHistory:" + userId, orderId); } // 获取用户的订单历史 public List<String> getOrderHistory(String userId) { return redisTemplate.opsForList().range("orderHistory:" + userId, 0, -1); }
示例
// 添加订单到用户 ID 为 1 的历史记录 addOrderToHistory("1", "order:500"); addOrderToHistory("1", "order:501"); // 获取用户 ID 为 1 的订单历史 List<String> orderHistory = getOrderHistory("1"); // ["order:501", "order:500"]
3. 最近浏览的商品
记录和获取最近浏览的商品
// 添加商品到最近浏览列表 public void addRecentlyViewed(String userId, String productId) { redisTemplate.opsForList().leftPush("recentlyViewed:" + userId, productId); } // 获取用户最近浏览的商品 public List<String> getRecentlyViewed(String userId) { return redisTemplate.opsForList().range("recentlyViewed:" + userId, 0, -1); }
示例
// 添加商品到用户 ID 为 1 的最近浏览列表 addRecentlyViewed("1", "product:300"); addRecentlyViewed("1", "product:400"); // 获取用户 ID 为 1 的最近浏览商品 List<String> recentlyViewed = getRecentlyViewed("1"); // ["product:400", "product:300"]
Redis 命令示例
-
用户购物车
LPUSH cart:1 "product:100" LPUSH cart:1 "product:200" LRANGE cart:1 0 -1 LREM cart:1 1 "product:100"
-
订单历史记录
LPUSH orderHistory:1 "order:500" LPUSH orderHistory:1 "order:501" LRANGE orderHistory:1 0 -1
-
最近浏览的商品
LPUSH recentlyViewed:1 "product:300" LPUSH recentlyViewed:1 "product:400" LRANGE recentlyViewed:1 0 -1
这些代码示例和 Redis 命令展示了 Redis 列表类型的各种操作和应用场景。Redis 列表类型适用于需要有序操作的数据,如购物车、历史记录和最近浏览的商品等。
四 集合(Set)
Redis 的集合类型(Set)是一种无序的集合,它不允许重复的元素。集合类型非常适合处理需要去重、集合运算(如交集、并集、差集)的数据。下面我们将通过一个虚拟电商平台的示例来展示 Redis 集合类型的各种操作和应用场景。
应用场景
假设我们在开发一个电商平台,需要管理以下几个方面:
-
用户收藏的商品:管理用户收藏的商品列表,并进行去重操作。
-
商品的标签:为商品分配标签,支持标签的集合运算(如查找拥有多个标签的商品)。
-
系统黑名单:管理系统中的黑名单用户,以便进行禁止操作。
Java 代码示例
1. 用户收藏的商品
添加、获取和删除用户收藏的商品
@Autowired private RedisTemplate<String, String> redisTemplate; // 添加商品到用户收藏 public void addFavorite(String userId, String productId) { redisTemplate.opsForSet().add("favorites:" + userId, productId); } // 获取用户收藏的商品列表 public Set<String> getFavorites(String userId) { return redisTemplate.opsForSet().members("favorites:" + userId); } // 删除用户收藏的商品 public void removeFavorite(String userId, String productId) { redisTemplate.opsForSet().remove("favorites:" + userId, productId); }
示例
// 添加商品到用户 ID 为 1 的收藏列表 addFavorite("1", "product:100"); addFavorite("1", "product:200"); // 获取用户 ID 为 1 的收藏列表 Set<String> favorites = getFavorites("1"); // ["product:100", "product:200"] // 删除用户 ID 为 1 的收藏商品 removeFavorite("1", "product:100");
2. 商品的标签
为商品添加和获取标签
// 为商品添加标签 public void addTagToProduct(String productId, String tag) { redisTemplate.opsForSet().add("product:tags:" + productId, tag); } // 获取商品的所有标签 public Set<String> getProductTags(String productId) { return redisTemplate.opsForSet().members("product:tags:" + productId); } // 查找拥有特定标签的商品 public Set<String> getProductsByTag(String tag) { return redisTemplate.opsForSet().members("tag:" + tag); } // 将商品和标签关联 public void associateProductWithTag(String productId, String tag) { redisTemplate.opsForSet().add("tag:" + tag, productId); }
示例
// 为商品 ID 为 100 添加标签 addTagToProduct("100", "electronics"); addTagToProduct("100", "laptop"); // 获取商品 ID 为 100 的所有标签 Set<String> tags = getProductTags("100"); // ["electronics", "laptop"] // 将标签和商品关联 associateProductWithTag("100", "electronics"); // 获取所有标记为 "electronics" 的商品 Set<String> products = redisTemplate.opsForSet().members("tag:electronics"); // ["100"]
3. 系统黑名单
添加、获取和删除黑名单用户
// 添加用户到黑名单 public void addToBlacklist(String userId) { redisTemplate.opsForSet().add("blacklist", userId); } // 获取黑名单中的所有用户 public Set<String> getBlacklist() { return redisTemplate.opsForSet().members("blacklist"); } // 移除用户从黑名单 public void removeFromBlacklist(String userId) { redisTemplate.opsForSet().remove("blacklist", userId); }
示例
// 添加用户 ID 为 1 的到黑名单 addToBlacklist("1"); // 获取黑名单中的所有用户 Set<String> blacklist = getBlacklist(); // ["1"] // 移除用户 ID 为 1 从黑名单 removeFromBlacklist("1");
Redis 命令示例
-
用户收藏的商品
SADD favorites:1 "product:100" SADD favorites:1 "product:200" SMEMBERS favorites:1 SREM favorites:1 "product:100"
-
商品的标签
SADD product:tags:100 "electronics" SADD product:tags:100 "laptop" SMEMBERS product:tags:100 SADD tag:electronics "100" SMEMBERS tag:electronics
-
系统黑名单
SADD blacklist "1" SMEMBERS blacklist SREM blacklist "1"
这些代码示例和 Redis 命令展示了 Redis 集合类型的各种操作和应用场景。集合类型非常适合处理无序的、去重的数据,并支持高效的集合运算,如并集、交集和差集。
五 有序集合(Sorted Set)
Redis 的有序集合类型(Sorted Set)是 Redis 中的一个非常强大的数据结构。它结合了集合的唯一性和列表的排序特性。每个元素在有序集合中都有一个分数(score),并且集合中的元素会根据分数自动排序。这使得有序集合非常适合用于处理需要按分数排序的数据,例如排行榜、优先队列等。
应用场景
假设我们在开发一个电商平台,需要管理以下几个方面:
-
用户积分排行榜:展示用户积分的排行榜。
-
商品评分系统:根据用户评分对商品进行排序。
-
任务优先级管理:按照任务的优先级处理任务。
Java 代码示例
1. 用户积分排行榜
添加用户积分、获取排行榜和获取用户排名
@Autowired private RedisTemplate<String, String> redisTemplate; // 添加用户积分 public void addUserScore(String userId, double score) { redisTemplate.opsForZSet().add("user:scoreboard", userId, score); } // 获取用户积分排行榜 public Set<ZSetOperations.TypedTuple<String>> getScoreboard(int start, int end) { return redisTemplate.opsForZSet().rangeWithScores("user:scoreboard", start, end); } // 获取用户排名 public Long getUserRank(String userId) { return redisTemplate.opsForZSet().reverseRank("user:scoreboard", userId); }
示例
// 添加用户 ID 为 1 和 2 的积分 addUserScore("1", 1000.0); addUserScore("2", 1500.0); // 获取用户积分排行榜,前 10 名 Set<ZSetOperations.TypedTuple<String>> scoreboard = getScoreboard(0, 9); // 获取用户 ID 为 1 的排名 Long rank = getUserRank("1"); // 排名在列表中的位置
2. 商品评分系统
添加和获取商品评分
// 添加商品评分 public void addProductScore(String productId, double score) { redisTemplate.opsForZSet().add("product:ratings", productId, score); } // 获取商品评分 public Set<ZSetOperations.TypedTuple<String>> getTopRatedProducts(int start, int end) { return redisTemplate.opsForZSet().reverseRangeWithScores("product:ratings", start, end); }
示例
// 为商品 ID 为 100 和 200 添加评分 addProductScore("100", 4.5); addProductScore("200", 4.8); // 获取评分前 5 的商品 Set<ZSetOperations.TypedTuple<String>> topRatedProducts = getTopRatedProducts(0, 4);
3. 任务优先级管理
添加任务优先级、获取任务列表和移除任务
// 添加任务和优先级 public void addTask(String taskId, double priority) { redisTemplate.opsForZSet().add("task:priority", taskId, priority); } // 获取优先级最高的任务 public Set<ZSetOperations.TypedTuple<String>> getHighestPriorityTasks(int start, int end) { return redisTemplate.opsForZSet().reverseRangeWithScores("task:priority", start, end); } // 移除任务 public void removeTask(String taskId) { redisTemplate.opsForZSet().remove("task:priority", taskId); }
示例
// 添加任务 ID 为 1 和 2 的优先级 addTask("1", 5.0); addTask("2", 3.0); // 获取优先级最高的前 10 个任务 Set<ZSetOperations.TypedTuple<String>> highestPriorityTasks = getHighestPriorityTasks(0, 9); // 移除任务 ID 为 1 removeTask("1");
Redis 命令示例
-
用户积分排行榜
ZADD user:scoreboard 1000 "1" ZADD user:scoreboard 1500 "2" ZREVRANGE user:scoreboard 0 9 WITHSCORES ZREVRANK user:scoreboard "1"
-
商品评分系统
ZADD product:ratings 4.5 "100" ZADD product:ratings 4.8 "200" ZREVRANGE product:ratings 0 4 WITHSCORES
-
任务优先级管理
ZADD task:priority 5.0 "1" ZADD task:priority 3.0 "2" ZREVRANGE task:priority 0 9 WITHSCORES ZREM task:priority "1"
这些代码示例和 Redis 命令展示了 Redis 有序集合类型的各种操作和应用场景。有序集合非常适合用于需要排序和排名的数据处理,例如排行榜、评分系统和优先级队列等。
六 位图(Bitmap)
Redis 的 Bitmap 类型是一个用于高效存储和操作二进制位的数据结构。它在需要大规模位运算的场景中非常有用,比如统计用户活跃度、跟踪事件发生情况等。Bitmap 可以被视为一个字符串,但每个字符的位置代表一个位(bit),允许你进行位级操作。
应用场景
假设我们在开发一个电商平台,需要管理以下几个方面:
-
用户登录状态:记录用户每日的登录状态(已登录或未登录)。
-
活动参与情况:跟踪用户是否参与了某个活动。
-
广告点击统计:统计广告的点击情况。
Java 代码示例
1. 用户登录状态
设置和获取用户的登录状态
@Autowired private RedisTemplate<String, String> redisTemplate; // 设置用户登录状态 public void setUserLoginStatus(String userId, int dayOfMonth, boolean status) { redisTemplate.opsForValue().setBit("user:login:" + userId, dayOfMonth, status); } // 获取用户登录状态 public boolean getUserLoginStatus(String userId, int dayOfMonth) { return redisTemplate.opsForValue().getBit("user:login:" + userId, dayOfMonth); }
示例
// 设置用户 ID 为 1 在 4 号登录状态为 true setUserLoginStatus("1", 4, true); // 获取用户 ID 为 1 在 4 号的登录状态 boolean loginStatus = getUserLoginStatus("1", 4); // true
2. 活动参与情况
记录用户参与活动
// 记录用户参与活动 public void recordUserParticipation(String activityId, String userId) { redisTemplate.opsForValue().setBit("activity:" + activityId, userId.hashCode(), true); } // 检查用户是否参与了活动 public boolean hasUserParticipated(String activityId, String userId) { return redisTemplate.opsForValue().getBit("activity:" + activityId, userId.hashCode()); }
示例
// 记录用户 ID 为 1 参与了活动 ID 为 101 recordUserParticipation("101", "1"); // 检查用户 ID 为 1 是否参与了活动 ID 为 101 boolean participated = hasUserParticipated("101", "1"); // true
3. 广告点击统计
记录和获取广告点击情况
// 记录广告点击 public void recordAdClick(String adId, int clickIndex) { redisTemplate.opsForValue().setBit("ad:clicks:" + adId, clickIndex, true); } // 获取广告点击总数 public long getAdClickCount(String adId) { return redisTemplate.execute((RedisCallback<Long>) connection -> connection.bitCount("ad:clicks:" + adId.getBytes())); }
示例
// 记录广告 ID 为 200 的第 5 次点击 recordAdClick("200", 5); // 获取广告 ID 为 200 的点击总数 long clickCount = getAdClickCount("200"); // 返回点击的位数总和
Redis 命令示例
-
用户登录状态
SETBIT user:login:1 4 1 GETBIT user:login:1 4
-
活动参与情况
SETBIT activity:101 1 1 GETBIT activity:101 1
-
广告点击统计
SETBIT ad:clicks:200 5 1 BITCOUNT ad:clicks:200
这些代码示例和 Redis 命令展示了 Redis Bitmap 类型的各种操作和应用场景。Bitmap 在处理大规模位操作时非常高效,适用于需要进行位级统计和标记的场景。
七 HyperLogLog
Redis 的 HyperLogLog 是一个用于估算集合中不同元素数量的数据结构。它特别适合于处理需要高效存储和估算大规模数据集合的场景,如统计独立用户数量或独立事件数量。HyperLogLog 可以在使用较少内存的情况下提供接近准确的结果。
应用场景
假设我们在开发一个电商平台,需要管理以下几个方面:
-
独立访问用户统计:估算网站的独立访问用户数量。
-
独立商品浏览统计:统计浏览过不同商品的独立用户数量。
-
唯一广告点击统计:估算广告被点击的独立用户数量。
Java 代码示例
1. 独立访问用户统计
添加用户访问记录和获取用户总数
@Autowired private RedisTemplate<String, String> redisTemplate; // 记录用户访问 public void recordUserVisit(String visitId, String userId) { redisTemplate.opsForHyperLogLog().add(visitId, userId); } // 获取估算的独立用户数量 public Long getUniqueUserCount(String visitId) { return redisTemplate.opsForHyperLogLog().size(visitId); }
示例
// 记录用户 ID 为 1 和 2 访问网站 recordUserVisit("site:visits", "1"); recordUserVisit("site:visits", "2"); // 获取估算的独立用户数量 Long uniqueUserCount = getUniqueUserCount("site:visits"); // 2
2. 独立商品浏览统计
记录用户浏览商品和获取浏览过的独立商品数量
// 记录用户浏览商品 public void recordProductView(String productId, String userId) { redisTemplate.opsForHyperLogLog().add("product:" + productId + ":views", userId); } // 获取浏览过商品的独立用户数量 public Long getUniqueProductViewers(String productId) { return redisTemplate.opsForHyperLogLog().size("product:" + productId + ":views"); }
示例
// 记录用户 ID 为 1 和 2 浏览了商品 ID 为 100 recordProductView("100", "1"); recordProductView("100", "2"); // 获取浏览商品 ID 为 100 的独立用户数量 Long uniqueViewers = getUniqueProductViewers("100"); // 2
3. 唯一广告点击统计
记录广告点击和获取点击的独立用户数量
// 记录广告点击 public void recordAdClick(String adId, String userId) { redisTemplate.opsForHyperLogLog().add("ad:" + adId + ":clicks", userId); } // 获取点击广告的独立用户数量 public Long getUniqueAdClickers(String adId) { return redisTemplate.opsForHyperLogLog().size("ad:" + adId + ":clicks"); }
示例
// 记录用户 ID 为 1 和 2 点击了广告 ID 为 200 recordAdClick("200", "1"); recordAdClick("200", "2"); // 获取点击广告 ID 为 200 的独立用户数量 Long uniqueClickers = getUniqueAdClickers("200"); // 2
Redis 命令示例
-
独立访问用户统计
PFADD site:visits "1" "2" PFCOUNT site:visits
-
独立商品浏览统计
PFADD product:100:views "1" "2" PFCOUNT product:100:views
-
唯一广告点击统计
PFADD ad:200:clicks "1" "2" PFCOUNT ad:200:clicks
这些代码示例和 Redis 命令展示了 Redis HyperLogLog 类型的各种操作和应用场景。HyperLogLog 在处理需要高效估算独立元素数量的场景中非常有用,如网站访问统计、商品浏览统计和广告点击统计等。
八 地理空间 (Geospatial)
Redis 的地理空间数据结构(Geospatial)用于存储和查询地理位置数据。Redis 支持地理位置的存储、距离计算和附近位置的查询等功能,这对于实现位置服务和地理相关应用非常有用。
应用场景
假设我们在开发一个电商平台,需要管理以下几个方面:
-
商店位置查询:查找离用户最近的商店。
-
配送服务:找到离配送地点最近的仓库。
-
活动推荐:根据用户当前位置推荐附近的活动。
Java 代码示例
1. 商店位置查询
添加商店位置和查询最近的商店
@Autowired private RedisTemplate<String, String> redisTemplate; // 添加商店位置 public void addStoreLocation(String storeId, double latitude, double longitude) { redisTemplate.opsForGeo().add("stores", new Point(longitude, latitude), storeId); } // 查找离用户最近的商店 public List<GeoLocation<String>> getNearbyStores(double userLat, double userLon, double radius) { Circle within = new Circle(new Point(userLon, userLat), radius); return redisTemplate.opsForGeo().radius("stores", within, GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().sortAscending()); }
示例
// 添加商店位置 addStoreLocation("store1", 37.7749, -122.4194); // San Francisco addStoreLocation("store2", 34.0522, -118.2437); // Los Angeles // 查找离用户位置(37.7749, -122.4194)5公里内的商店 List<GeoLocation<String>> nearbyStores = getNearbyStores(37.7749, -122.4194, 5000); // 半径为5公里
2. 配送服务
添加仓库位置和查询最近的仓库
// 添加仓库位置 public void addWarehouseLocation(String warehouseId, double latitude, double longitude) { redisTemplate.opsForGeo().add("warehouses", new Point(longitude, latitude), warehouseId); } // 查找离配送地点最近的仓库 public List<GeoLocation<String>> getNearbyWarehouses(double deliveryLat, double deliveryLon, double radius) { Circle within = new Circle(new Point(deliveryLon, deliveryLat), radius); return redisTemplate.opsForGeo().radius("warehouses", within, GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().sortAscending()); }
示例
// 添加仓库位置 addWarehouseLocation("warehouse1", 40.7128, -74.0060); // New York addWarehouseLocation("warehouse2", 41.8781, -87.6298); // Chicago // 查找离配送地点(40.7128, -74.0060)100公里内的仓库 List<GeoLocation<String>> nearbyWarehouses = getNearbyWarehouses(40.7128, -74.0060, 100000); // 半径为100公里
3. 活动推荐
添加活动位置和查询附近的活动
// 添加活动位置 public void addEventLocation(String eventId, double latitude, double longitude) { redisTemplate.opsForGeo().add("events", new Point(longitude, latitude), eventId); } // 查找离用户位置最近的活动 public List<GeoLocation<String>> getNearbyEvents(double userLat, double userLon, double radius) { Circle within = new Circle(new Point(userLon, userLat), radius); return redisTemplate.opsForGeo().radius("events", within, GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().sortAscending()); }
示例
// 添加活动位置 addEventLocation("event1", 37.7749, -122.4194); // San Francisco addEventLocation("event2", 34.0522, -118.2437); // Los Angeles // 查找离用户位置(37.7749, -122.4194)50公里内的活动 List<GeoLocation<String>> nearbyEvents = getNearbyEvents(37.7749, -122.4194, 50000); // 半径为50公里
Redis 命令示例
-
商店位置查询
GEOADD stores -122.4194 37.7749 "store1" GEOADD stores -118.2437 34.0522 "store2" GEORADIUS stores -122.4194 37.7749 5000 km WITHDIST ASC
-
配送服务
GEOADD warehouses -74.0060 40.7128 "warehouse1" GEOADD warehouses -87.6298 41.8781 "warehouse2" GEORADIUS warehouses -74.0060 40.7128 100 km WITHDIST ASC
-
活动推荐
GEOADD events -122.4194 37.7749 "event1" GEOADD events -118.2437 34.0522 "event2" GEORADIUS events -122.4194 37.7749 50000 km WITHDIST ASC
这些代码示例和 Redis 命令展示了 Redis 地理空间数据结构的各种操作和应用场景。地理空间数据结构非常适合用于处理位置相关的数据,如查找附近的商店、仓库或活动等。
九 流(Stream)
Redis Streams 是 Redis 5.0 引入的一种数据结构,用于处理实时数据流和消息队列。它提供了高效的数据流存储、消费和处理能力,适用于日志记录、事件处理、实时分析等场景。
应用场景
假设我们在开发一个电商平台,需要管理以下几个方面:
-
订单日志:记录用户的订单操作。
-
实时消息队列:处理实时的用户活动数据。
-
事件流处理:跟踪和处理实时事件,如用户登录、商品浏览等。
Java 代码示例
1. 订单日志
添加订单记录和获取订单记录
@Autowired private RedisTemplate<String, String> redisTemplate; // 添加订单记录 public void addOrder(String orderId, Map<String, String> orderDetails) { redisTemplate.opsForStream().add("orders", orderDetails); } // 获取订单记录 public List<MapRecord<String, String, String>> getOrders(long count) { return redisTemplate.opsForStream().read(Consumer.from("group", "consumer"), StreamReadOptions.empty().count(count), "orders"); }
示例
// 添加订单记录 Map<String, String> orderDetails = new HashMap<>(); orderDetails.put("userId", "1"); orderDetails.put("productId", "100"); orderDetails.put("quantity", "2"); addOrder("order:123", orderDetails); // 获取最新的 10 个订单记录 List<MapRecord<String, String, String>> orders = getOrders(10);
2. 实时消息队列
添加消息和获取消息
// 添加消息 public void addMessage(String channel, Map<String, String> message) { redisTemplate.opsForStream().add(channel, message); } // 获取消息 public List<MapRecord<String, String, String>> getMessages(String channel, long count) { return redisTemplate.opsForStream().read(Consumer.from("group", "consumer"), StreamReadOptions.empty().count(count), channel); }
示例
// 添加消息 Map<String, String> message = new HashMap<>(); message.put("event", "user_signup"); message.put("userId", "1"); addMessage("user:events", message); // 获取最新的 10 条消息 List<MapRecord<String, String, String>> messages = getMessages("user:events", 10);
3. 事件流处理
添加事件和获取事件
// 添加事件 public void addEvent(String eventType, Map<String, String> eventData) { redisTemplate.opsForStream().add("events:" + eventType, eventData); } // 获取事件 public List<MapRecord<String, String, String>> getEvents(String eventType, long count) { return redisTemplate.opsForStream().read(Consumer.from("group", "consumer"), StreamReadOptions.empty().count(count), "events:" + eventType); }
示例
// 添加事件 Map<String, String> eventData = new HashMap<>(); eventData.put("action", "login"); eventData.put("userId", "1"); addEvent("login", eventData); // 获取最新的 10 个登录事件 List<MapRecord<String, String, String>> events = getEvents("login", 10);
Redis 命令示例
-
订单日志
XADD orders * userId 1 productId 100 quantity 2 XRANGE orders - + COUNT 10
-
实时消息队列
XADD user:events * event user_signup userId 1 XRANGE user:events - + COUNT 10
-
事件流处理
XADD events:login * action login userId 1 XRANGE events:login - + COUNT 10
这些代码示例和 Redis 命令展示了 Redis Streams 类型的各种操作和应用场景。Redis Streams 提供了强大的流数据处理能力,适合用于处理日志记录、消息队列和事件流等实时数据处理任务。
十 BitField
Redis 的 BitField 类型用于处理比特位操作,可以用来存储和操作大量的位数据。BitField 类型支持高效的位运算操作,适用于处理位数组、位掩码以及其他需要按位操作的场景。
应用场景
假设我们在开发一个游戏统计系统,需要管理以下几个方面:
-
玩家成就记录:记录玩家完成的成就或任务。
-
用户权限控制:管理用户的权限位。
-
事件标记:标记事件是否发生过。
Java 代码示例
1. 玩家成就记录
设置玩家成就和获取成就状态
@Autowired private RedisTemplate<String, String> redisTemplate; // 设置玩家成就 public void setAchievement(String playerId, int bitOffset) { redisTemplate.opsForValue().setBit("player:" + playerId + ":achievements", bitOffset, true); } // 获取玩家成就状态 public Boolean getAchievement(String playerId, int bitOffset) { return redisTemplate.opsForValue().getBit("player:" + playerId + ":achievements", bitOffset); }
示例
// 设置玩家 ID 为 1 的成就,成就位偏移量为 5 setAchievement("1", 5); // 获取玩家 ID 为 1 的成就状态,偏移量为 5 Boolean achievement = getAchievement("1", 5); // true or false
2. 用户权限控制
设置用户权限位和获取权限状态
// 设置用户权限 public void setUserPermission(String userId, int bitOffset) { redisTemplate.opsForValue().setBit("user:" + userId + ":permissions", bitOffset, true); } // 获取用户权限状态 public Boolean getUserPermission(String userId, int bitOffset) { return redisTemplate.opsForValue().getBit("user:" + userId + ":permissions", bitOffset); }
示例
// 设置用户 ID 为 1 的权限位偏移量为 3 setUserPermission("1", 3); // 获取用户 ID 为 1 的权限状态,偏移量为 3 Boolean permission = getUserPermission("1", 3); // true or false
3. 事件标记
设置事件标记和获取事件状态
// 设置事件标记 public void setEventFlag(String eventId, int bitOffset) { redisTemplate.opsForValue().setBit("event:" + eventId + ":flags", bitOffset, true); } // 获取事件标记状态 public Boolean getEventFlag(String eventId, int bitOffset) { return redisTemplate.opsForValue().getBit("event:" + eventId + ":flags", bitOffset); }
示例
// 设置事件 ID 为 "event1" 的标记位偏移量为 2 setEventFlag("event1", 2); // 获取事件 ID 为 "event1" 的标记状态,偏移量为 2 Boolean eventFlag = getEventFlag("event1", 2); // true or false
Redis 命令示例
-
玩家成就记录
SETBIT player:1:achievements 5 1 GETBIT player:1:achievements 5
-
用户权限控制
SETBIT user:1:permissions 3 1 GETBIT user:1:permissions 3
-
事件标记
SETBIT event:event1:flags 2 1 GETBIT event:event1:flags 2
BitField 扩展操作
设置和获取多位数据
// 批量设置和获取位数据,使用 BitField 操作 // 设置 8 位宽的整数值,起始偏移量为 0 redisTemplate.execute((RedisCallback<Long>) connection -> connection.bitField("bitfield:key".getBytes(), BitFieldSubCommands.create().set(BitFieldSubCommands.BitFieldType.unsigned(8).at(0), 123) )); // 获取 8 位宽的整数值 redisTemplate.execute((RedisCallback<Long>) connection -> connection.bitField("bitfield:key".getBytes(), BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType.unsigned(8).at(0)) ));
Redis 命令示例:
BITFIELD bitfield:key SET u8 0 123 BITFIELD bitfield:key GET u8 0
这些代码示例和 Redis 命令展示了 Redis BitField 类型的各种操作和应用场景。BitField 适合于需要处理大量位数据的场景,如记录成就、权限管理和事件标记等。