铁佛 发表于 2024-9-26 17:21:56

[Redis][String][下]详细解说

1.其他命令

1.APPEND



[*]功能:

[*]如果key已经存在而且是⼀个string,命令会将value追加到原有string的后边
[*]如果key不存在, 则效果等同于SET命令。

[*]语法:APPEND KEY VALUE
[*]时间复杂度:                                        O                            (                            1                            )                                  O(1)                     O(1),追加的字符串⼀般⻓度较短,可以视为                                        O                            (                            1                            )                                  O(1)                     O(1)
[*]返回值:追加完成之后string的⻓度(单位是字节)
2.GETRANGE



[*]功能:返回key对应的string的⼦串,由start和end确定(左闭右闭)

[*]可以使⽤负数表⽰倒数:-1代表倒数第⼀个字符,-2代表倒数第⼆个,其他的与此雷同
[*]超过范围的偏移量会根据string的⻓度调整成精确的值
[*]注意:如果字符串中保存的是汉字,此时举行字串切分,切出来的很可能不是完成的汉字

[*]语法:GETRANGE key start end
[*]返回值:string类型的字串
[*]时间复杂度:                                        O                            (                            N                            )                                  O(N)                     O(N),N为区间的⻓度,由于string通常⽐较短,可以视为是O(1)
3.SETRANGE



[*]功能:覆盖字符串的⼀部分,从指定的偏移开始

[*]注意:针对不存在的key,也可以操纵,不过会把offset之前的内容填充成0x00

[*]语法:SETRANGE key offset value
[*]返回值:更换后的string的长度
[*]时间复杂度:                                        O                            (                            N                            )                                  O(N)                     O(N),N为value的⻓度,由于string通常⽐较短,可以视为是O(1)
4.STRLEN



[*]功能:获取key对应的string的长度,当key存放的类型不是string时,报错
[*]语法:STRLEN key
[*]返回值:

[*]string的⻓度
[*]当key不存在时,返回0

[*]时间复杂度:                                        O                            (                            1                            )                                  O(1)                     O(1)
2.内部编码



[*]字符串类型的内部编码有3种

[*]int:8个字节的长整形
[*]embstr:小于即是39个字节的字符串
[*]raw:大于39个字节的字符串

[*]Redis会根据当前值的类型和长度动态决定利用哪种内部编码实现
# 整形
> set key 2333
OK
> object encoding key
"int"

# 短字符串
> set key "hello"
OK
> object encoding key
"embstr"

# ⼤于39个字节的字符串
> set key "one string greater than 39 bytes ........"
OK
> object encoding key
"raw
3.典范利用场景

1.缓存(Cache)功能



[*] 典范缓存利用场景:Redis作为缓冲层,MySQL作为存储层,绝⼤部分请求的数据都是从Redis中获取。由于Redis具有⽀撑⾼并发的特性,以是缓存通常能起到加速读写和低沉后端压⼒的作⽤
https://i-blog.csdnimg.cn/direct/8915b610500147ad977798ac9a06824f.png
[*] 模仿以上业务数据访问过程:

[*]根据用户uid获取用户信息UserInfo GetUserInfo(long uid) { ... }

[*]先从Redis获取用户信息,假设用户信息保存在"user:info:<uid>对应的键中// 根据uid得到Redis的键
String key = "user:info:" + uid;

// 尝试从Redis中获取对应的值
String value = Redis 执⾏命令: get key;

// 如果缓存命中(hit)
if(value != null)
{
        // 假设⽤⼾信息按照JSON格式存储
        UserInfo userInfo = JSON 反序列化 (value);
        return userInfo;
}

[*]如果没有从Redis中得到⽤⼾信息,及缓存miss,则进⼀步从MySQL中获取对应的信息,随后写⼊缓存并返回// 如果缓存未命中(miss)
if (value == null)
{
        // 从数据库中,根据 uid 获取⽤⼾信息
        UserInfo userInfo = MySQL 执⾏ SQL:
                                                select * from user_info where uid = <uid>

        // 如果表中没有 uid 对应的⽤⼾信息
        if (userInfo == null)
        {
                响应404
                return null;
        }

        // 将⽤⼾信息序列化成 JSON 格式
        String value = JSON 序列化 (userInfo);

        // 写⼊缓存,为了防⽌数据腐烂(rot),设置过期时间为 1 ⼩时(3600秒)
        Redis 执⾏命令: set key value ex 3600

        // 返回用户信息
        return userInfo;
}


[*] 通过增长缓存功能,在理想情况下,每个⽤⼾信息,⼀个⼩时期间只会有⼀次MySQL查询,极⼤地提升了查询效率,也低沉了MySQL的访问数
[*] 注意:

[*]与MySQL等关系型数据库不同的是,Redis没有表、字段这种命名空间,⽽且也没有对键名有强制要求(除了不能使⽤⼀些特别字符)
[*]但**计划公道的键名,有利于防⽌键冲突和项⽬的可维护性**,⽐较推荐的⽅式是使⽤"业务名:对象名:唯⼀标识:属性"作为键名

[*]例如:MySQL的数据库名为vs,⽤⼾表名为user_info

[*]那么对应的键可以使⽤ “vs:user_info:2333"、"vs:user_info:2333:name” 来表⽰
[*]如果当前Redis只会被⼀个业务使⽤,可以省略业务名"vs:"


[*]如果键名过长,则可以使⽤团队内部都认同的缩写更换

[*]例如:"user:2333:friends:messages:6666"可以被"u:2333:fr:m:666"代替
[*]毕竟键名过⻓,照旧会导致Redis的性能显着下降的


2.计数(Counter)功能



[*] 很多应⽤都会使⽤Redis作为计数的基础⼯具,它可以实现快速计数、查询缓存的功能,同时数 据可以异步处理或者落地到其他数据源
https://i-blog.csdnimg.cn/direct/60e9fb6723cd4291bb42d9b2691d78d2.png
[*] 示例:在Redis中统计某视频的播放次数
long IncrVideoCounter(long vid)
{
        key = "video:" + vid;
        long count = Redis 执⾏命令:incr key
        return counter;
}

注意:实际中要开发⼀个成熟、稳定的真实计数体系,要⾯临的挑衅远不⽌如此简朴:防作弊、按 照不同维度计数、制止单点题目、数据长期化到底层数据源等
3.共享会话(Session)



[*] 为什么?:⼀个分布式Web服务将⽤⼾的Session信息(例如⽤⼾登录信息)保存在各⾃的服务器中,但如许会造成⼀个题目:出于负载平衡的考虑,分布式服务会将⽤⼾的访问请求平衡到不同的服务器上,而且通常⽆法包管⽤⼾每次请求都会被平衡到同⼀台服务器上,如许当⽤⼾刷新⼀次访问是可能会发现需要重新登录,这个题目是⽤⼾⽆法容忍的
https://i-blog.csdnimg.cn/direct/3994bf39561b4e42b2223605addc111f.png
[*] 题目解决:使⽤Redis将⽤⼾的Session信息进⾏集中管理,在这种模式下,只要包管Redis是⾼可⽤和可扩展性的,⽆论⽤⼾被平衡到哪台Web服务器上,都集中从Redis中查询、更新Session信息
https://i-blog.csdnimg.cn/direct/016fdc7645034405ae3258dac412ecc3.png
[*] 示例:手机验证码
String SendCapcha(String phoneNumber)
{
        key = "shortMsg:limit:" + phoneNumber;

        // 设置过期时间为1分钟
        // 使用NX,只在不存在key时才能设置成功
        bool r = Redis 执行命令:set key ex 60 nx
        if(r == false)
        {
                // 说明之前设置过该手机的验证码了
                long c = Redis 执行命令:incr key
                if(c > 5)
                {
                        // 说明超过一分钟5次的限制了
                        // 限制发送
                        return null;
                }
        }

        // 说明要么之前没有设置过⼿机的验证码;要么次数没有超过 5 次
        String validationCode = ⽣成随机的 6 位数的验证码 ();

        validationKey = "validation:" + phoneNumber;
        // 验证码 5 分钟内有效
        Redis 执⾏命令: set validationKey validationCode ex 300;

        // 返回验证码,随后通过手机短信发送给用户
        return validationCode;
}

// 验证用户输入的验证码是否正确
bool VerifyCode(phoneNumber, validationCode)
{
        validationKey = "validation:" + phoneNumber;

        String value = Redis 执⾏命令: get validationKey;
        if(value == null) // 说明没有这个手机的验证码记录,验证失败
        {
                return false;
        }

        if(value == validationCode)
        {
                return true;
        }
        else
        {
                return false;
        }
}


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: [Redis][String][下]详细解说