包含标签 redis articles

后端服务动态转发

一、背景

当前我们游戏架构通过水平扩展wgame节点(和区服无关只处理玩家连接和玩家服务数据)来承载在线玩家的。通过一直扩展减轻单个wgame节点负载和承载更多在线玩家。

在wgame节点前面增加一层nginx以实现wss(客户端和服务端通过websocket连接,但是微信等小程序要求wss)。以前单个渠道不用太多wgame节点就能满足线上需求,随着业务增长和游戏类型决定同时在线玩家数较以前出现较大增长,每次增加线上新机器或者机器上面新增wgame节点(wgame监听客户端连接端口)就需要重新生成nginx配置并reload一次,导致nginx配置越来越难维护。后期统一入口即在nginx前面加入SLB之后每次还需要在SLB增加新的端口监听和转发。

……

Continue reading

Redis String

一、数据结构基础

  1. sds在C字符数组的基础上增加了长度和空间元数据,使基于字符串长度的追加、复制、比较等操作可以直接读取元数据,提升效率。。
  2. SDS总共设计了五种类型,分别为sdshdr5、sdshdr8、sdshdr16、sdshdr32和sdshdr64。他们的主要区别是数据结构中字符数组现有len和分配空间长度alloc的不同,sdshdr5没有被使用,后四种len数据类型分别为uint8_t、uint16_t、uint32_t、uint64_t。
struct __attribute__ ((__packed__)) sdshdr8 {
    uint8_t len; /* used */
    uint8_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};

struct __attribute__ ((__packed__)) sdshdr64 {
    uint64_t len; /* used */
    uint64_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
  1. SDS设计不同的结构头是为了灵活保存不同大小的字符串,从而有效节省空间。结构头占用内存空间不一样,保存小字符串时结构头占用小可以节约内存。
  2. 结构体定义中__attribute__ ((__packed__))的作用是告诉编译器不要使用字节对齐方式,而是采用紧凑型额方式分配内存(默认情况编译器会按照8字节对齐的方式分配内存)。
  3. 为了避免频繁内存重新分配,当SDS扩容时,如果所需内存小于1M时扩容翻倍,当大于等于1M时扩大1M。
  4. SDS保存数据的末尾设置为空字符,并且总会为buf数组分配空间时多分配一个字节来容纳这个空字符,使保存文本数据的SDS可以重用一部分<string.h>库定义的函数。
  5. SDS采用惰性空间的释放策略。

二、C字符串与SDS比较

……

Continue reading

Redis Hash

  1. Redis中的dict数据结构采用链式哈希方式存储。负载因子大于等于1时触发哈希扩容检测,当存在RDB子进程或者AOF子进程时关闭哈希扩容(避免父进程大量写时复制),不过即使没开启hash扩容在负载因子大于dict_force_resize_ratio时也会执行哈希扩容,扩容大小为当前容量的2倍。
  2. 当往Redis中写入新的键值对或者是修改键值对时,Redis都会判断是否需要rehash,函数调用链为:dictAdd/dictReplace/dictAddOrFind -> dictAddRaw -> _dictKeyIndex -> _dictExpandIfNeeded。
  3. Redis哈希扩容时使用渐进式rehash,即每次只进行n个bucket的rehash处理,避免大量的键需要从原来的位置拷贝到新位置时主线程无法执行其他请求而阻塞;rehash时当出现10*n个都为空bucket时会结束本次处理,防止阻塞太长时间。
  4. Redis中有五处函数调用_dictRehashStep进而调用dictRehash函数来执行rehash,调用链为:ictAddRow/dictGenericDelete/dictFind/dictGetRandomKey/dictGetSomeKeys -> _dictRehashStep -> dictRehash。
  5. 全局哈希表除了主动函数调用(增删改查)执行rehash外还有定时rehash,主线程会默认每间隔100ms执行一次迁移操作。单次以100bucket作为单位迁移数据,如果超过1ms就结束当前迁移。
  6. 在rehash期间,查询hash表找不到结果时还会在新哈希表查询一次。
……

Continue reading

Redis核心技术与实战 学习笔记 一

Redis的特性是“快”。一方面是因为它是内存数据库,所有操作都在内存上完成,内存的访问速度本身就很快。另一方面归功于它的数据结构。键值对是按一定的数据结构来组织的,操作键值对最终就是对数据结构进行增删改查操作,所以高效的数据结构是Redis快速处理的基础。

……

Continue reading