Redis学习

Redis基本了解

Redis(Remote Dictionary Server)是一个开源的使用ANSI C语言编写、支持网络,可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。其次redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并在此基础上实现master-slave(主从)同步。

Redis是免费开源,当下最热门的NoSQL技术之一,也叫结构化数据库。很多人就好奇Redis到底能干嘛,简单说:1、内存存储,持久化,内存中是断电即失、所以持久化很重要,常用的持久化方法(RDB做镜像全量持久化、AOF做增量持久化)。2、效率高,可以用于高速缓存。3、发布订阅系统。4、地图信息分析。5、计时器,计数器(浏览量)等。

首先我们要知道Redis中文文档 点击跳转.

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命令大全 →
访问Redis论坛 →
Redis使用内存计算器 →

其次说一下redis-key,简单说一下redis中key指令,

        首先启动redis-server.exe,开启redis服务,再启动redis-cli.exe连接redis,在客户端测试连接是否成功。        

 

127.0.0.1:6379> ping  #查看当前连接是否正常,正常返回PONG
PONG
127.0.0.1:6379> clear  #清楚当前控制台
127.0.0.1:6379> keys *  #查看当前库里所有的key
1) "age"
127.0.0.1:6379> flushall  #清空所有库的内容
OK
127.0.0.1:6379> keys * 
(empty list or set)
127.0.0.1:6379> set name local #添加一个key为‘name’ value为‘local ’的数据
OK
127.0.0.1:6379> get name  #查询key为‘name’的value值
"local "
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> set name1 host
OK
127.0.0.1:6379> get name1
"host"
127.0.0.1:6379> keys *  #查看当前库里所有的key
1) "name1"
2) "name"
127.0.0.1:6379> exists name  #判断当前key是否存在
(integer) 1
127.0.0.1:6379> move name 1  #移除当前库的key为‘name‘的数据,将数据放到数据库1
(integer) 1
127.0.0.1:6379> select 1    #选择数据库1
OK
127.0.0.1:6379[1]> keys *    #查询当前数据库的key
1) "name"
127.0.0.1:6379[1]> select 0    #选择数据库0
OK
127.0.0.1:6379> keys *
1) "name1"
127.0.0.1:6379> flushall  #再次清空所有库的内容
OK

## 多加几条数据 下面测试设置key的过期时间
127.0.0.1:6379> set name local
OK
127.0.0.1:6379> set name1 host
OK
127.0.0.1:6379> set name2 zdh
OK
127.0.0.1:6379> expire name 15  #设置key为’name‘的数据过期时间为15秒 单位seconds
(integer) 1
127.0.0.1:6379> ttl name  #查看当前key为’name‘的剩余生命周期时间
(integer) 13
127.0.0.1:6379> ttl name
(integer) 12
127.0.0.1:6379> ttl name
(integer) 11
127.0.0.1:6379> ttl name
(integer) 8
127.0.0.1:6379> ttl name
(integer) 6
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) 0
127.0.0.1:6379> ttl name  #如若返回-2,证明key已过期
(integer) -2
127.0.0.1:6379> get name    #再次查询即为空
(nil)
127.0.0.1:6379> type name1
string
127.0.0.1:6379> 

更多命令参考redis官网


Redis五大数据类型

 String(字符串),List(列表),Set(集合),Hash(哈希),zSet(有序集合)

1、String(字符串)

String是Redis中最常用的一种数据类型,也是Redis中最简单的一种数据类型,其表面上是字符串,但其实他可以灵活的表示字符串、整数、浮点数3种值,redis会自动的识别这三种值。

①进行添加、查询、追加、获取长度,判断是否存在的操作

127.0.0.1:6379> set name jack  #插入一个key为‘name’值为‘dingdada’的数据
OK
127.0.0.1:6379> get name  #获取key为‘name’的数据
"jack"
127.0.0.1:6379> keys *  #查看当前库的所有数据
1) "name"
127.0.0.1:6379> exists name  #判断key为‘name’的数据存在不存在,存在返回1
(integer) 1
127.0.0.1:6379> exists name1  #不存在返回0
(integer) 0
127.0.0.1:6379> append name1 love  #追加到key为‘name1’的数据后拼接值为‘love’,如果key存在类似于java中字符串‘+’,不存在则新增一个,类似于Redis中的set name1 love,并且返回该数据的总长度
(integer) 4
127.0.0.1:6379> get name1
"love"
127.0.0.1:6379> strlen name1  #查看key为‘name1’的字符串长度
(integer) 4
127.0.0.1:6379> append name1 ,rose  #追加,key存在的话,拼接‘+’,返回总长度
(integer) 9
127.0.0.1:6379> strlen name1
(integer) 9
127.0.0.1:6379> get name1
"love,rose"
127.0.0.1:6379> set key1 "hello world!"  #注意点:插入的数据中如果有空格的数据,请用“”双引号,否则会报错!
OK
127.0.0.1:6379> set key1 hello world!  #报错,因为在Redis中空格就是分隔符,相当于该参数已结束
(error) ERR syntax error
127.0.0.1:6379> set key1 hello,world!  #逗号是可以的
OK

②自增自减操作

127.0.0.1:6379> set num 12    #插入一个初始值为12的数据
OK
127.0.0.1:6379> get num
"12"
127.0.0.1:6379> incr num    #指定key为'num'的数据自增1,返回结果 相当于java中的i++
(integer) 13
127.0.0.1:6379> get num    #一般用来做文章浏览量、点赞数、收藏数等功能
"13"
127.0.0.1:6379> incr num
(integer) 14
127.0.0.1:6379> incr num
(integer) 15
127.0.0.1:6379> get num
"15"
127.0.0.1:6379> decr num  #指定key为'num'的数据自减1返回结果相当于java中的i--,可以减为负数
(integer) 14
127.0.0.1:6379> decr num  #一般用来做文章取消点赞,取消收藏等功能
(integer) 13
127.0.0.1:6379> decr num
(integer) 12
127.0.0.1:6379> decr num
(integer) 11
127.0.0.1:6379> incrby num 10 #后面跟上by 指定key为'num'的数据自增'参数(10)',返回结果
(integer) 21
127.0.0.1:6379> incrby num 10
(integer) 31
127.0.0.1:6379> decrby num 11 #后面跟上by 指定key为'num'的数据自减'参数(11)',返回结果
(integer) 20
127.0.0.1:6379> decrby num 10
(integer) 10
127.0.0.1:6379>

③截取,替换字符串操作

127.0.0.1:6379> set key1 "hello world!"
OK
127.0.0.1:6379> get key1
"hello world!"
127.0.0.1:6379> getrange key1 0 4    #截取字符串,相当于java中的subString,下标从0开始,不会改变原有数据
"hello"
127.0.0.1:6379> get key1
"hello world!"
127.0.0.1:6379> getrange key1 0 -1    #0至-1相当于 get key1,效果一致,获取整条数据
"hello world!"
127.0.0.1:6379> set key2 "local host"
OK
127.0.0.1:6379> get key2
"local host"
127.0.0.1:6379> setrange key2 5 ooo    #此语句跟java中replace有点类似,下标也是从0开始,但是有区别:java中是指定替换字符,Redis中是从指定位置开始替换,替换的数据根据你所需替换的长度一致,返回值是替换后的长度
(integer) 10
127.0.0.1:6379> get key2
"localooost"
127.0.0.1:6379> setrange key2 5 22    #该处只替换了两位
(integer) 10
127.0.0.1:6379> get key2
"local22ost"
127.0.0.1:6379>

④设置过期时间、不存在设置操作

#设置过期时间,跟Expire的区别是前者设置已存在的key的过期时间,而setex是在创建的时候设置过期时间
127.0.0.1:6379> setex name1 20 csdn    #新建一个key为'name1',值为'csdn',过期时间为20s的字符串数据
OK
127.0.0.1:6379> ttl name1    #查看key为'name1'的key的过期时间
(integer) 17
127.0.0.1:6379> ttl name1
(integer) 14
127.0.0.1:6379> ttl name1
(integer) 7
127.0.0.1:6379> ttl name1
(integer) 2
127.0.0.1:6379> ttl name1    #此时返回-2,证明该key已经过期,即不存在了
(integer) -2
127.0.0.1:6379> setnx name2 java    #如果key为'name2'不存在,新增数据,返回值为1证明成功
(integer) 1
127.0.0.1:6379> get name2
"java"
127.0.0.1:6379> keys *
1) "name2"
127.0.0.1:6379> setnx name2 node    #如果key为'name2'已存在,新增数据会失败,返回值为0,和set的区别在于:set会替换原有的值,而setnx不会,存在即不设置,确保数据误操作
(integer) 0
127.0.0.1:6379> get name2
"java"
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) "k1"
2) "k3"
3) "k2"
127.0.0.1:6379> mget k1 k2 k3    #查询key为 '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> keys *
1) "k1"
2) "k3"
3) "k2"
127.0.0.1:6379> msetnx k5 v5 k4 v4    #全部成功,返回值为1
(integer) 1
127.0.0.1:6379> keys *
1) "k1"
2) "k4"
3) "k3"
4) "k2"
5) "k5"
127.0.0.1:6379>

⑥添加获取对象,getset操作

#这里其实本质上还是字符串,但是我们讲其key巧妙的设计了一下。
##mset student:1:name  student 相当于类名,1 相当于id,name 相当于属性
#如果所需数据全部这样设计,那么我们在java的业务代码中,就不需要关注太多的key
#只需要找到student类,下面哪个id,需要哪个属性即可,减少了代码的繁琐,在一定程度上可以理解为这个一个类的对象!
127.0.0.1:6379> mset student:1:name jack student:1:age 22 #新增一个key为'student:1:name' value为'jack',key为'student:1:age',value为'22'的数据
OK
127.0.0.1:6379> keys *    #查看所有的key
1) "student:1:name"
2) "student:1:age"
127.0.0.1:6379> mget student:1:age student:1:name    #获取数据
1) "22"
2) "jack"
127.0.0.1:6379> getset name1 shy    #getset操作,先get再set,先获取key,如果没有,set值进去,返回的是get的值
(nil)
127.0.0.1:6379> get name1
"shy"
127.0.0.1:6379> getset name1 theshy    #先获取key,如果有,set(替换)最新的值进去,返回的是get的值
"shy"
127.0.0.1:6379> get name1    #替换成功
"theshy"
127.0.0.1:6379>

2、List(列表)

list实际上是一个链表(存储元素可重复),before node after,left,right都可以插入值,如果key不存在创建新的链表,如果key存在新增内容,如果移除了所有值,变为空链表也代表不存在,在两边插入或改动值效率最高,中间元素效率相对低一些,消息排队,消息队列(Lpush Rpop),栈(Lpush Lpop)

①lpush(左插入),lrange(查询集合),rpush(右插入)操作

127.0.0.1:6379> lpush list v1    #新增一个集合
(integer) 1
127.0.0.1:6379> lpush list v2
(integer) 2
127.0.0.1:6379> lpush list v3
(integer) 3
127.0.0.1:6379> lrange list 0 -1    #查询list所有元素值
1) "v3"
2) "v2"
3) "v1"
127.0.0.1:6379> lpush list1 v1 v2 v3 v4 v4    #批量添加集合元素
(integer) 5
127.0.0.1:6379> lrange list 0 -1    #注意lpush是左插入,left先进去的会到后面
1) "v3"
2) "v2"
3) "v1"
127.0.0.1:6379> lrange list1 0 -1    #注意lpush是左插入,left先进去的会到后面
1) "v4"
2) "v4"
3) "v3"
4) "v2"
5) "v1"
127.0.0.1:6379> lrange list 0 1    #指定查询列表中的元素,从下标零开始,1结束,两个元素
1) "v3"
2) "v2"
127.0.0.1:6379> lrange list 0 0    #指定查询列表中的唯一元素
1) "v3"
127.0.0.1:6379> rpush list v0    #右插入,跟lpush相反,这里添加进去元素是在尾部!
(integer) 4
127.0.0.1:6379> lrange list 0 -1    #查看集合所有元素
1) "v3"
2) "v2"
3) "v1"
4) "v0"
127.0.0.1:6379>
##这里我们可以做一个,保存的记录值(如:账号密码的记录),
每次都使用lpush,旧的数据永远在后面,我们每次获取 0 0 位置的元素,是不是相当于更新了
数据操作,但是数据记录还在?想要查询记录即可获取集合所有元素!

②lpop(左移除),rpop(右移除)操作

127.0.0.1:6379> lrange list 0 -1
1) "v3"
2) "v2"
3) "v1"
4) "v0"
127.0.0.1:6379> lpop list    #从头部开始移除第一个元素
"v3"
127.0.0.1:6379> lrange list 0 -1
1) "v2"
2) "v1"
3) "v0"
127.0.0.1:6379> rpop list
"v0"
127.0.0.1:6379> lrange list 0 -1    #从尾部开始移除第一个元素
1) "v2"
2) "v1"
127.0.0.1:6379>

③lindex(查询指定下标元素),llen(获取集合长度)操作

127.0.0.1:6379> lrange list 0 -1
1) "v2"
2) "v1"
127.0.0.1:6379> lindex list 1    #获取指定下标位置集合的元素,下标从0开始计数
"v1"
127.0.0.1:6379> lindex list 0    #类似java中的indexof
"v2"
127.0.0.1:6379> llen list    #获取指定集合的元素长度,类似于java中的length或size
(integer) 2
127.0.0.1:6379>

④lrem(根据value移除指定的值)这里

127.0.0.1:6379> lrange list 0 -1
1) "v2"
2) "v1"
127.0.0.1:6379> lrem list 1 v1    #移除集合list中的元素是v1的元素1个
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "v2"
127.0.0.1:6379> lrem list 0 v2    #移除集合list中的元素是v2的元素1个,这里的0和1效果是一致的
(integer) 1
127.0.0.1:6379> lrange list 0 -1
(empty list or set)
127.0.0.1:6379> lpush list v3 v2 v2 v2
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "v2"
2) "v2"
3) "v2"
4) "v3"
127.0.0.1:6379> lrem list 2 v2    #移除集合list中元素为v2的'2'个,这里的参数数量,如果实际中集合元素数量不达标,不会报错,全部移除后返回成功移除后的数量值
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "v2"
2) "v3"
127.0.0.1:6379>

⑤ltrim(截取元素),rpoplpush(移除指定集合中最后一个元素到一个新的集合中)操作

127.0.0.1:6379> lpush list v1 v2 v3 v4 v5
(integer) 5
127.0.0.1:6379> lrange list 0 -1
1) "v5"
2) "v4"
3) "v3"
4) "v2"
5) "v1"
127.0.0.1:6379> ltrim list 1 2    #通过下标截取指定的长度,这个list已经被改变了,只剩下我们所指定截取后的元素
OK
127.0.0.1:6379> lrange list 0 -1
1) "v4"
2) "v3"
127.0.0.1:6379> lpush list1 v0 v1 v2 v3 v4
(integer) 5
127.0.0.1:6379> lrange list1 0 -1
1) "v4"
2) "v3"
3) "v2"
4) "v1"
5) "v0"
127.0.0.1:6379> rpoplpush list1 newlist    #移除list集合中的最后一个元素到新的集合newlist中,返回值是移除的最后一个元素值
"v0"
127.0.0.1:6379> lrange list1 0 -1
1) "v4"
2) "v3"
3) "v2"
4) "v1"
127.0.0.1:6379> lrange newlist 0 -1    #确实存在该newlist集合并且有刚刚移除的元素,证明成功
1) "v0"
127.0.0.1:6379>

⑥lset(更新),linsert(插入)操作

127.0.0.1:6379> lrange list 0 -1
1) "v4"
2) "v3"
3) "v2"
4) "v1"
5) "v0"
127.0.0.1:6379> lset list 1 v004    #更新list集合中下标为‘1’的元素为'v004'
OK
127.0.0.1:6379> lrange list 0 -1    #查看证明更新成功
1) "v4"
2) "v004"
3) "v2"
4) "v1"
5) "v0"
127.0.0.1:6379> lset list1 0 v0v       #如果指定的'集合'不存在,报错
(error) ERR no such key
127.0.0.1:6379> lset list 8 v8v        #如果集合存在,但是指定的'下标'不存在,报错
(error) ERR index out of range
127.0.0.1:6379> lrange list 0 -1
1) "v4"
2) "v004"
3) "v2"
4) "v1"
5) "v0"
127.0.0.1:6379> linsert list after v1 insertv1    #在集合中的'v1'元素 '(after)之后' 加上一个元素
(integer) 6
127.0.0.1:6379> lrange list 0 -1
1) "v4"
2) "v004"
3) "v2"
4) "v1"
5) "insertv1"
6) "v0"
127.0.0.1:6379> linsert list before v1 insertv1    #在集合中的'v1'元素 '(before)之前' 加上一个元素
(integer) 7
127.0.0.1:6379> lrange list 0 -1
1) "v4"
2) "v004"
3) "v2"
4) "insertv1"
5) "v1"
6) "insertv1"
7) "v0"
127.0.0.1:6379>

3、Set(集合)

元素唯一不重复,可实现共同好友、共同关注等需求

①sadd(添加)、smembers(查看所有元素)、sismember(判断是否存在)、scard(查看长度)、srem(移除指定元素)操作

127.0.0.1:6379> sadd set1 I love you    #添加set集合可批量可单个
(integer) 3
127.0.0.1:6379> smembers set1    #查看set中所有元素
1) "I"
2) "love"
3) "you"
127.0.0.1:6379> sismember set1 I    #判断某个值在不在set中,在返回1
(integer) 1
127.0.0.1:6379> sismember set1 local    #不在返回0
(integer) 0
127.0.0.1:6379> scard set1    #查看集合的长度,相当于size、length
(integer) 3
127.0.0.1:6379> srem set1 you    #移除set中指定的元素
(integer) 1
127.0.0.1:6379> smembers set1    #查看set中所有元素,移除成功
1) "I"
2) "love"
127.0.0.1:6379>

②srandmember(抽随机)操作

127.0.0.1:6379> sadd sets 1 2 3 4 5 6 7    #在set中添加7个元素
(integer) 7
127.0.0.1:6379> smembers sets
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
127.0.0.1:6379> srandmember sets 1    #随机抽取sets中1个元素返回
1) "6"
127.0.0.1:6379> srandmember sets 1    #随机抽取sets中1个元素返回
1) "7"
127.0.0.1:6379> srandmember sets 1    #随机抽取sets中1个元素返回
1) "5"
127.0.0.1:6379> srandmember sets      #不填后参数,默认抽1个值,但是下面返回不会带序号
"2"
127.0.0.1:6379> srandmember sets 3    #随机抽取sets中3个元素返回
1) "7"
2) "6"
3) "3"
127.0.0.1:6379> srandmember sets 3    #随机抽取sets中3个元素返回
1) "4"
2) "7"
3) "6"
127.0.0.1:6379>

③spop(随机删除元素) ,smove(移动指定元素到新的集合中)

127.0.0.1:6379> smembers sets
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
127.0.0.1:6379> spop sets    #随机删除1个元素,不指定参数值即删除1个
"4"
127.0.0.1:6379> spop sets 1    #随机删除1个元素
1) "2"
127.0.0.1:6379> spop sets 2    #随机删除2个元素
1) "3"
2) "1"
127.0.0.1:6379> smembers sets    #查询删除后的结果
1) "5"
2) "6"
3) "7"
127.0.0.1:6379> smove sets set_local 1    #移动指定set中的指定元素到新的set中,失败(该元素不存在)
(integer) 0
127.0.0.1:6379> smove sets set_local 5    #移动指定set中的指定元素到新的set中,成功
(integer) 1
127.0.0.1:6379> smembers sets    #查询原来的set集合
1) "6"
2) "7"
127.0.0.1:6379> smembers set_local    #查询新的set集合,如果新的set存在,即往后加,如果不存在,则自动创建set并且加入进去
1) "5"
127.0.0.1:6379>

 ④sdiff(差集)、sinter(交集)、sunion(并集)操作

127.0.0.1:6379> sadd set1 1 2 3 4 5
(integer) 5
127.0.0.1:6379> sadd set2 4 5 6 7 8
(integer) 5
127.0.0.1:6379> smembers set1
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
127.0.0.1:6379> smembers set2
1) "4"
2) "5"
3) "6"
4) "7"
5) "8"
127.0.0.1:6379> sdiff set1 set2    #查询指定的set之间的差集,可以是多个set
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> sinter set1 set2     #查询指定的set之间的交集,可以是多个set
1) "4"
2) "5"
127.0.0.1:6379> sunion set1 set2    #查询指定的set之间的并集,可以是多个set
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
8) "8"
127.0.0.1:6379>

4、Hash(哈希)

比String更加适合存对象~

①hset(添加hash)、hget(查询)、hgetall(查询所有)、hdel(删除hash中指定的值)、hlen(获取hash的长度)、hexists(判断key是否存在)操作

127.0.0.1:6379> hmset hash_local name tx age 23     #添加hash多个,使用hmset
OK
127.0.0.1:6379> hset hash_local sex 1   #添加hash单个,使用hset
(integer) 1
127.0.0.1:6379> hget hash_local name    #获取hash中key是name的值
"tx"    
127.0.0.1:6379> hget hash_local age    #获取hash中key是age的值
"23"
127.0.0.1:6379> hget hash_local sex    #获取hash中key是sex的值
"1"
127.0.0.1:6379> hgetall hash_local    #获取hash中所有的值,包含key
1) "name"
2) "tx"
3) "age"
4) "23"
5) "sex"
6) "1"
127.0.0.1:6379> hset hash_local id 101    #添加
(integer) 1
127.0.0.1:6379> hgetall hash_local
1) "name"
2) "tx"
3) "age"
4) "23"
5) "sex"
6) "1"
7) "id"
8) "101"
127.0.0.1:6379> hdel hash_local sex id    #删除指定hash中的key(可多个),key删除后对应的value也会被删除
(integer) 2
127.0.0.1:6379> hgetall hash_local
1) "name"
2) "tx"
3) "age"
4) "23"
127.0.0.1:6379> hlen hash_local    #获取指定hash的长度,相当于length、size
(integer) 2
127.0.0.1:6379> hexists hash_local name    #判断key是否存在于指定的hash,存在返回1
(integer) 1
127.0.0.1:6379> hexists hash_local sex    #判断key是否存在于指定的hash,存在返回1
(integer) 0
127.0.0.1:6379>

②hkeys(获取所有key)、hvals(获取所有value)、hincrby(给值加增量)、hsetnx(存在不添加)操作 

127.0.0.1:6379> hset hashs name local    #添加hash单个
(integer) 1
127.0.0.1:6379> hmset hashs weight 120 high 180    #添加hash多个
OK
127.0.0.1:6379> hgetall hashs    #获取hash中所有的值,包含key
1) "name"
2) "local"
3) "weight"
4) "120"
5) "high"
6) "180"
127.0.0.1:6379> hkeys hashs    #获取指定hash中的所有key
1) "name"
2) "weight"
3) "high"
127.0.0.1:6379> hvals hashs    #获取指定hash中的所有value
1) "local"
2) "120"
3) "180"
127.0.0.1:6379> hincrby hashs weight 5    #让hash中weight的value指定+5(自增)
(integer) 125
127.0.0.1:6379> hincrby hashs weight -10    #让hash中weight的value指定-10(自减)
(integer) 115
127.0.0.1:6379> hsetnx hashs noKey noValue    #添加不存在就新增返回新增成功的数量(只能单个增加)
(integer) 1    
127.0.0.1:6379> hsetnx hashs name host    #添加存在则失败返回0
(integer) 0
127.0.0.1:6379> hgetall hashs
1) "name"
2) "local"
3) "weight"
4) "115"
5) "high"
6) "180"
7) "noKey"
8) "noValue"
127.0.0.1:6379>

5、zSet(有序集合)

成绩表排序,工资表排序,年龄排序等需求可以用zset来实现!

①zadd(添加)、zrange(查询)、zrangebyscore(排序小-大)、zrevrange(排序大-小)、zrangebyscore withscores(查询所有值包含key)操作

127.0.0.1:6379> zadd myzset 1 one 2 two 3 three    #添加zset值可以多个
(integer) 3
127.0.0.1:6379> zrange myzset 0 -1    #查询所有的值
1) "one"
2) "two"
3) "three"
127.0.0.1:6379> zrangebyscore myzset -inf +inf    #将zset的值根据key来从小到大排序并输出    -inf 负无穷  +inf 正无穷
1) "one"
2) "two"
3) "three"
127.0.0.1:6379> zrangebyscore myzset (1 2    #返回所有符合条件 1 < score <= 2 的成员
1) "two"
127.0.0.1:6379> zrangebyscore myzset (1 (3  #返回所有符合条件 1 < score < 3 的成员  
1) "two"
127.0.0.1:6379> zrange myzset 0 -1 withscores    # 递增排列
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
127.0.0.1:6379> zrevrange myzset 0 -1 withscores    # 递减排列
1) "three"
2) "3"
3) "two"
4) "2"
5) "one"
6) "1"
127.0.0.1:6379> zrangebyscore myzset -inf +inf withscores    #查询指定zset的所有值,包含序号的值
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
127.0.0.1:6379>

②zrem(移除元素)、zcard(查看元素个数)、zcount(查询指定区间内的元素个数)操作

127.0.0.1:6379> zadd myset 1 v1 2 v2 3 v3 4 v4
(integer) 4
127.0.0.1:6379> zrange myset 0 -1
1) "v1"
2) "v2"
3) "v3"
4) "v4"
127.0.0.1:6379> zrem myset v3    #移除指定的元素,可多个
(integer) 1
127.0.0.1:6379> zrange myset 0 -1
1) "v1"
2) "v2"
3) "v4"
127.0.0.1:6379> zcard myset    #查看zset的元素个数,相当于长度,size。
(integer) 3
127.0.0.1:6379> zcount myset 0 100    #查询指定区间内的元素个数
(integer) 3
127.0.0.1:6379> zcount myset 0 2    #查询指定区间内的元素个数
(integer) 2
127.0.0.1:6379>

<think>好的,我现在需要帮助用户学习Redis,从入门到精通。首先,用户已经提供了一些参考资料,包括引用1、2、3,我需要结合这些内容来组织回答。 首先,我应该确定用户的需求是什么。用户想要学习Redis的相关知识,从入门到精通。所以回答需要结构清晰,分阶段指导,并且提供学习资料和相关问题。 根据用户提供的引用,引用2提到Redis是内存数据库/缓存/消息队列,所以需要先介绍Redis的基本概念和应用场景。引用1和引用3涉及环境搭建和配置,以及一些参考资料链接,比如优快云的博客和另一篇博客。这些可以作为学习资料的一部分推荐给用户。 接下来,我需要按照系统级指令的要求,确保数学公式正确使用,但Redis相关的内容可能较少涉及数学公式,所以可能不需要太多这方面的处理。但如果有性能分析或算法部分,可能需要使用行内或独立公式,例如时间复杂度O(n)之类的,可以写成$O(n)$。 然后,用户要求生成相关问题,放在最后。需要确保问题与Redis相关,覆盖入门、进阶、配置优化、应用场景、高可用方案以及高级数据结构等方面。 回答的结构应该分为几个部分:入门阶段、进阶阶段、精通阶段,每个阶段推荐资料和重点内容。同时,结合用户提供的引用,例如环境搭建部分可以参考引用1和引用2,HyperLogLog部分可以参考引用3中的链接。 还需要注意引用标识的正确添加,例如在提到环境搭建时引用[^1][^2],在HyperLogLog部分引用[^3]。 最后,检查是否符合所有系统级指令:正确使用LaTeX(如果有的话),中文回答,生成相关问题,引用标识自然添加。同时,确保回答真实可靠,结构清晰,帮助用户逐步学习。 现在开始组织内容: 入门阶段需要介绍Redis的基本概念、安装配置和基础命令。引用2提到Redis是内存数据库,可以作为缓存和消息队列,这部分需要强调。引用1的环境搭建步骤需要整理,比如复制配置文件到/etc/redis,修改配置并启动。可以推荐官方文档和用户提供的优快云博客作为资料。 进阶阶段包括持久化机制、主从复制、哨兵模式、集群部署,以及数据类型的使用场景。需要结合引用中的信息,比如环境配置可能涉及持久化的设置,引用3中的HyperLogLog属于高级数据结构,可以放在进阶或精通阶段。 精通阶段涉及源码分析、性能调优、高可用方案(如Redis Cluster)、高级数据结构(HyperLogLog、Streams)。引用3中的HyperLogLog部分可以作为参考资料。 相关问题需要涵盖各个阶段的内容,例如如何选择数据结构、持久化机制的区别、集群部署步骤、性能优化方法、高可用方案比较,以及HyperLogLog的应用,这些问题可以帮助用户深入学习。 最后,确保所有引用正确对应,例如引用对应环境配置,引用对应Redis定义,引用[^3]对应HyperLogLog的参考链接。</think>### Redis学习路径:从入门到精通 #### 一、**入门阶段** 1. **核心概念** Redis是一个基于内存的键值存储系统,支持多种数据结构(字符串、哈希、列表等),常用于缓存、消息队列和实时数据分析。 关键术语:键值对、持久化(RDB/AOF)、单线程模型、数据类型(如`String`, `Hash`, `List`)。 2. **环境搭建** - **安装步骤**: ```bash # 下载源码编译安装 wget http://download.redis.io/releases/redis-6.2.6.tar.gz tar xzf redis-6.2.6.tar.gz cd redis-6.2.6 make make install ``` - **配置启动**: 复制配置文件到`/etc/redis`目录,修改`redis.conf`(如设置`daemonize yes`后台运行),启动命令:`redis-server /etc/redis/redis.conf`[^1]。 3. **基础操作** 学习`SET/GET`命令、数据类型操作(如`HSET/HGET`)、过期时间设置(`EXPIRE`)等。 **推荐资料**: - [Redis官方文档](https://redis.io/documentation) - [《Redis设计与实现》](http://redisbook.com/)(入门章节) --- #### 二、**进阶阶段** 1. **核心机制** - **持久化**: RDB(快照)通过`SAVE`或`BGSAVE`生成数据快照;AOF(追加日志)记录写操作,提供更高数据安全性。 配置示例: ```bash # redis.conf appendonly yes # 启用AOF appendfsync everysec # 每秒同步 ``` - **高可用**: 主从复制(`replicaof`配置)、哨兵模式(故障自动切换)、Redis Cluster(分布式分片)。 2. **应用场景** - **缓存**:缓存雪崩/穿透/击穿解决方案(如布隆过滤器)。 - **消息队列**:使用`List`实现队列,或`Streams`支持消费者组。 - **实时统计**:利用`HyperLogLog`估算基数(如UV统计)[^3]。 3. **推荐资料**: - [Redis实战](https://book.douban.com/subject/26612779/)(应用案例详解) - [Redis进阶笔记](https://zhangc233.github.io/2021/05/02/Redis/)(含`HyperLogLog`解析) --- #### 三、**精通阶段** 1. **源码与性能优化** - 阅读Redis源码(如事件循环`ae.c`、数据结构`dict.c`)。 - 性能调优:内存碎片整理(`MEMORY PURGE`)、慢查询分析(`SLOWLOG`)、网络瓶颈排查。 2. **高级特性** - **Lua脚本**:原子化执行复杂操作。 - **模块化扩展**:自定义数据类型(如[RedisJSON](https://redis.io/docs/stack/json/))。 - **流处理**:`Streams`支持消息持久化和消费者组。 3. **推荐资料**: - [Redis源码剖析](https://github.com/huangz1990/redis-3.0-annotated)(注释版源码) - [Redis深度历险](https://book.douban.com/subject/30386804/)(原理与优化) --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值