Redis学习笔记
NoSQL
什么是NoSQL
NoSQL = Not Only SQL(不仅仅是SQL)
关系型数据库:表格、行、列
泛指非关系型数据库,随着Web2.0互联网的诞生!传统的关系型数据库很难对付Web2.0时代!尤其是超大规模的高并发的社区!暴露出来很多难以克服的问题,NoSQL在当今大数据环境下发展十分迅速,Redis是发展最快的,而且是我们当下必须要掌握的一个技术!
很多数据类型用户的的个人信息,社交网络,地理位置。这些数据类型的存储不需要一个固定格式!不需要多余的操作就可以横向扩展。
NoSQL特点
解耦!
-
方便扩展(数据之间没有关系,很好扩展!)
-
大数据量高性能(Redis 1s写8万次,读取11万次,NoSQL的缓存记录,是一种细粒度的缓存,性能会比较高)
-
数据类型是多样的!(不需要事先设计数据库!随取随用!如果是数据量十分大的表,很多人就无法设计了
-
传统RDBMS和NoSQL
传统的RDBMS(关系型数据库) - 组织化结构 - SQL - 数据和关系都存在单独的表中 - 操作数据、数据定义语言 - 严格的一致性 - 基础的事务 - ...
NoSQL - 不仅仅是数据 - 没有固定的查询语言 - 键值对存储,列存储,文档存储,图形数据库(社交关系) - 最终一致性 - CAP定理和BASE(异地多活) - 高性能,高可用,高可扩
了解:3V+3高
大数据时代的3V:主要是描述问题的
- 海量Volume
- 多样Variety
- 实时Velocity
大数据时代的3高:主要是对程序的要求
- 高并发
- 高可扩(随时水平拆分,机器不够,可以扩展机器解决)
- 高性能
真正企业级开发实践:NoSQL+RDBMS一起使用才是最强的,阿里巴巴的架构演进!
NoSQL的四大分类
KV键值对:
新浪: Redis
美团:Redis + Tair
阿里、百度:Redis + memecache
文档型数据库(bson格式 和json一样):
MongoDB (一般必须要掌握)
MongoDB 是一个基于分布式文件存储的数据库,C++ 编写,主要用来处理大量的文档!
MongoDB 是一个介于关系型数据库和非关系型数据中中间的产品!MongoDB 是非关系型数
据库中功能最丰富,最像关系型数据库的!
ConthDB
列存储数据库
HBase
分布式文件系统
图关系数据库
# 他不是存图形,放的是关系,比如:朋友圈社交网络,广告推荐!
Neo4j ,InfoGrid;
Redis入门
Redis 能干嘛?
1 、内存存储、持久化,内存中是断电即失、所以说持久化很重要(rdb、aof)
2 、效率高,可以用于高速缓存
3 、发布订阅系统
4 、地图信息分析
5 、计时器、计数器(浏览量!)
6 、........
特性
1 、多样的数据类型
2 、持久化
3 、集群
4 、事务
......
Redis 性能测试
redis-benchmark 是一个压力测试工具!
官方自带的性能测试工具!
Redis 性能测试是通过同时执行多个命令实现的。
语法
redis 性能测试的基本命令如下:
redis-benchmark [option] [option value]
注意:该命令是在 redis 的目录下执行的,而不是 redis 客户端的内部指令。
实例一
以下实例同时执行 10000 个请求来检测性能:
$ redis-benchmark -n 10000 -q
PING_INLINE: 141043.72 requests per second
PING_BULK: 142857.14 requests per second
SET: 141442.72 requests per second
GET: 145348.83 requests per second
INCR: 137362.64 requests per second
LPUSH: 145348.83 requests per second
LPOP: 146198.83 requests per second
SADD: 146198.83 requests per second
SPOP: 149253.73 requests per second
LPUSH (needed to benchmark LRANGE): 148588.42 requests per second
LRANGE_100 (first 100 elements): 58411.21 requests per second
LRANGE_300 (first 300 elements): 21195.42 requests per second
LRANGE_500 (first 450 elements): 14539.11 requests per second
LRANGE_600 (first 600 elements): 10504.20 requests per second
MSET (10 keys): 93283.58 requests per second
redis 性能测试工具可选参数如下所示:
序号 | 选项 | 描述 | 默认值 |
---|---|---|---|
1 | -h | 指定服务器主机名 | 127.0.0.1 |
2 | -p | 指定服务器端口 | 6379 |
3 | -s | 指定服务器 socket | |
4 | -c | 指定并发连接数 | 50 |
5 | -n | 指定请求数 | 10000 |
6 | -d | 以字节的形式指定 SET/GET 值的数据大小 | 3 |
7 | -k | 1=keep alive 0=reconnect | 1 |
8 | -r | SET/GET/INCR 使用随机 key, SADD 使用随机值 | |
9 | -P | 通过管道传输 请求 | 1 |
10 | -q | 强制退出 redis。仅显示 query/sec 值 | |
11 | –csv | 以 CSV 格式输出 | |
12 | -l | 生成循环,永久执行测试 | |
13 | -t | 仅运行以逗号分隔的测试命令列表。 | |
14 | -I | Idle 模式。仅打开 N 个 idle 连接并等待。 |
实例二
以下实例我们使用了多个参数来测试 redis 性能:
$ redis-benchmark -h 127.0.0.1 -p 6379 -t set,lpush -n 10000 -q
SET: 146198.83 requests per second
LPUSH: 145560.41 requests per second
以上实例中主机为 127.0.0.1,端口号为 6379,执行的命令为 set,lpush,请求数为 10000,通过 -q 参数让结果只显示每秒执行的请求数。
我们来简单测试下:
# 测试: 100 个并发连接 100000 请求
redis-benchmark -h localhost -p 6379 -c 100 -n 100000
基础的知识
# redis默认有 16 个数据库
# 默认使用的是第 0 个
# 可以使用 select 进行切换数据库!
select index # 0-16
# 清除当前数据库
flushdb
# 清除全部数据库的内容
FLUSHALL
keys * # 查看数据库所有的key
五大数据类型
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件MQ。
它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合
(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。
Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。
127 .0.0.1:6379> keys * # 查看所有的key
(empty list or set)
127 .0.0.1:6379> set name zhy # set key
OK
127 .0.0.1:6379> keys *
1 ) "name"
127 .0.0.1:6379> set age 1
OK
127 .0.0.1:6379> keys *
1 ) "age"
2 ) "name"
127 .0.0.1:6379> EXISTS name # 判断当前的key是否存在
(integer) 1
127 .0.0.1:6379> EXISTS name
(integer) 0
127 .0.0.1:6379> move name 1 # 移动当前的key到指定数据库
(integer) 1
127 .0.0.1:6379> keys *
1 ) "age"
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> keys *
1) "name"
127.0.0.1:6379[1]> get name
"zhy"
127.0.0.1:6379[1]> select 0
OK
127.0.0.1:6379> keys *
1) "age"
127.0.0.1:6379> set name zhy
OK
127.0.0.1:6379> keys *
1) "age"
2) "name"
127 .0.0.1:6379> clear
127 .0.0.1:6379> keys *
1 ) "age"
2 ) "name"
127 .0.0.1:6379> get name
"zhy"
127 .0.0.1:6379> EXPIRE name 10 #设置key的过期时间,单位是秒
(integer) 1
127 .0.0.1:6379> ttl name # 查看当前key的剩余时间
(integer) 4
127 .0.0.1:6379> ttl name
(integer) 3
127 .0.0.1:6379> ttl name
(integer) 2
127 .0.0.1:6379> ttl name
(integer) 1
127 .0.0.1:6379> ttl name
(integer) -2
127 .0.0.1:6379> get name # 就会自动删除 keys *也就没了
(nil)
127 .0.0.1:6379> type name # 查看当前key的一个类型!
string
127 .0.0.1:6379> type age # string
String类型
基本用法
############################################################
127 .0.0.1:6379> set name zhy # 设置值
127 .0.0.1:6379> get name # 获得值
127 .0.0.1:6379> keys * # 获得所有的key
127 .0.0.1:6379> EXISTS name # 判断某一个key是否存在
(integer) 1
#追加字符串,如果当前key不存在,就相当于setkey
127 .0.0.1:6379> APPEND name "hehe" # 7就是name的值的长度
(integer) 7
127 .0.0.1:6379> get name
"zhyhehe"
127 .0.0.1:6379> STRLEN name # 获取字符串的长度!
(integer) 7
############################################################
# i++
# 步长 i+=
127 .0.0.1:6379> set views 0 # 初始浏览量为 0
OK
127 .0.0.1:6379> get views
"0"
127 .0.0.1:6379> incr views # 自增 1 浏览量变为 1
(integer) 1
127 .0.0.1:6379> incr views
(integer) 2
127 .0.0.1:6379> get views
"2"
127 .0.0.1:6379> decr views # 自减 1 浏览量-1
(integer) 1
127 .0.0.1:6379> decr views
(integer) 0
127 .0.0.1:6379> decr views
(integer) -1
127 .0.0.1:6379> get views
"-1"
127 .0.0.1:6379> INCRBY views 10 # 可以设置步长,指定增量!
(integer) 9
127 .0.0.1:6379> INCRBY views 10
(integer) 19
127 .0.0.1:6379> DECRBY views 5
(integer) 14
############################################################
字符串范围range
127.0.0.1:6379> set key1 "hello,zhy" # 设置 key1 的值
OK
127.0.0.1:6379> GETRANGE key1 0 3 # 截取字符串 [0,3]
"hell"
127.0.0.1:6379> GETRANGE key1 0 -1 # 获取全部的字符串 和 get key是一样的
"hello,zhy"
127.0.0.1:6379> set key2 abcdefg
OK
127.0.0.1:6379> get key2
"abcdefg"
127.0.0.1:6379> SETRANGE key2 1 xx #替换指定位置开始的字符串!写多少长度的就换多少长度的
(integer) 7
127.0.0.1:6379> get key2
"axxdefg"
设置set的过期时间
setex (set with expire) # 设置过期时间
setnx (set if not exist) # 不存在,再设置(在分布式锁中会常常使用!)
ttl key # 查看过期时间
127.0.0.1:6379> SETEX key3 10 zhy # key1 的值为 zhy,10秒后过期
OK
127.0.0.1:6379> SETNX mykey "redis" # 如果mykey 不存在,创建mykey
(integer) 1
127.0.0.1:6379> keys *
1) "key2"
2) "mykey"
3) "key1"
# 同时设置多个值
# mset
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379> keys *
1) "k3"
2) "k2"
3) "k1"
# 同时获取多个值
# mget
127 .0.0.1:6379> mget k1 k2 k3
1 ) "v1"
2 ) "v2"
3 ) "v3"
127.0.0.1:6379> msetnx k1 v1 k4 v4 #msetnx 是一个原子性的操作,要么一起成功,要么一起失败!
(integer) 0
127.0.0.1:6379> get k4
(nil)
# 对象
# 这里的key是一个巧妙的设计:user:{id}:{field},这种设计在redis中是允许的
127.0.0.1:6379> mset user:1:name zhy user:1:age 2
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhy"
2) "2"
# getset
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"
# 数据结构是相通的!
String类似的使用场景:value除了是字符串还可以是数字。
- 计数器
- 统计多单位的数量
- 粉丝数
- 对象缓存存储
List(列表)
基本的数据类型,列表
命令 | 描述 |
---|---|
LPUSH/RPUSH key value1[value2…] | 从左边/右边向列表中PUSH值(一个或者多个)。 |
LRANGE key start end | 获取list 起止元素==(索引从左往右 递增)== |
LPUSHX/RPUSHX key value | 向已存在的列名中push值(一个或者多个) |
LINSERT key BEFORE | AFTER pivot value |
LLEN key | 查看列表长度 |
LINDEX key index | 通过索引获取列表元素 |
LSET key index value | 通过索引为元素设值 |
LPOP/RPOP key | 从最左边/最右边移除值 并返回 |
RPOPLPUSH source destination | 将列表的尾部(右)最后一个值弹出,并返回,然后加到另一个列表的头部 |
LTRIM key start end | 通过下标截取指定范围内的列表 |
LREM key count value | List中是允许value重复的 count > 0:从头部开始搜索 然后删除指定的value 至多删除count个 count < 0:从尾部开始搜索… count = 0:删除列表中所有的指定value。 |
BLPOP/BRPOP key1[key2] timout | 移出并获取列表的第一个/最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 |
BRPOPLPUSH source destination timeout | 和RPOPLPUSH功能相同,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 |
在redis里面,我们可以把list玩成 ,栈、队列、阻塞队列!
所有的list命令都是用l开头的,Redis不区分大小命令
##########################################################################
# LPUSH
# RPUSH
# 这边只能左边插入右边插入 但是取值只能LRANGE
127.0.0.1:6379> LPUSH list one # 将一个值或者多个值,插入到列表头部 (左)
(integer) 1
127.0.0.1:6379> LPUSH list two
(integer) 2
127.0.0.1:6379> LPUSH list three
(integer) 3
127.0.0.1:6379> LRANGE list 0 -1 # 获取list中值!
1 ) "three"
2 ) "two"
3 ) "one"
127.0.0.1:6379> LRANGE list 0 1 # 通过区间获取具体的值!
1 ) "three"
2 ) "two"
127.0.0.1:6379> rpush list right # 将一个值或者多个值,插入到列表尾部 (右)
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "right"
##########################################################################
# 双端队列的感觉
# LPOP
# RPOP
127.0.0.1:6379> Lpop list # 移除list的第一个元素
"three"
127.0.0.1:6379> Rpop list # 移除list的最后一个元素
"right"
127.0.0.1:6379> LRANGE list 0 -1
1 ) "two"
2 ) "one"
##########################################################################
# Lindex
127.0.0.1:6379> LRANGE list 0 -1
1 ) "two"
2 ) "one"
127.0.0.1:6379> lindex list 1 # 通过下标获得 list 中的某一个值!
"one"
127.0.0.1:6379> lindex list 0
"two"
##########################################################################
# Llen key # list的长度
127.0.0.1:6379> Llen list # 返回列表的长度
(integer) 2
##########################################################################
# 移除指定的值!
# lrem key 个数 具体的值 # 移除指定的值 可移除多个
127.0.0.1:6379> lpush list three
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "three"
3) "two"
4) "one"
127.0.0.1:6379> lrem list 1 one # 移除list集合中指定个数的value,精确匹配
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "three"
3) "two"
127.0.0.1:6379> lrem list 1 three
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "three"
3) "two"
127.0.0.1:6379> lrem list 2 three
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "two"
##########################################################################
# ltrim 修剪 没有rtrim
127.0.0.1:6379> rpush mylist hello hello1 hello2 hello3
(integer) 4
127.0.0.1:6379> LRANGE mylist 0 -1
1) "hello"
2) "hello1"
3) "hello2"
4) "hello3"
# 通过下标截取指定的长度,这个list已经被改变了,截断了只剩下截取的元素!
127.0.0.1:6379> LTRIM mylist 1 2
OK
127.0.0.1:6379> LRANGE mylist 0 -1
1) "hello1"
2) "hello2"
##########################################################################
# 移除列表的最后一个元素,将他移动到新的列表中!
# RPOPLPUSH source destination
# rpoplpush list名称 newlist名称
127.0.0.1:6379> LRANGE mylist 0 -1
1) "hello"
2) "hello1"
3) "hello2"
4) "hello3"
127.0.0.1:6379> RPOPLPUSH mylist mylistnew
"hello3"
127.0.0.1:6379> LRANGE mylist 0 -1
1) "hello"
2) "hello1"
3) "hello2"
127.0.0.1:6379> LRANGE mylistnew 0 -1
1) "hello3"
# lset 将列表中的指定下标的值替换为另外一个值,更新操作
127.0.0.1:6379> exists list
(integer) 0
127.0.0.1:6379> lset list 0 value # 如果不存在列表去更新会报错
(error) ERR no such key
127.0.0.1:6379> lpush list value1
(integer) 1
127.0.0.1:6379> lrange list 0 0
1) "value1"
127.0.0.1:6379> lset list 0 item # 如果存在,更新当前下标的值
OK
127.0.0.1:6379> lrange list 0 0
1) "item"
127.0.0.1:6379> lset list 1 other # 如果不存在该下标,报错
(error) ERR index out of range
# linsert 将某个具体的value插入到列表中某个元素的前面或后面
127.0.0.1:6379> rpush mylist "hello" "world"
(integer) 2
127.0.0.1:6379> linsert mylist before "world" "new"
(integer) 3
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "new"
3) "world"
127.0.0.1:6379> linsert mylist after "world" "!"
(integer) 4
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "new"
3) "world"
4) "!"
小结
list实际上是一个链表,before Node after , left, right 都可以插入值
如果key不存在,则创建新的链表
如果key存在,新增内容
如果移除了所有值,空链表,也代表不存在
在两边插入或者改动值,效率最高!修改中间元素,效率相对较低
应用
消息排队!消息队列(Lpush Rpop),栈(Lpush Lpop)
Set(集合)
Redis的Set是string类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
Redis 中 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。
命令 | 描述 |
---|---|
SADD key member1[member2…] | 向集合中无序增加一个/多个成员 |
SCARD key | 获取集合的成员数 |
SMEMBERS key | 返回集合中所有的成员 |
SISMEMBER key member | 查询member元素是否是集合的成员,结果是无序的 |
SRANDMEMBER key [count] | 随机返回集合中count个成员,count缺省值为1 |
SPOP key [count] | 随机移除并返回集合中count个成员,count缺省值为1 |
SMOVE source destination member | 将source集合的成员member移动到destination集合 |
SREM key member1[member2…] | 移除集合中一个/多个成员 |
SDIFF key1[key2…] | 返回所有集合的差集 key1- key2 - … |
SDIFFSTORE destination key1[key2…] | 在SDIFF的基础上,将结果保存到集合中==(覆盖)==。不能保存到其他类型key噢! |
SINTER key1 [key2…] | 返回所有集合的交集 |
SINTERSTORE destination key1[key2…] | 在SINTER的基础上,存储结果到集合中。覆盖 |
SUNION key1 [key2…] | 返回所有集合的并集 |
SUNIONSTORE destination key1 [key2…] | 在SUNION的基础上,存储结果到及和张。覆盖 |
SSCAN KEY [MATCH pattern] [COUNT count] | 在大量数据环境下,使用此命令遍历集合中元素,每次遍历部分 |
---------------SADD--SCARD--SMEMBERS--SISMEMBER--------------------
127.0.0.1:6379> SADD myset m1 m2 m3 m4 # 向myset中增加成员 m1~m4
(integer) 4
127.0.0.1:6379> SCARD myset # 获取集合的成员数目
(integer) 4
127.0.0.1:6379> smembers myset # 获取集合中所有成员
1) "m4"
2) "m3"
3) "m2"
4) "m1"
127.0.0.1:6379> SISMEMBER myset m5 # 查询m5是否是myset的成员
(integer) 0 # 不是,返回0
127.0.0.1:6379> SISMEMBER myset m2
(integer) 1 # 是,返回1
127.0.0.1:6379> SISMEMBER myset m3
(integer) 1
---------------------SRANDMEMBER--SPOP----------------------------------
127.0.0.1:6379> SRANDMEMBER myset 3 # 随机返回3个成员
1) "m2"
2) "m3"
3) "m4"
127.0.0.1:6379> SRANDMEMBER myset # 随机返回1个成员
"m3"
127.0.0.1:6379> SPOP myset 2 # 随机移除并返回2个成员
1) "m1"
2) "m4"
# 将set还原到{m1,m2,m3,m4}
---------------------SMOVE--SREM----------------------------------------
127.0.0.1:6379> SMOVE myset newset m3 # 将myset中m3成员移动到newset集合
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "m4"
2) "m2"
3) "m1"
127.0.0.1:6379> SMEMBERS newset
1) "m3"
127.0.0.1:6379> SREM newset m3 # 从newset中移除m3元素
(integer) 1
127.0.0.1:6379> SMEMBERS newset
(empty list or set)
-----------------------------SDIFF------------------------------------
# 下面开始是多集合操作,多集合操作中若只有一个参数默认和自身进行运算
# setx=>{m1,m2,m4,m6}, sety=>{m2,m5,m6}, setz=>{m1,m3,m6}
127.0.0.1:6379> SDIFF setx sety setz # 等价于setx-sety-setz
1) "m4" #这就是看setx中与其他集合中有不一样的列出来 只针对setx中的列出来
127.0.0.1:6379> SDIFF setx sety # setx - sety
1) "m4"
2) "m1"
127.0.0.1:6379> SDIFF sety setx # sety - setx
1) "m5"
-------------------------SINTER---------------------------------------
# 共同关注(交集)
127.0.0.1:6379> SINTER setx sety setz # 求 setx、sety、setx的交集
1) "m6"
127.0.0.1:6379> SINTER setx sety # 求setx sety的交集
1) "m2"
2) "m6"
-------------------------SUNION---------------------------------------
127.0.0.1:6379> SUNION setx sety setz # setx sety setz的并集
1) "m4"
2) "m6"
3) "m3"
4) "m2"
5) "m1"
6) "m5"
127.0.0.1:6379> SUNION setx sety # setx sety 并集
1) "m4"
2) "m6"
3) "m2"
4) "m1"
5) "m5"
Hash(哈希)
Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。(就是key-value 都是字段 一行数据)
Set就是一种简化的Hash,只变动key,而value使用默认值填充(就跟java的set跟hashmap一个道理)。可以将一个Hash表作为一个对象进行存储,表中存放对象的信息。
命令 | 描述 |
---|---|
HSET key field value | 将哈希表 key 中的字段 field 的值设为 value 。重复设置同一个field会覆盖,返回0 |
HMSET key field1 value1 [field2 value2…] | 同时将多个 field-value (域-值)对设置到哈希表 key 中。 |
HSETNX key field value | 只有在字段 field 不存在时,设置哈希表字段的值。 |
HEXISTS key field | 查看哈希表 key 中,指定的字段是否存在。 |
HGET key field value | 获取存储在哈希表中指定字段的值 |
HMGET key field1 [field2…] | 获取所有给定字段的值 |
HGETALL key | 获取在哈希表key 的所有字段和值 |
HKEYS key | 获取哈希表key中所有的字段 |
HLEN key | 获取哈希表中字段的数量 |
HVALS key | 获取哈希表中所有值 |
HDEL key field1 [field2…] | 删除哈希表key中一个/多个field字段 |
HINCRBY key field n | 为哈希表 key 中的指定字段的整数值加上增量n,并返回增量后结果 一样只适用于整数型字段 |
HINCRBYFLOAT key field n | 为哈希表 key 中的指定字段的浮点数值加上增量 n。 |
HSCAN key cursor [MATCH pattern] [COUNT count] | 迭代哈希表中的键值对。 |
------------------------HSET--HMSET--HSETNX----------------
127.0.0.1:6379> HSET studentx name sakura # 将studentx哈希表作为一个对象,设置name为sakura
(integer) 1
127.0.0.1:6379> HSET studentx name zhy # 重复设置field进行覆盖,并返回0
(integer) 0
127.0.0.1:6379> HSET studentx age 20 # 设