Redis网络模型

打印 上一主题 下一主题

主题 825|帖子 825|积分 2475

主从复制原理


  • 建立毗连

    • 从节点在配置了 replicaof 配置了主节点的ip和port
    • 从库实验replicaof 并发送psync下令

  • 同步数据到从库

    • 主库bgsave生成RDB文件,并发送给从库,同时为每一个slave开辟一块 replication buffer 缓冲区记载从生成rdb文件开始收到的全部写下令。
    • 从库清空数据并加载rdb

  • 发送新写的下令给从库

    • 从节点加载 RDB 完成后,主节点将 replication buffer 缓冲区的数据(增量写下令)发送到从节点,slave 接收并实验,从节点同步至主节点雷同的状态。

  • 基于长毗连传播

    • 方便后续下令传输,除了写下令,还维持着心跳机制

网络模型


  • 壅闭IO
  • 非壅闭IO

    • 没啥用,还是需要等待数据准备就绪

  • IO多路复用
  • 信号驱动IO
  • 异步IO
IO多路复用

文件描述符:简称FD

select

流程:

  • 创建fd_set rfds

    • 假设要监听的fd为1,2,5

  • 实验select(5+1,null,null,3)

    • 第一个参数为最大长度+1,后面是等待时间

  • 内核遍历fd

    • 没有数据,休眠

      • 等待数据就绪或者超时


  • 遍历fd_set 找到就绪的数据

存在的标题


  • 需要将整个fd_set从用户空间拷贝到内核空间,select竣事后还要拷贝回用户空间
  • 需要遍历一次
  • 最大为监听1024
poll

将数据改为了链表,还是需要遍历

epoll


  • epoll_create 创建epoll实例
  • epoll_ctl 添加需要监听的fd,关联callback
  • epoll_wait 等待fd就绪

epoll_wait有两种通知模式

  • levelTriggered 简称LT 当FD有数据可读的时间,会重复通知多次,直到数据处理完成。是epoll的默认模式
  • EdgeTriggered 简称ET 。当FD有数据可读的时间只会被通知一次,不管数据是否处理完成
ET模式避免了LT的惊群效应。
ET模式最好结合非壅闭IO。
镌汰策略

分类:全体,ttl
LRU
抽样LRU 不是严酷的
LFU
RedisObject中使用逻辑访问次数
访问频率越高,增长的越小,还会衰减(16位记载时间,8位记载逻辑访问次数)
总结


附带的tcp毗连redis客户端 使用go编写的
[code]package mainimport (    "bufio"    "errors"    "fmt"    "io"    "net"    "strconv")// RedisClient 封装用于毗连type RedisClient struct {    conn net.Conn    //包装一层 方便读写    writer *bufio.Writer    reader *bufio.Reader}func main() {    //毗连redis    conn, err := net.Dial("tcp", "127.0.0.1:6379")    if err != nil {       fmt.Println("毗连redis失败", err)    }    client := RedisClient{conn: conn, writer: bufio.NewWriter(conn), reader: bufio.NewReader(conn)}    defer client.conn.Close()    //发送下令    client.sendRequest([]string{"set", "name", "方块"})    //zrange boards:2024-4 0 -1    //client.sendRequest([]string{"zrange", "boards:2024-4", "0", "-1"})    //LRANGE tlist 0 -1    client.sendRequest([]string{"LRANGE", "tlist", "0", "-1"})}func (client *RedisClient) sendRequest(args []string) interface{} {    length := len(args)    firstCommand := fmt.Sprintf("%s%d", "*", length)    client.writeCommand(firstCommand)    for _, s := range args {       n := len(s)       client.writeCommand("$" + strconv.Itoa(n))       client.writeCommand(s)       println(n, s)    }    response := client.handleResponse()    //fmt.Printf("%v", response)    return response}// 写下令func (client *RedisClient) writeCommand(s string) {    client.conn.Write([]byte(s + "\r\n"))}// 解析返回结果func (client *RedisClient) handleResponse() interface{} {    //先读取第一个字符    r, _, _ := client.reader.ReadRune()    flag := string(r)    fmt.Println("第一个操作数:" + flag)    switch flag {    case "+":       //一行字符串       return client.ReadLine()    case "-":       //异常       return client.ReadLine()    case ":":       //数字       line := client.ReadLine()       res, _ := strconv.Atoi(line)       return res    case "$":       // 多行字符串       //readRune, _, _ := client.reader.ReadRune()       //去掉换行       readRune := client.ReadLine()       length := string(readRune)       if length == "-1" {          return nil       } else if length == "0" {          return ""       }       lll, _ := strconv.Atoi(length)       //+2是跳过\r\n       bytes := make([]byte, lll+2)       n, _ := client.reader.Read(bytes)       return string(bytes[:n])    case "*":       //多行字符串 递归获取       return client.readBulkString()    default:       return errors.New("错误")    }}// 读一行func (client *RedisClient) ReadLine() string {    bytes, _, _ := client.reader.ReadLine()    return string(bytes)}// 读到末尾 估计有点标题func (client *RedisClient) ReadToEnd() string {    var size = 1024    bytes := make([]byte, size)    var temp = ""    for {       n, err := client.reader.Read(bytes)       temp += string(bytes[:n])       //n, err := client.conn.Read(bytes)       if err == io.EOF || n == 0 || n < size {          break       }    }    return temp}func (client *RedisClient) readBulkString() interface{} {    counts, _ := strconv.Atoi(client.ReadLine())    if counts

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

张国伟

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表