sentinel_adapter.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. package redis
  2. import (
  3. "fmt"
  4. "github.com/FZambia/sentinel"
  5. "github.com/gomodule/redigo/redis"
  6. "github.com/spf13/viper"
  7. "strings"
  8. "time"
  9. )
  10. // sentinel适配器
  11. type SentinelAdapter struct {
  12. pool *redis.Pool
  13. }
  14. // 返回sentinel适配器新实例
  15. func NewSentinelAdapter(nodes []string, masterName string) (IRedisAdapter, error) {
  16. opts := []redis.DialOption{redis.DialConnectTimeout(5 * time.Second)}
  17. password := viper.GetString("redis.password")
  18. if len(strings.TrimSpace(password)) > 0 {
  19. opts = append(opts, redis.DialPassword(strings.TrimSpace(password)))
  20. }
  21. s := &sentinel.Sentinel{
  22. Addrs: nodes,
  23. MasterName: masterName,
  24. Dial: func(addr string) (redis.Conn, error) {
  25. c, err := redis.Dial("tcp", addr, opts...)
  26. if err != nil {
  27. return nil, err
  28. }
  29. return c, nil
  30. },
  31. }
  32. maxIdle := viper.GetInt("redis.max_idle")
  33. maxActive := viper.GetInt("redis.max_active")
  34. idleTimeout := viper.GetDuration("redis.timeout")
  35. pool := &redis.Pool{
  36. MaxIdle: maxIdle,
  37. MaxActive: maxActive,
  38. IdleTimeout: idleTimeout,
  39. Dial: func() (redis.Conn, error) {
  40. addr, err := s.MasterAddr()
  41. if err != nil {
  42. return nil, err
  43. }
  44. if conn, err := redis.Dial("tcp", addr, opts...); nil != err {
  45. return nil, err
  46. } else {
  47. return conn, nil
  48. }
  49. },
  50. TestOnBorrow: func(c redis.Conn, t time.Time) error {
  51. if !sentinel.TestRole(c, "master") {
  52. return fmt.Errorf("redis sentinel role check failed")
  53. } else {
  54. return nil
  55. }
  56. },
  57. }
  58. return &SentinelAdapter{
  59. pool: pool,
  60. }, nil
  61. }
  62. // 关闭Redis连接
  63. func (a *SentinelAdapter) Close() error {
  64. return a.pool.Close()
  65. }
  66. // 执行Redis命令
  67. func (a *SentinelAdapter) Do(commandName string, args ...interface{}) (interface{}, error) {
  68. conn := a.pool.Get()
  69. defer func(conn redis.Conn) {
  70. _ = conn.Close()
  71. }(conn)
  72. if nil == conn {
  73. return nil, ErrRedisConnNil
  74. } else {
  75. return conn.Do(commandName, args...)
  76. }
  77. }
  78. // 返回命令管道操作对象
  79. func (a *SentinelAdapter) Pipeline() IRedisPipeline {
  80. return &RedigoPipeline{ // sentinel库兼容redigo库,返回RedigoPipeline即可
  81. conn: a.pool.Get(),
  82. }
  83. }