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เริ่มต้นอย่างรวดเร็ว
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)
}การกำหนดค่าการเชื่อมต่อ
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
}การสร้างการเชื่อมต่อ
// สร้างไคลเอนต์เชื่อมต่อ Redis
redisClient := redis.NewClient(&redis.Options{
Addr: "192.168.48.134:6379",
Password: "123456",
DB: 0, // ใช้ DB เริ่มต้น
})การปิดการเชื่อมต่อ
ไดรเวอร์ภายในดูแลพูลการเชื่อมต่อ ไม่ต้องปิดการเชื่อมต่อทุกครั้งหลังดำเนินการ
defer redisClient.Close()ไดรเวอร์ Redis นี้เกือบล็อกการดำเนินการทั้งหมดไว้แล้ว คำสั่ง Redis และชื่อวิธีการตรงกันหนึ่งต่อหนึ่ง โดยพื้นฐานแล้วเพียงรู้วิธีใช้คำสั่ง Redis วิธีการที่สอดคล้องกับไดรเวอร์ก็จะรู้เช่นกัน
คำสั่ง Redis: คู่มือคำสั่ง redis
การดำเนินการพื้นฐาน
ลบคีย์
redisClient.Set("name", "jack", 0)
fmt.Println(redisClient.Del("name").Result())เวลาหมดอายุ
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())ยกเลิกเวลาหมดอายุ
redisClient.Set("name", "jack", 2)
// ยกเลิกเวลาหมดอายุ
redisClient.Persist("name")
time.Sleep(time.Second * 2)
fmt.Println(redisClient.Get("name"))สอบถามเวลาหมดอายุ
fmt.Println(redisClient.TTL("name"))
fmt.Println(redisClient.PTTL("name"))เปลี่ยนชื่อ
redisClient.Rename("name", "newName")สอบถามประเภท
redisClient.Type("name")สแกน
fmt.Println(redisClient.Scan(0, "", 4))สตริง
เก็บและดึงอย่างง่าย
redisClient.Set("token", "abcefghijklmn", 0)
fmt.Println(redisClient.Get("token").Val())เก็บและดึงเป็นชุด
redisClient.MSet("cookie", "12345", "token", "abcefg")
fmt.Println(redisClient.MGet("cookie", "token").Val())เพิ่มและลดตัวเลข
redisClient.Set("age", "1", 0)
// เพิ่มอัตโนมัติ
redisClient.Incr("age")
fmt.Println(redisClient.Get("age").Val())
// ลดอัตโนมัติ
redisClient.Decr("age")
fmt.Println(redisClient.Get("age").Val())ตารางแฮช
การอ่านและเขียน
// ตั้งค่าเดียว
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]ลบคีย์
// ลบฟิลด์หนึ่งของ map
redisClient.HDel("map", "a")ตรวจสอบว่าคีย์มีอยู่หรือไม่
// ตรวจสอบว่าฟิลด์มีอยู่หรือไม่
redisClient.HExists("map", "a")ดึงคีย์ทั้งหมด
// ดึงคีย์ทั้งหมดของ map
redisClient.HKeys("map")ดึงความยาวตารางแฮช
// ดึงความยาว map
redisClient.HLen("map")วนซ้ำคีย์ค่าของตารางแฮช
// วนซ้ำคีย์ค่าใน map
redisClient.HScan("map", 0, "", 1)รายการ
แก้ไของค์ประกอบ
// เพิ่มด้านซ้าย
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")เข้าถึงความยาว
// เข้าถึงความยาวรายการ
redisClient.LLen("list")เข้าถึงองค์ประกอบ
// ป๊อปองค์ประกอบจากด้านซ้าย
redisClient.LPop("list")
// ป๊อปองค์ประกอบจากด้านขวา
redisClient.RPop("list")
// เข้าถึงองค์ประกอบดัชนีที่ระบุ
redisClient.LIndex("list", 1)
// เข้าถึงองค์ประกอบในช่วงที่ระบุ
redisClient.LRange("list", 0, 1)ลบองค์ประกอบ
// ลบองค์ประกอบที่ระบุ
redisClient.LRem("list", 0, "a")
// ลบองค์ประกอบในช่วงที่ระบุ
redisClient.LTrim("list", 0, 1)
// เก็บองค์ประกอบในช่วงที่ระบุ
redisClient.LTrim("list", 0, 1)เซต
เพิ่มองค์ประกอบ
// เพิ่มองค์ประกอบในเซต
redisClient.SAdd("set", "a", "b", "c")
redisClient.SAdd("set2", "c", "d", "e")เข้าถึงองค์ประกอบเซต
// ดึงสมาชิกทั้งหมดในเซต
redisClient.SMembers("set")
// ตรวจสอบว่าองค์ประกอบเป็นของเซตนี้หรือไม่
redisClient.SIsMember("set", "a")
// ส่งคืนองค์ประกอบ count แบบสุ่ม
redisClient.SRandMemberN("set", 1)
// ดึงจำนวนองค์ประกอบของเซต
redisClient.SCard("set")การดำเนินการเซต
// ส่งคืนผลต่างของเซตที่กำหนด
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")ลบองค์ประกอบ
// ป๊อปและลบองค์ประกอบนั้น
redisClient.SPop("set")
// ป๊อปและลบ N องค์ประกอบ
redisClient.SPopN("set", 2)ย้ายองค์ประกอบ
// ย้ายองค์ประกอบที่ระบุจากเซตต้นทางไปยังเซตเป้าหมาย
redisClient.SMove("set", "set2", "a")ลบองค์ประกอบ
// ลบองค์ประกอบที่ระบุ
redisClient.SRem("set", "a", "b")วนซ้ำ
// วนซ้ำเซต
redisClient.SScan("set", 0, "", 2)เซตที่มีลำดับ
เพิ่มองค์ประกอบ
// เพิ่มองค์ประกอบในเซตที่มีลำดับ
redisClient.ZAdd("ss", redis.Z{
Score: 1,
Member: "a",
}, redis.Z{
Score: 2,
Member: "b",
})อันดับองค์ประกอบ
// ส่งคืนอันดับขององค์ประกอบในเซตที่มีลำดับ เรียงจากต่ำไปสูง
redisClient.ZRank("ss", "1")
// ส่งคืนอันดับขององค์ประกอบในเซตที่มีลำดับ เรียงจากสูงไปต่ำ
redisClient.ZRevRank("ss", "1")เข้าถึงองค์ประกอบ
// ส่งคืนจำนวนสมาชิกระหว่าง 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,
})แก้ไขค่าน้ำหนัก
// เพิ่มค่าน้ำหนักที่สอดคล้องให้กับองค์ประกอบที่ระบุ
redisClient.ZIncr("ss", redis.Z{
Score: 2,
Member: "b",
})ลบองค์ประกอบ
// ลบองค์ประกอบที่ระบุ
redisClient.ZRem("ss", "a")
// ลบองค์ประกอบในช่วงอันดับที่ระบุ
redisClient.ZRemRangeByRank("ss", 1, 2)
// ลบองค์ประกอบในช่วงค่าน้ำหนัก min และ max
redisClient.ZRemRangeByScore("ss", "1", "2")สคริปต์
// โหลดสคริปต์ ส่งคืนค่า sha
redisClient.ScriptLoad("return 0")
// ดำเนินการสคริปต์ตามค่า sha
redisClient.EvalSha("sha", []string{}, "")
// ดำเนินการสคริปต์โดยตรง
redisClient.Eval("return 0", []string{}, "")
// ล้างแคชสคริปต์
redisClient.ScriptFlush()
// ฆ่าสคริปต์ที่กำลังทำงานอยู่
redisClient.ScriptKill()
// ตรวจสอบว่าสคริปต์ของค่าแฮชที่ระบุมีอยู่หรือไม่
redisClient.ScriptExists("")เผยแพร่และติดตาม
// ส่งข้อความไปยังช่องที่ระบุ
redisClient.Publish("channel", "message")
// ติดตามช่องที่ระบุ
redisClient.Subscribe("channel")
// ดูสถานะการติดตาม
redisClient.PubSubNumSub("channel")