• Redis_01_redis五大基础类型和三大特殊类型


    1.Redis

    Redis 是完全开源的,遵守 BSD 协议,是一个高性能的 key-value 数据库。

    Redis 与其他 key - value 缓存产品有以下三个特点:

    • Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
    • Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
    • Redis支持数据的备份,即master-slave模式的数据备份。
    • 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。

    2.redis安装

    1.下载redis.tar.gz

    2.make

    3.make install PREFIX=/usr/local/redis

    4.赋值配置文件 并且修改redi.config 将daemonize no 改成daemonize yes 使用redis.config后台启动redis.server

    3. redis基础命令

    redis有16个数据库默认使用第0个可以使用select 进行切换数据库

    127.0.0.1:6379> select 3  #切换数据库
    OK
    127.0.0.1:6379[3]> dbsize #查看db大小
    (integer) 0
    127.0.0.1:6379[3]> set name  hdh #在三号数据库设置一个值
    OK
    127.0.0.1:6379[3]> dbsize #查看db大小
    (integer) 1
    127.0.0.1:6379[3]> set name  hdh #在三号数据库设置一个值
    OK
    127.0.0.1:6379[3]> flushdb #清除当前数据库
    OK
    127.0.0.1:6379[3]> flushall #清除所有数据库
    OK

    redis 是单线程的

    Redis是非常快的,Redis是基于内存操作,CPU不是Redis的性能瓶颈,Redis的瓶颈是根据内存和网络带宽来决定的。

    为什么Redis是单线程还是很快?

    Redis是基于内存操作,Redis所有的数据都是存放在内存中的,多线程直接的切换都是每必要的耗时行为,对于内存来说单线程是最快的

    4.Redis五大数据类型

     Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。它支持[字符串、[哈希表]、[列表]、[集合]、[有序集合],[位图],[hyperloglogs]等数据类型。内置复制、[Lua脚本]、LRU收回、[事务]以及不同级别磁盘持久化功能,同时通过Redis Sentinel提供高可用,通过Redis Cluster提供自动[分区]。

    1.redisKey的基本操作

    127.0.0.1:6379[3]> set name hdh
    OK
    127.0.0.1:6379[3]> set age 18
    OK
    127.0.0.1:6379[3]> exists name  #判断一个key是否存在
    (integer) 1
    127.0.0.1:6379[3]> exists name1
    (integer) 0
    127.0.0.1:6379[3]> move name 1 #移除第一个key为name的
    (integer) 1
    127.0.0.1:6379> set name hdh
    OK
    127.0.0.1:6379> get name 
    "hdh"
    127.0.0.1:6379> expire name 10 #设置key的过期时间 单位秒
    (integer) 1
    127.0.0.1:6379> ttl name #查询Key剩余过期时间 -2已过期
    (integer) 7
    127.0.0.1:6379> ttl name
    (integer) -2
    127.0.0.1:6379> set name hdh
    OK
    127.0.0.1:6379> type name 判断key的类型
    string

    2.String类型

    以下的所有的方法都会被转化为java操作的中的方法

    127.0.0.1:6379> set key1 v1
    OK
    127.0.0.1:6379> get key1
    "v1"
    127.0.0.1:6379> get key
    (nil)
    127.0.0.1:6379> exists key1 #判断key是否存在
    (integer) 1
    127.0.0.1:6379> append key1 hello #向key追加一个值 key不存在创建
    (integer) 7 #返回key的长度
    127.0.0.1:6379> get key1
    "v1hello"
    127.0.0.1:6379> strlen key1 #查询key的长度
    (integer) 7

     

    127.0.0.1:6379> set views 0
    OK
    127.0.0.1:6379> get views
    "0"
    127.0.0.1:6379> incr views #value值自增1
    (integer) 1
    127.0.0.1:6379> get views
    "1"
    127.0.0.1:6379> decr views #value值减1
    (integer) 0
    127.0.0.1:6379> incrby views 10 #设置步长value值自增10
    (integer) 10
    127.0.0.1:6379> get views
    "10"

     

    127.0.0.1:6379> set key abcdefg
    OK
    127.0.0.1:6379> get key
    "abcdefg"
    127.0.0.1:6379> getrange key 0 3 #截取字符串 开始和结尾的下标
    "abcd"
    127.0.0.1:6379> getrange key 0 -1
    "abcdefg"

     

    127.0.0.1:6379> set key1 abcdefg
    OK
    127.0.0.1:6379> get key1
    "abcdefg"
    127.0.0.1:6379> setrange key1 1 x #替换下标为1的值
    (integer) 7
    127.0.0.1:6379> get key1
    "axcdefg"

     

    #setex (set with expire)#设置过期时间
    #setnx (set if not exist) #不存在设置(在分布式锁中常常会用到)
    127.0.0.1:6379> setex key3 30 abcd #设置key3的为abcd  30秒后过期
    OK
    127.0.0.1:6379> ttl key3  #查选key3 的过期时间 -1没有过期时间 -2 已经过期
    (integer) 24
    127.0.0.1:6379> get key3
    "abcd"
    127.0.0.1:6379> setnx mykey redis #判断mykey是不是存在 不存在创建返回 1  存在返回0 
    (integer) 1
    127.0.0.1:6379> get mykey  
    "redis"
    127.0.0.1:6379> ttl key3
    (integer) -2
    127.0.0.1:6379> setnx mykey java
    (integer) 0

     

    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> msetnx k1 a k4 d #msetnx是原子操作 
    (integer) 0 #失败

     

    #redis 对象用作key json用来存值
    #巧妙地设计 user:{id}:{filed}
    127.0.0.1:6379> mset user:1:name zhansan user:1:age 2
    OK
    127.0.0.1:6379> mget user:1:name user:1:age
    1) "zhansan"
    2) "2"
    
    127.0.0.1:6379> getset #先get再set 如果存在值先get 不存在返回nul 。

    3.List类型

    redis中 list可以实现栈、堆、队列

    list可以左边进值右边出值,可以完成消息队列(lpush,rpop), 先进先出

    栈操作:(lpush,lpop)先进后出

    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 whree
    (integer) 3
    127.0.0.1:6379> lrange list 0 -1 #获取list中的值(全部)
    1) "whree"
    2) "two"
    3) "one"
    127.0.0.1:6379> lrange list 0 1 #获取list中的值(下标为0和1的)
    1) "whree"
    2) "two"
    127.0.0.1:6379> rpush list right #向尾部追加一个或者多个值
    (integer) 4
    127.0.0.1:6379> lrange list 0 -1  #获取list中的值(全部)
    1) "whree"
    2) "two"
    3) "one"
    4) "right"

     

    127.0.0.1:6379> lrange list 0 -1
    1) "whree"
    2) "two"
    3) "one"
    4) "right"
    127.0.0.1:6379> lpop list #移除头部的一个值
    "whree"
    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 list 0 #获取指定下标的值
    "two"
    127.0.0.1:6379> 
    ############################################################
    llen
    127.0.0.1:6379> llen list #返回列表的长度
    (integer) 3


    127.0.0.1:6379> lrem list 1 a  #移除list中指定个数的value  移除1个value是a的值
    (integer) 1
    127.0.0.1:6379> lrange list 0 -1
    1) "d"
    2) "c"
    3) "b"

     

    127.0.0.1:6379> RPUSH list key1 key2 key3 key4 #向list尾部插入值
    (integer) 4
    127.0.0.1:6379> ltrim list 1 2 #截取list 从下标1到2
    OK
    127.0.0.1:6379> lrange list 0 -1
    1) "key2"
    2) "key3"

     

    127.0.0.1:6379> lrange list 0 -1
    1) "1"
    2) "2"
    3) "3"
    4) "4"
    127.0.0.1:6379> lset list 1 a #通过下标修改list中的值  修改list下标为1的值 如果不存在会报错
    OK
    127.0.0.1:6379> lrange list 0 -1
    1) "1"
    2) "a"
    3) "3"
    4) "4"

     

    #linsert 将一个值插入到list中 一个值的后面
    127.0.0.1:6379> lrange list 0 -1
    1) "1"
    2) "a"
    3) "3"
    4) "4"
    127.0.0.1:6379> linsert list before 4 5 #向list值为4 的后面(前面)插入一个值为5数
    (integer) 5
    127.0.0.1:6379> lrange list 0 -1
    1) "1"
    2) "a"
    3) "3"
    4) "5"
    5) "4"

    4.set

    set中的值是不能重复的

    127.0.0.1:6379> sadd name hdh #向set中存入一个或者多个元素
    (integer) 1
    127.0.0.1:6379> sadd name xj
    (integer) 1
    127.0.0.1:6379> sadd name dd
    (integer) 1
    127.0.0.1:6379> smembers name #查选set中所有的元素
    1) "xj"
    2) "dd"
    3) "hdh"
    127.0.0.1:6379> sismember name hdh #判断set中是否有某个元素
    (integer) 1

     

    127.0.0.1:6379> sadd set a 
    (integer) 1
    127.0.0.1:6379> sadd set b
    (integer) 1
    127.0.0.1:6379> sadd set c
    (integer) 1
    127.0.0.1:6379> scard set #查询set中元素个数
    (integer) 3

     

    127.0.0.1:6379> srem set a #移除set中一个指定的元素
    (integer) 1
    127.0.0.1:6379> smembers set 
    1) "c"
    2) "b"

     

    127.0.0.1:6379> srandmember set #随机抽出一个元素
    "c"
    127.0.0.1:6379> srandmember set
    "b"

     

    127.0.0.1:6379> spop set  #随机删除一个元素
    "c"
    127.0.0.1:6379> spop set 
    "b"

     

    127.0.0.1:6379> sadd set a b c d e
    (integer) 5
    127.0.0.1:6379> smembers set
    1) "d"
    2) "c"
    3) "a"
    4) "b"
    5) "e"
    127.0.0.1:6379> smove set set1 f #将set集合中的f元素移动到set1集合中
    (integer) 1
    127.0.0.1:6379> smember set
    1) "b"
    2) "c"
    3) "d"
    4) "e"
    127.0.0.1:6379> smembers set1
    1) "a"
    2) "f"

     

    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) "d"
    5) "e"

    5.Hash(哈希)

    Map集合,key-map-->key-<key-vle>!这时候vle就是一个Map1

    hash变更数据:可以存放一个user

    hset user:1 name hdh

    hset user:1 age 24

    ...

    127.0.0.1:6379> hset myhash filed hdh  #set一个key-value
    (integer) 1
    127.0.0.1:6379> hget myhash filed
    "hdh"
    127.0.0.1:6379> hmset myhash filed xj filed1 hello #set多个key-value
    OK
    127.0.0.1:6379> hmget myhash filed filed1  #get一个或者多个key-value
    1) "xj"
    2) "hello"
    127.0.0.1:6379> hgetall myhash #get全部的key-value
    1) "filed"
    2) "xj"
    3) "filed1"
    4) "hello"

     

    127.0.0.1:6379> hdel myhash filed  #删除指定的key
    (integer) 1
    127.0.0.1:6379> hgetall myhash
    1) "filed1"
    2) "hello"
    127.0.0.1:6379> hlen myhash #计算hash长度 有多少个key-map键值对 
    (integer) 1
    127.0.0.1:6379> 
    127.0.0.1:6379> hexists myhash filed1 #判断hash中key是否存在
    (integer) 1
    127.0.0.1:6379> hexists myhash filed2
    (integer) 0
    127.0.0.1:6379> hkeys myhash #获取hash中的所有的key
    1) "filed1"
    127.0.0.1:6379> hvals myhash #获取hash中的所有的value
    1) "hello"

     

    127.0.0.1:6379> hset myhash age 10
    (integer) 1
    127.0.0.1:6379> hincrby myhash age 10 #hash自增10
    (integer) 20
    127.0.0.1:6379> hincrby myhash age -10 #hash自增-10
    (integer) 10

     

    127.0.0.1:6379> hsetnx myhash name hdh #如果不存在可以设置
    (integer) 1
    127.0.0.1:6379> hsetnx myhash name hdh#如果存在不可以设置
    (integer) 0

     6.Zset(有序集合)

    在set的基础上,增加了一个值

    set k1 v1

    zset k1 score1 v1

    127.0.0.1:6379> zadd myzset 1 one #向zset中添加一个值
    (integer) 1
    127.0.0.1:6379> zadd myzset 2 two 3 three #向zset中添加多个值
    (integer) 2
    127.0.0.1:6379> zrange myzset 0 -1 #获取zet中所有的值
    1) "one"
    2) "two"
    3) "three"

     

    127.0.0.1:6379> zadd salary 1000 hdh 
    (integer) 1
    127.0.0.1:6379> zadd salary 2000 xj
    (integer) 1
    127.0.0.1:6379> zadd salary 3000 zs
    (integer) 1
    127.0.0.1:6379> zrangebyscore salary -inf +inf #按照salary正序排序-inf +inf 所有的
    1) "hdh"
    2) "xj"
    3) "zs"
    127.0.0.1:6379> zrangebyscore salary -inf +inf withscores #按照salary升序排序带上value
    1) "hdh"
    2) "1000"
    3) "xj"
    4) "2000"
    5) "zs"
    6) "3000"
    
    127.0.0.1:6379> zrange salary 0 -1 withscores #从大到小排序
    1) "xj"
    2) "2000"
    3) "zs"
    4) "3000"
    127.0.0.1:6379> 

     

    127.0.0.1:6379> zrange salary 0 -1
    1) "hdh"
    2) "xj"
    3) "zs"
    127.0.0.1:6379> zrem salary hdh #移除一个元素
    (integer) 1
    127.0.0.1:6379> zrange salary 0 -1
    1) "xj"
    2) "zs"
    127.0.0.1:6379> zcard salary #集合中元素的个数
    (integer) 2

     

    127.0.0.1:6379> zadd myzset 1 a 2 b 3 c 
    (integer) 3
    127.0.0.1:6379> zcount myzset 1 3 #获取zset指定区间之间的元素数量
    (integer) 3
    127.0.0.1:6379>  zcard myzset #获取zset的元素数量
    (integer) 3

    5.三种特殊的数据类型  

    1.geospatial

    朋友圈定位,附近的人,打车的距离

    GEOADD:

    该命令以采用标准格式的参数x,y,所以经度必须在纬度之前。这些坐标的限制是可以被编入索引的,区域面积可以很接近极点但是不能索引。具体的限制,由EPSG:900913 / EPSG:3785 / OSGEO:41001 规定如下:

    • 有效的经度从-180度到180度。

    • 有效的纬度从-85.05112878度到85.05112878度。

    当坐标位置超出上述指定范围时,该命令将会返回一个错误

    (error) ERR invalid longitude,latitude pair 39.900000,116.400000#及维度超出范围
    
    127.0.0.1:6379> geoadd china:city 116.40 39.90 beijin #添加一个或者多个地理位置
    (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 chongqin 114.05 22.52 shengzhen
    (integer) 2
    127.0.0.1:6379> geoadd china:city 120.16 30.24 hangzhou 108.96 34.26 xian
    (integer) 2

     

    127.0.0.1:6379> geopos china:city beijin #获取指定的城市的经纬度
    1) 1) "116.39999896287918091"
       2) "39.90000009167092543"

    2.geodist

    返回两个给定位置之间的距离。

    如果两个位置之间的其中一个不存在, 那么命令返回空值。

    指定单位的参数 unit 必须是以下单位的其中一个:

    • m 表示单位为米。

    • km 表示单位为千米。

    • mi 表示单位为英里。

    • ft 表示单位为英尺。

    如果用户没有显式地指定单位参数, 那么 GEODIST 默认使用米作为单位。

    GEODIST 命令在计算距离时会假设地球为完美的球形, 在极限情况下, 这一假设最大会造成 0.5% 的误差。

    127.0.0.1:6379> geodist china:city beijin shanghai km #北京到上海的距离
    "1067.3788"

     

    我附近的人?(获得我附近所有人的地址,定位)

    127.0.0.1:6379> georadius china:city 110 30 1000 km #查找指定坐标 110 30 附近1000km的人
    1) "chongqin"
    2) "xian"
    3) "shengzhen"
    4) "hangzhou"
    127.0.0.1:6379> georadius china:city 110 30 1000 km withdist #查找指定坐标 110 30 附近1000km的人 显示和你的距离
    1) 1) "chongqin"
       2) "341.9374" #和你的距离
    2) 1) "xian"
       2) "483.8340"
    3) 1) "shengzhen"
       2) "924.6408"
    4) 1) "hangzhou"
       2) "977.5143"
    127.0.0.1:6379> GEORADIUS china:city 100 30 1000 km withdist withcoord count 1
    ##查找指定坐标 110 30 附近1000km的人并且显示 withcoord详细坐标 count取一个
    1) 1) "chongqin"
       2) "629.6756" 
       3) 1) "106.49999767541885376"
          2) "29.52999957900659211"

     

    通过指定的元素查找附近的人

    127.0.0.1:6379> georadiusbymember china:city beijin 1000 km withdist withcoord
    #找出指定元素(beijin)1000km之内的所有元素的详情
    1) 1) "beijin"
       2) "0.0000"
       3) 1) "116.39999896287918091"
          2) "39.90000009167092543"
    2) 1) "xian"
       2) "910.0565"
       3) 1) "108.96000176668167114"
          2) "34.25999964418929977"

     

     geohash 返回一个或者多个位置元素的经纬度 GeoHash表示

    #将二维码的经纬度转换为一维的字符串,如果两个字符串越接近,那么距离越接近
    127.0.0.1:6379> geohash china:city beijin chongqin
    1) "wx4fbxxfke0"
    2) "wm5xzrybty0

     

     geo底层的实现原理是Zste!意味着我们可以使用Zset命令操作

    127.0.0.1:6379> zrange china:city  0 -1 #查看地图中所有的元素
    1) "chongqin"
    2) "xian"
    3) "shengzhen"
    4) "hangzhou"
    5) "shanghai"
    6) "beijin"
    127.0.0.1:6379> zrem china:city beijin #移除地图中指定的元素
    (integer) 1

     2.Hyperloglog 数据结构

    什么是基数?

    一个集合中不存在重复的元素,Hyperloglog存储的就是基数

    网页的的访问数量(多次访问只算一次)

    Hyperloglog 存放:2^64次方个不同的用户id,只需要12kb内存,但是存在0.81%的误差

    传统方式 set方式保存用户id。数量级过大时非常消耗资源。而且我们需要的不是用户id,需要的事访问数量。

    127.0.0.1:6379> pfadd key1 1 2 3 4 #创建一组数据结构 
    (integer) 1
    127.0.0.1:6379> pfadd key2 3 4 5 6 #创建一组数据结构 
    (integer) 1
    127.0.0.1:6379> pfmerge key3 key 1 key2 #合并两个数据结构
    OK
    127.0.0.1:6379> pfcount key3 #查询一组组数据结构的个数
    (integer) 6

     3.Bitmaps

    位存储

    统计活跃和不活跃用户,登录,不登陆的用户。只有2种状态的都可以使用Bitmap表示。

    127.0.0.1:6379> setbit id+y+y  1 0 #设置 用户id+y+y  用户 哪一年 哪一月 哪一天是否登录
    (integer) 0
    127.0.0.1:6379> setbit id+y+y 2 0
    (integer) 0
    127.0.0.1:6379> getbit id+y+y 1 #获得 用户id+y+y  用户 哪一年 哪一月 哪一天是否登录
    (integer) 0
    127.0.0.1:6379> bitcount id+y+y 获得 用户id+y+y  当月的打卡次数
    (integer) 2

     

  • 相关阅读:
    Java实战项目收集
    Drebin数据集
    网络“法官”
    沉醉
    孔方兄
    《Qt 5.9 C++开发指南》例程源码
    《论语》中那些耳熟能详的词汇
    破祟
    Qt使用UI编辑器添加的控件Icon运行时不显示
    Ubuntu格式化SD卡
  • 原文地址:https://www.cnblogs.com/asndxj/p/14247912.html
Copyright © 2020-2023  润新知