Redis 您所在的位置:网站首页 redis中hash存储 Redis

Redis

2024-07-10 06:12| 来源: 网络整理| 查看: 265

Redis五大数据类型 Redis的介绍Redis常用类型stringstring 类型数据的基本操作string 类型数据的扩展操作数据增减操作数据时效性设置string类型数据的一些其他操作 string 类型数据操作的注意事项string 类型应用场景 hashhash 类型数据的基本操作hash 类型数据扩展操作hash 类型数据操作的注意事项hash 类型应用场景电商网站购物车设计与实现商家抢购活动

Redis的介绍

Redis是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件MQ。它支持多种类型的数据结构,如 字符串(string),散列(hashes),列表(list),集合(sets),有序集合(sorted sets)与范围查询,bitmaps,hyperloglogs和地理空间(geospatial)索引半径查询。Redis内置了 复制(replocation),LUA脚本(Lua scripting),LRU驱动事件(LRU eviction),事务(transactions)和不同级别的 磁盘持久化(persistence),并通过 Redis哨兵(Sentinel)和自动分区(Cluster)提供高可用性(high availability)

Redis常用类型 string Stringhash HashMaplist LinkedListset HashSetsorted_set TreeSet

redis 数据存储格式

redis自身是一个Map,其中所有的数据都是采用key:value的形式存储数据类型指的是存储的数据的类型,也就是value部分的类型,key部分永远都是字符串 string 存储的数据:单个数据,最简单的数据存储类型,也是最常用的数据存储类型存储数据的格式:一个存储空间保存一个数据存储内容:通常使用字符串,如果字符串以整数的形式展示,可以作为数字操作使用 string 类型数据的基本操作 添加/修改数据

set key value

获取数据

get key

删除数据

del key

127.0.0.1:6379> set name maomao OK 127.0.0.1:6379> get name "maomao" 127.0.0.1:6379> del name (integer) 1 127.0.0.1:6379> get name (nil) 添加/修改多个数据

mset key1 value1 key2 value2 …

获取多个数据

mget key1 key2 …

获取数据字符串长度(字符串个数)

strlan key

追加信息到原始信息后部(如果原始信息存在就追加,否则新建)

append key value

127.0.0.1:6379> mset k1 a k2 b k3 c OK 127.0.0.1:6379> mget k1 k2 k3 1) "a" 2) "b" 3) "c" 127.0.0.1:6379> set name maomao OK 127.0.0.1:6379> strlen name (integer) 6 127.0.0.1:6379> append hello world (integer) 5 127.0.0.1:6379> get hello "world" 127.0.0.1:6379> append name zhu (integer) 9 127.0.0.1:6379> get name "maomaozhu" string 类型数据的扩展操作 数据增减操作

业务场景

大型企业级应用中,分表操作是基本操作,使用多张表存储同类型数据,但是对应的主键 id 必须保证统一性,不能重复。Oracle 数据库具有 sequence 设定,可以解决该问题,但是 MySQL数据库并不具有类似的机制,那么如何解决?

解决方案

设置数值数据增加指定范围的值

incr key incrby key increment incrbyfloat key increment

设置数值数据减少指定范围的值

decr key decrby key increment

redis本身就是单线程的,所以可以用这种方式解决分布式ID的问题

127.0.0.1:6379> set num 0 OK 127.0.0.1:6379> incr num # 自增1 (integer) 1 127.0.0.1:6379> incr num (integer) 2 127.0.0.1:6379> get num "2" 127.0.0.1:6379> decr num # 自减1 (integer) 1 127.0.0.1:6379> decr num (integer) 0 127.0.0.1:6379> decr num (integer) -1 127.0.0.1:6379> get num "-1" 127.0.0.1:6379> incrby num 10 # 可以设置步长 指定增量 (integer) 9 127.0.0.1:6379> incrby num 10 (integer) 19 127.0.0.1:6379> decrby num 9 (integer) 10 127.0.0.1:6379> incrbyfloat num 2.5 # 小数 "12.5" 127.0.0.1:6379> incrby num 3.5 # incrby只能是int类型 (error) ERR value is not an integer or out of range

string 作为数值操作

string在redis内部存储默认就是一个字符串,当遇到增减类操作incr,decr时会转成数值型进行计算。redis所有的操作都是原子性的,采用单线程处理所有业务,命令是一个一个执行的,因此无需考虑并发 带来的数据影响。注意:按数值进行操作的数据,如果原始数据不能转成数值,或超越了redis 数值上限范围,将报错。 9223372036854775807(java中long型数据最大值,Long.MAX_VALUE)

redis 用于控制数据库表主键id,为数据库表主键提供生成策略,保障数据库表的主键唯一性。适用于所有数据库,且支持数据库集群

数据时效性设置

业务场景

海选投票,只能通过微信投票,每个微信号每 4 小时只能投1票。电商商家开启热门商品推荐,热门商品不能一直处于热门期,每种商品热门期维持3天,3天后自动取消热门。新闻网站会出现热点新闻,热点新闻最大的特征是时效性,如何自动控制热点新闻的时效性。

解决方案

设置数据具有指定的生命周期

setex key seconds value psetex key milliseconds value

设置独立的数据

setnx key value

127.0.0.1:6379> setex tel 10 '123456789' # 设置一个keys的值为num 10秒后过期 OK 127.0.0.1:6379> ttl tel # 生命周期 (integer) 6 127.0.0.1:6379> get tel "123456789" 127.0.0.1:6379> ttl tel (integer) 1 127.0.0.1:6379> get tel (nil) 127.0.0.1:6379> setnx subject 'redis' # 如果key不存在 则创建相应的 (integer) 1 127.0.0.1:6379> setnx subject 'mongodb' # 如果key存在 则创建失败 (integer) 0 127.0.0.1:6379> get subject "redis" 127.0.0.1:6379> psetex zhu 5000 'zhuzhu' # 毫秒 OK 127.0.0.1:6379> ttl zhu (integer) 1 127.0.0.1:6379> get zhu (nil) 127.0.0.1:6379> set k1 v1 OK 127.0.0.1:6379> get k1 "v1" 127.0.0.1:6379> get k4 (nil) 127.0.0.1:6379> msetnx k1 v1 k4 v4 # msetnx 是一个原子性的操作,要么一起成功,要么一起失败 (integer) 0 127.0.0.1:6379> get k4 (nil) 127.0.0.1:6379> get k1 "v1"

redis 控制数据的生命周期,通过数据是否失效控制业务行为,适用于所有具有时效性限定控制的操作

string类型数据的一些其他操作

获取字符串的范围

getrange key start end

替换指定范围的字符串

setrange key offset value

127.0.0.1:6379> set name 'hello,maomao' OK 127.0.0.1:6379> get name "hello,maomao" 127.0.0.1:6379> getrange name 0 3 "hell" 127.0.0.1:6379> getrange name 0 -1 "hello,maomao" 127.0.0.1:6379> setrange name 2 mmm (integer) 12 127.0.0.1:6379> get name "hemmm,maomao" 127.0.0.1:6379> setrange name 0 ilove (integer) 12 127.0.0.1:6379> getrange name 0 -1 "ilove,maomao" 先get再set

getset key value

127.0.0.1:6379> getset db redis # 如果不存在值 则返回 nil (nil) 127.0.0.1:6379> get db "redis" 127.0.0.1:6379> getset db mongoDB # 如果存在值,获取原来的值,并设置新的值 "redis" 127.0.0.1:6379> get db "mongoDB" 储存一个对象 set user:1 {name:maomao,age:18} # 设置一个user:1 对象 值为 json字符来保存一个对象! 这里的key是一个巧妙地设计:user:{id}:{filed} , 如此设计在Redis中完全ok 127.0.0.1:6379> mset user:1:name maomao user:1:age 18 user:1:gender nv OK 127.0.0.1:6379> mget user:1:name user:1:age user:1:gender 1) "maomao" 2) "18" 3) "nv" string 类型数据操作的注意事项 数据操作不成功的反馈与数据正常操作之间的差异 表示运行结果是否成功 (integer) 0 → false 失败 (integer) 1 → true 成功表示运行结果值 (integer) 3 → 3 3个 (integer) 1 → 1 1个 数据未获取到 (nil)等同于null数据最大存储量 512MB数值计算最大范围(java中的long的最大值) 9223372036854775807 string 类型应用场景

主页高频访问信息显示控制,例如B站up主,主页显示粉丝数与,获赞数,播放数 在这里插入图片描述

在redis中为大V用户设定用户信息,以用户主键和属性值作为key,后台设定定时刷新策略即可 user: id:110:fans → 2389000user: id:110:likes → 9476000user: id:110:views → 480000000 在redis中以json格式存储up主信息,定时刷新(也可以使用hash类型) eg: user: id:110 → {“id”:110,“name”:“王老菊”,“fans”:2389000,“likes”:9476000, “views”:480000000} 127.0.0.1:6379> mset user:id:110:fans 2389000 user:id:110:likes 9476000 user:id:110:views 480000000OK 127.0.0.1:6379> mget user:id:110:fans user:id:110:likes user:id:110:views 1) "2389000" 2) "9476000" 3) "480000000" 127.0.0.1:6379> incr user:id:110:fans (integer) 2389001 127.0.0.1:6379> incr user:id:110:views (integer) 480000001 127.0.0.1:6379> incr user:id:110:views (integer) 480000002 127.0.0.1:6379> mget user:id:110:fans user:id:110:likes user:id:110:views 1) "2389001" 2) "9476000" 3) "480000002" 127.0.0.1:6379> set user:id:120 {id:120,name:wanglaoju,fans:2389000,likes:9476000,views:480000000}OK 127.0.0.1:6379> get user:id:120 "{id:120,name:wanglaoju,fans:2389000,likes:9476000,views:480000000}"

key 的设置约定

数据库中的热点数据key命名惯例 表名 :主键名 :主键值 : 字段名 order : id : 294375951 : name equip : id : 390472345 : type news : id : 202004150 : title hash 新的存储需求:对一系列存储的数据进行编组,方便管理,典型应用存储对象信息需要的存储结构:一个存储空间保存多个键值对数据hash类型:底层使用哈希表结构实现数据存储

关于哈希表参考 大佬的文章 在这里插入图片描述

hash存储结构优化

如果field数量较少,存储结构优化为类数组结构如果field数量较多,存储结构使用HashMap结构 hash 类型数据的基本操作

添加/修改数据

hset key field value

获取数据

hget key field hgetall key

删除数据

hdel key field1 [field2]

127.0.0.1:6379> hset user name xiaotian (integer) 1 127.0.0.1:6379> hset user age 20 (integer) 1 127.0.0.1:6379> hset user gender nan (integer) 1 127.0.0.1:6379> hgetall user 1) "name" 2) "xiaotian" 3) "age" 4) "20" 5) "gender" 6) "nan" 127.0.0.1:6379> hget user name "xiaotian" 127.0.0.1:6379> hget user gender "nan" 127.0.0.1:6379> hdel user gender (integer) 1 127.0.0.1:6379> hgetall user 1) "name" 2) "xiaotian" 3) "age" 4) "20" 添加/修改多个数据

hmset key field1 value1 field2 value2 …

获取多个数据

hmget key field1 field2 …

获取哈希表中字段的数量

hlen key

获取哈希表中是否存在指定的字段

hexists key field

127.0.0.1:6379> hmget user name age 1) "xiaotian" 2) "20" 127.0.0.1:6379> hmset user name feifei age 22 weight 46 OK 127.0.0.1:6379> hgetall user 1) "name" 2) "feifei" 3) "age" 4) "22" 5) "weight" 6) "46" 127.0.0.1:6379> hlen user # 获取的是field的数量 (integer) 3 127.0.0.1:6379> hexists user age # 判断是否存在指定字段 (integer) 1 127.0.0.1:6379> hexists user height (integer) 0 hash 类型数据扩展操作 获取哈希表中所有的字段名或字段值

hkeys key hvals key

设置指定字段的数值数据增加指定范围的值

hincrby key field increment hincrbyfloat key field increment

127.0.0.1:6379> hkeys user # 所有的字段名 1) "name" 2) "age" 3) "weight" 127.0.0.1:6379> hvals user # 所有的字段值 1) "feifei" 2) "22" 3) "46" 127.0.0.1:6379> hincrby user age 1 (integer) 23 127.0.0.1:6379> hincrby user weight 10 # 指定增量 (integer) 56 127.0.0.1:6379> hincrby user weight -5 # 指定减量 (integer) 51 hash 类型数据操作的注意事项 hash类型下的value只能存储字符串,不允许存储其他数据类型,不存在嵌套现象。如果数据未获取到,对应的值为(nil)每个 hash 可以存储 2^32 - 1 个键值对hash类型十分贴近对象的数据存储形式,并且可以灵活添加删除对象属性。但hash设计初衷不是为了存储大量对象而设计的,切记不可滥用,更不可以将hash作为对象列表使用hgetall 操作可以获取全部属性,如果内部field过多,遍历整体数据效率就很会低,有可能成为数据访问瓶颈 hash 类型应用场景 电商网站购物车设计与实现

在这里插入图片描述 业务分析

仅分析购物车的redis存储模型 添加、浏览、更改数量、删除、清空 购物车于数据库间持久化同步购物车于订单间关系 提交购物车:读取数据生成订单商家临时价格调整:隶属于订单级别 未登录用户购物车信息存储 cookie存储

解决方案

以客户id作为key,每位客户创建一个hash存储结构存储对应的购物车信息将商品编号作为field,购买数量作为value进行存储添加商品:追加全新的field与value浏览:遍历hash更改数量:自增/自减,设置value值  删除商品:删除field清空:删除key id:001指用户id g01 g02 指商品id 127.0.0.1:6379> hmset id:001 g01 100 g02 200 OK 127.0.0.1:6379> hmset id:002 g02 10 g04 8 g05 100 OK 127.0.0.1:6379> hset id:001 g03 5 (integer) 1 127.0.0.1:6379> hgetall id:001 1) "g01" 2) "100" 3) "g02" 4) "200" 5) "g03" 6) "5" 127.0.0.1:6379> hdel id:001 g01 (integer) 1 127.0.0.1:6379> hgetall id:001 1) "g02" 2) "200" 3) "g03" 4) "5" 127.0.0.1:6379> hincrby id:001 g03 3 (integer) 8 127.0.0.1:6379> hgetall id:001 1) "g02" 2) "200" 3) "g03" 4) "8"

但目前这样是不够的,当前仅仅是将数据存储到了redis中,并没有起到加速的作用,商品信息还需要二次查询数据库

解决方案

每条购物车中的商品记录保存成两条field

field1专用于保存购买数量

命名格式:商品id:nums 保存数据:数值

field2专用于保存购物车中显示的信息,包含文字描述,图片地址,所属商家信息等

命名格式:商品id:info 保存数据:json 127.0.0.1:6379> hmset id:003 g01:nums 100 g01:info {diannao,8000} OK 127.0.0.1:6379> hgetall id:003 1) "g01:nums" 2) "100" 3) "g01:info" 4) "{diannao,8000}" 127.0.0.1:6379> hmset id:004 g01:nums 50 g01:info {diannao,8000} OK 127.0.0.1:6379> hgetall id:004 1) "g01:nums" 2) "50" 3) "g01:info" 4) "{diannao,8000}"

但这样又出现新的问题 就是g01:info是重复的,因此我们把field2作为独立hash 专门用来保存商品信息的hash

在这里插入图片描述 最后再做一个判断 ,如果field有值,则不添加,没有值就添加

hsetnx key field value

127.0.0.1:6379> hset id:004 g01:nums 200 (integer) 0 127.0.0.1:6379> hget id:004 g01:nums "200" 127.0.0.1:6379> hsetnx id:004 g01:nums 400 (integer) 0 127.0.0.1:6379> hsetnx id:004 g05:nums 400 (integer) 1 127.0.0.1:6379> hgetall id:004 1) "g01:nums" 2) "200" 3) "g01:info" 4) "{diannao,8000}" 5) "g05:nums" 6) "400" 商家抢购活动

双11活动日,iphone商家对iPhone12,iPad Pro, MacBook Pro的5000元、6000元、10000元商品推出抢购活动,每种商 品抢购上限100台

解决方案

以商家id作为key将参与抢购的商品id作为field将参与抢购的商品数量作为对应的value抢购时使用降值的方式控制产品数量 127.0.0.1:6379> hmset shop:001 iphone12 100 ipad 100 macbook 100 OK 127.0.0.1:6379> hincrby shop:001 iphone12 -1 (integer) 99 127.0.0.1:6379> hincrby shop:001 macbook -20 (integer) 80 127.0.0.1:6379> hgetall shop:001 1) "iphone12" 2) "99" 3) "ipad" 4) "100" 5) "macbook" 6) "80"


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有