Redis学习笔记:String内部编码及其应用场景

一、概述

字符串类型是Redis最基础的数据结构,Redis中的键都是字符串类型,其他几种数据结构都是在字符串基础之上构建的;

字符串类型的值实际可以是字符串(如简单的字符串、JSON、XML),数字(整型、浮点数),也可以是二进制(图片、音频、视频),但是值的最大不能超过512MB。

二、常用命令

  1. 设置值:

set key value [ex seconds] [px milliseconds] [nx | xx]

set命令选项说明:

  • ex seconds:为键设置秒级过期时间
  • px milliseconds:为键设置毫秒级过期时间
  • nx:键必须不存在时,才可以设置成功,用于添加
  • xx:与xx相反,键必须存在,才可以设置成功,用于更新

同时,Redis也提供了 setex 和 setnx两个命令,其作用与ex,nx选项一样,但在实际应用中需要注意,当同时用到ex和nx机制时,要尽可能地使用set ex nx的组合命令,而不能拆分成两条setex 和setnx,根据Redis性能测试报告:how fast is redis,Redis执行一条指令的并发量约为7w,当同时使用setnx和setex而不使用set ex nx组合命令时,Redis的并发量相当于减少了一半,这点是应用当中的细节部分,需要铭记。

当然,setmx和setex也有其优点和对应的应用场景,以setnx为例,由于Redis的单线程命令处理机制,如果多个客户端同时执行setnx key value,根据setnx的特性,只有一个客户端能设置成功,setnx可以作为分布式锁的一种实现方案,Redis官方废除了使用setnx实现分布式锁的方法:

  1. 获取值:
  • 获取单个值:get key,如果获取的键不存在,则返回nil(空)
  • 批量获取值:mget key [key]...,批量操作命令可以提高开发效率,学会合理使用批量操作,有助于提高业务处理效率,但是并不是说批量操作是无节制的,如果key数量过多,很可能造成Redis阻塞或者网络拥塞。
  1. 计数:

incr key:用于对值做自增操作,返回结果分为3种情况:

  • 值不是整数,返回错误;
  • 值是整数,返回自增后的结果;
  • 键不存在,按照值为0自增,返回结果为1;
    例如,对一个不存在的键执行Incr操作,返回结果为1;

除了自增命令外,Redis还提供了decr(自减)、incrby(自增指定数字)、decrby(自减指定数字)、incrbyfloat(自增浮点数):

decr key
incrby key increment
decrby key decrement
incrbyfloat key increment

在Java里面可以使用CAS(compare and swap)机制来实现计数功能,但会有一定的CPU开销(线程安全,通过硬件上的阻塞来实现软件上的非阻塞,再次基础上可以拓展出AQS机制),在Redis中不存在CPU开销问题,因为Redis是单线程架构,任何命令都在Redis服务端上顺序执行。

  1. 其他命令:
del key:删除key;
mset key value [key value ...]:批量设置键值;
append key value:向字符串尾部追加值;
strlen key:字符串长度;
getset key value:设置并返回原值;
setrange key offeset value:设置指定位置的字符;
getrange ket start end:获取部分字符串

三、内部编码

字符串类型的内部编码有3种:

  • int:8个字节的长整型;
  • embstr:小于等于39个字节的字符串;
  • raw:大于39个字节的字符串;

Redis会根据当前值的类型和长度决定使用哪种内部编码实现。

四、应用场景

Redis字符串应用场景非常广泛,这里列举几个比较常见的应用场景:

  1. 缓存功能:
    使用Redis作为缓存在业界应用非常地广泛,常常与memcache做比较,关于其选型,可参考该文章:技术选型:Redis还是memcache
    Redis作为缓存设计的架构图大致如下,Redis作为缓存层,MySQL最为存储层,绝大部分请求的数据都是从Redis中获取,用于Redis具有支撑高并发的特性,所以缓存通常能加速读写和降低后端压力。
缓存设计.png

实现思路:首先定义一个方法用于获取用户的基础信息,当请求到来时,优先从Redis中获取用户信息,如果命中缓存则直接返回结果,如果不命中缓存,则从MySQL中获取数据,同时将结果写入Redis缓存中,并添加过期时间,一种可能的实现(伪代码)如下:

public UserInfo getUserInfo(long id){
   userRediskey = "user:info:" +id;
   value = redis.get(userRediskey);
   UserInfo userInfo;
   if(value != null){
     userInfo = deserialize(value);
   }else{
     userInfo = mysql.get(id);
   if(userInfo != null){
     redis.setnx(userRediskey,3600,serialize(userInfo));
   }
 }
   return userInfo;
}
  1. 分布式session共享:

在分布式应用中,一个亟需解决的问题便是session的一致性问题,分布式web服务将用户的session信息(如:登录信息)保存在各自服务器上,这样会造成一个问题,出于负载均衡的考虑,分布式服务会将用户的访问均衡到不同的服务器上,用户刷新一次访问可能会发现需要重新登录,这个问题对于用户来说是不可容忍的。

为解决这个问题,可以使用Redis将用户的session进行集中管理,如下图所示,在这种模式下,只要保证Redis是高可用和扩展性的,每次用户更新或者查询登录信息都直接从Redis中集中获取。

分布式session.png
  1. 计数器:

Redis还可以作为计数的基础工具,实现快速计数、查询缓存的功能,同时数据可以异步落地到其他数据源,如视频播放量、文章阅读量的记录,一种可能的简单实现如下:

public long incrVideoCounter(long id){
   key = "video:playCount:" + id;
   return redis.incr(key);
}

实际上,一个真实的计数系统还要考虑:防作弊、不同维度计数、数据持久化等问题。

  1. 限速:

出于安全考虑(防脚本),很多应用会在每次进行登录时,会让用户输入手机验证码,从而确定是否是用户本人,短信接口会限制用户每分钟获取验证码的频率,如一分钟内不超过5次,一种可能的实现如下:

iphoneNum = "138xxxxx";
key = "shortMsg:limit:" +phoneNum;
//set key value EX 60 NX
isExists = redis.set(key,1,"EX 60","NX");
if(isExists != null || redis.incr(key)<=5){
 //pass,通过
}else{
 //wait,限速
}
  1. 总结:Redis的应用场景非常广,远不止以上列出的几种,更多的功能设计仍需要结合业务去挖掘。

感谢阅读~~

参考资料:


《Redis开发与运维》付磊、张益军[著]

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343