redis.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // Redis模块 - 负责Redis连接管理和消息存储
  2. package wsClient
  3. import (
  4. "context"
  5. "encoding/json"
  6. "log"
  7. "time"
  8. "github.com/redis/go-redis/v9"
  9. )
  10. // Redis客户端实例,全局变量
  11. var redisClient *redis.Client
  12. // Redis上下文
  13. var ctx = context.Background()
  14. // ChatMessage 表示存储在Redis中的聊天消息结构
  15. type ChatMessage struct {
  16. Content string `json:"content"` // 原始消息内容(JSON字符串)
  17. Timestamp time.Time `json:"timestamp"` // 存储时间戳
  18. RoomName string `json:"room_name"` // 房间名称
  19. }
  20. // InitRedis 初始化Redis连接
  21. func InitRedis(addr, password string, db int) error {
  22. redisClient = redis.NewClient(&redis.Options{
  23. Addr: addr, // Redis服务器地址 (例如: "localhost:6379")
  24. Password: password, // Redis密码 (如果没有密码则为空字符串)
  25. DB: db, // Redis数据库编号 (0-15)
  26. })
  27. // 测试Redis连接
  28. pong, err := redisClient.Ping(ctx).Result()
  29. if err != nil {
  30. log.Printf("Redis连接失败: %v", err)
  31. return err
  32. }
  33. log.Printf("Redis连接成功: %s", pong)
  34. return nil
  35. }
  36. // StoreRawMessage 将原始消息内容存储到Redis中
  37. // 使用房间名作为Redis列表的键,存储消息历史记录
  38. func StoreRawMessage(roomName string, rawMessage []byte) error {
  39. if redisClient == nil {
  40. log.Println("Redis客户端未初始化")
  41. return nil
  42. }
  43. // 创建消息对象,包含原始消息内容和时间戳
  44. chatMsg := ChatMessage{
  45. Content: string(rawMessage), // 直接存储原始JSON字符串
  46. Timestamp: time.Now(),
  47. RoomName: roomName,
  48. }
  49. // 将消息序列化为JSON
  50. msgBytes, err := json.Marshal(chatMsg)
  51. if err != nil {
  52. log.Printf("消息序列化失败: %v", err)
  53. return err
  54. }
  55. // 使用房间名作为Redis键,将消息添加到列表的右端
  56. // 键格式: "room_messages:{房间名}"
  57. key := "room_messages:" + roomName
  58. err = redisClient.RPush(ctx, key, msgBytes).Err()
  59. if err != nil {
  60. log.Printf("消息存储到Redis失败: %v", err)
  61. return err
  62. }
  63. // 设置过期时间(可选)- 7天后自动删除
  64. redisClient.Expire(ctx, key, 7*24*time.Hour)
  65. log.Printf("消息已存储到Redis - 房间: %s\n\n", roomName)
  66. return nil
  67. }
  68. // StoreMessage 将消息存储到Redis中(保留旧接口以兼容)
  69. // 使用房间名作为Redis列表的键,存储消息历史记录
  70. func StoreMessage(roomName, username, message string) error {
  71. if redisClient == nil {
  72. log.Println("Redis客户端未初始化")
  73. return nil
  74. }
  75. // 构建与新格式兼容的消息结构
  76. msgContent := map[string]interface{}{
  77. "name": username,
  78. "message": message,
  79. }
  80. msgBytes, _ := json.Marshal(msgContent)
  81. return StoreRawMessage(roomName, msgBytes)
  82. }
  83. // GetRoomMessages 获取房间的历史消息
  84. // 返回指定数量的最新消息
  85. func GetRoomMessages(roomName string, count int64) ([]ChatMessage, error) {
  86. if redisClient == nil {
  87. log.Println("Redis客户端未初始化")
  88. return nil, nil
  89. }
  90. key := "room_messages:" + roomName
  91. // 获取列表中的最新消息(从右端开始,即最新的消息)
  92. // -count 表示从列表末尾开始的count个元素
  93. result, err := redisClient.LRange(ctx, key, -count, -1).Result()
  94. if err != nil {
  95. log.Printf("从Redis获取消息失败: %v", err)
  96. return nil, err
  97. }
  98. var messages []ChatMessage
  99. for _, msgStr := range result {
  100. var msg ChatMessage
  101. if err := json.Unmarshal([]byte(msgStr), &msg); err != nil {
  102. log.Printf("消息反序列化失败: %v", err)
  103. continue
  104. }
  105. messages = append(messages, msg)
  106. }
  107. return messages, nil
  108. }
  109. // GetRoomMessageCount 获取房间的消息总数
  110. func GetRoomMessageCount(roomName string) (int64, error) {
  111. if redisClient == nil {
  112. return 0, nil
  113. }
  114. key := "room_messages:" + roomName
  115. return redisClient.LLen(ctx, key).Result()
  116. }
  117. // CloseRedis 关闭Redis连接
  118. func CloseRedis() error {
  119. if redisClient != nil {
  120. return redisClient.Close()
  121. }
  122. return nil
  123. }