Redis入门——数据类型(五种基本数据类型和三种特殊类型)

本文是作者学习Redis的详细笔记,涵盖了Redis的基础知识,包括数据库切换、清空操作,以及五大数据类型的使用:String(计数、统计)、List(消息队列)、Set(无序集合)、Hash(对象存储)和Zset(有序集合)。此外,还介绍了Redis的特殊类型,如Geo(地理位置)和HyperLogLog(基数统计)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先声明,本系列Redis博文内容是本人学习 【狂神说Java】Redis最新超详细版教程通俗易懂整理的学习笔记,本人也是初次接触Redis,水平有限,难免有错误不足之处,欢迎大家评论指正交流。
 

一、Redis基础知识

Redis默认有16个数据库,使用select num,可以切换数据库, 默认使用下标为0的数据库,下标从0开始[0,15],dbsize可以看数据库当前大小
 
 
flushdb//清空当前数据库
flushall//清空所有数据库
 
redis是单线程的,指的是网络请求模块只使用了一个线程(不需要考虑并发安全性),即一个线程处理所有网络请求,其他模块仍用了多个线程
        Redis很快,Redis是基于内存操作的,CPU不是Redis性能瓶颈,Redis的瓶颈是机器的内存和网络带宽,既然可以使用单线程来实现,就使用单线程了!
        为什么Redis单线程还这么快?每秒100000QPS
            ——绝大多数请求是基于内存操作(非常快速),Redis数据都存储在内存中
            ——单线程,避免了不必要的上下文切换和竞争条件,不需要考虑各种锁的性能消耗
            ——非阻塞IO,多路IO复用
 
    如果CPU成为Redis瓶颈,或者不想让服务器其他CPU核闲置,可以多起几个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 Key 
        基本命令:keys *       //查看当前数据库所有key
                        EXISTS key    //查看key是否存在
                        set key value    //添加key-value
                        move key db    //将key从当前数据库移动到db数据库
                        expire key seconds    //将可以设置为seconds后过期
                        del key        //删除key
                        ttl key            //查看当前key的剩余时间
                        type key        //查看当前key的类型
    
       
 

1.string类型

     基本命令:
    append key str  //追加字符串
    strlen key  //key长度
    incr key    //自增1
    decr key    //自减1
    incrby key length //自增length
    decrby key 10 //自减10
    getrange key start end //截取字符串,从start到end,从0开始
    setex(set with expire) //设置过期时间
    setex key2 30 hello //设置key2对应的value为hello,30秒后过期
    setnx(set if not exist)//分布式锁常用(原子性操作),如果不存在则创建,如果存在就创建失败 ,在分布式锁中经常用到
    
    批量设置与获取
    mset     mset key1 v1 key2 v2 key3 v3 key4 v4 ...//批量设置key-value
    mget     mget key1 key2 key3 key4 ...        //批量获取key对应的value
    msetnx(批量操作,原子性操作,要么都成功,要么都不成功,如果其中存在一个key则所有的都失败,即当且仅当所有key都不存在)
    getset key value //如果不存在值,则返回NULL,如果存在值,先返回旧值再设置新值
    
 
127.0.0.1:6379> set key1 v1//添加key-value
OK
127.0.0.1:6379> get key1//获得value
"v1"
127.0.0.1:6379> append key1 helloworld//追加字符串,如果当前key不存在就相当于set key value
(integer) 12
127.0.0.1:6379> get key1
"v1helloworld"
127.0.0.1:6379> strlen key1//获得当前key对应value的长度
(integer) 12
127.0.0.1:6379>
 
127.0.0.1:6379> incr views    //自增1
(integer) 2
127.0.0.1:6379> incr views    //自增1
(integer) 3
127.0.0.1:6379> incr views    //自增1
(integer) 1
127.0.0.1:6379> incr views     //自增1
(integer) 2
127.0.0.1:6379> incr views
(integer) 4
127.0.0.1:6379> incr views
(integer) 5
127.0.0.1:6379> get views
"5"
127.0.0.1:6379> incr views
(integer) 6
127.0.0.1:6379> get views
"6"
127.0.0.1:6379> decr views
(integer) 5
127.0.0.1:6379> get views
"5"
127.0.0.1:6379> get views
"5"
127.0.0.1:6379> decr views
(integer) 4
127.0.0.1:6379> incr by views 10   //自增10
(error) ERR wrong number of arguments for 'incr' command
127.0.0.1:6379> incrby views 10   //自增10
(integer) 14
127.0.0.1:6379> incrby views 10
(integer) 24
127.0.0.1:6379> decrby views 5    //自减5
(integer) 19
127.0.0.1:6379> decrby views 5    //自减5
(integer) 14
127.0.0.1:6379>
 
127.0.0.1:6379> set key1 hello,world
OK
127.0.0.1:6379> get keys
(nil)
127.0.0.1:6379> get key1
"hello,world"
127.0.0.1:6379> getrange key1 0 3
"hell"
127.0.0.1:6379> getrange key1 0 -1
"hello,world"
127.0.0.1:6379>
 
string类型类似的使用场景:value除了是字符串还能是数字
    ——计数器
    ——统计单位的数量
    ——粉丝数
    ——对象缓存存储
 

2.List类型

基本的数据类型,列表    
    lpush key value1 value2...  //将一个值或者多个值,插入到列表头部(左)
    lpop key             //从头开始弹出
    rpush key value1 value2    //从尾部插入
    rpop key             //从尾部弹出
    lrange key start end      //获取List中的值
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> lpush list1 one two three //插入列表
(integer) 3
127.0.0.1:6379> lrange list1 0 -1 //获取List中的值
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> lpop list1 2  //弹出
1) "three"
2) "two"
127.0.0.1:6379> lrange list1 0 -1  //获取List中的值
1) "one"
127.0.0.1:6379> lpush list1 two three //插入列表
(integer) 3
127.0.0.1:6379> lrange list1 0 -1
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> rpop list1 1  //从尾部弹出1个元素
1) "one"
127.0.0.1:6379> rpop list1   //从尾部弹出1个元素
"two"
127.0.0.1:6379> lrange list1 0 -1
1) "three"
 
********************************************************
127.0.0.1:6379> lrange list1 0 -1
1) "three"
2) "two"
3) "three"
127.0.0.1:6379> lindex list1 0    //显示index index0的value
"three"
127.0.0.1:6379> lindex list1 1    //显示index index1的value
"two"
127.0.0.1:6379> lindex list1 2    //显示index index2的value
"three"
********************************************************
rpoplpush  //移除列表的最后一个元素并将其移动到另一个list中
127.0.0.1:6379> lrange list1 0 -1
1) "three"
2) "two"
3) "three"
127.0.0.1:6379> rpopLpush list1 list2
"three"
127.0.0.1:6379> lrange list1 0 -1
1) "three"
2) "two"
127.0.0.1:6379> lrange list2 0 -1
1) "three"
127.0.0.1:6379> keys *
1) "list1"
2) "list2"
********************************************************
127.0.0.1:6379> exists list1    //判断list1是否存在,存在返回1,不存在返回0
(integer) 1
127.0.0.1:6379> exists list2    //判断list2是否存在,存在返回1,不存在返回0
(integer) 1
127.0.0.1:6379> exists list3
(integer) 0
********************************************************
127.0.0.1:6379> lrange list1 0 -1
1) "three"
2) "two"
127.0.0.1:6379> lset list1 1 three   //lset通过索引下标设置value
OK
127.0.0.1:6379> lrange list1 0 -1
1) "three"
2) "three"
127.0.0.1:6379>
********************************************************
linsert 将某个具体的value插入到List中某个元素的前面或者后面
 
List使用场景,可用作消息队列,栈、队列
 

3.Set类型

********************************************************
set中命令大都以s开头
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> sadd myset hello world moring   //新建set往里面存值
(integer) 3
127.0.0.1:6379> smembers mysat
(empty array)
127.0.0.1:6379> smembers myset            //查看myset中的成员
1) "moring"
2) "world"
3) "hello"
127.0.0.1:6379> sismember myset world        //查看myset中是否存在world
(integer) 1
127.0.0.1:6379> sismember myset worl         //查看myset中是否存在worl
(integer) 0
127.0.0.1:6379> scard myset               //查看myset中的元素个数
(integer) 3
127.0.0.1:6379> sadd myset wto
(integer) 1
127.0.0.1:6379> scard myset                //查看myset中的元素个数
(integer) 4
127.0.0.1:6379> srem myset world             //移除myset中某个元素
(integer) 1
127.0.0.1:6379> scard myset
(integer) 3
127.0.0.1:6379> sismember myset world
(integer) 0
********************************************************
Set集合是无序不重复集合,可以做随机抽取
127.0.0.1:6379> srandmember myset              //随机抽取元素
"moring"
127.0.0.1:6379> srandmember myset
"hello"
127.0.0.1:6379> srandmember myset
"hello"
127.0.0.1:6379> srandmember myset
"hello"
127.0.0.1:6379> srandmember myset
"hello"
127.0.0.1:6379> srandmember myset
"moring"
127.0.0.1:6379> srandmember myset
"hello"
127.0.0.1:6379> srandmember myset
"moring"
127.0.0.1:6379> srandmember myset
"hello"
127.0.0.1:6379> srandmember myset
"moring"
127.0.0.1:6379> srandmember myset
"wto"
********************************************************
127.0.0.1:6379> smembers myset
1) "wto"
2) "moring"
3) "hello"
127.0.0.1:6379> spop myset            //随机移除一个元素
"hello"
127.0.0.1:6379> spop myset
"wto"
********************************************************
127.0.0.1:6379> smembers myset
1) "moring"
127.0.0.1:6379> smembers myset2
1) "zhangsan"
127.0.0.1:6379> smove myset myset2 moring    //将myset中的moring元素移动到myset2中
(integer) 1
127.0.0.1:6379> smembers myset2
1) "moring"
2) "zhangsan"
127.0.0.1:6379> smembers myset
(empty array)
********************************************************
微博,B站,共同关注(交集)
数字集合类的交集
微博,A用户将所有关注的人放在一个set集合中!将它的粉丝也放在一个集合中
A和B的共同关注,共同粉丝,二度好友,推荐好友等等都是用set集合做
127.0.0.1:6379> smembers myset   //查看myset中的元素
1) "a"
2) "b"
3) "c"
127.0.0.1:6379> smembers myset2    //查看myset2中的元素
1) "zhangsan"
2) "d"
3) "moring"
4) "ec"
5) "c"
127.0.0.1:6379> sdiff myset myset2    //以myset为标准去对比myset2,看其中的差异元素
1) "a"
2) "b"
127.0.0.1:6379> sdiff myset2 myset    //以myset2为标准去对比myset,看其中的差异元素
1) "moring"
2) "zhangsan"
3) "ec"
4) "d"
127.0.0.1:6379> sinter myset myset2    //交集
1) "c"
127.0.0.1:6379> sunion myset myset2     //并集
1) "a"
2) "zhangsan"
3) "b"
4) "d"
5) "moring"
6) "ec"
7) "c"
127.0.0.1:6379>、
 

4.Hash类型

********************************************************
hash变更的数据user name age ,尤其是用户信息之类的,经常变动的信息,hash更适合于对象的存储!
key-value,只是这个value是一个map集合,本质和string类型没太大区别,相当于key-(keyn,valuen)
127.0.0.1:6379> hset myhash key1 value1       //myhash-(key1,value1)
(integer) 1
127.0.0.1:6379> hget myhash key1 
"value1"
127.0.0.1:6379> hset myhash key1 value1 key2 value2   //设置多个值
(integer) 1
127.0.0.1:6379> hmget  myhash key1 key2    //
1) "value1"
2) "value2"
127.0.0.1:6379> hgetall myhash   //获取全部的key-value
1) "key1"
2) "value1"
3) "key2"
4) "value2"
127.0.0.1:6379> hgetall myhash
1) "key1"
2) "value1"
3) "key2"
4) "value2"
 
127.0.0.1:6379> hstrlen myhash key1         //获取长度
(integer) 6
127.0.0.1:6379> hexists myhash key1        //查看是否存在
(integer) 1
127.0.0.1:6379> hexists myhash key3        //查看是否存在
(integer) 0
127.0.0.1:6379> hgetall myhash           //获取hash中全部的值
1) "key1"
2) "value1"
3) "key2"
4) "value2"
 
127.0.0.1:6379> hgetall myhash
1) "key1"
2) "value1"
3) "key2"
4) "value2"
127.0.0.1:6379> hsetnx myhash key3 value3         //如果不存在则设置
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "key1"
2) "value1"
3) "key2"
4) "value2"
5) "key3"
6) "value3"
127.0.0.1:6379> hsetnx myhash key3 value4        //如果存在则设置失败
(integer) 0
127.0.0.1:6379> hgetall myhash
1) "key1"
2) "value1"
3) "key2"
4) "value2"
5) "key3"
6) "value3"
 
127.0.0.1:6379> hset user:1 name qinjiang       //设置值
(integer) 1
127.0.0.1:6379> hget user:1 name
"qinjiang"
 

5.Zset

********************************************************
有序集合,与set不同的是每个元素会关联一个double的分数,redis正是通过分数来为集合中的成员进行从小到大的排序的,有序集合的成员是唯一的,但分数却可以重复
127.0.0.1:6379> zadd salary 2500 xiaohong
(integer) 1
127.0.0.1:6379> zadd salary 2000 zhangsan
(integer) 1
127.0.0.1:6379> zadd salary 1000 lisi
(integer) 1
127.0.0.1:6379> zrange salary 0 2500
1) "lisi"
2) "zhangsan"
3) "xiaohong"
127.0.0.1:6379> zrange salary 0 2400
1) "lisi"
2) "zhangsan"
3) "xiaohong"
127.0.0.1:6379> zrange salary 0 1
1) "lisi"
2) "zhangsan"
127.0.0.1:6379> zrange salary 0 2500            //通过索引区间返回有序集合指定索引区间内的成员
1) "lisi"
2) "zhangsan"
3) "xiaohong"
 
127.0.0.1:6379> zrange salary -inf +inf
(error) ERR value is not an integer or out of range
127.0.0.1:6379> zrange salary -inf +inf withscores
(error) ERR value is not an integer or out of range
127.0.0.1:6379> zrangebyscore salary -inf +inf              //按照score返回指定区间内的值
1) "lisi"
2) "zhangsan"
3) "xiaohong"
127.0.0.1:6379> zrangebyscore salary 0 2400                //按照score返回指定区间内的值
1) "lisi"
2) "zhangsan"
127.0.0.1:6379> zrangebyscore salary 2000 2500            //按照score返回指定区间内的值
1) "zhangsan"
2) "xiaohong"
127.0.0.1:6379> zrangebyscore salary -inf +inf                //按照score返回指定区间内的值,负无穷到正无穷
1) "lisi"
2) "zhangsan"
3) "xiaohong"
127.0.0.1:6379> zrangebyscore salary 0 2400
1) "lisi"
2) "zhangsan"
127.0.0.1:6379> zrangebyscore salary 2000 2500
1) "zhangsan"
2) "xiaohong"
127.0.0.1:6379> zrange salary -1 2
1) "xiaohong"
127.0.0.1:6379> zrangebyscore salary 2000 2500 withsccores
(error) ERR syntax error
127.0.0.1:6379> zrangebyscore salary 2000 2500 withscores
1) "zhangsan"
2) "2000"
3) "xiaohong"
4) "2500"
127.0.0.1:6379> zcard salary                //统计元素个数
(integer) 3
127.0.0.1:6379> zrem salary xiaohong   //移除元素
(integer) 1
127.0.0.1:6379> zcard salary                //统计元素个数
(integer) 2
 
 
127.0.0.1:6379> zcard salary
(integer) 3
127.0.0.1:6379> zrem salary xiaohong          //移除元素
(integer) 1
127.0.0.1:6379> zcard salary
(integer) 2
127.0.0.1:6379> zrevrange salary 0 -
(error) ERR value is not an integer or out of range
127.0.0.1:6379> zrevrange salary 0 -1            //从大到小排序
1) "zhangsan"
2) "lisi"
案例思路:set排序,存储班级成绩表,工资表排序
普通消息 1,重要消息2,带权重排序进行判断
排行榜应用实现
 

三、三种特殊类型

 

1.geospatial地理位置详解

********************************************************
将指定的地理空间位置(经度、 纬度、 名称)添加到指定的key中。这些数据会存储到sorted set这样的目的是为了方便使用georadius或者georadiusbymember命令对数据进行半径查询等操作
 
#geoadd添加数据
127.0.0.1:6379> geoadd china:city 116.40 39.90 beijing                //添加数据  key-value (经度、纬度、名称)
(integer) 1
127.0.0.1:6379> geoadd china:city 121.47 31.23 shanghai
(integer) 1
127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqing
(integer) 1
127.0.0.1:6379> geoadd china:city 114.05 22.52 shengzhen
(integer) 1
127.0.0.1:6379> geoadd china:city 120.06 30.24 hangzhou 108.96 34.26 xian
(integer) 2
 
#geopos获得当前定位,一定是个经纬度定位
127.0.0.1:6379> geopos china:city beijing                            //获取经纬度
1) 1) "116.39999896287918091"
   2) "39.90000009167092543"
127.0.0.1:6379> geopos china:city hangzhou
1) 1) "120.0600019097328186"
   2) "30.2400003229490224"
#geodist,获取两地之间的距离
127.0.0.1:6379> geodist china:city beijing shanghai        //查看beijing shanghai之间的距离 单位m
"1067378.7564"
127.0.0.1:6379> geodist china:city beijing shanghai km    //查看beijing shanghai之间的距离,单位km
"1067.3788"
 
# georadius,以给定的定位为圆心,找出半径内的元素
127.0.0.1:6379> georadius china:city 110 30 1000 km withdist         //以经度110 纬度30 为圆心,查找半径1000Km范围内的地点(集合中存在的),显示距离
1) 1) "chongqing"
   2) "341.9374"
2) 1) "xian"
   2) "483.8340"
3) 1) "shengzhen"
   2) "924.6408"
4) 1) "hangzhou"
   2) "967.9068"
127.0.0.1:6379> georadius china:city 110 30 1000 km withcoord        //以经度110 纬度30 为圆心,查找半径1000Km范围内的地点(集合中存在的),带定位信息
1) 1) "chongqing"
   2) 1) "106.49999767541885376"
      2) "29.52999957900659211"
2) 1) "xian"
   2) 1) "108.96000176668167114"
      2) "34.25999964418929977"
3) 1) "shengzhen"
   2) 1) "114.04999762773513794"
      2) "22.5200000879503861"
4) 1) "hangzhou"
   2) 1) "120.0600019097328186"
      2) "30.2400003229490224"
127.0.0.1:6379> georadius china:city 110 30 1000 km withcoord count 2    //以经度110 纬度30 为圆心,查找半径1000Km范围内的地点(集合中存在的),带定位,限制两个(由近到远)
1) 1) "chongqing"
   2) 1) "106.49999767541885376"
      2) "29.52999957900659211"
2) 1) "xian"
   2) 1) "108.96000176668167114"
      2) "34.25999964418929977"
127.0.0.1:6379> georadius china:city 110 30 1000 km withcoord count 1//以经度110 纬度30 为圆心,查找半径1000Km范围内的地点(集合中存在的),带定位信息,限制一个(由近到远)
1) 1) "chongqing"
   2) 1) "106.49999767541885376"
      2) "29.52999957900659211"
#georadiusbymember 找出位于指定元素周围范围内的其他元素
127.0.0.1:6379> georadiusbymember china:city  beijing 400 km        //找出位于指定beijing400km范围内的其他元素
1) "beijing"
127.0.0.1:6379> georadiusbymember china:city  beijing 500 km        //找出位于指定beijing500km范围内的其他元素
1) "beijing"
127.0.0.1:6379> georadiusbymember china:city  beijing 1100 km        //找出位于指定beijing1100km范围内的其他元素
1) "beijing"
2) "shanghai"
3) "xian"
127.0.0.1:6379> georadiusbymember china:city  shanghai 500 km        //找出位于指定shanghai500km范围内的其他元素
1) "hangzhou"
2) "shanghai"
 
#geo底层是Zset实现的。可以使用Zset命令来操作geo
127.0.0.1:6379> zrange china:city 0 -1     //查看全部元素
1) "chongqing"
2) "xian"
3) "shengzhen"
4) "hangzhou"
5) "shanghai"
6) "beijing"
127.0.0.1:6379> zrem china:city xian         //移除元素
(integer) 1
127.0.0.1:6379> zrange china:city 0 -1
1) "chongqing"
2) "shengzhen"
3) "hangzhou"
4) "shanghai"
5) "beijing"

2.hyperloglog详解

做基数统计的算法

基数:集合中不重复元素的个数,可以接收误差

比如要统计网页的UV(一个人访问网站多次,还是算一个人)
传统方式:set保存用户ID,利用其去重性质来统计。如果用户过多,就会占用大量内存,目的是为了计数,而不是保存用户ID
hyperloglog解决,占用的内存固定,2^64不同的元素的技术,只需要12KB内存,如果要从内存角度来比较的话,Hyperloglog首选!
有0.81%的误差率,可以接受。如果允许容错,那么一定可以使用Hyperloglog,如果不允许容错,就使用set或者自己的数据类型
127.0.0.1:6379> pfadd mykey a b c d e f g h i j        //创建第一组
(integer) 1
127.0.0.1:6379> pfcount mykey                  //统计元素个数
(integer) 10
127.0.0.1:6379> pfadd mykey2 i j z x c v b n m        //创建第一组
(integer) 1
127.0.0.1:6379> pfcount mykey2
(integer) 9
127.0.0.1:6379> pfmerge mykey3 mykey mykey2         //合并两组
OK
127.0.0.1:6379> pfcount mykey3
(integer) 15

3.Bitmap

位存储
统计用户信息,活跃,不活跃,登录,未登录! 打卡,未打卡,650天打卡。两个状态的,都可以使用Bitmaps
Bitmaps位图,数据结构,都是操作二进制位来进行记录,就只有0和1两个状态
365天=365bit   1Byte=8bit   46个字节左右
127.0.0.1:6379> setbit sign 0 1      //设置0号位置状态为1
(integer) 0
127.0.0.1:6379> setbit sign 1 0    //设置1号位置状态为0
(integer) 0
127.0.0.1:6379> setbit sign 2 0
(integer) 0
127.0.0.1:6379> setbit sign 3 1
(integer) 0
127.0.0.1:6379> setbit sign 4 1
(integer) 0
127.0.0.1:6379> setbit sign 5 0
(integer) 0
127.0.0.1:6379> setbit sign 6 0
(integer) 0
127.0.0.1:6379> getbit sign 0       //获取0号位置状态
(integer) 1
127.0.0.1:6379> getbit sign 1
(integer) 0
127.0.0.1:6379> bitcount sign        //统计状态为1的数量
(integer) 3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值