Skip to content

Redis

Redis เป็นฐานข้อมูลคีย์ค่า (Key-Value) แบบโอเพนซอร์สที่เขียนด้วยภาษา ANSI C ปฏิบัติตามข้อตกลง BSD รองรับเครือข่าย สามารถใช้หน่วยความจำเป็นพื้นฐาน แบบกระจาย และมีความคงทนแบบเลือกได้ มี API หลายภาษา Redis สามารถใช้เป็นฐานข้อมูล NoSQL ได้ ยังสามารถใช้เป็นแคชความเร็วสูง และรองรับคิวข้อความอย่างง่าย

บทความนี้เพียงอธิบายวิธีการใช้ไดรเวอร์ภาษา Go เพื่อดำเนินการกับฐานข้อมูล Redis จะไม่อธิบายเกี่ยวกับ Redis เอง

เอกสารทางการ: Golang Redis client (uptrace.dev)

ที่เก็บทางการ: go-redis/redis: Type-safe Redis client for Golang (github.com)

การติดตั้ง

เกี่ยวกับไดรเวอร์ของ Redis มีมากมาย บทความนี้ใช้ github.com/go-redis/redis

หากคุณใช้ Redis เวอร์ชัน 6

go get github.com/go-redis/redis/v8

หากคุณใช้ Redis เวอร์ชัน 7

go get github.com/go-redis/redis/v9

เริ่มต้นอย่างรวดเร็ว

go
import (
   "fmt"
   "log"
   "testing"

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

func TestQuickStart(t *testing.T) {
   // สร้างไคลเอนต์เชื่อมต่อ Redis
   redisClient := redis.NewClient(&redis.Options{
      Addr:     "192.168.48.134:6379",
      Password: "123456",
      DB:       0, // ใช้ DB เริ่มต้น
   })

   // ตั้งค่าคีย์ค่า 0 คือไม่หมดอายุ
   redisClient.Set("hello", "world", 0)

   // อ่านค่า
   result, err := redisClient.Get("hello").Result()
   if err == redis.Nil {
      fmt.Println("ket not exist")
   } else if err != nil {
      log.Panic(err)
   }
   fmt.Println(result)
}

การกำหนดค่าการเชื่อมต่อ

go
type Options struct {
  // ประเภทเครือข่าย tcp หรือ unix
  // ค่าเริ่มต้นคือ tcp
  Network string
  // ที่อยู่ redis รูปแบบ host:port
  Addr string

    // Dialer สร้างการเชื่อมต่อเครือข่ายใหม่และมีความสำคัญสูงกว่า Network และ Addr
  // Network and Addr options.
  Dialer func() (net.Conn, error)

  // เมื่อสร้างการเชื่อมต่อ redis ใหม่ จะเรียกฟังก์ชันนี้
  OnConnect func(*Conn) error

  // รหัสผ่าน redis หาก redis server ไม่ได้ตั้งค่าสามารถเว้นว่างได้
  Password string

  // ฐานข้อมูล redis เลขลำดับเริ่มจาก 0 ค่าเริ่มต้นคือ 0 ไม่ต้องตั้งค่า
  DB int

  // จำนวนครั้งลองใหม่สูงสุดเมื่อดำเนินการ redis ล้มเหลว ค่าเริ่มต้น 0
  MaxRetries int

  // ช่วงเวลาลองใหม่ขั้นต่ำ
  // ค่าเริ่มต้นคือ 8ms ; -1 หมายถึงปิด
  MinRetryBackoff time.Duration

  // ช่วงเวลาลองใหม่สูงสุด
  // ค่าเริ่มต้นคือ 512ms; -1 หมายถึงปิด
  MaxRetryBackoff time.Duration

  // เวลาหมดอายุการเชื่อมต่อ redis ใหม่
  // ค่าเริ่มต้นคือ 5 วินาที
  DialTimeout time.Duration

  // เวลาหมดอายุการอ่าน socket
  // ค่าเริ่มต้น 3 วินาที
  ReadTimeout time.Duration

  // เวลาหมดอายุการเขียน socket
  WriteTimeout time.Duration

  // จำนวนการเชื่อมต่อสูงสุดในพูลการเชื่อมต่อ redis
  // ขนาดพูลการเชื่อมต่อเริ่มต้นเท่ากับจำนวน cpu * 10
  PoolSize int

  // จำนวนการเชื่อมต่อว่างขั้นต่ำในพูลการเชื่อมต่อ redis
  MinIdleConns int

  // เวลาการอยู่รอดสูงสุดของการเชื่อมต่อ redis ค่าเริ่มต้นจะไม่ปิดการเชื่อมต่อที่ล้าสมัย
  MaxConnAge time.Duration

  // เมื่อคุณได้รับหนึ่งการเชื่อมต่อจากพูลการเชื่อมต่อ redis พูลการเชื่อมต่อจะรอการเชื่อมต่อนี้นานเท่าใดหลังจากนำออกไป
  // ค่าเริ่มต้นคือรอ ReadTimeout + 1 วินาที
  PoolTimeout time.Duration

  // พูลการเชื่อมต่อ redis จะปิดการเชื่อมต่อว่างนานเท่าใด
  // ค่าเริ่มต้นคือ 5 นาที -1 หมายถึงปิดการกำหนดค่านี
  IdleTimeout time.Duration

  // ตรวจสอบการเชื่อมต่อว่างนานเท่าใด
  // ค่าเริ่มต้นคือ 1 นาที -1 หมายถึงปิดการตรวจสอบการเชื่อมต่อว่าง
  IdleCheckFrequency time.Duration

  // การตั้งค่าอ่านอย่างเดียว หากตั้งค่าเป็น true ในอินสแตนซ์โหนดปัจจุบัน redis สามารถสอบถามแคชได้เท่านั้นไม่สามารถอัปเดต
  readOnly bool

    // การกำหนดค่า TLS
  TLSConfig *tls.Config
}

การสร้างการเชื่อมต่อ

go
// สร้างไคลเอนต์เชื่อมต่อ Redis
redisClient := redis.NewClient(&redis.Options{
    Addr:     "192.168.48.134:6379",
    Password: "123456",
    DB:       0, // ใช้ DB เริ่มต้น
})

การปิดการเชื่อมต่อ

ไดรเวอร์ภายในดูแลพูลการเชื่อมต่อ ไม่ต้องปิดการเชื่อมต่อทุกครั้งหลังดำเนินการ

go
defer redisClient.Close()

ไดรเวอร์ Redis นี้เกือบล็อกการดำเนินการทั้งหมดไว้แล้ว คำสั่ง Redis และชื่อวิธีการตรงกันหนึ่งต่อหนึ่ง โดยพื้นฐานแล้วเพียงรู้วิธีใช้คำสั่ง Redis วิธีการที่สอดคล้องกับไดรเวอร์ก็จะรู้เช่นกัน

คำสั่ง Redis: คู่มือคำสั่ง redis

การดำเนินการพื้นฐาน

ลบคีย์

go
redisClient.Set("name", "jack", 0)
fmt.Println(redisClient.Del("name").Result())

เวลาหมดอายุ

go
redisClient.Set("name", "jack", 0)
// ตั้งค่าเวลาหมดอายุ
redisClient.Expire("name", time.Second*2)
fmt.Println(redisClient.Get("name").Val())
time.Sleep(time.Second * 3)
fmt.Println(redisClient.Get("name").Val())

ยกเลิกเวลาหมดอายุ

go
redisClient.Set("name", "jack", 2)
// ยกเลิกเวลาหมดอายุ
redisClient.Persist("name")
time.Sleep(time.Second * 2)
fmt.Println(redisClient.Get("name"))

สอบถามเวลาหมดอายุ

go
fmt.Println(redisClient.TTL("name"))
fmt.Println(redisClient.PTTL("name"))

เปลี่ยนชื่อ

go
redisClient.Rename("name", "newName")

สอบถามประเภท

go
redisClient.Type("name")

สแกน

go
fmt.Println(redisClient.Scan(0, "", 4))

สตริง

เก็บและดึงอย่างง่าย

go
redisClient.Set("token", "abcefghijklmn", 0)
fmt.Println(redisClient.Get("token").Val())

เก็บและดึงเป็นชุด

go
redisClient.MSet("cookie", "12345", "token", "abcefg")
fmt.Println(redisClient.MGet("cookie", "token").Val())

เพิ่มและลดตัวเลข

go
redisClient.Set("age", "1", 0)
// เพิ่มอัตโนมัติ
redisClient.Incr("age")
fmt.Println(redisClient.Get("age").Val())
// ลดอัตโนมัติ
redisClient.Decr("age")
fmt.Println(redisClient.Get("age").Val())

ตารางแฮช

การอ่านและเขียน

go
// ตั้งค่าเดียว
redisClient.HSet("map", "name", "jack")
// ตั้งค่าเป็นชุด
redisClient.HMSet("map", map[string]interface{}{"a": "b", "c": "d", "e": "f"})
// เข้าถึงเดียว
fmt.Println(redisClient.HGet("map", "a").Val())
// เข้าถึงเป็นชุด
fmt.Println(redisClient.HMGet("map", "a", "b").Val())
// ดึงทั้ง map
fmt.Println(redisClient.HGetAll("map").Val())

ผลลัพธ์

b
[b <nil>]
map[a:b c:d e:f name:jack]

ลบคีย์

go
// ลบฟิลด์หนึ่งของ map
redisClient.HDel("map", "a")

ตรวจสอบว่าคีย์มีอยู่หรือไม่

go
// ตรวจสอบว่าฟิลด์มีอยู่หรือไม่
redisClient.HExists("map", "a")

ดึงคีย์ทั้งหมด

go
// ดึงคีย์ทั้งหมดของ map
redisClient.HKeys("map")

ดึงความยาวตารางแฮช

go
// ดึงความยาว map
redisClient.HLen("map")

วนซ้ำคีย์ค่าของตารางแฮช

go
// วนซ้ำคีย์ค่าใน map
redisClient.HScan("map", 0, "", 1)

รายการ

แก้ไของค์ประกอบ

go
// เพิ่มด้านซ้าย
redisClient.LPush("list", "a", "b", "c", "d", "e")
// เพิ่มด้านขวา
redisClient.RPush("list", "g", "i", "a")
// แทรกค่าด้านหน้าค่าอ้างอิง
redisClient.LInsertBefore("list", "a", "aa")
// แทรกค่าด้านหลังค่าอ้างอิง
redisClient.LInsertAfter("list", "a", "gg")
// ตั้งค่าค่าขององค์ประกอบดัชนีที่ระบุ
redisClient.LSet("list", 0, "head")

เข้าถึงความยาว

go
// เข้าถึงความยาวรายการ
redisClient.LLen("list")

เข้าถึงองค์ประกอบ

go
// ป๊อปองค์ประกอบจากด้านซ้าย
redisClient.LPop("list")
// ป๊อปองค์ประกอบจากด้านขวา
redisClient.RPop("list")
// เข้าถึงองค์ประกอบดัชนีที่ระบุ
redisClient.LIndex("list", 1)
// เข้าถึงองค์ประกอบในช่วงที่ระบุ
redisClient.LRange("list", 0, 1)

ลบองค์ประกอบ

go
// ลบองค์ประกอบที่ระบุ
redisClient.LRem("list", 0, "a")
// ลบองค์ประกอบในช่วงที่ระบุ
redisClient.LTrim("list", 0, 1)
// เก็บองค์ประกอบในช่วงที่ระบุ
redisClient.LTrim("list", 0, 1)

เซต

เพิ่มองค์ประกอบ

go
// เพิ่มองค์ประกอบในเซต
redisClient.SAdd("set", "a", "b", "c")
redisClient.SAdd("set2", "c", "d", "e")

เข้าถึงองค์ประกอบเซต

go
// ดึงสมาชิกทั้งหมดในเซต
redisClient.SMembers("set")
// ตรวจสอบว่าองค์ประกอบเป็นของเซตนี้หรือไม่
redisClient.SIsMember("set", "a")
// ส่งคืนองค์ประกอบ count แบบสุ่ม
redisClient.SRandMemberN("set", 1)
// ดึงจำนวนองค์ประกอบของเซต
redisClient.SCard("set")

การดำเนินการเซต

go
// ส่งคืนผลต่างของเซตที่กำหนด
redisClient.SDiff("set", "set2")
// เก็บผลต่างของเซตที่กำหนดในเซตผลลัพธ์ ส่งคืนความยาวของเซตผลลัพธ์
redisClient.SDiffStore("store", "set", "se2")
// ส่งคืนจุดตัดของเซตที่กำหนด
redisClient.SInter("set", "set2")
// เก็บจุดตัดของเซตที่กำหนดในเซตผลลัพธ์ ส่งคืนความยาวของเซตผลลัพธ์
redisClient.SInterStore("store", "set", "set2")
// ส่งคืนยูเนียนของเซตที่กำหนด
redisClient.SUnion("set", "set2")
// เก็บยูเนียนของเซตที่กำหนดในเซตผลลัพธ์ ส่งคืนความยาวของเซตผลลัพธ์
redisClient.SUnionStore("store", "set", "store")

ลบองค์ประกอบ

go
// ป๊อปและลบองค์ประกอบนั้น
redisClient.SPop("set")
// ป๊อปและลบ N องค์ประกอบ
redisClient.SPopN("set", 2)

ย้ายองค์ประกอบ

go
// ย้ายองค์ประกอบที่ระบุจากเซตต้นทางไปยังเซตเป้าหมาย
redisClient.SMove("set", "set2", "a")

ลบองค์ประกอบ

go
// ลบองค์ประกอบที่ระบุ
redisClient.SRem("set", "a", "b")

วนซ้ำ

go
// วนซ้ำเซต
redisClient.SScan("set", 0, "", 2)

เซตที่มีลำดับ

เพิ่มองค์ประกอบ

go
// เพิ่มองค์ประกอบในเซตที่มีลำดับ
redisClient.ZAdd("ss", redis.Z{
   Score:  1,
   Member: "a",
}, redis.Z{
   Score:  2,
   Member: "b",
})

อันดับองค์ประกอบ

go
// ส่งคืนอันดับขององค์ประกอบในเซตที่มีลำดับ เรียงจากต่ำไปสูง
redisClient.ZRank("ss", "1")
// ส่งคืนอันดับขององค์ประกอบในเซตที่มีลำดับ เรียงจากสูงไปต่ำ
redisClient.ZRevRank("ss", "1")

เข้าถึงองค์ประกอบ

go
// ส่งคืนจำนวนสมาชิกระหว่าง min และ max
redisClient.ZCount("ss", "1", "2")

// ส่งคืนค่าน้ำหนักขององค์ประกอบ
redisClient.ZScore("ss", "a")

// ส่งคืนองค์ประกอบในช่วงที่ระบุ
redisClient.ZRange("ss", 1, 2)
// ส่งคืนรายการสมาชิกทั้งหมดระหว่าง min และ max
redisClient.ZRangeByScore("ss", redis.ZRangeBy{
   Min:    "1",
   Max:    "2",
   Offset: 0,
   Count:  1,
})

แก้ไขค่าน้ำหนัก

go
// เพิ่มค่าน้ำหนักที่สอดคล้องให้กับองค์ประกอบที่ระบุ
redisClient.ZIncr("ss", redis.Z{
   Score:  2,
   Member: "b",
})

ลบองค์ประกอบ

go
// ลบองค์ประกอบที่ระบุ
redisClient.ZRem("ss", "a")
// ลบองค์ประกอบในช่วงอันดับที่ระบุ
redisClient.ZRemRangeByRank("ss", 1, 2)
// ลบองค์ประกอบในช่วงค่าน้ำหนัก min และ max
redisClient.ZRemRangeByScore("ss", "1", "2")

สคริปต์

go
// โหลดสคริปต์ ส่งคืนค่า sha
redisClient.ScriptLoad("return 0")
// ดำเนินการสคริปต์ตามค่า sha
redisClient.EvalSha("sha", []string{}, "")
// ดำเนินการสคริปต์โดยตรง
redisClient.Eval("return 0", []string{}, "")
// ล้างแคชสคริปต์
redisClient.ScriptFlush()
// ฆ่าสคริปต์ที่กำลังทำงานอยู่
redisClient.ScriptKill()
// ตรวจสอบว่าสคริปต์ของค่าแฮชที่ระบุมีอยู่หรือไม่
redisClient.ScriptExists("")

เผยแพร่และติดตาม

go
// ส่งข้อความไปยังช่องที่ระบุ
redisClient.Publish("channel", "message")
// ติดตามช่องที่ระบุ
redisClient.Subscribe("channel")
// ดูสถานะการติดตาม
redisClient.PubSubNumSub("channel")

Golang by www.golangdev.cn edit