重大突破!权限系统高可用方案原来是这样设计的?
在构建高可用的权限系统时,我们需要考虑多个层面的容错和故障恢复机制。权限系统作为整个业务系统的核心组件,一旦出现故障可能导致整个系统瘫痪,因此设计一个高可用的权限系统至关重要。
1. 权限系统高可用架构设计
权限系统的高可用设计需要从多个维度考虑,包括数据存储、服务部署、缓存策略、故障恢复等。
1.1 数据存储高可用
权限数据的存储是整个权限系统的核心,我们需要保证数据的高可用性和一致性。
// PermissionDatabase 权限数据库配置typePermissionDatabasestruct{PrimaryDSNstringReplicaDSNs[]stringMaxIdleConnsintMaxOpenConnsintConnMaxLifetime time.Duration}// PermissionDB 权限数据库连接池typePermissionDBstruct{master*sql.DB replicas[]*sql.DB mutex sync.RWMutex}// NewPermissionDB 创建权限数据库连接池funcNewPermissionDB(config*PermissionDatabase)(*PermissionDB,error){db:=&PermissionDB{}// 初始化主库连接masterDB,err:=sql.Open("mysql",config.PrimaryDSN)iferr!=nil{returnnil,fmt.Errorf("failed to connect to master database: %w",err)}masterDB.SetMaxIdleConns(config.MaxIdleConns)masterDB.SetMaxOpenConns(config.MaxOpenConns)masterDB.SetConnMaxLifetime(config.ConnMaxLifetime)// 测试主库连接iferr:=masterDB.Ping();err!=nil{returnnil,fmt.Errorf("failed to ping master database: %w",err)}db.master=masterDB// 初始化从库连接池for_,dsn:=rangeconfig.ReplicaDSNs{replicaDB,err:=sql.Open("mysql",dsn)iferr!=nil{returnnil,fmt.Errorf("failed to connect to replica database: %w",err)}replicaDB.SetMaxIdleConns(config.MaxIdleConns)replicaDB.SetMaxOpenConns(config.MaxOpenConns)replicaDB.SetConnMaxLifetime(config.ConnMaxLifetime)// 测试从库连接iferr:=replicaDB.Ping();err!=nil{returnnil,fmt.Errorf("failed to ping replica database: %w",err)}db.replicas=append(db.replicas,replicaDB)}returndb,nil}// GetMaster 获取主库连接func(p*PermissionDB)GetMaster()*sql.DB{returnp.master}// GetReplica 获取从库连接(负载均衡)func(p*PermissionDB)GetReplica()*sql.DB{p.mutex.RLock()deferp.mutex.RUnlock()iflen(p.replicas)==0{returnp.master}// 简单的轮询负载均衡rand.Seed(time.Now().UnixNano())idx:=rand.Intn(len(p.replicas))returnp.replicas[idx]}1.2 缓存高可用设计
缓存是提升权限系统性能的关键,同时也需要保证其高可用性。
// CacheCluster 缓存集群配置typeCacheClusterstruct{RedisAddrs[]stringPasswordstringDBintPoolSizeintTimeout time.Duration}// PermissionCache 权限缓存typePermissionCachestruct{client*redis.ClusterClient timeout time.Duration}// NewPermissionCache 创建权限缓存实例funcNewPermissionCache(config*CacheCluster)*PermissionCache{client:=redis.NewClusterClient(&redis.ClusterOptions{Addrs:config.RedisAddrs,Password:config.Password,PoolSize:config.PoolSize,DialTimeout:config.Timeout,ReadTimeout:config.Timeout,WriteTimeout:config.Timeout,})return&PermissionCache{client:client,timeout:config.Timeout,}}// GetPermission 获取权限信息func(pc*PermissionCache)GetPermission(ctx context.Context,keystring)(string,error){val,err:=pc.client.Get(ctx,key).Result()iferr==redis.Nil{return"",nil// 缓存未命中}iferr!=nil{return"",fmt.Errorf("failed to get permission from cache: %w",err)}returnval,nil}// SetPermission 设置权限信息func(pc*PermissionCache)SetPermission(ctx context.Context,key,valuestring,expiration time.Duration)error{err:=pc.client.Set(ctx,key,value,expiration).Err()iferr!=nil{returnfmt.Errorf("failed to set permission to cache: %w",err)}returnnil}// DeletePermission 删除权限信息func(pc*PermissionCache)DeletePermission(ctx context.Context,keystring)error{err:=pc.client.Del(ctx,key).Err()iferr!=