中间件系列1 Redis

参考《Java EE 互联网轻量级框架整合开发》相关章节

一.Redis概述

1.适用场景
  • 传统关系型数据库无法满足高并发场景(如商品抢购、主页瞬间大量访问)的需要
  • Redis适用于缓存场景,现实场景中读操作远多于写操作,80%的读取集中在20%的数据
  • Redis适用于高速读/写场景,将高速读/写的数据缓存到Redis,满足一定条件后再写入数据库
2.Redis性能优势
  • 基于ANSI C语言编写,接近于汇编语言的机器语言,运行速度快
  • 基于内存的读/写,比磁盘IO快
  • 数据库结构比较简单(只有6种数据类型),规则较少
3.NoSQL与传统数据库
  • NoSQL使用内存存储数据,传统数据库使用磁盘
  • NoSQL数据结构比较简单,功能有限,不如传统数据库的SQL语句强大
  • NoSQL基于内存,持久化能力受外部条件影响,不如基于磁盘的传统数据库
  • NoSQL数据完整性、事务能力、安全性、可靠性及可扩展性都远不及传统数据库
  • NoSQL短期内难以取代传统数据库,但能够作为提高互联网应用性能的辅助工具

二.Redis数据结构和常用命令

1.字符串
  • Redis最基本的数据结构,以键值对的形式存储于Redis内部,Redis通过键查找值
  • Redis字符串基本命令
命令 说明 备注
set key value 设置键值对
get key 通过键获取值
del key 通过键删除键值对 返回删除的键值对个数
strlen key 求key指向字符串的长度 返回长度
getset key value 修改原key对应的值,并返回原值 若原值为空则返回空
getrange key start end 获取子串 返回(start,end)截取的字符串
append key value 将新value加入到key指向的value末尾 返回拼接后value的长度
  • 如果字符串是数字(整数或浮点数),Redis还能支持简单的加减运算
命令 说明 备注
incr key 原字段加1 限整数
incrby key increment 原字段加整数(increment) 限整数
decr key 原字段减1 限整数
decrby key decrement 原字段减整数(decrement) 限整数
incrbyfloat key increment 原字段加浮点数(increment) 整数或浮点数
2.哈希
  • Redis中hash是一个String类型的field和value的映射表,一个哈希里有许多键值对,适合存储对象
  • Redis哈希常用命令
命令 说明 备注
hdel key field1 [field2...] 删除hash结构中的某字段 可同时删除多个字段
hexists key field 判断hash结构中是否存在field字段 存在返回1,否则返回0
hgetall key 获取hash结构中所有键值
hincrby key field increment hash结构的指定字段加上一个整数 要求该字段本身为整数字符串
hincrby float key field increment hash结构的指定字段加上一个浮点数 要求该字段本身为数字型字符串
hkeys key 返回hash中所有键
hvals key 返回hash中所有值
hlen key 返回hash中键值对的数量
hmget key field1 [field2 ...] 返回hash中指定键的值,可以是多个键 依次返回值
hmset key field1 value1 [field2 value2 ...] hash设置多个键值对
hset key field value hash设置单个键值对
hsetnx key field vaule 当hash结构中不存在对应的键,才设置值
3.链表(linked-list)
  • Redis链表底层是双向链表
  • 便于增删但不便于查询
  • 因为是双向链表结构,所以Redis链表命令分为左操作和右操作两种,常见链表命令如下
命令 说明 备注
lpush key node1 [node2...] 把node1加到链表最左边
rpush key node1 [node2...] 把node1加到链表最右边
lindex key index 读取下标为index的节点 返回节点字符串
llen key 求链表的长度 返回链表节点数
lpop key 删除左边第一个节点,并将其返回
rpop key 删除右边第一个节点,并将其返回
insert key before/after pivot node 在节点pivot的前/后插入node节点 如果list不存在,则报错;如果没有值为pivot的节点,将插入失败返回-1
lpushx list node 如果存在key为list的链表,则从左边插入节点node 如果list不存在,则失败
rpushx list node 如果存在key为list的链表,则从右边插入节点node 如果list不存在,则失败
Irange list start end 获取链表list从start下标到end下标的节点值 包含start和end下标
lrem list count value 如果count为0,则删除所有值等于value的节点;若count不为0,则从左到右删除不大于count绝对值数目值为value的节点
lset key index node 设置列表下标为index的节点的值为node
ltrim key start stop 修剪链表,只保留从start到stop区间的节点 包含start和end下标
  • 上述命令未对Redis的链表加锁,在多个Redis客户端同时操作同一链表时将造成并发数据安全和一致性问题,Redis提供链表的阻塞命令以保障链表操作的安全性
命令 说明 备注
blpop key timeout 移出并获取链表的第一个元素,如果链表没有元素会阻塞链表直到等待超时或发现可弹出元素为止 相对于lpop命令线程安全
brpop key timeout 移出并获取链表的最后一个元素,如果链表没有元素会阻塞链表直到等待超时或发现可弹出元素为止 相对于rpop命令线程安全
rpoplpush key src dest 将原链表最右边一个元素移除,并插入目标链表最左边 不能设置超时时间
brpoplpush key src dest timeout 将原链表最右边一个元素移除,并插入目标链表最左边,可以设置超时时间
4.集合
  • Redis集合是一个哈希表结构,插入、删除和查找的复杂度都是O(1)
  • 集合是无序、不可重复的,集合的每一个元素都是String数据结构类型
  • Redis集合可对两个或多个集合求交集、差集和并集,常用命令如下
命令 说明 备注
sadd key member1 [member2 member3 ...] 给集合key增加成员 可以同时增加多个
srem key member1 [member2 ...] 移除集合key的元素
scard key 统计集合key的成员数
sdiff key1 [key2] 找出两个集合的差集 参数如果只有一个集合,则返回这个集合的所有元素
sdiffstore des key1 [key2] 找出两个集合的差集,并保存在集合des中
sinter key1 [key2] 求集合key1和集合key2的交集 参数如果只有一个集合,则返回这个集合的所有元素
sinterstore des key1 key2 求集合key1和集合key2的交集并保存到des
sismember key member 判断member是否为集合key的成员 是返回1,否返回0
smembers key 返回集合key的所有成员 数据量大时需考虑迭代遍历
smove src des member 将成员member从集合src迁移到集合des
spop key 随机弹出集合key的一个元素
srandmember key[count] 随机返回集合key的一个或多个元素 count为整数,不填默认为1,负数取绝对值,count大于集合元素总数时返回整个集合
sunion key1 [key2] 求集合key1和集合key2的并集
sunionstore des key1 key2 求并集并将结果保存到键为des的集合
5.有序集合
  • Redis有序集合和集合类似,通过哈希表实现,添加、删除、查找的时间复杂度均为O(1)
  • 区别在于每个元素除了值之外,还多一个分数,Redis根据分数进行排序
命令 说明 备注
zadd key score1 value1 [score2 value2 ...] 给有序集合key增加成员 如果不存在有序集合key,则自动创建
zcard key 统计有序集合key的成员数
zcount key min max 根据分数返回对应的成员列表 分数在最小值min与最大值max间
zincrby key increment member 给有序集合成员值为member的分数增加increment
zinterstore desKey numkeys key1 [key2 key3 ...] 求多个有序集合的交集并存入desKey
zlexcount key min max 求有序集合key成员值在min和max的范围集合
zrange key start stop [withscores] 按照分值的大小从小到大返回成员,start和stop参数可截取某一段返回,若输入可选项withscores则连同分数一起返回
zrank key member 按从小到大求有序集合的排行
zrangebylex key min max [limit offset count] 根据值的大小,从小到大排序,min和max为最小/最大值,Redis求出范围集合后根据偏移量offset和限定返回数count返回对应的成员
zrangebyscore key min max [withscore] [limit offset count] 根据分数的大小,从小到大排序,min和max为最小/最大值,Redis求出范围集合后根据偏移量offset和限定返回数count返回对应的成员
zremrangebyscore key start stop 根据分数区间进行删除
zremrangebyrank key start stop 按照分数排行从小到大的顺序删除
zremrangebylex key min max 按照值得分布进行删除
zrevrange key start stop [withscores] 从大到小按分数排序,参数参照zrange
zrevrangebyscore key max min [withscores] 从大到小按分数排序,参数参见zrangebyscore
zrevrank key member 按从大到小顺序求元素的排行
zscore key member 返回成员的分数值
zunionstore desKey numKeys key1 [key2 key3 key4...] 求多个有序集合的并集 numKeys是有序集合的个数
6.基数(HyperLogLog)
  • 基数并不存储元素,存储元素需要较大内存空间
  • 基数用于给某个有重复元素的数据集合评估需要的空间单元数(即数据集合中不重复的元素数量)

三. Redis事务

1.概述
  • 在多个客户端同时向Redis系统发送命令的时候,同一个数据同时可能被不同线程操纵,产生并发下的数据一致性问题
  • Redis通过事务解决并发场景的数据安全问题,事务使用Multi-Exec命令组合
    1)事务是一个被隔离的操作,事务中的方法都会被Redis进行序列化并按顺序执行,事务在执行过程中不会被其他客户端发出的命令所打断
    2)事务是一个原子性操作,要么全部执行,要么全部不执行
2.事务过程
  • Redis事务将经历3个过程
    1)开启事务
    2)命令进入队列
    3)执行事务

  • 事务命令

命令 说明 备注
multi 开启事务,之后的命令进入队列,但不会立刻执行
watch key1 [key2...] 监听某些键,当被监听的键在事务执行前被修改,则事务将被回滚 乐观锁机制
unwatch key1 [key2...] 取消监听的键
exec 执行事务,但如果被监听的键发生改变,则执行回滚 执行事务队列存储的命令前,Redis会检测被监听的键值对有没有发生变化
discard 回滚事务 回滚后的事务不能再提交
  • 事务执行流程示例
时刻 客户端1 客户端2 说明
T1 set key1 value1 客户端1:返回OK
T2 watch key1 客户端1:监控key1
T3 multi 客户端1:开启事务
T4 set key2 value2 客户端1:事务命令入列
T5 - set key1 value1 客户端2:修改key1的值
T6 exec - 客户端1:执行事务,执行前检测到key1的值被其他命令修改过,所以将进行回滚
3.流水线(pipelined)
  • Redis通过事务提供队列,作为一个可以批量执行任务的队列,但使用事务会检测对应的锁和序列化命令,存在系统开销
  • Redis提供流水线技术,用来在没有任何附加条件的场景下使用队列批量执行一系列的命令,从而提高系统性能
  • 应用场景
    1)Redis执行读/写速度非常快,系统的瓶颈往往是网络通信的延时
    2)使用Redis的流水线(本质是一种通信协议),可以有效提高性能
    3)使用流水线产生的返回对象,可能占用服务器上较多的内存空间,导致OOM异常
4.发布订阅
  • 场景
    使用银行卡消费时,银行通过微信、短信或邮件通知用户该笔交易信息
  • 观察者模式
    1)记账系统是消息源,收到交易指令,成功记账后,就会发布消息
    2)要有消息渠道,记账系统通过消息渠道向订阅者发布消息
    3)要有订阅者(微信、短信、邮件等系统)订阅消息渠道的消息

四. 超时命令——Redis内存回收

1. Redis键值对的超时
  • 超时命令
命令 说明 备注
persist key 持久化key,取消超时时间
ttl key 查看key的超时时间 以秒计算,-1代表没有超时时间,-2代表不存在key或key已超时
expire key seconds 设置超时时间戳 以秒为单位
expireat key timestamp 设置超时时间点 用unix时间戳确定
pptl key milliseconds 查看key的超时时间戳 以毫秒为单位
pexpire key 设置键值超时的时间 以毫秒为单位
pexpireat key stamptimes 设置超时时间点 以毫秒为单位的unix时间戳
  • Redis的key超时不会被自动回收,而是被标识为已经超时
    1)好处:避免因很大的键值对超时的回收造成卡顿
    2)坏处:被标记为超时而未回收的键值对会占用空间
2. Redis回收机制
  • 定时回收:在某个确定的时间统一回收超时的键值对
    1)可以完全回收超时的键值对
    2)一次性回收的键值对较多时,Redis会停顿影响业务,故定时回收一般在没有业务发生的时刻触发
  • 惰性回收:再次执行访问(get命令)超时的键时回收该键
    1)优点是可以指定回收超时的键值对
    2)缺点是通过get命令指定回收,需要额外执行get操作
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容