redis(1)-基础知识

redis是单进程单线程进行工作的,通过维护一个内部的FIFO(先进先出)队列进行指令的顺序执行,所以对于redis本身来说是不存在并发问题的。redis本身是一个Map的数据结构,所有的数据类型都是Key:Value形式进行存储,Key只能是String类型的。

数据类型

  • String:基本的字符串类型支持,单个key对应的值最大存储空间为512M(一般不会存这么大的值,很占用内存空间)。如果要使用String类型储存对象,可以将对象转换成JSON格式的字符串后进行存储,比较适合整体读一个对象,如果需要将对象中的某一个字段进行写操作,则需要将整个对象先读出来更新对应的字段值后,再将整体的对象重新放入redis中。常用命令:
    1. set、get、del、mset(批量set)、mget(批量get)、append(追加内容)。
    2. incr(原子性加)、incrby、incrbyfloat、decr(原子性减)、decrby,原子性操作命令,将指定key的值进行原子性的加减1或者自定应加减N(默认为1,incrby/decrby指定自定义加减数值)。
    3. setnx,当指定的key不存在时才set,可以用来做分布式锁的实现(set成功则说明拿到锁,执行完业务逻辑后主动将加锁的key删除进行锁释放,由于拿到锁的客户端有可能出现异常或其他原因未能主动删除key,导致锁一直被占用不能释放,所以一般会在执行setnx的时候设置一个key的自动过期时间,用来防止锁一直被占用)。
  • Hash:Hash类型的value中存放的也是一个Map结构,但是这个Map只能有一层(即:这个Map中的value只能是String类型的)。相对于String来说,hash存储的都是对象类型,如果需要更新某个字段值时,不需要像String一样操作,直接更新指定的某个字段值就行。常用命令:
    1. hset、hget(指定获取某个对象下的某个字段)、hgetall(获取某个对象的所有字段,返回的是Map结构)、hdel(删除某个对象的指定字段)。
    2. hmset(批量设置某个对象的字段)、hmget(批量获取某个对象的字段)、hlen(对象的字段数量)、hexists(判断某个对象下是否存在指定的字段)。
    3. hkeys(获取某个对象的所有key)、hvals(获取某个对象的所有value)、hincrby(对某个对象的指定字段进行原子性加减操作,需要指定操作的值,减时值前面加-)、hincrbyfloat。
  • List:保存多个String类型的数据,底层使用双向链表的存储结构进行实现,基于双向链表的特性,可以实现FIFO(先进先出,从一边进,从另一边出)、LIFO(后进先出,从哪边进就从哪边出,类似于栈)的队列。常用命令:
    1. lpush(从左边添加一个元素)、rpush(从右边添加一个元素)。
    2. lrange(范围查找,开始位置为0,结束位置为-1时表示查到list的最后一个元素)。
    3. lindex(根据list的数据下标查找值)、llen(获取list的长度)
    4. lpop(获取并删除左边的第一个元素)、rpop(获取并删除右边的第一个元素)。
    5. blpop、brpop(阻塞型获取值,可以设阻塞的超时时间,list中无值取时阻塞等待,直到超时或者取到值才结束),可以用来实现阻塞型的任务队列。
    6. lrem,从队列中移除指定的值,因为值是可以重复的,则可以设置需要移除的值的个数。
  • Set:保存多个String类型的数据,跟List的数据结构不一样,其内部是Hash的存储结构(但是只储存Key,value值不存储,永恒为空(nil)),所以Set中的元素是不会重复的。相比较于List,Set查询速度更快,但是List插入、删除速度更快。常用命令:
    1. sadd(增加元素)、smembers(获取Set中的所有元素)、srem(删除Set中指定的值)。
    2. scard(Set中的元素个数)、sismember(判断某个值是否存在)。
    3. srandmember(只获取)、spop(获取之后从Set集合中移除),随机获取Set集合中指定个数的元素,可以应用于随机推荐需求场景。
    4. sinter、sunion、sdiff,求二个集合的交、并、差集。
    5. sinterstore destination、sunionstore destination、sdiffstore destination,求二个集合的交、并、差集并将结果存储到指定集合。
    6. smove source destination [member],将指定数据从原始集合中移动到目标集合。
  • sorted_set:带有排序的数据集合,在Set类型的存储结构上添加可排序字段score,重复添加值时会更新score值,value值不会更新。常用命令:
    1. zadd [key] [score1] [member1],为指定key添加元素,并为每个元素指定排序值score
    2. zrange [key] [start] [stop] [WITHSCORES],按照升序查找指定位置区间的值。
    3. zrevrange [key] [start] [stop] [WITHSCORES],按照降序查找指定位置区间的值。
    4. zrem [key] [member],删除指定key的某个元素。
    5. zcount [key] [min] [max](统计key中指定最小到最大区间的元素个数),zcard [key](统计key的元素个数)。
    6. zrangebyscore [key] [min] [max] [WITHSCORES] [LIMIT offset count](按照score值升序获取指定区间的匹配数据),zrevrangebyscore [key] [max] [min] [WITHSCORES] [LIMIT offset count](按照score值降序获取指定区间的匹配数据)。
    7. zremrangebyrank [key] [start] [stop](根据索引位置区间删除指定key的匹配数据),zremrangebyscore [key] [min] [max](根据score值区间删除指定key的匹配数据)。
  • Bitmaps:计算机中最小单位是位(Java中最小单位是字节,一个字节占8位),通过在二进制位中存储0或1的状态来管理是与否的状态值。在缓存穿透场景中使用的解决方案布隆过滤器的实现原理就是类似这种方式。

持久化

  • RDB:以快照的方式进行数据持久化,当服务器出现故障时会导致在一定时间内的数据丢失(根据业务场景及配置的不同,可能是1分钟,也可能是几分钟或十几分钟),由于是直接备份的内存快照,所以恢复数据的速度会很快。redis默认采用bgsave形式进行持久化(bgsave通过fork一个子进程执行数据备份,所以是后台执行,不会阻塞当前的redis线程进行其他操作),可以在conf文件中使用save [second] [changes]配置在多长时间内有多少个值变化则执行一次bgsave操作来管理执行间隔。
  • AOF:操作日志级别的持久化方式,记录的是一条条的操作指令(类似于MySql的归档日志),恢复数据的时候需要将备份的指令一条一条的执行,所以恢复数据的速度要慢一些,但是由于AOF的持久化特性(写数据时持久化数据的三种策略),当服务器出现故障时,最多只会丢失一秒钟的数据。
    1. always,每次写数据都同步进行持久化,写的频次高,IO性能占用较大。
    2. everysec,每秒钟执行一次持久化,在这一秒钟之内的写指令都会被放入一个缓冲区中,时间到了则将缓冲区中的指令一次性全部写入备份磁盘,这种策略也是AOF的默认配置策略。
    3. no,交由系统自由控制,这种策略会有一定的不可控因素,一般不建议使用。
  • AOF指令重写
    由于AOF持久化备份的是写操作的指令,在那些连续设置某个key的值的场景下,对于恢复数据而言,是可以只保留这批连续指令当中的最后一个指令的,所以redis就针对于AOF持久化提供了指令重写的功能。指令重写的执行原理和RDB模式的bgsave操作类似,都是fork一个子进程在后台进行操作。AOF重写的触发类型:
    1. 手动重写,执行指令bgrewriteaof
    2. 自动重写,通过配置项auto-aof-rewrite-min-size [size](根据当前aof文件大小判断是否达到了设置值,默认为64M,即aof文件最小要达到64M才触发指令重写)、auto-aof-rewrite-percentage [percent](根据当前文件大小(aof-current-size)和上一次重写后aof文件大小(aof-base-size)的比值进行触发),aof-current-size和aof-base-size的大小可以通过info命令进行查看。

事务

  • multi,设定事务的开启位置,后续的所有指令均加入该事务中(将整个事务中的指令放入一个任务队列,并没有立即执行)。
  • exec,设定事务的结束位置,同时执行事务(将整个事务队列按放入的顺序全部执行),一般与multi成对使用。如果某个指令语法错误,则取消整个事务。如果某个指令没有语法错误,但是运行错误,则整个事务中运行正确的指令会执行成功、运行错误的指令会执行失败。
  • discard,取消事务,销毁事务队列。
  • watch,在开启事务前,可以设置监控指定的key,如果在提交事务时被监控的某个值发生了变化(可以同时监控多个key),则事务会执行失败(相当于在事务开启之前加了把锁,在提交事务的时候需要这个值还是以前的值,有点类似于JUC的CAS)。

删除策略

在redis中单独有个Map结构来存储设置了过期时间的key信息(这个Map的key为设置了过期时间的key的内存地址,value为过期的这个时间),redis的过期删除主要就是维护的这个Map结构的数据(每一个库里面都有这个Map结构)。

  • 定时删除:通过定时器,key到期了就直接删除(可以如果设置了过期时间,则相应的开启一个定时器)。
  • 惰性删除:在get时如果发现key过期了就删除(如果key过期之后一直没有执行get进行获取,则该数据会一直在内存中不会被删除),redis中所有get操作之前都会调用expireIfNeeded()来判断这个key是否已经过期了。
  • 定期删除:通过周期性轮询每个数据库(redis一共有16个数据库)进行随机检查删除,可以通过server.hz配置每秒执行多少次定时轮询(默认是10次),在redis中同时使用了惰性删除和定期删除二中策略。
  • 逐出算法:当新数据进入redis时,如果内存不足,则会使用逐出算法清理内存空间。通过配置项maxmemory(最大可使用内存,默认为0,即不限制)、maxmemory-samples(每次通过删除策略选取待删除数据的个数)、maxmemory-policy(当达到最大使用内存时,挑选删除数据的策略)来控制逐出算法的具体操作。
    1. volatile-lru,最长时间不适用的数据,推荐使用这个策略
    2. volatile-lfu,最少使用次数
    3. volatile-ttl,挑选将要过期的数据
    4. volatile-random,随机选择数据淘汰
    5. no-enviction,放弃数据驱逐(即不淘汰数据),会报OOM,是redis4.0中的默认策略。

缓存命中率

在redis中会自动统计缓存命中次数及未命中次数信息,可以通过info命令进行查看。

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