Skip to content

Commit

Permalink
添加了详细中文注释方便初学者学习
Browse files Browse the repository at this point in the history
  • Loading branch information
wangxiao1024 committed Jul 23, 2024
1 parent e20e783 commit 36caceb
Show file tree
Hide file tree
Showing 10 changed files with 233 additions and 158 deletions.
44 changes: 22 additions & 22 deletions interface/database/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,38 @@ import (
"github.com/hdt3213/rdb/core"
)

// CmdLine is alias for [][]byte, represents a command line
// CmdLine 是命令行的别名,表示一个命令行为一个二维字节切片
type CmdLine = [][]byte

// DB is the interface for redis style storage engine
// DB 是一个接口,为Redis风格的存储引擎定义了必要的方法
type DB interface {
Exec(client redis.Connection, cmdLine [][]byte) redis.Reply
AfterClientClose(c redis.Connection)
Close()
LoadRDB(dec *core.Decoder) error
Exec(client redis.Connection, cmdLine [][]byte) redis.Reply // 执行给定的命令行,并返回响应
AfterClientClose(c redis.Connection) // 客户端关闭后的回调处理
Close() // 关闭数据库连接
LoadRDB(dec *core.Decoder) error // 从RDB解码器加载数据到数据库
}

// KeyEventCallback will be called back on key event, such as key inserted or deleted
// may be called concurrently
// KeyEventCallback 是键事件的回调函数类型,如键被插入或删除时调用
// 可能会并发调用
type KeyEventCallback func(dbIndex int, key string, entity *DataEntity)

// DBEngine is the embedding storage engine exposing more methods for complex application
// DBEngine 是一个更高级的存储引擎接口,提供了更多的方法以支持复杂的应用场景
type DBEngine interface {
DB
ExecWithLock(conn redis.Connection, cmdLine [][]byte) redis.Reply
ExecMulti(conn redis.Connection, watching map[string]uint32, cmdLines []CmdLine) redis.Reply
GetUndoLogs(dbIndex int, cmdLine [][]byte) []CmdLine
ForEach(dbIndex int, cb func(key string, data *DataEntity, expiration *time.Time) bool)
RWLocks(dbIndex int, writeKeys []string, readKeys []string)
RWUnLocks(dbIndex int, writeKeys []string, readKeys []string)
GetDBSize(dbIndex int) (int, int)
GetEntity(dbIndex int, key string) (*DataEntity, bool)
GetExpiration(dbIndex int, key string) *time.Time
SetKeyInsertedCallback(cb KeyEventCallback)
SetKeyDeletedCallback(cb KeyEventCallback)
ExecWithLock(conn redis.Connection, cmdLine [][]byte) redis.Reply // 在执行命令时加锁保护
ExecMulti(conn redis.Connection, watching map[string]uint32, cmdLines []CmdLine) redis.Reply // 执行多个命令,支持事务
GetUndoLogs(dbIndex int, cmdLine [][]byte) []CmdLine // 获取撤销日志
ForEach(dbIndex int, cb func(key string, data *DataEntity, expiration *time.Time) bool) // 遍历数据库中的键
RWLocks(dbIndex int, writeKeys []string, readKeys []string) // 读写锁定一组键
RWUnLocks(dbIndex int, writeKeys []string, readKeys []string) // 解锁一组键
GetDBSize(dbIndex int) (int, int) // 获取数据库大小
GetEntity(dbIndex int, key string) (*DataEntity, bool) // 获取与键关联的数据实体
GetExpiration(dbIndex int, key string) *time.Time // 获取键的过期时间
SetKeyInsertedCallback(cb KeyEventCallback) // 设置键插入事件的回调
SetKeyDeletedCallback(cb KeyEventCallback) // 设置键删除事件的回调
}

// DataEntity stores data bound to a key, including a string, list, hash, set and so on
// DataEntity 存储绑定到键的数据,包括字符串、列表、哈希、集合等
type DataEntity struct {
Data interface{}
Data interface{} // 存储实际的数据,数据类型可以是任何类型
}
12 changes: 8 additions & 4 deletions interface/tcp/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ import (
"net"
)

// HandleFunc represents application handler function
// HandleFunc 定义了一个应用程序处理函数的类型
// 这种类型的函数接收一个context和一个网络连接
// ctx context.Context:上下文,用于控制子程序的生命周期
// conn net.Conn:表示一个网络连接,用于读取和写入数据
type HandleFunc func(ctx context.Context, conn net.Conn)

// Handler represents application server over tcp
// Handler 接口代表一个基于TCP的应用服务器
// 它定义了处理连接和关闭服务器的方法
type Handler interface {
Handle(ctx context.Context, conn net.Conn)
Close() error
Handle(ctx context.Context, conn net.Conn) // 处理接收到的网络连接
Close() error // 关闭服务器,清理资源,如果有错误返回错误
}
31 changes: 16 additions & 15 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,40 +20,41 @@ var banner = `
`

var defaultProperties = &config.ServerProperties{
Bind: "0.0.0.0",
Port: 6399,
AppendOnly: false,
AppendFilename: "",
MaxClients: 1000,
RunID: utils.RandString(40),
Bind: "0.0.0.0", // 默认绑定的IP地址
Port: 6399, // 默认端口号
AppendOnly: false, // 是否开启追加模式
AppendFilename: "", // 追加模式的文件名
MaxClients: 1000, // 最大客户端连接数
RunID: utils.RandString(40), // 生成一个随机的运行ID
}

// fileExists 检查文件是否存在且不是目录
func fileExists(filename string) bool {
info, err := os.Stat(filename)
return err == nil && !info.IsDir()
}

func main() {
print(banner)
logger.Setup(&logger.Settings{
print(banner) // 打印启动标志
logger.Setup(&logger.Settings{ // 设置日志文件配置
Path: "logs",
Name: "godis",
Ext: "log",
TimeFormat: "2006-01-02",
})
configFilename := os.Getenv("CONFIG")
configFilename := os.Getenv("CONFIG") // 获取环境变量中的配置文件名
if configFilename == "" {
if fileExists("redis.conf") {
config.SetupConfig("redis.conf")
if fileExists("redis.conf") { // 检查默认配置文件是否存在
config.SetupConfig("redis.conf") // 使用默认配置文件
} else {
config.Properties = defaultProperties
config.Properties = defaultProperties // 使用内置默认配置
}
} else {
config.SetupConfig(configFilename)
config.SetupConfig(configFilename) // 使用环境变量指定的配置文件
}
err := tcp.ListenAndServeWithSignal(&tcp.Config{
err := tcp.ListenAndServeWithSignal(&tcp.Config{ // 启动TCP服务器
Address: fmt.Sprintf("%s:%d", config.Properties.Bind, config.Properties.Port),
}, RedisServer.MakeHandler())
}, RedisServer.MakeHandler()) //调用我们的RedisServer.MakeHandler
if err != nil {
logger.Error(err)
}
Expand Down
92 changes: 51 additions & 41 deletions redis/connection/conn.go
Original file line number Diff line number Diff line change
@@ -1,74 +1,79 @@
package connection

import (
"github.com/hdt3213/godis/lib/logger"
"github.com/hdt3213/godis/lib/sync/wait"
"net"
"sync"
"time"

"github.com/hdt3213/godis/lib/logger"
"github.com/hdt3213/godis/lib/sync/wait"
)

const (
// flagSlave means this a connection with slave
// flagSlave 表示这是一个从服务器的连接
flagSlave = uint64(1 << iota)
// flagSlave means this a connection with master
// flagMaster 表示这是一个主服务器的连接
flagMaster
// flagMulti means this connection is within a transaction
// flagMulti 表示这个连接正在执行事务
flagMulti
)

// Connection represents a connection with a redis-cli
// Connection 代表与一个Redis客户端的连接
type Connection struct {
conn net.Conn
conn net.Conn // 网络连接实例

// wait until finish sending data, used for graceful shutdown
// sendingData 用于优雅关闭时等待数据发送完成
sendingData wait.Wait

// lock while server sending response
// mu 用于在发送响应时的互斥锁
mu sync.Mutex
flags uint64
flags uint64 // 连接的标志位,如是否为主从连接、是否处于事务中等

// subscribing channels
/// subs 保存订阅的频道
subs map[string]bool

// password may be changed by CONFIG command during runtime, so store the password
// password 可能会在运行时通过CONFIG命令被修改,因此需要存储密码
password string

// queued commands for `multi`
queue [][][]byte
// queue 保存在事务中排队的命令
queue [][][]byte
// watching 保存被WATCH命令监视的键及其版本号
watching map[string]uint32
// txErrors 保存事务中的错误信息
txErrors []error

// selected db
// selectedDB 表示当前选择的数据库索引
selectedDB int
}

// 连接池,用于重用连接对象
var connPool = sync.Pool{
New: func() interface{} {
return &Connection{}
},
}

// RemoteAddr returns the remote network address
// RemoteAddr 返回远程连接的网络地址
func (c *Connection) RemoteAddr() string {
return c.conn.RemoteAddr().String()
}

// Close disconnect with the client
// Close 用于断开与客户端的连接
func (c *Connection) Close() error {
c.sendingData.WaitWithTimeout(10 * time.Second)
_ = c.conn.Close()
c.sendingData.WaitWithTimeout(10 * time.Second) // 等待正在发送的数据完成或超时
_ = c.conn.Close() // 关闭底层网络连接
// 清理连接相关的状态信息
c.subs = nil
c.password = ""
c.queue = nil
c.watching = nil
c.txErrors = nil
c.selectedDB = 0
connPool.Put(c)
connPool.Put(c) // 将连接对象放回池中
return nil
}

// NewConn creates Connection instance
// NewConn 用于创建新的Connection实例
func NewConn(conn net.Conn) *Connection {
c, ok := connPool.Get().(*Connection)
if !ok {
Expand All @@ -81,7 +86,7 @@ func NewConn(conn net.Conn) *Connection {
return c
}

// Write sends response to client over tcp connection
// Write 向客户端发送响应
func (c *Connection) Write(b []byte) (int, error) {
if len(b) == 0 {
return 0, nil
Expand All @@ -101,7 +106,7 @@ func (c *Connection) Name() string {
return ""
}

// Subscribe add current connection into subscribers of the given channel
// Subscribe 将当前连接添加到指定频道的订阅者中
func (c *Connection) Subscribe(channel string) {
c.mu.Lock()
defer c.mu.Unlock()
Expand All @@ -112,7 +117,7 @@ func (c *Connection) Subscribe(channel string) {
c.subs[channel] = true
}

// UnSubscribe removes current connection into subscribers of the given channel
// UnSubscribe 从指定频道的订阅者中移除当前连接
func (c *Connection) UnSubscribe(channel string) {
c.mu.Lock()
defer c.mu.Unlock()
Expand All @@ -123,12 +128,12 @@ func (c *Connection) UnSubscribe(channel string) {
delete(c.subs, channel)
}

// SubsCount returns the number of subscribing channels
// SubsCount 返回当前连接订阅的频道数量
func (c *Connection) SubsCount() int {
return len(c.subs)
}

// GetChannels returns all subscribing channels
// GetChannels 返回当前连接订阅的所有频道
func (c *Connection) GetChannels() []string {
if c.subs == nil {
return make([]string, 0)
Expand All @@ -142,87 +147,92 @@ func (c *Connection) GetChannels() []string {
return channels
}

// SetPassword stores password for authentication
// SetPassword 设置连接的密码,用于认证
func (c *Connection) SetPassword(password string) {
c.password = password
}

// GetPassword get password for authentication
// GetPassword 获取连接的密码
func (c *Connection) GetPassword() string {
return c.password
}

// InMultiState tells is connection in an uncommitted transaction
// InMultiState 检查连接是否处于事务状态
func (c *Connection) InMultiState() bool {
return c.flags&flagMulti > 0
}

// SetMultiState sets transaction flag
// SetMultiState 设置连接的事务状态
func (c *Connection) SetMultiState(state bool) {
if !state { // reset data when cancel multi
if !state { // 如果取消事务,重置相关数据
c.watching = nil
c.queue = nil
c.flags &= ^flagMulti // clean multi flag
c.flags &= ^flagMulti // 清除事务标志
return
}
c.flags |= flagMulti
c.flags |= flagMulti // 设置事务标志
}

// GetQueuedCmdLine returns queued commands of current transaction
// GetQueuedCmdLine 返回事务中排队的命令
func (c *Connection) GetQueuedCmdLine() [][][]byte {
return c.queue
}

// EnqueueCmd enqueues command of current transaction
// EnqueueCmd 将命令添加到事务队列
func (c *Connection) EnqueueCmd(cmdLine [][]byte) {
c.queue = append(c.queue, cmdLine)
}

// AddTxError stores syntax error within transaction
// AddTxError 添加事务执行中的错误
func (c *Connection) AddTxError(err error) {
c.txErrors = append(c.txErrors, err)
}

// GetTxErrors returns syntax error within transaction
// GetTxErrors 获取事务中的错误
func (c *Connection) GetTxErrors() []error {
return c.txErrors
}

// ClearQueuedCmds clears queued commands of current transaction
// ClearQueuedCmds 清除事务中排队的命令
func (c *Connection) ClearQueuedCmds() {
c.queue = nil
}

// GetWatching returns watching keys and their version code when started watching
// GetWatching 返回被监视的键和它们的版本号
func (c *Connection) GetWatching() map[string]uint32 {
if c.watching == nil {
c.watching = make(map[string]uint32)
}
return c.watching
}

// GetDBIndex returns selected db
// GetDBIndex 返回选定的数据库索引
func (c *Connection) GetDBIndex() int {
return c.selectedDB
}

// SelectDB selects a database
// SelectDB 选择一个数据库
func (c *Connection) SelectDB(dbNum int) {
c.selectedDB = dbNum
}

// SetSlave 设置连接为从服务器模式
func (c *Connection) SetSlave() {
c.flags |= flagSlave
}

// IsSlave 检查连接是否为从服务器模式
func (c *Connection) IsSlave() bool {
return c.flags&flagSlave > 0
}

// SetMaster 设置连接为主服务器模式

func (c *Connection) SetMaster() {
c.flags |= flagMaster
}

// IsMaster 检查连接是否为主服务器模式
func (c *Connection) IsMaster() bool {
return c.flags&flagMaster > 0
}
Loading

0 comments on commit 36caceb

Please sign in to comment.