db.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // Author: simon (ynwdlxm@163.com)
  2. // Date: 2025/9/15 18:04
  3. // Desc: Redis 数据库核心实现
  4. package database
  5. import (
  6. "strings"
  7. "github.com/runningwater/go-redis/datastruct/dict"
  8. "github.com/runningwater/go-redis/interface/database"
  9. "github.com/runningwater/go-redis/interface/resp"
  10. "github.com/runningwater/go-redis/resp/reply"
  11. )
  12. // DB 表示一个 Redis 数据库实例(StandaloneDatabase 里面的 dbSet)
  13. type DB struct {
  14. index int // 数据库索引
  15. data dict.Dict // 存储键值对的数据结构
  16. addAof func(CmdLine) // 添加AOF记录的函数指针
  17. }
  18. // ExecFunc 定义命令执行函数的类型
  19. // 参数:
  20. // - db: 数据库实例
  21. // - args: 命令参数列表(不包括命令名称)
  22. //
  23. // 返回值:
  24. // - resp.Reply: 命令执行结果的回复
  25. type ExecFunc func(db *DB, args [][]byte) resp.Reply
  26. // CmdLine 定义命令行类型,是字节切片的切片
  27. type CmdLine = [][]byte
  28. // NewDB 创建一个新的数据库实例
  29. // 返回值:
  30. // - *DB: 新创建的数据库实例
  31. func NewDB() *DB {
  32. return &DB{
  33. data: dict.NewSyncDict(),
  34. addAof: func(cmd CmdLine) {}, // 默认的添加AOF记录函数
  35. }
  36. }
  37. // Exec 执行一个redis命令
  38. // 参数:
  39. // - c: 客户端连接对象,表示发送命令的客户端连接
  40. // - cmdLine: 命令行参数,包含命令名称和所有参数的字节切片
  41. //
  42. // 返回值:
  43. // - resp.Reply: 命令执行结果的回复
  44. func (d *DB) Exec(c resp.Connection, cmdLine CmdLine) resp.Reply {
  45. // 检查命令行参数是否为空
  46. if len(cmdLine) == 0 {
  47. return reply.NewErrReply("empty command")
  48. }
  49. // 获取命令名称并转换为小写
  50. cmdName := strings.ToLower(string(cmdLine[0]))
  51. // 查找命令
  52. cmd, ok := cmdTable[cmdName]
  53. if !ok {
  54. return reply.NewUnknownErrReply(cmdName)
  55. }
  56. // 参数校验
  57. if !validateArity(cmd.arity, cmdLine) {
  58. return reply.NewArgNumErrReply(cmdName)
  59. }
  60. if cmd.executor == nil {
  61. return reply.NewErrReply("command not implement")
  62. }
  63. return cmd.executor(d, cmdLine[1:])
  64. }
  65. // validateArity 验证命令参数数量是否正确
  66. // 参数:
  67. // - arity: 命令期望的参数数量
  68. // - 正数表示精确匹配该数量
  69. // - 负数表示至少需要 -arity 个参数
  70. // - args: 实际传入的参数列表
  71. //
  72. // 返回值:
  73. // - bool: 参数数量是否符合要求
  74. func validateArity(arity int, args [][]byte) bool {
  75. if arity >= 0 {
  76. return arity == len(args)
  77. }
  78. // 变长的 arity 设置为 负的最小个数
  79. return len(args) >= -arity
  80. }
  81. // GetEntity 根据键获取数据实体
  82. // 参数:
  83. // - key: 要获取的键
  84. //
  85. // 返回值:
  86. // - *database.DataEntity: 键对应的数据实体
  87. // - bool: 键是否存在
  88. func (d *DB) GetEntity(key string) (*database.DataEntity, bool) {
  89. raw, ok := d.data.Get(key)
  90. if !ok {
  91. return nil, false
  92. }
  93. entity, _ := raw.(*database.DataEntity)
  94. return entity, true
  95. }
  96. // PutEntity 插入或更新键值对
  97. // 参数:
  98. // - key: 键
  99. // - entity: 数据实体
  100. //
  101. // 返回值:
  102. // - int: 操作结果,1表示新增,0表示更新
  103. func (d *DB) PutEntity(key string, entity *database.DataEntity) int {
  104. return d.data.Put(key, entity)
  105. }
  106. // PuIfExists 当键存在时才更新键值对
  107. // 参数:
  108. // - key: 键
  109. // - entity: 数据实体
  110. //
  111. // 返回值:
  112. // - int: 操作结果,1表示更新成功,0表示键不存在未更新
  113. func (d *DB) PuIfExists(key string, entity *database.DataEntity) int {
  114. return d.data.PutIfExists(key, entity)
  115. }
  116. // PutIfAbsent 当键不存在时才插入键值对
  117. // 参数:
  118. // - key: 键
  119. // - entity: 数据实体
  120. //
  121. // 返回值:
  122. // - int: 操作结果,1表示插入成功,0表示键已存在未插入
  123. func (d *DB) PutIfAbsent(key string, entity *database.DataEntity) int {
  124. return d.data.PutIfAbsent(key, entity)
  125. }
  126. // Remove 根据键删除键值对
  127. // 参数:
  128. // - key: 要删除的键
  129. //
  130. // 返回值:
  131. // - int: 操作结果,1表示删除成功,0表示键不存在
  132. func (d *DB) Remove(key string) int {
  133. return d.data.Remove(key)
  134. }
  135. // Removes 批量删除多个键
  136. // 参数:
  137. // - keys: 要删除的键列表
  138. //
  139. // 返回值:
  140. // - deleted: 成功删除的键数量
  141. func (d *DB) Removes(keys ...string) (deleted int) {
  142. deleted = 0
  143. for _, key := range keys {
  144. // 使用Remove方法的返回值判断是否删除成功,避免两次查找
  145. if d.data.Remove(key) > 0 {
  146. deleted++
  147. }
  148. }
  149. return deleted
  150. }
  151. // Flush 清空数据库中的所有键值对
  152. func (d *DB) Flush() {
  153. d.data.Clear()
  154. }