Redis入门
概述和环境配置
Redis是什么?
Redis(Remote Dictionary Server),即远程字典服务!
是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
当下最热门的NoSQL技术之一。
Redis能干啥?
1,内存存储,持久化,内存中是断电即失,所以说持久化很重要(人多不,aof)
2,效率高,可以用于高速缓存
3,发布订阅系统
4,地图学习分析
5,计时器,计数器(浏览量!)
6,。。。。
特性
多样化 持久化 集群 事务
官网:链接: link.
下载地址:
推荐在Linux服务器上搭建,学习
redis的环境安装
Liunx下载安装教程: 链接.
把Redis的配置文件复制一份出来,使用这个文件。本来那个配置文件作为备份
1,reids默认不是后台启动的,修改配置文件!
redis.conf 编辑这个文件:vim redis.conf
修改:daemonize 这个属性 后面加上yes
2,启动Redis服务!
3,测试redis-cli 进行连接测试!
keys * :查看所有的key
4,查看redis的进程是否开启!
5,关闭Reids服务。shutdown
shutdown:关闭redis
exit :退出
6,查看redis,是否关闭!
测试性能(redis-benchmark)
redis-benchmark是一个压力测试工具!
官方自带的性能测试工具!
redis-benchmark命令参数!
图片来自菜鸟教程:
简单测试下:
测试:100个并发连接 100000请求
redis-benchmark -h localhost -p 6379 -c 100 -n 100000
基础知识
redis默认有16个数据库
默认使用第0个数据库
可以使用select进行切换数据库!
127.0.0.1:6379> select 3 //切换数据库
OK
127.0.0.1:6379[3]> dbsize //查看数据库大小
(integer) 0
keys * //查看所有的key
flushdb //清空当前数据库
flushall //清空全部的数据库
为啥liunx的端口号是6379。
Redis是单线程的!
Redis的瓶颈是根据机器的内存和网络带宽,单线程可以实现,所以就使用单线程了!
Redis是C语言写的,官方提供的数据为100000+的QPS,完全不比同样是使用key-vale的Memecache差!
Redis为什么单线程还这么快!
1,误区1:高性能的服务器一定是多线程的?
2,误区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 //判断有没有这个name值key
(integer) 1
move name 1 //移除
expire name 10 //十秒钟过后过期
ttl name //查看此信息还有多久过期
type key //查了当前key的类型
String(字符串)
127.0.0.1:6379> set key1 v1 //设置值
OK
127.0.0.1:6379> get key1 //获得值
"v1"
127.0.0.1:6379> keys * //获得所有的key
"key1"
127.0.0.1:6379> exists key1 //判断某一个key是否存在
(integer) 1
127.0.0.1:6379> append key1 "hello" //追加一个字符串,如果当前key不存在,就相当于 set key
(integer) 7
127.0.0.1:6379> get key1
"v1hello"
127.0.0.1:6379> strlen key1 //获取字符串的长度!
(integer) 7
127.0.0.1:6379> append key1 ",chaoyang"
(integer) 16
127.0.0.1:6379>
//i++
//步长 i+=
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 浏览量变为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> decr views //自减1 浏览量-1
(integer) 1
127.0.0.1:6379> decr views
(integer) 0
127.0.0.1:6379> incrby views 10 //可以设置步长 ,指定增量
(integer) 10
127.0.0.1:6379> decrby views 5 //可以设置步长,指定减量
(integer) 5
127.0.0.1:6379>
截取字符串 range
127.0.0.1:6379> set key1 "hello,songchao"
OK
127.0.0.1:6379> get key1
"hello,songchao"
127.0.0.1:6379> getrange key1 0 3 //截取字符串【0,3】
"hell"
127.0.0.1:6379> getrange key1 0 -1 //获取全部的字符串和 get key是一样的
"hello,songchao"
字符串替换!
127.0.0.1:6379> set key2 abcdefg
OK
127.0.0.1:6379> get key2
"abcdefg"
127.0.0.1:6379> setrange key2 2 xx //替换指定位置开始的字符串
(integer) 7
127.0.0.1:6379> get key2
"abxxefg"
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) 22
127.0.0.1:6379> get key3
"hello"
127.0.0.1:6379> setnx mykey "redis" //如果mykey不存在,创建mykey
(integer) 1
127.0.0.1:6379> keys *
1) "mykey"
2) "foo"
127.0.0.1:6379> ttl key3
(integer) -2
127.0.0.1:6379> setnx mykey "MongoDB" //如果mykey存在,创建失败!
(integer) 0
127.0.0.1:6379> get mykey
"redis"
mset
mget
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 //同时设置多个值
OK
127.0.0.1:6379> keys *
1) "k3"
2) "k2"
3) "k1"
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:zhangsan,age:3} //设置一个user:1 对象 值为jsion字符来保存一个对象!
//这里的key是一个巧妙的设计:user:{id}:{filed},如此设计在Redis中是完全ok了!
127.0.0.1:6379> mset user:2:name zhangsan user:2:age 2
OK
127.0.0.1:6379> mget user:2:name user:2:age
1) "zhangsan"
2) "2"
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"
数据结构是相同。
String类似的使用场景:value除了是我们的字符串还可以是我们的数字!
- 计数器
- 统计多单位的数量
- 粉丝数
- 对象缓存存储!
List:基本的数据类型,列表
所有的List命令都是以L开头的。Redis的命令不区分大小写
127.0.0.1:6379> lpush list one //将第一个值插入进去(左边)
(integer) 1
127.0.0.1:6379> lpush list two //d第二个值
(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 righr //将一个值插入进去(右边)
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "righr"
#######################################################################################
lpop
rpop
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "righr"
127.0.0.1:6379> lpop list //移除list的第一个元素
"three"
127.0.0.1:6379> rpop list //移除list的最后一个元素
"righr"
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
#######################################################################################
Lindex
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
127.0.0.1:6379> lindex list 1 //通过下标获得list中的某一个值
"one"
127.0.0.1:6379> lindex list 0
"two"
#######################################################################################
llen
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> Llen list //返回列表长度
(integer) 3
#######################################################################################
移除指定的值!
lrem
127.0.0.1:6379> lpush list three
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "three"
3) "two"
4) "one"
127.0.0.1:6379> lrem list 1 one //移除list集合中指定个数的value,精确匹配
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "three"
3) "two"
127.0.0.1:6379> lrem list 1 three
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> lrem list 2 three
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "two"
#######################################################################################
trim 修剪:list:截断
127.0.0.1:6379> keys *
(empty array)
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> rpush mylist "hello3"
(integer) 4
127.0.0.1:6379> ltrim mylist 1 2 //通过下标截取指定的长度,这个list会被改变,截断了只剩下截取的元素!
OK
127.0.0.1:6379> lrange mylist 0 -1
1) "hello1"
2) "hello2"
#######################################################################################
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"
#######################################################################################
lset 将列表中指定下标的值替换为另外一个值,更新操作
127.0.0.1:6379> exists list //判断这个列表是否存在
(integer) 0
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"
小结
- 他实际上是一个链表,before Node after,left,right都可以插值
- 如果key不存在,创建新的链表
- 如果key存在,新增内容
- 如果移除了所有值,空链表,也代表不存在!
- 在两边插入或者改动值,效率最高!中间元素,相对来说效率会低一点~
消息队列!消息队列(Lpush Rpop),栈(Lpush Lpop)
Set(集合)
set中的值是不能重读的!
#######################################################################################
127.0.0.1:6379> sadd myset "hello" //set集合中添加元素
(integer) 1
127.0.0.1:6379> sadd myset "songchao"
(integer) 1
127.0.0.1:6379> sadd myset "yang"
(integer) 1
127.0.0.1:6379> smembers myset //查看指定set的所有值
1) "yang"
2) "songchao"
3) "hello"
127.0.0.1:6379> sismember myset hello //判断某一个值是不是在set集合中
(integer) 1
127.0.0.1:6379> sismember myset world
(integer) 0
#######################################################################################
127.0.0.1:6379> scard myset
(integer) 5 //获取set集合中的内容元素个数!
#######################################################################################
rem
127.0.0.1:6379> srem myset hello //移除set集中的指定元素
(integer) 1
127.0.0.1:6379> smembers myset
1) "yang"
2) "songchao"
3) "lovehuahua2"
4) "lovehuahua"
#######################################################################################
set 无序不重复集合。
删除指定的key
127.0.0.1:6379> srandmember myset //随机抽选出一个元素
"lovehuahua2"
127.0.0.1:6379> srandmember myset
"lovehuahua"
127.0.0.1:6379> srandmember myset
"lovehuahua"
127.0.0.1:6379> srandmember myset 2 //随机冲选出指定个数的元素
1) "lovehuahua"
2) "songchao"
#######################################################################################
随机删除key!
127.0.0.1:6379> smembers myset
1) "lovehuahua2"
2) "lovehuahua"
3) "yang"
4) "songchao"
127.0.0.1:6379> spop myset //随机删除一些set集合中的元素!
"yang"
127.0.0.1:6379> spop myset
"lovehuahua2"
127.0.0.1:6379> smembers myset
1) "lovehuahua"
2) "songchao"
#######################################################################################
将一个指定的值,移动到另外一个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 "chaoyang"
(integer) 1
127.0.0.1:6379> sadd myset2 "set2"
(integer) 1
127.0.0.1:6379> smove myset myset2 "chaoyang"
(integer) 1
127.0.0.1:6379> smembers myset
1) "world"
2) "hello"
127.0.0.1:6379> smembers myset2
1) "set2"
2) "chaoyang"
#######################################################################################
微博,B站,共同关注!(并集)
数字集合类:
差集 交集 并集
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) "c"
3) "b"
4) "e"
5) "d"
微博,A用户将所有关注的人放在一个set集合中!将他的粉丝也放到一个集合中!
共同关注,共同爱好,二度好友,推荐好友!(六度分隔理论)
Hash(哈希)
Map集合,key-Map!这个时候value是一个map集合!本质和String类型没有太大区别,还是一个简单的key-value!
#######################################################################################
127.0.0.1:6379> hset myhash field1 chaoyang //set一个具体key-value
(integer) 1
127.0.0.1:6379> hget myhash field1 //获取一个字段值
"chaoyang"
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 //获取全部的数据
1) "field1"
2) "hello"
3) "field2"
4) "world"
127.0.0.1:6379> hdel myhash field1 //删除hash指定key字段!对应的value值也就消失了!
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field2"
2) "world"
#######################################################################################
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> hexists myhash field1 //判断hash中指定字段是否存在!
(integer) 1
127.0.0.1:6379> hexists myhash field3
(integer) 0
#######################################################################################
#只获得所有field
#只获得所有value
127.0.0.1:6379> hkeys myhash
1) "field2"
2) "field1"
127.0.0.1:6379> hvals myhash
1) "world"
2) "hello"
#######################################################################################
incr decr
127.0.0.1:6379> hset myhash field3 5 //指定增量
(integer) 1
127.0.0.1:6379> hincrby myhash field3 1
(integer) 6
127.0.0.1:6379> hincrby myhash field3 -1
(integer) 5
127.0.0.1:6379> hsetnx myhash field4 hello //如果不存在则可以设置
(integer) 1
127.0.0.1:6379> hsetnx myhash field4 world //如果存在则不能设置
(integer) 0
hash 变更的数据 user name age,可以用来存用户信息,经常变动的信息!hash更适合于对象的存储,String更适合字符串存储!
Zset(有序集合)
在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> zadd salary 2500 godan //添加三个用户
(integer) 1
127.0.0.1:6379> zadd salary 2500 zhangsan
(integer) 1
127.0.0.1:6379> zadd salary 500 chaoyang
(integer) 1
127.0.0.1:6379> zrevrange salary 0 -1 //从大到小进行排序
1) "godan"
2) "chaoyang"
127.0.0.1:6379> zrangebyscore salary -inf +inf //显示全部的用户 从小到大!
1) "chaoyang"
2) "godan"
3) "zhangsan"
127.0.0.1:6379> zrangebyscore salary -inf +inf withscores //显示全部的用户并且附带成绩
1) "chaoyang"
2) "500"
3) "godan"
4) "2500"
5) "zhangsan"
6) "2500"
127.0.0.1:6379> zrangebyscore salary -inf 2500 withscores //显示工资小于2500员工的升序排序!
1) "chaoyang"
2) "500"
3) "godan"
4) "2500"
5) "zhangsan"
6) "2500"
#######################################################################################
移除rem中的元素!
127.0.0.1:6379> zrange salary 0 -1
1) "chaoyang"
2) "godan"
3) "zhangsan"
127.0.0.1:6379> zrem salary zhangsan //移除有序集合中的指定元素
(integer) 1
127.0.0.1:6379> zrange salary 0 -1
1) "chaoyang"
2) "godan"
127.0.0.1:6379> zcard salary //获取有序集合中的个数
(integer) 2
#######################################################################################
127.0.0.1:6379> zadd myset 1 hello
(integer) 1
127.0.0.1:6379> zadd myset 2 world 3 chaoyang
(integer) 2
127.0.0.1:6379> zcount myset 1 3 //获取指定区间的成员数量!
(integer) 6
127.0.0.1:6379> zcount myset 1 2
(integer) 4
案例思路:set 排序 存储班级成绩表,工资表排序!
普通消息,1,重要消息 2,带权重进行判断!
排行榜应用实现,取Top N 测试!
三种特殊数据类型
Geospatial地理位置详解
geospatial 地理位置
朋友的定位,附近的人,打车距离计算?
Redis的Geo在Redis3.2版本就推出了!这个功能可以推算地理位置的信息,两地之间的距离,方圆几里的人!
可以查询一些测试数据:http://life.chacuo.net/postion/
官方文档:https://www.redis.net.cn/order/3685.html
有效的经度从-180度到180度。
有效的纬度从-85.05112878度到85.05112878度。
当坐标位置超出上述指定范围时,该命令将会返回一个错误。
getadd
#getadd 添加地理位置
#规则:两级无法直接添加,可以直接下载城市数据,直接通过java程序一次性导入!
#参数key值(纬度、经度、名称)
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 shengzheng
(integer) 2
127.0.0.1:6379> geoadd china:city 120.16 30.24 hangzhou 108.96 34.26 xian
(integer) 2
getpos:获得当前定位:一定是一个坐标值!
127.0.0.1:6379> geopos china:city beijin //获取指定的城市的经纬度和维度!
1) 1) "116.39999896287918091"
2) "39.90000009167092543"
127.0.0.1:6379> geopos china:city beijin chongqin
1) 1) "116.39999896287918091"
2) "39.90000009167092543"
2) 1) "106.49999767541885376"
2) "29.52999957900659211"
geodist
两人的距离!
单位:
- m 表示单位为米。 km 表示单位为千米。 mi 表示单位为英里。 ft 表示单位为英尺。
127.0.0.1:6379> geodist china:city beijin shanghai km //查看北京到上海的直线距离
"1067.3788"
127.0.0.1:6379> geodist china:city beijin chongqin km //查看北京到重庆的直线距离
"1464.0708"
georadius:以给定的经纬度为中心
我附近的人?(获得所有附近的人的地址,定位!)通过半径来查询!
所有数据都需要录入:china:city
127.0.0.1:6379> georadius china:city 110 30 1000 km //以110,30这个经纬度为中心,寻找方圆1000km的以内的城市
1) "chongqin"
2) "xian"
3) "shengzheng"
4) "hangzhou"
127.0.0.1:6379> georadius china:city 110 30 500 km
1) "chongqin"
2) "xian"
127.0.0.1:6379> georadius china:city 110 30 500 km withdist //显示到中间距离的位置
1) 1) "chongqin"
2) "341.9374"
2) 1) "xian"
2) "483.8340"
127.0.0.1:6379> georadius china:city 110 30 500 km withcoord //显示他人的定位信息
1) 1) "chongqin"
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 500 km withdist withcoord count 1 //筛选出指定的结果
1) 1) "chongqin"
2) "341.9374"
3) 1) "106.49999767541885376"
2) "29.52999957900659211"
127.0.0.1:6379> georadius china:city 110 30 500 km withdist withcoord count 2
1) 1) "chongqin"
2) "341.9374"
3) 1) "106.49999767541885376"
2) "29.52999957900659211"
2) 1) "xian"
2) "483.8340"
3) 1) "108.96000176668167114"
2) "34.25999964418929977"
GEORADIUSBYMEMBER
# 找出位于指定范围内的元素,中心点是由给定的位置元素决定
127.0.0.1:6379> georadiusbymember china:city beijin 1000 km
1) "beijin"
2) "xian"
127.0.0.1:6379> georadiusbymember china:city beijin 400 km
1) "beijin"
127.0.0.1:6379> georadiusbymember china:city shanghai 400 km
1) "hangzhou"
2) "shanghai"
GEOHASH 命令 - 返回一个或多个位置元素的 Geohash 表示
该命令将返回11个字符的Geohash字符串!
#将二维的经纬度转换为唯一的字符串,如果两个字符串越接近,那么则距离越近!
127.0.0.1:6379> geohash china:city beijin chongqin
1) "wx4fbxxfke0"
2) "wm5xzrybty0"
GEO底层的实现原理其实就是Zset!我们可以使用Zset命令来操作geo!
127.0.0.1:6379> zrange china:city 0 -1 //查看地图中全部的元素!
1) "chongqin"
2) "xian"
3) "shengzheng"
4) "hangzhou"
5) "shanghai"
6) "beijin"
127.0.0.1:6379> zrem china:city beijin //移除指定的元素
(integer) 1
127.0.0.1:6379> zrange china:city 0 -1
1) "chongqin"
2) "xian"
3) "shengzheng"
4) "hangzhou"
5) "shanghai"
Hyperloglog基数统计
什么是基数?
A{1,3,5,7,8,7}
B{1,3,5,7,8}
基数(不重复的元素)=5,可以接受误差!
简介
Redis2.8.9版本就更新了Hyperloglog数据结构!
Redis Hyperloglog基数统计的算法!
优点:占用的内存是固定,2^64不同的元素的技术,只需要废12KB内存!如果要从内存角度来比较的话Hyperloglog首选!
网页的UV(一个人访问一个网站多次,但是还是算作一个人!)
传统的方式,set保存用户的id,然后就可以统计set中的元素数量作为标准判断!
这个方式如果保存大量的用户id,就会比较麻烦!我们的目的是为了计数,而不是保存用户id;
0.81%错误率!统计UV任务,可以忽略不记的!
测试使用
127.0.0.1:6379> pfadd mykey a b c d e f g h i j //创建第一组元素mykey
(integer) 1
127.0.0.1:6379> pfcount mykey //统计mykey元素的基数数量
(integer) 10
127.0.0.1:6379> pfadd mykey2 i j z x c v b n m //创建第二组元素mykey2
(integer) 1
127.0.0.1:6379> pfcount mykey2
(integer) 9
127.0.0.1:6379> pfmerge mykey3 mykey mykey2 //合并两组mykey mykey => mykey3 并集
OK
127.0.0.1:6379> pfcount mykey3 //看并集的数量!
(integer) 15
如果允许容错,那么一定可以使用Htperloglog!
如果不允许容错,就使用set或者自己的数据类型即可!
Bitmaps基本的事务操作
位存储
统计用户信息,活跃,不活跃!登录,未登录!打卡,365打卡!两个状态的,都可以使用Bitmaps!Bitmaps位图,数据结构!都是操作二进制位来进行记录,就只有0和1两个状态!
365天=365bit 1字节=8bit 46个字节左右
使用bitmap来记录 周一到周日的打卡!
周一:1 周二:1 周三:0 .。。。
127.0.0.1:6379> setbit sign 0 1
(integer) 0
127.0.0.1:6379> setbit sign 1 1
(integer) 0
127.0.0.1:6379> setbit sign 2 0
(integer) 0
127.0.0.1:6379> setbit sign 3 0
(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 3
(integer) 0
127.0.0.1:6379> getbit sign 4
(integer) 1
统计操作,统计打卡的天数!
127.0.0.1:6379> bitcount sign //统计这周的打卡记录,就可以看到是否有全勤
(integer) 3