Redis对象——字符串(string)

文章目录


 

一、Redis是什么?

Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写的Key-Value内存数据库。

Redis应用非常广泛,如Twitter、暴雪娱乐、Github、Stack Overflow、腾讯、阿里巴巴、京
东、华为、新浪微博等,很多中小型公司也在使用。

 

二、使用步骤

1.编译安装

git clone https://gitee.com/mirrors/redis.git -b 6.2
cd redis
make
make test
make install
# 默认安装在 /usr/local/bin
# redis-server 是服务端程序
# redis-cli 是客户端程序

2.启动与登录

修改redis.conf,把配置文件放到/usr/local/bin/目录下(和redis-server同级目录)

   - 可配置登录密码                      requirepass 123456

   - 可设置为守护进程方式打开: daemonize yes

启动redis:  

cd /usr/local/bin
./redis-server

使用客户端登录redis:

cd /usr/local/bin
./redis-cli -h 127.0.0.1 -a 123456

三、Redis数据结构

redis的内部整体的存储结构就是一个大的dict,内部实现是数组实现hash。其中,string/list/hash/set/zset都是该数组的value。

对于地址冲突是通过链地址法解决的

Redis包含五种常用的数据结构:string、list、hash、set、zset

四、string类型

字符串类型是redis中最基本的数据类型,它能存储任何形式的字符串,包括二进制数据(可存储图片等)。

字符串长度小于1M时,加倍扩容;超过1M每次只多扩1M;

字符串最大长度为512M。

常用操作:

# 设置 key 的 value 值
SET key val
# 获取 key 的 value
GET key

# 执行原子加一的操作
INCR key
# 执行原子加一个整数的操作
INCRBY key increment

# 执行原子减一的操作
DECR key
# 执行原子减一个整数的操作
DECRBY key decrement

# 如果key不存在,这种情况下等同SET命令。 当key存在时,什么也不做
SETNX key value
# 删除 key val 键值对
DEL key

# 设置或者清空key的value(字符串)在offset处的bit值。
SETBIT key offset value
# 返回key对应的string在offset处的bit值
GETBIT key offset
# 统计字符串被设置为1的bit数.
BITCOUNT key

string存储结构:

如图所示: 

                        * 当string长度小于等于20,且可以转换为整数时,使用int类型存储

                        * 当string长度小于等于44时,使用embstr存储

                        * 当string长度大于44,使用raw存储

思考:为什么使用44为边界(注:redis3.2以前的版本,边界值是39)?这么做有什么好处?

//server.h
typedef struct redisObject {
    unsigned type:4;
    unsigned encoding:4;
    unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
                            * LFU data (least significant 8 bits frequency
                            * and most significant 16 bits access time). */
    int refcount;
    void *ptr;
} robj;

//sds.h 大于等于3.2版本
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[];
};

// 小于3.2版本
struct sdshdr {
    unsigned int len;
    unsigned int free;
    char buf[];
};

//object.c
/* Create a string object with EMBSTR encoding if it is smaller than
 * OBJ_ENCODING_EMBSTR_SIZE_LIMIT, otherwise the RAW encoding is
 * used.
 *
 * The current limit of 44 is chosen so that the biggest string object
 * we allocate as EMBSTR will still fit into the 64 byte arena of jemalloc. */
#define OBJ_ENCODING_EMBSTR_SIZE_LIMIT 44

robj *createStringObject(const char *ptr, size_t len) {
    if (len <= OBJ_ENCODING_EMBSTR_SIZE_LIMIT)
        return createEmbeddedStringObject(ptr,len);
    else
        return createRawStringObject(ptr,len);
}

 从redis源码中可以看到,“The current limit of 44 is chosen so that the biggest string object we allocate as EMBSTR will still fit into the 64 byte arena of jemalloc.”

即EMBSTR适用于redis的内存分配器jemalloc的64字节的分配管理区域arena,也就是说和和jemalloc的机制相关。x64系统中,sizeof(redisObject) = (4+4+24)/8 +4 + 8 = 16 byte, 对于字符串类型,ptr指向sdshdr8结构体,sizeof(sdshdr8) = 1 + 1 +1 + X +1 = 4 byte,此处 X 的最大值就是44 byte。

redis 内存分配器认为 大于 64个字节为大字符串;所以留给小字符串的大小为 64 - 16 - 3 - 1 = 44 (小于3.2版本:64 - 16 - 4 - 4 - 1 = 39) ;

这么做的好处:

查看createStringObject函数可知:

1.embstr申请或释放内存,只需要一次操作(一次性分配 robj *o = zmalloc(sizeof(robj)+sizeof(struct sdshdr8)+len+1); ),而raw需要两次(一次为raw分配sdshdr对象,另一次为redisObject分配对象(ptr指向sds对象))

2.embstr是内存连续的,读写更高效

 

应用场景:

累加器:

# 统计阅读数 累计加1
incr reads
# 累计加100
incrby reads 100

分布式锁(该方式不安全,不推荐使用),分布式锁是一个很大的课题,此处不扩展了。

# 加锁
setnx lock 1
# 释放锁
del lock

位运算

# 月签到功能 10001 用户id 202106 2021年6月份的签到 6月份的第1天
setbit sign:10001:202106 1 1

# 计算 2021年6月份 的签到情况
bitcount sign:10001:202106

# 获取 2021年6月份 第二天的签到情况 1 已签到 0 没有签到
getbit sign:10001:202106 2

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值