缓存集群槽分片的使用示例

举报
码乐 发表于 2024/12/31 11:01:09 2024/12/31
【摘要】 1 简介本文基于redis cluster 集群深入分析Redis Cluster 分片(槽分片机制),并且使用go 和go-redisv8 实现一个在2个cluster节点的商品零售排行榜服务,说明Cluster集群相对单节点的优势。 2 槽分片机制的分析Redis Cluster 分片(槽分片机制)分析,Redis Cluster 分片机制通过将数据分布在逻辑槽(hash slot)中...

1 简介

本文基于redis cluster 集群深入分析Redis Cluster 分片(槽分片机制),并且使用go 和go-redisv8 实现一个在2个cluster节点的商品零售排行榜服务,说明Cluster集群相对单节点的优势。

2 槽分片机制的分析

Redis Cluster 分片(槽分片机制)分析,Redis Cluster 分片机制通过将数据分布在逻辑槽(hash slot)中实现:

  • 槽分片机制:

Redis Cluster 将整个键空间划分为 16384 个逻辑槽。
每个键根据 CRC16 哈希计算结果取模 16384 决定其槽位。
每个节点负责一定范围的槽位。

  • 数据分布:

数据均匀分布在多个节点上,减少单节点负载。
客户端通过槽位直接访问目标节点,避免额外代理层。

  • 扩展性:

动态扩容/缩容时,以槽为单位迁移数据,降低迁移成本。

  • 高可用:

支持主从模式,主节点故障时从节点自动提升为主节点,保证服务可用性。

3 Cluster 集群的优势

  • 性能扩展:
    数据分布在多个节点,支持高并发和大数据存储。

  • 高可用性:
    支持主从复制和自动故障转移,增强系统可靠性。

  • 动态扩展:
    集群节点可动态添加或删除,灵活应对容量变化。

  • 无代理层:
    客户端通过槽位直连目标节点,减少中间层开销。

  • 实现商品零售排行榜服务

目标:构建一个商品销售排行榜服务,使用 Redis Cluster 分片存储销售数据,并根据销售额动态生成排行榜。

4 Redis 数据设计

键结构:
sales:{product_id}:存储单个商品的销售额。

有序集合:

使用 Redis 的 Sorted Set 维护全局排行榜,键名为 sales:ranking。

技术栈

5 编程语言实现应用

go-redis/v8:支持 Redis Cluster 的 Go 客户端。代码实现如下

package main

import (
	"context"
	"fmt"
	"log"
	"strconv"

	"github.com/go-redis/redis/v8"
)

// Redis Cluster configuration
var redisClusterAddrs = []string{"127.0.0.1:6379", "127.0.0.1:6380"}
var ctx = context.Background()

// Redis Client initialization
func initRedisCluster() *redis.ClusterClient {
	rdb := redis.NewClusterClient(&redis.ClusterOptions{
		Addrs: redisClusterAddrs,
	})
	// Ping to check the connection
	if err := rdb.Ping(ctx).Err(); err != nil {
		log.Fatalf("Failed to connect to Redis Cluster: %v", err)
	}
	return rdb
}

// RecordSale: Add sales for a product
func recordSale(rdb *redis.ClusterClient, productID string, amount float64) error {
	// Increment the sales for the product
	productKey := fmt.Sprintf("sales:%s", productID)
	if err := rdb.IncrByFloat(ctx, productKey, amount).Err(); err != nil {
		return fmt.Errorf("failed to record sale: %w", err)
	}
	// Update the global ranking
	if err := rdb.ZIncrBy(ctx, "sales:ranking", amount, productID).Err(); err != nil {
		return fmt.Errorf("failed to update ranking: %w", err)
	}
	return nil
}

// GetTopProducts: Retrieve top N products from the ranking
func getTopProducts(rdb *redis.ClusterClient, topN int) ([]string, error) {
	rankings, err := rdb.ZRevRangeWithScores(ctx, "sales:ranking", 0, int64(topN-1)).Result()
	if err != nil {
		return nil, fmt.Errorf("failed to retrieve top products: %w", err)
	}
	var results []string
	for _, ranking := range rankings {
		results = append(results, fmt.Sprintf("ProductID: %s, Sales: %.2f", ranking.Member, ranking.Score))
	}
	return results, nil
}

func main() {
	// Initialize Redis Cluster client
	rdb := initRedisCluster()
	defer rdb.Close()

	// Example: Record sales
	products := []string{"prod1", "prod2", "prod3", "prod4"}
	sales := []float64{150.0, 200.0, 50.0, 300.0}

	fmt.Println("Recording sales...")
	for i, product := range products {
		if err := recordSale(rdb, product, sales[i]); err != nil {
			log.Printf("Error recording sale for %s: %v", product, err)
		}
	}

	// Retrieve and display the top 3 products
	fmt.Println("Top products:")
	topProducts, err := getTopProducts(rdb, 3)
	if err != nil {
		log.Fatalf("Error retrieving top products: %v", err)
	}
	for _, product := range topProducts {
		fmt.Println(product)
	}
}

6 程序说明

功能细节,记录销售额(recordSale):

使用 IncrByFloat 更新单个商品的销售总额。
使用 ZIncrBy 更新排行榜(Sorted Set)。

查询排行榜(getTopProducts):

使用 ZRevRangeWithScores 按销售额降序获取前 N 个商品。

  • 运行环境

Redis Cluster 配置:
至少 2 个节点(127.0.0.1:6379 和 127.0.0.1:6380)。
可通过 Docker 或手动搭建 Redis Cluster。
Cluster 相对单节点的优势

  • 数据分布:

Cluster 自动分片,销售数据(如 sales:prod1 和 sales:prod2)存储在不同节点,避免单节点瓶颈。
单节点模式无法水平扩展,当数据或流量增加时容易超出处理能力。

  • 高可用性:

Cluster 提供主从备份和故障转移能力,确保服务可用性。
单节点模式没有容错能力,节点故障会导致服务中断。

  • 动态扩展:

Cluster 支持动态扩容,节点增加后自动迁移部分槽位。
单节点模式需要手动分片并迁移数据,增加运维复杂度。

7 小结

Cluster 将请求分散到多个节点,提升并发处理能力。
单节点模式的资源有限,性能瓶颈明显。

通过以上实现,我们展示了 Redis Cluster 的分片机制和高可用特性,适合大规模、高并发的商品零售场景,而单节点模式仅适用于小规模场景。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。