REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。
Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Hash), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。
Redis:nosql(非关系型数据库)。
NoSQL演变史参考:https://www.cnblogs.com/lukelook/p/11135209.html
NoSQL 概述
NoSQL(NoSQL = Not Only SQL ),意即“不仅仅是SQL”,
泛指非关系型的数据库。随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题,包括超大规模数据的存储。
(例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。
MySQL的扩展性瓶颈:MySQL数据库也经常存储一些大文本字段,导致数据库表非常的大,在做数据库恢复的时候就导致非常的慢,不容易快速恢复数据库。比如1000万4KB大小的文本就接近40GB的大小,如果能把这些数据从MySQL省去,MySQL将变得非常的小。关系数据库很强大,但是它并不能很好的应付所有的应用场景。MySQL的扩展性差(需要复杂的技术来实现),大数据下IO压力大,表结构更改困难,正是当前使用MySQL的开发人员面临的问题。
NoSQL代表:MongDB、 Redis、Memcache
NoSQL特点:解耦!
方便拓展(数据之间没有关系,很好拓展!)
大数据量高性能(redis一秒读11完次,一秒写8完次,NoSQL是缓存记录级。是一种细粒度的缓存,性能比较高)
数据类型是多样的(不需要实现设计数据库,随取随用)
传统的RDBMS和NoSQL
传统的RDBMS
-结构化组织
-SQL
-数据和关系都存在单独的表中
-操作数据,数据定义语言
-严格的一致性
-...
NoSQL
-不仅仅是数据
-没有固定的查询语言
-键值对存储,列存储,文档存储,图数据库
-最终一致性
-CAP定理和BASE理论(异地多活)
-高性能,高可用,高扩展
-...
KV键值对:
文档型数据库(bson格式 和json一样):
列存储数据库
图关系数据库
分类 | Examples举例 | 典型应用场景 | 数据模型 | 优点 | 缺点 |
---|---|---|---|---|---|
键值(key-value)[3] | Tokyo Cabinet/Tyrant, Redis, Voldemort, Oracle BDB | 内容缓存,主要用于处理大量数据的高访问负载,也用于一些日志系统等等。[3] | Key 指向 Value 的键值对,通常用hash table来实现[3] | 查找速度快 | 数据无结构化,通常只被当作字符串或者二进制数据[3] |
列存储数据库[3] | Cassandra, HBase, Riak | 分布式的文件系统 | 以列簇式存储,将同一列数据存在一起 | 查找速度快,可扩展性强,更容易进行分布式扩展 | 功能相对局限 |
文档型数据库[3] | CouchDB, MongoDb | Web应用(与Key-Value类似,Value是结构化的,不同的是数据库能够了解Value的内容) | Key-Value对应的键值对,Value为结构化数据 | 数据结构要求不严格,表结构可变,不需要像关系型数据库一样需要预先定义表结构 | 查询性能不高,而且缺乏统一的查询语法。 |
图形(Graph)数据库[3] | Neo4J, InfoGrid, Infinite Graph | 社交网络,推荐系统等。专注于构建关系图谱 | 图结构 | 利用图结构相关算法。比如最短路径寻址,N度关系查找等 | 很多时候需要对整个图做计算才能得出需要的信息,而且这种结构不太好做分布式的集群方案。[3] |
Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
redis与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
免费,开源,是当下最热门的NoSQL技术之一,也被称之为结构化数据库。
Redis能干什么:
特点:
Redis中文网:https://www.redis.net.cn/
Windows下使用非常简单,但是Redis推荐我们使用Redis去开发使用。
下载安装包(官网下载)
解压Redis的安装包到指定包
进入解压后的文件,可以看到Redis的配置文件(redis.conf)
环境安装
[root@zhourui redis-6.0.9]# yum install gcc-c++
[root@zhourui redis-6.0.9]# make
make install
再次make
make install
Redis的默认安装路径:/usr/local/bin
将redis的配置文件(redis.conf)复制到当前目录下
[root@zhourui bin]# mkdir zconfig
[root@zhourui bin]# cp /www/server/redis/redis-6.0.9/redis.conf zconfig/
redis默认不是后台启动的,修改配置文件将 no 改为 yes
启动Redis服务,通过指定的配置文件启动服务
[root@zhourui bin]# redis-server zconfig/redis.conf
启动客户端redis-cli
[root@zhourui bin]# redis-cli -p 6379
127.0.0.1:6379> ping #测试连接
PONG
127.0.0.1:6379> set name zr #存值
OK
127.0.0.1:6379> get name #取值
"zr"
127.0.0.1:6379> keys * #查看所有的key
1) "name"
127.0.0.1:6379>
查看redis的进程是否开启
关闭redis服务,在连接的客户端输入 shutdown
再次查看进程是否存在,ps -ef|grep redis
单机多redis修改端口即可
redis-benchmark 是一个压力测试工具。
官方自带的性能测试工具。
redis-benchmark 命令参数!
redis 性能测试工具可选参数如下所示:
序号 | 选项 | 描述 | 默认值 |
---|---|---|---|
1 | -h | 指定服务器主机名 | 127.0.0.1 |
2 | -p | 指定服务器端口 | 6379 |
3 | -s | 指定服务器 socket | |
4 | -c | 指定并发连接数 | 50 |
5 | -n | 指定请求数 | 10000 |
6 | -d | 以字节的形式指定 SET/GET 值的数据大小 | 2 |
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后新开一个窗口,执行
# 测试:100个并发连接,100000个请求
redis-benchmark -h localhost -p 6379 -c 100 -n 100000
redis默认有16个数据库(从 redis.conf 中可以看到)。
默认使用的是第 0 个。
可以使用 select 进行切换。
flushdb:清空当前数据库,flushall:清空所有的数据库,dbsize :数据库的大小,keys * :查看所有的key。
127.0.0.1:6379> select 3 #切换数据库
OK
127.0.0.1:6379[3]> dbsize
(integer) 0
127.0.0.1:6379[3]> set name zhou
OK
127.0.0.1:6379[3]> dbsize #数据库的大小
(integer) 1
127.0.0.1:6379[3]> select 6
OK
127.0.0.1:6379[6]> dbsize
(integer) 0
127.0.0.1:6379[6]> get name
(nil)
127.0.0.1:6379[6]> select 3
OK
127.0.0.1:6379[3]> get name
"zhou"
127.0.0.1:6379[3]> flushdb #清空数据库
OK
127.0.0.1:6379[3]> get name
(nil)
127.0.0.1:6379> flushall #清空所有的数据库
OK
127.0.0.1:6379[3]>
Redis是单线程的!
官方表示,Redis是基于内存操作的,CPU不是Redis的性能瓶颈,Redis的性能瓶颈是根据机器的内存和网络的带宽,既然可以使用单线程来实现,就使用单线程了。
Redis是C语言写的,官方提供的数据100000+的QPS,这个完全不比同样是使用 key-value 的Memcache差!
Redis是单线程为什么还这么快?
误区1:认为高性能的服务器一定是多线程的.
误区2:多线程(cpu会上下文切换)一定比单线程效率高。
核心:Redis是将所有的数据放在内存中的,所以使用单线程去操作效率就是最高的,多线程(cpu会上下文切换,耗时的操作),对于内存系统来说没有上下文的切换效率就是最高的,多次读写都是在一个CPU上的,在内存情况下,这个就是最佳方案。
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。
Redis-Key
127.0.0.1:6379> exists name #判断键是否存在
(integer) 1
127.0.0.1:6379> move name 1 #移除1数据库的name键
(integer) 1
127.0.0.1:6379> set name zzrr
OK
127.0.0.1:6379> keys * #查看所有的key
1) "name"
2) "age"
127.0.0.1:6379> expire name 10 #设置key过期时间 单位是秒
(integer) 1
127.0.0.1:6379> keys *
1) "name"
2) "age"
127.0.0.1:6379> ttl name #查看当前key的剩余时间
(integer) 6
127.0.0.1:6379> ttl name
(integer) 2
127.0.0.1:6379> keys *
1) "age"
127.0.0.1:6379> type name #查看当前key的类型
string
127.0.0.1:6379> type age
string
127.0.0.1:6379>
###############################################################################
127.0.0.1:6379> set name zr #设置值
OK
127.0.0.1:6379> get name
"zr"
127.0.0.1:6379> keys * #查看所有的key
1) "name"
127.0.0.1:6379> append name "hello" #追加字符串,如果当前的key不存在,就相当于 set key
(integer) 7
127.0.0.1:6379> get name
"zrhello"
127.0.0.1:6379> strlen name #查看字符串的长度
(integer) 7
127.0.0.1:6379>
###############################################################################
# 增量
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
(integer) 1
127.0.0.1:6379> incr views
(integer) 2
127.0.0.1:6379> get views
"2"
127.0.0.1:6379>
127.0.0.1:6379> decr views #自减1
(integer) 1
127.0.0.1:6379> get views
"1"
127.0.0.1:6379> incrby views 10 #设置步长,指定增量
(integer) 11
127.0.0.1:6379> decrby views 10 #设置步长,指定减量
(integer) 1
127.0.0.1:6379>
###############################################################################
# 字符串范围 range
127.0.0.1:6379> flushdb #清空数据库
OK
127.0.0.1:6379> set name zhour #设置值
OK
127.0.0.1:6379> get name #获取值
"zhour"
127.0.0.1:6379> getrange name 0 3 #截取字符串 [0,3]
"zhou"
127.0.0.1:6379> getrange name 0 -1 #获得全部的字符串,和getkey是一样的
"zhour"
127.0.0.1:6379>
# 替换
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"
###############################################################################
# setex (set with expire) 设置过期时间
# setnx (set if not exist) 不存在再设置 在分布式锁中常使用
127.0.0.1:6379> setex key3 30 "hello" #设置key3的值为hello,30秒后过期
OK
127.0.0.1:6379> ttl key3 #查看还有多长时间过期
(integer) 25
127.0.0.1:6379> setnx key4 "redis" #如果key4不存在,就创建key4
(integer) 1
127.0.0.1:6379> setnx key4 "MongoDB" #如果key4存在,就创建失败
(integer) 0
127.0.0.1:6379> get key4
"redis"
127.0.0.1:6379>
###############################################################################
# mset
# mget
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 #同时设置多个值
OK
127.0.0.1:6379> keys *
1) "k2"
2) "k1"
3) "k3"
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)
# 对象
set user:1 {name:zhour,age:3} #设置一个user:1对象 值为json字符串来保存一个对象
# user:{id}:{filed},这样设计在redis中是可以的
127.0.0.1:6379> mset user:1:name zhour user:1:age 3
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhour"
2) "3"
127.0.0.1:6379>
###############################################################################
# getset 先get再set
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"
127.0.0.1:6379>
String 类型的使用场景:value除了是字符串还可以是数字。
基本的数据类型,列表。
在redis中,可以把list玩出成,栈,队列,阻塞队列。
所有的 list 命令都是以 l 开头的。Redis不区分大小写命令。
###############################################################################
# lpush
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"
127.0.0.1:6379>
###############################################################################
# lpop
# rpop
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "right"
127.0.0.1:6379> lpop list #移除列表的第一个元素
"three"
127.0.0.1:6379> rpop list #移除列表的最后一个元素
"right"
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
127.0.0.1:6379>
###############################################################################
# lindex
127.0.0.1:6379> lindex list 0 #通过下标获取指定下标的值
"two"
127.0.0.1:6379> lindex list 1
"one"
127.0.0.1:6379>
###############################################################################
# llen
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
127.0.0.1:6379> llen list #获取列表的长度
(integer) 2
127.0.0.1:6379>
###############################################################################
# lrem 移除指定的值
127.0.0.1:6379> lrange list 0 -1
1) "four"
2) "four"
3) "three"
4) "two"
5) "one"
127.0.0.1:6379> lrem list 1 one #移除list集合中指定个数的value,精确匹配
(integer) 1
127.0.0.1:6379> lrem list 1 four
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "four"
2) "three"
3) "two"
127.0.0.1:6379> lpush list four
(integer) 4
127.0.0.1:6379> lrem list 2 four #移除list中的两个four
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
###############################################################################
# ltrim 袖箭
127.0.0.1:6379> rpush mylist hello
(integer) 1
127.0.0.1:6379> rpush mylist hello1
(integer) 2
127.0.0.1:6379> rpush mylist hello12
(integer) 3
127.0.0.1:6379> rpush mylist hello13
(integer) 4
127.0.0.1:6379> ltrim mylist 1 2 #通过下标截取指定的长度,只剩下截取的元素
OK
127.0.0.1:6379> lrange mylist 0 -1
1) "hello1"
2) "hello12"
127.0.0.1:6379>
###############################################################################
# rpoplpush 移除列表的最后一个元素,并将它添加到一个新的列表中
127.0.0.1:6379> rpush mylist hello
(integer) 1
127.0.0.1:6379> rpush mylist hello1
(integer) 2
127.0.0.1:6379> rpush mylist hello2
(integer) 3
127.0.0.1:6379> rpoplpush mylist myotherlist #移除列表的最后一个元素,并将它添加到一个新的列表中
"hello2"
127.0.0.1:6379> lrange mylist 0 -1 #查看原来的列表
1) "hello"
2) "hello1"
127.0.0.1:6379> lrange myotherlist 0 -1 #查看新的列表
1) "hello2"
127.0.0.1:6379>
###############################################################################
# lset 将列表中指定下标的值替换为另外一个值
127.0.0.1:6379> exists list #判断这个列表是否存在
(integer) 0
127.0.0.1:6379> lset list 0 item #如果不存在列表,去更新就会报错
(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
(integer) 1
127.0.0.1:6379> rpush mylist world
(integer) 2
127.0.0.1:6379> linsert mylist before world other
(integer) 3
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "other"
3) "world"
127.0.0.1:6379> linsert mylist after world new
(integer) 4
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "other"
3) "world"
4) "new"
list:实际上是一个链表,before Node after,left,right都可以插入值。
消息队列(Lpush,Rpop),栈(Lpush,Lpop)。
set中的值是不能重复的!
###############################################################################
# 存值,取值
127.0.0.1:6379> sadd myset hello #set中存值
(integer) 1
127.0.0.1:6379> sadd myset hellozr
(integer) 1
127.0.0.1:6379> sadd myset hellozhou
(integer) 1
127.0.0.1:6379> smembers myset #查看指定set的所有值
1) "hellozr"
2) "hello"
3) "hellozhou"
127.0.0.1:6379> sismember myset hello #判断某一个元素是否在set中,存在返回 1
(integer) 1
127.0.0.1:6379> sismember myset world #不存在这个元素会返回 0
(integer) 0
127.0.0.1:6379>
###############################################################################
127.0.0.1:6379> scard myset #获取set中元素的个数
(integer) 3
###############################################################################
# srem
127.0.0.1:6379> srem myset hello # 移除set中的指定元素
(integer) 1
127.0.0.1:6379> scard myset
(integer) 2
127.0.0.1:6379> smembers myset #查看set中的元素
1) "hellozr"
2) "hellozhou"
127.0.0.1:6379>
###############################################################################
# set 无序不重复集合
127.0.0.1:6379> sadd myset zhourr
(integer) 1
127.0.0.1:6379> smembers myset
1) "zhourr"
2) "hellozr"
3) "hellozhou"
127.0.0.1:6379> srandmember myset #随机抽选出一个元素
"hellozr"
127.0.0.1:6379> srandmember myset
"hellozhou"
127.0.0.1:6379> srandmember myset
"hellozr"
127.0.0.1:6379> srandmember myset
"hellozr"
127.0.0.1:6379>
###############################################################################
# 删除指定的key 随机删除key
127.0.0.1:6379> smembers myset
1) "zhourr"
2) "hellozr"
3) "hellozhou"
127.0.0.1:6379> spop myset #随机移除元素
"hellozr"
127.0.0.1:6379> spop myset
"hellozhou"
127.0.0.1:6379> smembers myset
1) "zhourr"
127.0.0.1:6379>
###############################################################################
# 将一个指定的值移动到另外一个set集合中
127.0.0.1:6379> sadd myset hello
(integer) 1
127.0.0.1:6379> sadd myset world
(integer) 1
127.0.0.1:6379> sadd myset zhour
(integer) 1
127.0.0.1:6379> sadd myset2 set2
(integer) 1
127.0.0.1:6379> smove myset myset2 zhour # 将一个指定的值移动到另外一个set集合中
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "hello"
2) "world"
127.0.0.1:6379> SMEMBERS myset2
1) "zhour"
2) "set2"
127.0.0.1:6379>
###############################################################################
# 共同关注(交集)
# SDIFF 差集
# SINTER 交集
# SUNION 并集
127.0.0.1:6379> sadd key1 a
(integer) 1
127.0.0.1:6379> sadd key1 b
(integer) 1
127.0.0.1:6379> sadd key1 c
(integer) 1
127.0.0.1:6379> sadd key2 c
(integer) 1
127.0.0.1:6379> sadd key2 d
(integer) 1
127.0.0.1:6379> sadd key2 e
(integer) 1
127.0.0.1:6379> SDIFF key1 key2 # 差集
1) "a"
2) "b"
127.0.0.1:6379> SINTER key1 key2 # 交集 共同好友
1) "c"
127.0.0.1:6379> SUNION key1 key2 # 并集
1) "a"
2) "b"
3) "c"
4) "e"
5) "d"
127.0.0.1:6379>
可以将 A 的所有关注放在一个集合中,将它的粉丝放在另一个集合中!
共同好友,共同爱好,二度好友,推荐好友!(六度分割理论)
Map集合,key-map集合,value变成了map集合!本质和String类型没有太大的区别,还是一个简单的key-value。
127.0.0.1:6379> hset myhash field1 zhourr # set一个具体的 key value
(integer) 1
127.0.0.1:6379> hget myhash field1 # 获取一个字段值
"zhourr"
127.0.0.1:6379> hmset myhash field1 hello field2 world # set 多个 key value
OK
127.0.0.1:6379> hmget myhash field1 field2 # 获取多个字段值
1) "hello"
2) "world"
127.0.0.1:6379> hgetall myhash # 获取全部的数据 key value
1) "field1"
2) "hello"
3) "field2"
4) "world"
127.0.0.1:6379>
###############################################################################
127.0.0.1:6379> hdel myhash field1 # 删除hash指定的key字段,对应的value值也被删除
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field2"
2) "world"
127.0.0.1:6379>
###############################################################################
# hlen
127.0.0.1:6379> hmset myhash field1 hello field2 world
OK
127.0.0.1:6379> hgetall myhash
1) "field2"
2) "world"
3) "field1"
4) "hello"
127.0.0.1:6379> hlen myhash # 获取hash 表的字段数量
(integer) 2
127.0.0.1:6379>
###############################################################################
# 判断 hash 中指定的key是否存在
127.0.0.1:6379> HEXISTS myhash field1 #判断 hash 中指定的key是否存在
(integer) 1
127.0.0.1:6379> HEXISTS myhash field3
(integer) 0
###############################################################################
#只获得所有的field
#只获得所有的value
127.0.0.1:6379> hkeys myhash #只获得所有的field
1) "field2"
2) "field1"
127.0.0.1:6379> hvals myhash #只获得所有的value
1) "world"
2) "hello"
127.0.0.1:6379>
###############################################################################
# hincrby
127.0.0.1:6379> hset myhash field3 5 # 指定增量
(integer) 1
127.0.0.1:6379> HINCRBY myhash field3 2
(integer) 7
127.0.0.1:6379> HINCRBY myhash field3 -3
(integer) 4
127.0.0.1:6379> hsetnx myhash field4 hello # 如果不存在,则可以设置
(integer) 1
127.0.0.1:6379> hsetnx myhash field4 world # 如果存在,则不可用设置
(integer) 0
127.0.0.1:6379>
hash 变更的数据 user name age ,尤其是用户信息的保存,或经常变动的信息。hash更适合对象的存储,string更适合字符串的存储。
在set的基础上增加了一个值,set k1 v1 , zset k1 score1 v1.
###############################################################################
127.0.0.1:6379> zadd myset 1 one #添加一个值
(integer) 1
127.0.0.1:6379> zadd myset 2 two 3 three # 添加多个值
(integer) 2
127.0.0.1:6379> zrange myset 0 -1 # 获取所有的值
1) "one"
2) "two"
3) "three"
127.0.0.1:6379>
###############################################################################
# 排序
127.0.0.1:6379> zadd salary 2500 xiaohong # 添加三个用户
(integer) 1
127.0.0.1:6379> zadd salary 5000 zhangsan
(integer) 1
127.0.0.1:6379> zadd salary 4000 zhour
(integer) 1
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf #显示全部用户,从负无穷到正无穷排序
1) "xiaohong"
2) "zhour"
3) "zhangsan"
127.0.0.1:6379> ZREVRANGE salary 0 -1 # 从大到小排序
1) "zhangsan"
2) "zhour"
3) "xiaohong"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf withscores # 从小到大显示,并附带成绩
1) "xiaohong"
2) "2500"
3) "zhour"
4) "4000"
5) "zhangsan"
6) "5000"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf 4000 withscores # 4000以下的员工的排序
1) "xiaohong"
2) "2500"
3) "zhour"
4) "4000"
127.0.0.1:6379> ZREVRANGEBYSCORE salary +inf -inf # 从大到小排序
1) "zhangsan"
2) "zhour"
3) "xiaohong"
###############################################################################
# 移除元素
127.0.0.1:6379> zrange salary 0 -1
1) "xiaohong"
2) "zhour"
3) "zhangsan"
127.0.0.1:6379> zrem salary xiaohong # 移除元素
(integer) 1
127.0.0.1:6379> zrange salary 0 -1
1) "zhour"
2) "zhangsan"
127.0.0.1:6379> zcard salary # 获取有序集合中的个数
(integer) 2
127.0.0.1:6379>
###############################################################################
# 获取指定区间的成员数量
127.0.0.1:6379> zadd myset 1 hello
(integer) 1
127.0.0.1:6379> zadd myset 2 world 3 zhour
(integer) 2
127.0.0.1:6379> zcount myset 1 3 # 获取指定区间的成员数量
(integer) 3