From 3ee707e60c42749185c76695ad85461e278bbafd Mon Sep 17 00:00:00 2001 From: "suguo.yao" Date: Wed, 13 Dec 2023 16:47:46 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0mysql=20redis=E7=9A=84docker?= =?UTF-8?q?=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mysql2/mysql.go | 105 +++++++++++++++++++++++++ mysql2/tables-mysql.go | 22 ++++++ redis2/redis.go | 169 +++++++++++++++++++++++++++++++++++++++++ redis2/user-redis.go | 41 ++++++++++ 4 files changed, 337 insertions(+) create mode 100644 mysql2/mysql.go create mode 100644 mysql2/tables-mysql.go create mode 100644 redis2/redis.go create mode 100644 redis2/user-redis.go diff --git a/mysql2/mysql.go b/mysql2/mysql.go new file mode 100644 index 0000000..07bc7b3 --- /dev/null +++ b/mysql2/mysql.go @@ -0,0 +1,105 @@ +package mysql + +import ( + "os" + "strconv" + "time" + + "gorm.io/driver/mysql" + "gorm.io/gorm" + "gorm.io/gorm/logger" + "gorm.io/gorm/schema" + "gorm.io/plugin/dbresolver" +) + +/* +docker配置 + +MYSQL_DSN=root:root@tcp(mysql:3306)/sample?charset=utf8mb4&parseTime=True&loc=Local \ +MYSQL_MAXLIFETIME=2\ +MYSQL_MAXIDLECONNS=2\ +MYSQL_MAXOPENCONNS=200\ +MYSQL_INIT=true \ +*/ +var ( + _db *gorm.DB +) + +// 创建实例 +func newDB() (*gorm.DB, error) { + if _db != nil { + return _db, nil + } + + dsn := os.Getenv("MYSQL_DSN") + if dsn == "" { + dsn = "root:root@tcp(127.0.0.1:3306)/mysql?charset=utf8&parseTime=True&loc=Local" + } + maxLifetime := func() int { + c := os.Getenv("MYSQL_MAXLIFETIME") + cc, err := strconv.Atoi(c) + if err != nil { + return 1 + } + + if cc <= 0 { + return 1 + } + if cc >= 1000 { + cc = 1000 + } + return cc + }() + maxIdleConns := func() int { + c := os.Getenv("MYSQL_MAXIDLECONNS") + cc, err := strconv.Atoi(c) + if err != nil { + return 1 + } + + if cc < 0 { + return 0 + } + if cc >= 1000 { + cc = 1000 + } + return cc + }() + maxOpenConns := func() int { + c := os.Getenv("MYSQL_MAXOPENCONNS") + cc, err := strconv.Atoi(c) + if err != nil { + return 1 + } + + if cc < 0 { + return 0 + } + if cc >= 1000 { + cc = 1000 + } + return cc + }() + + var err error + _db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{ + SkipDefaultTransaction: true, + Logger: logger.Default.LogMode(logger.Silent), + NamingStrategy: schema.NamingStrategy{ + SingularTable: true, + }, + }) + if err != nil { + return nil, err + } + _db.Use( + dbresolver.Register(dbresolver.Config{ + Sources: []gorm.Dialector{mysql.Open(dsn)}, + Replicas: []gorm.Dialector{mysql.Open(dsn)}, + Policy: dbresolver.RandomPolicy{}, + }).SetConnMaxIdleTime(time.Hour). + SetConnMaxLifetime(time.Duration(maxLifetime) * time.Hour). + SetMaxIdleConns(maxIdleConns). + SetMaxOpenConns(maxOpenConns)) + return _db, nil +} diff --git a/mysql2/tables-mysql.go b/mysql2/tables-mysql.go new file mode 100644 index 0000000..b9b4f33 --- /dev/null +++ b/mysql2/tables-mysql.go @@ -0,0 +1,22 @@ +package mysql + +import ( + "os" + + "myschools.me/suguo/intelligent-community/model" +) + +func init() { + //不初始化表时返回 + if os.Getenv("MYSQL_INIT") != "true" { + return + } + + db, err := newDB() + if err != nil { + panic(err) + } + if err := db.AutoMigrate(&model.User{}); err != nil { + panic(err) + } +} diff --git a/redis2/redis.go b/redis2/redis.go new file mode 100644 index 0000000..cfda52b --- /dev/null +++ b/redis2/redis.go @@ -0,0 +1,169 @@ +package redis + +import ( + "encoding/json" + "os" + "strconv" + "time" + + redigo "github.com/gomodule/redigo/redis" +) + +/* +REDIS_DSN=127.0.0.1:6379 \ +REDIS_PWD=eYX7EwxKPCDmwMtyKVge8oLd2t81 \ +REDIS_DB=0 \ +*/ +var pool *redigo.Pool + +func init() { + dbNumber := func() int { + db := os.Getenv("REDIS_DB") + database, err := strconv.Atoi(db) + if err != nil { + return 0 + } + if database < 0 { + database = 0 + } + if database > 16 { + database = 0 + } + return database + }() + pool = &redigo.Pool{ + MaxActive: 100, + MaxIdle: 1, + IdleTimeout: time.Second * time.Duration(60), + Dial: func() (redigo.Conn, error) { + return redigo.Dial("tcp", os.Getenv("REDIS_DSN"), + redigo.DialDatabase(dbNumber), + redigo.DialPassword(os.Getenv("REDIS_PWD")), + ) + }, + TestOnBorrow: func(conn redigo.Conn, t time.Time) error { + if time.Since(t) < time.Minute { + return nil + } + _, err := conn.Do("PING") + return err + }, + } +} + +// GetBytes 获取一个字节数组值 +func GetBytes(key *string) (*[]byte, error) { + conn := pool.Get() + defer conn.Close() + + data, err := redigo.Bytes(conn.Do("GET", *key)) + return &data, err +} + +// Get 获取一个值 +func Get(key string) interface{} { + conn := pool.Get() + defer conn.Close() + + var data []byte + var err error + if data, err = redigo.Bytes(conn.Do("GET", key)); err != nil { + return nil + } + var reply interface{} + if err = json.Unmarshal(data, &reply); err != nil { + return nil + } + + return reply +} + +// 集合Set增加元素 +func SetAdd(key string, data ...interface{}) error { + conn := pool.Get() + defer conn.Close() + var err error + for _, d := range data { + _, e := conn.Do("SADD", key, d) + if e != nil { + err = e + break + } + } + return err +} + +// 集合Set删除元素 +func SetRem(key string, data ...interface{}) error { + conn := pool.Get() + defer conn.Close() + + var err error + for _, d := range data { + _, e := conn.Do("SREM", key, d) + if e != nil { + err = e + break + } + } + + return err +} + +// 集合Set判断是否存在成员member,结果.(int64)==1表示存在 +func SetIsMember(key string, member interface{}) (interface{}, error) { + conn := pool.Get() + defer conn.Close() + + return conn.Do("SISMEMBER", key, member) +} + +// 设置一个值 +func Set(key string, val interface{}, timeout time.Duration) error { + data, err := json.Marshal(val) + if err != nil { + return err + } + return SetBytes(&key, &data, timeout) +} + +func SetBytes(key *string, data *[]byte, timeout time.Duration) error { + conn := pool.Get() + defer conn.Close() + + _, err := conn.Do("SETEX", *key, int64(timeout/time.Second), *data) + return err +} + +// IsExist 判断key是否存在 +func IsExist(key string) bool { + conn := pool.Get() + defer conn.Close() + + a, _ := conn.Do("EXISTS", key) + i := a.(int64) + return i > 0 +} + +// Delete 删除 +func Delete(key string) error { + conn := pool.Get() + defer conn.Close() + + if _, err := conn.Do("DEL", key); err != nil { + return err + } + + return nil +} + +// Expire 失效时间配置 +func Expire(key string, t int64) error { + conn := pool.Get() + defer conn.Close() + + if _, err := conn.Do("expire", key, t); err != nil { + return err + } + return nil +} diff --git a/redis2/user-redis.go b/redis2/user-redis.go new file mode 100644 index 0000000..f5dd8fa --- /dev/null +++ b/redis2/user-redis.go @@ -0,0 +1,41 @@ +package redis + +import ( + "encoding/json" + "errors" + "time" + + "github.com/sirupsen/logrus" + "myschools.me/suguo/intelligent-community/model" +) + +// 存储用户的Token +func UserTokenSet(key *string, usr *model.User) error { + + err := Set(*key, usr, 7210*time.Second) + if err != nil { + logrus.WithFields(logrus.Fields{ + "func": "UserTokenSet", + }).Warnf("Set: %s", err.Error()) + return err + } + return nil +} + +// 从redis中获取用户信息,最佳实践经验建议把此代码放service层 +func UserTokenGet(token *string) (*model.User, error) { + b, err := GetBytes(token) + if err != nil { + return nil, err + } + + if b == nil { + return nil, errors.New("无效token,请重新登录!") + } + + var user *model.User + if err := json.Unmarshal(*b, user); err != nil { + return nil, err + } + return user, nil +}