Redis学习1

Nosql

现在处于大数据时代.

大数据一般的数据库无法进行分析处理的

大数据时代的3V:主要是描述问题的

1.海量Voume

2.多样Variety

3.实时Velocity

大数据时代的3高,主要是对程序的要求

1.高并发

2.高可扩

3.高性能(保证用户体验和性能)


NoSQL的四大分类

KV键值对:

  • 新浪:Redis
  • 美团:Redis+Tair
  • 阿里,百度:Redis+memecache

文档形数据库:

MongoDB(一般必须要掌握)

  • MongoDB,是一个基于分布式文件存储的数据库,C++编写,主要用来处理大量的文档
  • MongoDB,是一个介于关系型数据库和非关系型数据中中间的产品,MongoDB是非关系型数据库中功能最丰富,最像关系型数据库的

ConthDB

列存储数据库

  • HBase
  • 分布式文件系统

图关系数据库

Redis学习1_第1张图片

  • 他不是存图形,放的是关系,比如:朋友圈社交网络,广告推荐!
  • Neo4j,infoGrid

Redis

Redis是什么?

Redis(Remote Dictionary Server) ,远超字典服务,开源的,用c语言编写,支持网络,基于内存可持久化的日志型,Key-Value数据库.并提供多种语言的API.

redis会周期性的把更新的数据写入磁盘或者修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步

免费和开源!当下最热门的NoSql技术之一,也被称为结构化数据库.

Redis能干嘛?

1.内存存储,持久化,内存中是断电即失,所以持久化很重要(rdb,aof)

2.效率高,可以用于高速缓存

3.发布订阅系统

4.地图信息分析

5.计时器,计数器(浏览量等)

特性

1.多样的数据类型

2.持久化

3.集群

4.事务

.......

学习中需要用到的东西

redis中文:http://redis.cn/

redis推荐都是再linux服务器上搭建的,基于linux学习


redis官网:https://redis.io/

redis中文官网:http://redis.cn/

linux安装redis,我将redis安装在阿里云服务器的centos7.x系统上,用xshell6连接服务器,xftp6传送数据

先下载redis6.0 用xftp将安装包放入linux系统中(我放在opt目录) 运行安装包

redis6需要gcc5.3以上版本

centos7还是4.8.5

安装scl源
yum install centos-release-scl scl-utils-build

安装gcc9

yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils

scl enable devtoolset-9 bash

gcc -v查看版本

解压源码包

tar zxvf redis-6.0.5.tar.gz

然后全程 y

配置文件在 /opt/redis-6.0.5

我们备份配置文件 到/home中

然后修改/home中的redis-conf

vim redis-conf

    requirepass xxxxxxxxxx    # 设置访问密码
    注释掉 bind 127.0.0.1    # 设置redis为任何ip都可访问,如需设置指定ip,则添加bind
    protected-mode no    # 设置为no,否则不能保证全网段进行访问
    daemonize yes    # 设置为yes,保证以守护进程的方式运行redis
运行文件在/opt/redis-6.0.5/src中

我们复制redis-server,redis-cli到/usr/local/bin中

然后输入redis-server /home/redis.conf启动服务

我这里还没有修改ip,只能本机访问

Redis学习1_第2张图片

用redis-cli -p 6379测试连接

如果设置了密码,输入 auth  [密码]  来验证密码

shutdown关闭连接

exit退出


redis-benchmark

redis自带的压力测试工具

Redis学习1_第3张图片

//测试:100个并发连接 100000请求
redis-benchmark -h localhost -p 6379 -c 100 -n 100000

set请求测试

Redis学习1_第4张图片

对10w个请求进行测试

100个并发客户端

每次写入3个字节

只有1台服务器来处理这些请求,单机性能

每秒平均处理82236.84次请求


基础知识

redis默认16个数据库

Redis学习1_第5张图片

默认使用的是第0个

127.0.0.1:6379> select 3  //切换到第3个数据库
OK
127.0.0.1:6379[3]> DBSIZE //返回当前数据库的 key 的数量
(integer) 0

查看所以的key: keys *

清除当前的数据库: flushdb

清除全部数据库的内容: flushall

Redis是单线程的!

明白Redis是很快的,官方表示,Redis是基于内存操作的,CPU不是Redis性能瓶颈

Redis的瓶颈是根据机器的内存和网络带宽,既然可以使用单线程来实现,就使用单线程了.

Redis是c语言写的,官方提供的数据为100000+的QPS,完全不必同样是使用key-vale的Memecache查!

Redis为什么单线程还这这么快?

1.误区:高性能的服务器一定是多线程的

2.误区2:多线程(CPU上下文会切换!)一定比单线程效率高!

CPU>内存>硬盘的速度

核心:redis是将所以的数据全部放在内存中的,所以用单线程操作就是效率最高的,多线程(cpu上下切换:耗时的操作!)对于内存系统来说,若干没有上下文切换效率就是最高,多次读写都在一个cpu上的,在内存情况下,就是最佳方案

127.0.0.1:6379> keys *  //获得当前数据库的所以key
1) "id"
2) "age"
3) "name"
127.0.0.1:6379> exists name    //判断name这个key是否存在
(integer) 1
127.0.0.1:6379> exists name1
(integer) 0
127.0.0.1:6379> exists age
(integer) 1
127.0.0.1:6379> move name 1    //移除name这个key
(integer) 1
127.0.0.1:6379> exists name
(integer) 0
127.0.0.1:6379> keys *
1) "id"
2) "age"
127.0.0.1:6379> set name wangtao  //设置name-wangtao 这个key
OK
127.0.0.1:6379> keys *
1) "id"
2) "age"
3) "name"
127.0.0.1:6379> get name     //获得name这个key的value
"wangtao"
127.0.0.1:6379> expire name 10  //设置name这个key在10秒后删除
(integer) 1
127.0.0.1:6379> ttl name        //获得name这个key还能存活的时间
(integer) 1                     //还能存活1秒
127.0.0.1:6379> ttl name        
(integer) -2                    //已经不在数据库中
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> ttl age
(integer) -1                    //一直存在,没有设置key的存活时间
127.0.0.1:6379> ttl ag
(integer) -2
127.0.0.1:6379> 

查看key的类型:

127.0.0.1:6379> keys *
1) "id"
2) "age"
127.0.0.1:6379> type age
string
127.0.0.1:6379> type id
string

Redis数据结构

ProcessOn:https://www.processon.com/mindmap/5f08b50cf346fb3fdc64a43a

String(字符串)

string 字符串

  • set [key] [value]           设置key-value
  • get [key]                        获得value
  • keys *                             获得所以的key
  • exists [key]                    判断某个key是否存在
  • append [key]    ["string"]    连接一个字符串
  • strlen [key]       获取value的长度   
127.0.0.1:6379> clear
127.0.0.1:6379> set key1 v1 //设置值
OK
127.0.0.1:6379> get key1    //获得值
"v1"
127.0.0.1:6379> keys *      //获得所有key
1) "key1"
127.0.0.1:6379> exists key1 //判断某个key是否存在
(integer) 1
127.0.0.1:6379> append key1 "abc" //追加字符串,如果当前key不存在,就相当于setkey
(integer) 5
127.0.0.1:6379> get key1
"v1abc"
127.0.0.1:6379> strlen key1
(integer) 5
127.0.0.1:6379> append key1 "kuangshen"
(integer) 14
127.0.0.1:6379> strlen kye1   //获得长度
(integer) 0
127.0.0.1:6379> strlen key1
(integer) 14
127.0.0.1:6379> get key1
"v1abckuangshen"

计数

  • incr [key]      value加1
  • decr [key]      value减1
  • incrby [key]  [count]  value加count
  • decrby [key] [count] value减count
127.0.0.1:6379> set views 0
OK
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incr views  //views 增1
(integer) 1
127.0.0.1:6379> incr views
(integer) 2
127.0.0.1:6379> decr views
(integer) 1
127.0.0.1:6379> incr views  //views 减1
(integer) 2
127.0.0.1:6379> get views
"2"
127.0.0.1:6379> incr views
(integer) 3
127.0.0.1:6379> incrby views 10 //views 增加10
(integer) 13
127.0.0.1:6379> decrby views 5  //views 减少10
(integer) 8

字符串范围截取 range

  • getrange [key] [st] [ed]   获得[st,ed]的字符串片段
  • getrange [key] [0] [-1]  获取字符串整个片段
127.0.0.1:6379> set key1 "hellowangtao"
OK
127.0.0.1:6379> get key1
"hellowangtao"
127.0.0.1:6379> getrange key1 0 3  //获得[0,3]的字符串片段
"hell"
127.0.0.1:6379> getrange key1 0 -1 //获得所有字符串片段
"hellowangtao"

字符替换

  • setrange [key] [st] [string]   从st开始,
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  从1位置开始 将后面的字符串替换为xx,替换的长度和xx相同
(integer) 7
127.0.0.1:6379> get key2
"axxdefg"

设置key-value并设置过期时间

  • setex [key] [time] [value]   
  • ttl [key]   查看过期时间
127.0.0.1:6379> setex key3 30 123abc
OK
127.0.0.1:6379> ttl key3
(integer) 23

不存在才就设置(在分布式锁中常常使用)

  • setnx [key] [value]
127.0.0.1:6379> set key1 3
OK
127.0.0.1:6379> keys *
1) "key1"
127.0.0.1:6379> setnx key1 4
(integer) 0
127.0.0.1:6379> setnx key2 5
(integer) 1
127.0.0.1:6379> keys *
1) "key1"
2) "key2"
127.0.0.1:6379> get key1
"3"
127.0.0.1:6379> get key2
"5"

批量设置key-value

  • mset [key1] [value1] [key2] [value2]  ....
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> get k2
"v2"
127.0.0.1:6379> get k3
"v3"
127.0.0.1:6379> keys *
1) "k2"
2) "k1"
3) "k3"

批量获得key-value

  • mget [key1] [key2] [key3]
127.0.0.1:6379> mget k1 k2 k3
1) "v1"
2) "v2"
3) "v3"

同时设置,如果一个失败,则都失败(保证原子性)

  • msetnx [key1] [value1] [key2] [value2]
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> msetnx k1 gg k4 v4
(integer) 0
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> get k4
(nil)

设置对象

本质还是字符串的操作

127.0.0.1:6379> set user:1 {name:wangtao,age:22}
OK
127.0.0.1:6379> get user:1
"{name:wangtao,age:22}"

127.0.0.1:6379> mset user:2:name zhangsan user:2:age 19
OK
127.0.0.1:6379> mget user:2:name user:2:age
1) "zhangsan"
2) "19"
//user:{id}:{filed},这种设计在redis中完全ok

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 mongdb//如果存在,获取原来的值,再设置新的值
"redis"
127.0.0.1:6379> get db
"mongdb"

使用场景:value除了字符串还可以是数字

  • 计数器
  • 统计多单位的数量
  • 粉丝数
  • 对象缓存存储

list

在redis里面,我们可以把list玩成栈,队列,阻塞队列

所有的list都是以l开头的,redis不区分大小写命令

push  插入元素

  • lpush [list] [value]   将一个值从头部插入
  • rpush [list] [value]   将一个值从尾部插入
  • lrang [list] [st] [ed]  获得list的里的元素,如果是st==0,ed==-1,则获得所以
127.0.0.1:6379> keys *
(empty array)
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  //按区间获得list中的值
1) "three"
2) "two"
127.0.0.1:6379> rpush list abc  //将一个值从尾部插入
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "abc"

pop 弹出元素

  • lpop [list]  从头部弹出
  • rpop [list] 从尾部弹出
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> lpop list  //移除第一个元素
"three"
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
127.0.0.1:6379> rpop list  //移除list最后一个元素
"one"
127.0.0.1:6379> lrange list 0 -1
1) "two"

通过下标获得值

  • lindex [list] [index]  通过下标获得元素
127.0.0.1:6379> lrange list 0 -1
1) "c"
2) "b"
3) "a"
4) "two"
127.0.0.1:6379> lindex list 1
"b"
127.0.0.1:6379> lindex list 0
"c"

获得list长度

  • llen [list]
127.0.0.1:6379> llen list
(integer) 4

移除指定的值

  • lrem [list] [size] [value] 移除制定数目的值,从头部开始
127.0.0.1:6379> lrange list 0 -1
1) "a"
2) "c"
3) "b"
4) "a"
5) "two"
127.0.0.1:6379> lrem list 1 a   //移除1个指定的值,从头部开始
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "c"
2) "b"
3) "a"
4) "two"


127.0.0.1:6379> lrange list 0 -1
1) "a"
2) "c"
3) "b"
4) "a"
5) "two"
127.0.0.1:6379> lrem list 2 a  //移除2个a
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "c"
2) "b"
3) "two"

只保留指定的值  ltrim   xx   a b   除了[a,b]区间的元素,别的元素全部删除

  • ltrim [list] [index1] [index2]  处理第index1,index2元素(从0开始算),其他全删除
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "hello1"
3) "hello2"
4) "hello3"
127.0.0.1:6379> ltrim mylist 1 2
OK
127.0.0.1:6379> lrange mylist 0 -1
1) "hello1"
2) "hello2"
127.0.0.1:6379> 

lpoplpush 移除列表最后的一个元素,并将其移动到新的列表中

127.0.0.1:6379> lpush mylist "hello"
(integer) 1
127.0.0.1:6379> lpush mylist "hello1"
(integer) 2
127.0.0.1:6379> lpush mylist "hello2"
(integer) 3
127.0.0.1:6379> rpoplpush mylist mylist2
"hello"
127.0.0.1:6379> lrange mylist 0 -1
1) "hello2"
2) "hello1"
127.0.0.1:6379> lrange mylist2 0 -1
1) "hello"
127.0.0.1:6379> 

修改指定下标的元素,若这个位置没有元素,则返回(error) ERR no such key

  • lset [key] [index] [value]
127.0.0.1:6379> lrange list 0 -1
1) "bb"
2) "aa"
127.0.0.1:6379> lset list 0 cc
OK
127.0.0.1:6379> lrange list 0 -1
1) "cc"
2) "aa"

在指定元素前/后插入一个指定的值

  • lindsert [list] [before/after] [value1] [value2] 在value的前/后面插入value2
127.0.0.1:6379> lrange list 0 -1
1) "aa"
2) "bb"
3) "cc"
127.0.0.1:6379> linsert list before cc xx  //在cc前插入xx
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "aa"
2) "bb"
3) "xx"
4) "cc"
127.0.0.1:6379> linsert list after bb yy   //在bb后面插入yy
(integer) 5
127.0.0.1:6379> lrange list 0 -1
1) "aa"
2) "bb"
3) "yy"
4) "xx"
5) "cc"
127.0.0.1:6379> 

小结

  • 它实际上是一个链表,before node after,left,rigth都可以插入值
  • 如果key不存在,创建新的链表
  • 如果key存在,新增内容
  • 如果移除了所有的值,空链表,也代表不存在
  • 在两边插入或改动值,效率最高!中间元素,相当来说效率会低一点

消息队列(Lpush,Rpop) ,栈(Lpush,Lpop)


set

set中的值是不重复的

sadd 插入值

  • sadd [set] [value]  插入一个值,插入成功返回1,否则返回0
  • smembers [set] 输出set中的值
  • sismember [set] [value] 判断set中是否有value这个元素,有则返回1,反之返回0
127.0.0.1:6379> sadd myset aa  //插入1个值,若插入成功,返回1,反之返回0
(integer) 1
127.0.0.1:6379> sadd myset bb
(integer) 1
127.0.0.1:6379> sadd mysey cc
(integer) 1
127.0.0.1:6379> smembers myset //输出set所有的值
1) "bb"
2) "aa"
127.0.0.1:6379> sadd myset aa  //重复插入,返回0
(integer) 0
127.0.0.1:6379> sismember myset bb  //判断set中是否有bb这个元素,1表示有,0表示没有
(integer) 1
127.0.0.1:6379> sismember myset dd
(integer) 0
127.0.0.1:6379> 

获取set的元素个数

  • scard [set] 返回set的元素数目
127.0.0.1:6379> scard myset
(integer) 2

移除元素

  • srem [set] [value] 移除set中的value元素
127.0.0.1:6379> srem myset bb
(integer) 1
127.0.0.1:6379> smembers myset
1) "aa"

随机获得一个元素

  • srandmember [set] 随机获得一个元素
127.0.0.1:6379> smembers myset
1) "aa"
2) "dd"
3) "cc"
127.0.0.1:6379> srandmember myset
"cc"
127.0.0.1:6379> srandmember myset
"dd"
127.0.0.1:6379> srandmember myset
"dd"
127.0.0.1:6379> srandmember myset
"aa"
127.0.0.1:6379> srandmember myset
"cc"

随机删除一个元素

  • spop [set] [value] 随机删除一个元素
127.0.0.1:6379> spop myset 1
1) "aa"

将一个指定的值,移动到另外一个set中

  • smove [set1] [set2] [value] 将set1中的value移动到set2中
127.0.0.1:6379> smembers myset
1) "bb"
2) "aa"
3) "cc"
127.0.0.1:6379> smembers myset2
1) "11"
2) "22"
3) "33"
127.0.0.1:6379> smove myset myset2 aa
(integer) 1
127.0.0.1:6379> smembers myset
1) "bb"
2) "cc"
127.0.0.1:6379> smembers myset2
1) "aa"
2) "22"
3) "33"
4) "11"

微博,B站,共同关注(并集)

数学集合:

  • sdiff [set1] [set2]   差集
  • sinter [set1] [set2] 交集
  • sunion [set1] [set2] 并集
127.0.0.1:6379> smembers myset
1) "bb"
2) "aa"
3) "tom"
127.0.0.1:6379> smembers myset2
1) "22"
2) "tom"
3) "11"
127.0.0.1:6379> sdiff myset myset2 //差集,myset有myset2没有的
1) "aa"
2) "bb"
127.0.0.1:6379> sinter myset myset2//交集
1) "tom"
127.0.0.1:6379> sunion myset myset2//并集
1) "22"
2) "tom"
3) "bb"
4) "aa"
5) "11"

微博,a用户将所有关注的人放在一个set集合中,将它的粉丝也放在一个集合中

共同关注,共同爱好,二度好友,推荐好友


Hash(哈希)

map集合,key-map 这个值是一个map集合,本质和string类型没有太大区别,还是一个简单的key-value

  • hset [hash] [key] [value]  插入一个key-value
  • hegt [hash] [key]  获取hash中的value
  • hmset [hash] [key1] [value1] [key2] [value2]  插入多个key-value
  • hmget [hash] [key1] [key2]
  • hgetall [hash] 获取收益key-value 
127.0.0.1:6379> hset myhash field1 wangtao //set一个具体的key-value
(integer) 1
127.0.0.1:6379> hget myhash field1   //获取一个字段值
"wangtao"
127.0.0.1:6379> hmset myhash field1 aa field2 bb  //set多个具体的key-value
OK
127.0.0.1:6379> hmget myhash field field2 //获取多个字段值
1) (nil)
2) "bb"
127.0.0.1:6379> hmget myhash field1 field2
1) "aa"
2) "bb"
127.0.0.1:6379> hgetall myhash  //获取全部数据
1) "field1"
2) "aa"
3) "field2"
4) "bb"
127.0.0.1:6379> hdel myhash field1//删除指定的key-value
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field2"
2) "bb"
  • hlen [set] 获得hash表中字段数目
  • hexists [set] [key] 判断是否存在
127.0.0.1:6379> hgetall myhash
1) "field2"
2) "bb"
3) "field1"
4) "aa"
5) "field3"
6) "cc"
127.0.0.1:6379> hlen myhash//获取字段长度
(integer) 3
127.0.0.1:6379> hexists myhash field1//判断指定字段是否存在
(integer) 1
127.0.0.1:6379> hexists myhash field4
(integer) 0

只获得所有的key/value

  • hkeys [set] 获取所以的key
  • hvals [set] 获取所以的value
127.0.0.1:6379> hkeys myhash
1) "field2"
2) "field1"
3) "field3"
127.0.0.1:6379> hvals myhash
1) "bb"
2) "aa"
3) "cc"

对一个value为数的字段进行+/-

  • hincrby [set] [key] [count]  set中的key对应的value增加count(可以为负数)
  • hsetnx [set] [key] [value] 没有才设置
127.0.0.1:6379> hset myhash field5 3
(integer) 1
127.0.0.1:6379> hincrby  myhash field5 3//指定增量
(integer) 6
127.0.0.1:6379> hincrby myhash field5 -1
(integer) 5
127.0.0.1:6379> hsetnx myhash field3 xx//不存在才设置
(integer) 0
127.0.0.1:6379> hsetnx myhash field4 vv
(integer) 1

hash变更的数据,经常变动的信息,更适合对象的存储,string更适合字符串


Zset(有序集合)

redis 有序集合zset和集合set一样也是string类型元素的集合,且不允许重复的成员

不同的是 zset 的每个元素都会关联一个分数(分数可以重复),redis 通过分数来为集合中 的成员进行从小到大的排序.

  • zadd [zset] [score] [value] 插入一个分数为score的元素value  可以连续插入
127.0.0.1:6379> zadd myzset 1 one
(integer) 1
127.0.0.1:6379> zadd myzset 2 two
(integer) 1
127.0.0.1:6379> zadd myzset 3 three 4 four
(integer) 2
127.0.0.1:6379> zrange myzset 0 -1
1) "one"
2) "two"
3) "three"
4) "four"

排序

  • zrangebyscore [zset] [-inf] [+inf]  升序排序
  • zrevrangebyscore [zset] [+inf] [-inf]  降序排序
  • zrangebyscore [zset] [-inf] [+inf] withscores 升序,并输出分数
127.0.0.1:6379> zadd salary 2500 wangtao
(integer) 1
127.0.0.1:6379> zadd salary 6500 zhangsan
(integer) 1
127.0.0.1:6379> zadd salary 1500 lisi
(integer) 1
127.0.0.1:6379> zrangebyscore salary -inf +inf//升序
1) "lisi"
2) "wangtao"
3) "zhangsan"
127.0.0.1:6379> zrevrangebyscore salary +inf -inf//降序
1) "zhangsan"
2) "wangtao"
3) "lisi"
127.0.0.1:6379> zrangebyscore salary -inf +inf withscores//查询并显示分数
1) "lisi"
2) "1500"
3) "wangtao"
4) "2500"
5) "zhangsan"
6) "6500"

删除一个元素

  • zrem [zset] [value] 移除一个元素
127.0.0.1:6379> zrangebyscore salary -inf +inf
1) "zhangsan"
2) "wangtao"
3) "lisi"
127.0.0.1:6379> zrem salary lisi
(integer) 1
127.0.0.1:6379> zrange salary 0 -1
1) "zhangsan"
2) "wangtao"

显示集合元素数目

zcard [zset] 显示zset元素数目

127.0.0.1:6379> zcard salary
(integer) 2

获取区间范围内元素数目

zcount [zset] [score1] [score2] 获取[score1,sorce2]区间的元素数目

127.0.0.1:6379> zcount salary -inf +inf
(integer) 2
127.0.0.1:6379> zcount salary 3000 4000
(integer) 1

我们工作中有需要,就去看官方文档

案例思路:set 排序,存储班级成绩表,工资表排序

带权重执行,排行榜实现


geospatial

这个功能可以推算地理位置的信息,两地的距离

只有6个命令

  • geoadd [name1] [经度] [纬度] [name2] 往地区name1中插入地区name2
  • geopos [name1] [name2] 获取地区name1中地区name2的经纬度
//两极无法添加,我们一般会下载城市数据,直接通过java程序导入
127.0.0.1:6379> geoadd china:city 116.23128 40.22077 beijing  //把城市的经纬度信息加入redis中
(integer) 1
127.0.0.1:6379> geoadd china:city 121.48941 31.40527 shanghai
(integer) 1
127.0.0.1:6379> geoadd china:city 106.54041 29.40268 chongqing
(integer) 1
127.0.0.1:6379> geoadd china:city 113.88308 22.55329 shenzheng
(integer) 1
127.0.0.1:6379> geoadd china:city 108.93425 34.23053 xian
(integer) 1
127.0.0.1:6379> geopos china:city beijing//获取城市的经纬度
1) 1) "116.23128265142440796"
   2) "40.22076905438526495"

计算两地直线距离

后面可以加单位:默认是米,km 千米,mi 英里,ft英尺

  • geodist [name1] [name2] [name2] [单位]  name2,name3包含在name1中,计算他们的距离 (后面可以设置单位km,不设置默认是m)
127.0.0.1:6379> geodist china:city beijing xian
"927537.1497"
127.0.0.1:6379> geodist china:city beijing chongqing km
"1491.5364"

查询某位置半径内的元素

  • georadius [name1] [经度] [纬度] [半径] [单位] 在地区name1中,输出距离给定经纬度不超过给定距离的地区
  • georadius [name1] [经度] [纬度] [半径] [单位] withcoord 在地区name1中,输出距离给定经纬度不超过给定距离的地区,同时输出经纬度
127.0.0.1:6379> georadius china:city  110 30 1000 km//输入在地点经纬度为(110,30),1000km内的元素.
1) "chongqing"
2) "xian"
3) "shenzheng"
127.0.0.1:6379> georadius china:city 110 30 1000 km withcoord//同时输出经纬度信息
1) 1) "chongqing"
   2) 1) "106.54040783643722534"
      2) "29.40268053517299762"
2) 1) "xian"
   2) 1) "108.93425256013870239"
      2) "34.23053097599082406"
3) 1) "shenzheng"
   2) 1) "113.88307839632034302"
      2) "22.55329111565713873"
127.0.0.1:6379> georadius china:city 110 30 1000 km count 2//只输入2个
1) "chongqing"
2) "xian"

查询一个元素附近的功能

  • georadiusbymember [name1] [name2] [距离] [单位] 查询name1下的name2地区指定距离内的元素
127.0.0.1:6379> georadiusbymember china:city beijing 1000 km//查询距离北京1000km内的元素
1) "beijing"
2) "xian"

将经纬度转化为geohash字符串

  • geohash [name1] [name2] 将经纬度转化为一个hash  (可以连续查询)
127.0.0.1:6379> geohash china:city beijing chongqing
1) "wx4sucvncn0"
2) "wm5z22s7520"

Hyperloglog

什么是基数?

A{1,3,5,7,8,7}

B{1,3,5,7,8}

Redis2.8.9版本更新了Hyperloglog数据结构

Redis Hyperloglog基数统计算法

优点:占用的内存是固定,2^64不同的元素计数,只需要用12k内存

网页的UV(一个人访问一个网站多次,但是还是算作一个人)

传统的方式,set保存用户id,然后统计set中的元素数目作为标准判断

这个方式如果保存大量的用户id,就会比较麻烦,我们的目的是为了计数,而不是保存用户id

测试使用:

  • pfadd [基数容器] [key] [value1] [value2] [value3]  插入一组元素
  • pfcount [基数容器] [key] 获取key容器的基数(不包括重复的)
  • pfmerge [基数容器3] [基数容器1] [基数容器2]  1,2容器合并出1  
127.0.0.1:6379> pfadd mykey a b c d   //创建第一组元素 mykey
(integer) 1
127.0.0.1:6379> pfadd mykey2 c d e f  
(integer) 1
127.0.0.1:6379> pfcount mykey          //统计mykey的基数数目
(integer) 4
127.0.0.1:6379> pfmerge mykey3 mykey mykey2  //合并两组mykey,mykey2生成mykey3
OK
127.0.0.1:6379> pfcount mykey3     //没有重复计算c,d
(integer) 6

如果允许容错,那么一定可以使用hyperloglog

如果不允许容错,就使用set或者自己的数据类型即可


Bitmap

位存储

统计用户信息,活跃,不活跃,登陆,未登录,打卡,365打卡,两个状态,都可以使用bitmaps

bitmaps位图,数据结构,都是二进制位来进行记录,就只有0和1两个状态

365天=365bit 1字节=8bit 46个字节左右

测试:

127.0.0.1:6379> setbit sign 0 1
(integer) 0
127.0.0.1:6379> setbit sign 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 1
(integer) 0
127.0.0.1:6379> setbit sign 6 0
(integer) 0

查看指定天是否打卡

127.0.0.1:6379> getbit sign 6
(integer) 0
127.0.0.1:6379> getbit sign 0
(integer) 1
127.0.0.1:6379> getbit sign 3
(integer) 1

统计打卡天数

setbit key [start end]        统计key的第start~end字节有多少个值为1

这李的start一般从0开始,每个占8个数值,0就是[0,7]  1就是[8,15]

setbit key 0 3 :求[0,31]这个区间的范围1的个数

127.0.0.1:6379> setbit sign 0 1
(integer) 0
127.0.0.1:6379> setbit sign 5 1
(integer) 0
127.0.0.1:6379> setbit sign 11 1
(integer) 0
127.0.0.1:6379> setbit sign 15 1
(integer) 0
127.0.0.1:6379> setbit sign 19 1
(integer) 0
127.0.0.1:6379> bitcount sign 
(integer) 5
127.0.0.1:6379> bitcount sign 10 20
(integer) 0
127.0.0.1:6379> bitcount sign 1 3
(integer) 3
127.0.0.1:6379> bitcount sign 0 1
(integer) 4
127.0.0.1:6379> bitcount sign 0 2
(integer) 5
127.0.0.1:6379> bitcount sign 1 2
(integer) 3
127.0.0.1:6379> bitcount sign 2 5
(integer) 1

视频学习链接:https://www.bilibili.com/video/BV1mc411h719?from=search&seid=16419983121936876555

你可能感兴趣的:(Redis学习1)