Redis的基本概念
- Remote Dictionary Server:远程字典服务
- Redis 是一个
开源
(BSD许可)的,内存中的数据结构存储系统
,它可以用作数据库、缓存和消息中间件 。 - 它
支持多种类型的数据结构
,如字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps,hyperloglogs 和地理空间(geospatial) 索引半径查询。 - Redis 内置了 复制(replication),LUA脚本(Luascripting), LRU驱动事件(LRU eviction),事务(transactions) 和
不同级别的磁盘持久化(persistence)-- RDB和AOF
, 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。
简单的横向对比
Redis能干什么?
- 内存存储、持久化、内存是断电即失,所以说持久化很重要(RDB和AOF);
- 效率高、可用于高速缓冲;
- 发布订阅系统;
- 地图信息分析;
- 计时器,计数器(浏览量);
- …
单线程的Redis
- 官方表示,Redis是基于内存操作的,
CPU不是Redis的性能瓶颈
,Redis的瓶颈就是根据机器的内存和网络带宽。既然可以使用单线程来实现,就使用单线程了! - Redis是C语言实现的,官方数据:读:110000/s 写: 80000/s,完全不比同样使用key-value的Memcached差
Redis为什么单线程这么快?
- 误区1: 高性能的服务器一定是多线程的
- 误区2: 多线程(CPU上下文切换)一定比单线程效率高
核心
: Redis是将所有的数据全部放在内存中的,所以说使用单线程去操作效率就是最高的,相比多线程,减少了CPU上下文切换的耗时。对于内存系统来说,没有上下文切换效率就是最高的,多次读写都是在一个CPU上的。
Redis的基本操作
注意
:Redis对大小写不敏感。
select
Redis默认有16个数据库,默认使用的是第0个数据库,可以通过select
切换数据库
127.0.0.1:6379> select 3
OK
127.0.0.1:6379[3]>
dbsize
查看数据库的大小
127.0.0.1:6379[3]> dbsize
(integer) 0
127.0.0.1:6379[3]> set name mk
OK
127.0.0.1:6379[3]> dbsize
(integer) 1
127.0.0.1:6379[3]> set age 22
OK
127.0.0.1:6379[3]> dbsize
(integer) 2
127.0.0.1:6379[3]>
keys
查看所有的key: 格式 : keys *
127.0.0.1:6379[3]> keys *
1) "name"
2) "age"
flushdb和flushall
清空当前数据库和清空所有数据库
127.0.0.1:6379[3]> flushdb
OK
127.0.0.1:6379[3]> keys *
(empty list or set)
127.0.0.1:6379[3]> flushall
OK
–下面进入正题–
Redis的五种基本类型
Redis-key
#set 设置key
#get 查看key的值
#expire 设置key的过期时间
#ttl 查看key的剩余时间
#exists 判断当前的key是否存在
#keys * 查看当前所有的key
#del key 删除当前的key
#type 查看key存储的value的类型
1、字符串String
set get
设置值和获取值
:格式:
127.0.0.1:6379[3]> set k1 v1
OK
127.0.0.1:6379[3]> get k1
"v1"
exists
判断key是否存在
:格式:
127.0.0.1:6379[3]> exists k1
(integer) 1
append
追加字符串,如果key不存在,相当于set命令
,格式:
127.0.0.1:6379[3]> append k1 hello
(integer) 7
127.0.0.1:6379[3]> get k1
"v1hello"
127.0.0.1:6379[3]> append k2 v2
(integer) 2
127.0.0.1:6379[3]> get k2
"v2"
strlen
获取字符串的长度
:格式:
127.0.0.1:6379[3]> strlen k1
(integer) 7
127.0.0.1:6379[3]> strlen k2
(integer) 2
127.0.0.1:6379[3]> append k2 hi
(integer) 4
127.0.0.1:6379[3]> strlen k2
(integer) 4
127.0.0.1:6379[3]>
incr 和decr
对value进行自增1和自减1操作
:格式:
127.0.0.1:6379[3]> set views 0
OK
127.0.0.1:6379[3]> get views
"0"
127.0.0.1:6379[3]> incr views
(integer) 1
127.0.0.1:6379[3]> incr views
(integer) 2
127.0.0.1:6379[3]> get views
"2"
127.0.0.1:6379[3]> decr views
(integer) 1
127.0.0.1:6379[3]> get views
"1"
incrby和decrby
设置加减的步长
:格式:
- incrby key num
- decrby key num
127.0.0.1:6379[3]> incrby views 10
(integer) 11
127.0.0.1:6379[3]> get views
"11"
127.0.0.1:6379[3]> decrby views 3
(integer) 8
127.0.0.1:6379[3]> get views
"8"
getrange
获取给定范围的字符串的值
:格式:
127.0.0.1:6379[3]> set k1 hello,mk
OK
127.0.0.1:6379[3]> get k1
"hello,mk"
127.0.0.1:6379[3]> getrange k1 0 4
"hello"
127.0.0.1:6379[3]> getrange k1 0 -1
"hello,mk"
setrange
从制定位置开始替换字符串的值
:格式:
- sterange key offset value
127.0.0.1:6379[3]> getrange k1 0 -1
"hello,mk"
127.0.0.1:6379[3]> setrange k1 6 bw
(integer) 11
127.0.0.1:6379[3]> getrange k1 0 -1
"hello,bw"
setex和ttl
(set with expire)
设置过期时间,查看剩余时间
:格式:
- setex key seconds value
- ttl key
127.0.0.1:6379[3]> setex k2 10 aaaa
OK
127.0.0.1:6379[3]> ttl k2
(integer) 7
127.0.0.1:6379[3]> ttl k2
(integer) 2
setnx
(set if not exist)
如果key不存在则设置,否则失败
:格式:
127.0.0.1:6379[3]> setnx k2 bw
(integer) 1
127.0.0.1:6379[3]> get k2
"bw"
127.0.0.1:6379[3]> setnx k2 xa
(integer) 0
127.0.0.1:6379[3]> get k2
"bw"
mset和mget
同时设置或者获取多个值
:格式:
- mset key1 value1 key2 value2…
- mget key1 key2…
127.0.0.1:6379[3]> mset k1 mk k2 bw
OK
127.0.0.1:6379[3]> keys *
1) "k2"
2) "k1"
127.0.0.1:6379[3]> mget k1 k2
1) "mk"
2) "bw"
msetnx
msetnx是一个原子操作,要么一起成功,要么一起失败
:
127.0.0.1:6379> msetnx k1 mk k2 bw k3 ccc
(integer) 0
127.0.0.1:6379> get k3
(nil)
用String存储对象时key值的设计
127.0.0.1:6379> set user:1 {name:mk,age:22}
OK
127.0.0.1:6379> mset user:1:name mk user:1:age 22
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "mk"
2) "22"
getset
先获取值,再设置值,如果不存在,返回nil,如果存在,获取原来的值,并设置新的值
:格式:
127.0.0.1:6379> getset k3 ccc
(nil)
127.0.0.1:6379> get k2
"bw"
127.0.0.1:6379> getset k2 mk
"bw"
127.0.0.1:6379> get k2
"mk"
2、列表List
在Redis中,我们可以用list完成栈、队列、阻塞队列
注意
:所有的list命令都是l开头的
lpush rpush lrange
从list左边或者右边插入值
- lpush key value
- rpush key value
lrange获取指定范围的值
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
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> lrange list 0 1
1) "three"
2) "two"
127.0.0.1:6379> rpush list zero
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "zero"
lpop和rpop
从列表左边或者右边移除值
:格式:
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "zero"
127.0.0.1:6379> lpop list
"three"
127.0.0.1:6379> rpop list
"zero"
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 0
"two"
127.0.0.1:6379> lindex list 1
"one"
llen
获取列表中的元素个数
:格式:
127.0.0.1:6379> llen list
(integer) 2
lrem
移除列表中的元素
:格式:
移除key中的count个value
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
127.0.0.1:6379> lrem list 1 two
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "one"
ltrim
截取列表的值
:格式:
127.0.0.1:6379> lpush list mk1 mk2 mk3 mk4
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "mk4"
2) "mk3"
3) "mk2"
4) "mk1"
127.0.0.1:6379> ltrim list 1 2
OK
127.0.0.1:6379> lrange list 0 -1
1) "mk3"
2) "mk2"
rpoplpush
移除列表中最后一个元素,将它添加到另一个列表中
,格式:
127.0.0.1:6379> lrange list 0 -1
1) "mk3"
2) "mk2"
127.0.0.1:6379> rpoplpush list list2
"mk2"
127.0.0.1:6379> lrange list 0 -1
1) "mk3"
127.0.0.1:6379> lrange list2 0 -1
1) "mk2"
lset
根据下标替换列表中的值,前提是这个值存在
,格式:
127.0.0.1:6379> lrange list 0 -1
1) "mk3"
127.0.0.1:6379> lset list 0 mk1
OK
127.0.0.1:6379> lrange list 0 -1
1) "mk1"
127.0.0.1:6379> lset list 1 mk2
(error) ERR index out of range
linsert
在列表中插入值
,格式:
- linsert key before | after value new_value
127.0.0.1:6379> linsert list after mk1 "mk2"
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "mk1"
2) "mk2"
小结
- List实际上是一个链表,before or after, left,right都可以插入值
- 如果key不存在,创建新的链表
- 如果key存在,新增内容
- 如果移除了所有的值,空链表,也代表不存在
- 在两端插入或者改动值,效率最高!中间元素,相对来说效率会低一点
- 队列——LPOP - RPUSH
- 栈——LPOP - LPUSH
3、集合set
注意
:set中的值是不可以重复的
给set中添加值
格式:
127.0.0.1:6379> sadd myset mk1
(integer) 1
127.0.0.1:6379> sadd myset mk2
(integer) 1
127.0.0.1:6379> sadd myset mk3
(integer) 1
127.0.0.1:6379> sadd myset mk1
(integer) 0
smembers
获取set中的所有值
:格式:
127.0.0.1:6379> smembers myset
1) "mk3"
2) "mk2"
3) "mk1"
sismember
判断某个值是否在set中
:格式:
127.0.0.1:6379> sismember myset mk1
(integer) 1
127.0.0.1:6379> sismember myset mk4
(integer) 0
scard
获取set中元素的个数
:格式:
127.0.0.1:6379> scard myset
(integer) 3
srem
删除set中的值
:格式:
127.0.0.1:6379> smembers myset
1) "mk3"
2) "mk2"
3) "mk1"
127.0.0.1:6379> srem myset mk1
(integer) 1
127.0.0.1:6379> srem myset mk4
(integer) 0
127.0.0.1:6379> smembers myset
1) "mk3"
2) "mk2"
srandmember
从set中获取随机值
,格式:
- srandmember key count
从key中随机获取count个值
127.0.0.1:6379> smembers myset
1) "mk3"
2) "mk2"
3) "mk1"
4) "mk4"
127.0.0.1:6379> srandmember myset
"mk1"
127.0.0.1:6379> srandmember myset
"mk4"
127.0.0.1:6379> srandmember myset 2
1) "mk3"
2) "mk1"
spop
随机删除指定个数个元素
:格式:
127.0.0.1:6379> smembers myset
1) "mk3"
2) "mk2"
3) "mk1"
4) "mk4"
127.0.0.1:6379> spop myset
"mk1"
127.0.0.1:6379> spop myset
"mk2"
smove
将指定的元素从一个set中移动到另一个set中
,格式:
127.0.0.1:6379> sadd myset mk1 mk2 mk3 mk4
(integer) 4
127.0.0.1:6379> smembers myset
1) "mk3"
2) "mk2"
3) "mk1"
4) "mk4"
127.0.0.1:6379> sadd myset2 bw1 bw2 bw3
(integer) 3
127.0.0.1:6379> smembers myset2
1) "bw1"
2) "bw3"
3) "bw2"
127.0.0.1:6379> smove myset myset2 mk1
(integer) 1
127.0.0.1:6379> smembers myset
1) "mk3"
2) "mk2"
3) "mk4"
127.0.0.1:6379> smembers myset2
1) "mk1"
2) "bw1"
3) "bw3"
4) "bw2"
数字集合类
- 差集 —— sdiff set1 set2
- 交集 —— sinter set1 set2
- 并集 —— sunion set1 set2
应用: A用户的关注列表放在一个set,将他的粉丝放在一个集合中,可以实现共同关注、共同爱好、推荐好友等:
127.0.0.1:6379> sadd set1 a b c d
(integer) 4
127.0.0.1:6379> sadd set2 c d e f
(integer) 4
127.0.0.1:6379> sdiff set1 set2
1) "b"
2) "a"
127.0.0.1:6379> sinter set1 set2
1) "d"
2) "c"
127.0.0.1:6379> sunion set1 set2
1) "b"
2) "d"
3) "e"
4) "f"
5) "c"
6) "a"
4、哈希
可以将哈希看成是一个Map集合,key-value中的value是一个map集合
hset和hget
设置或者获取一个hash的值
:格式:
- hset key field1 value1
- hget key field
127.0.0.1:6379> hset myhash field mk
(integer) 1
127.0.0.1:6379> hget myhash field
"mk"
hmset和hmget
设置或者获取一组hash的值
:格式
- hmset key field1 value1 field2 value2…
- hmget key field1 field2 …
127.0.0.1:6379> hmset myhash field1 mk field2 bw field3 ccc
OK
127.0.0.1:6379> hmget myhash field1 field2
1) "mk"
2) "bw"
hgetall
获取hash中的值
:格式:
127.0.0.1:6379> hgetall myhash
1) "field1"
2) "mk"
3) "field2"
4) "bw"
5) "field3"
6) "ccc"
hdel
删除指定field的hash键值对
,格式::
127.0.0.1:6379> hdel myhash field3
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field1"
2) "mk"
3) "field2"
4) "bw"
hlen
获取hash的键值对的个数
:格式:
127.0.0.1:6379> hlen myhash
(integer) 2
hexists
判断hash中的字段是否存在
:格式:
127.0.0.1:6379> hexists myhash field1
(integer) 1
127.0.0.1:6379> hexists myhash field3
(integer) 0
hkeys和hvals
获取hash中所有的字段或者值:格式:
127.0.0.1:6379> hkeys myhash
1) "field1"
2) "field2"
127.0.0.1:6379> hvals myhash
1) "mk"
2) "bw"
hincrby
给hash中指定字段的值加上一个增量
:
OK
127.0.0.1:6379> hset myhash field1 2
(integer) 1
127.0.0.1:6379> hincrby myhash field1 3
(integer) 5
127.0.0.1:6379> hincrby myhash field1 -1
(integer) 4
hsetnx
如果不存在则添加,如果存在则失败
:格式:
127.0.0.1:6379> hsetnx myhash field1 3
(integer) 0
127.0.0.1:6379> hsetnx myhash field3 5
(integer) 1
hash的应用
- hash中存储经常变更的值:比如用户信息: user : name-value,age-value,sex-value
- hash更适合对象的存储,String更加适合字符串存储
5、有序集合zset
zadd
向有序集合中添加值
:格式:
127.0.0.1:6379> zadd myzset 1 mk
(integer) 1
127.0.0.1:6379> zadd myzset 2 bw 3 cc
(integer) 2
zrange
获取zset中一个范围的值
,格式:
127.0.0.1:6379> zrange myzset 0 -1
1) "mk"
2) "bw"
3) "cc"
zrangebyscore
将zset中的值按照score从小到大排序输出
,格式:
- zrangebyscore key min max
127.0.0.1:6379> zrangebyscore myzset -inf +inf
1) "mk"
2) "bw"
3) "cc"
127.0.0.1:6379> zrangebyscore myzset -inf +inf withscores
1) "mk"
2) "1"
3) "bw"
4) "2"
5) "cc"
6) "3"
从大到小输出:zrevrange myset 0 -1
zrem
移除zset中指定的元素
,格式:
127.0.0.1:6379> zrange myzset 0 -1
1) "mk"
2) "bw"
3) "cc"
127.0.0.1:6379> zrem myzset cc
(integer) 1
127.0.0.1:6379> zrange myzset 0 -1
1) "mk"
2) "bw"
zcard
查看zset中的元素的个数
:格式:
127.0.0.1:6379> zrange myzset 0 -1
1) "mk"
2) "bw"
127.0.0.1:6379> zcard myzset
(integer) 2
zcount
根据score的值统计在给定区间的元素个数
,格式:
127.0.0.1:6379> zrange myzset 0 -1
1) "mk"
2) "bw"
127.0.0.1:6379> zcount myzset 1 1
(integer) 1
127.0.0.1:6379> zcount myzset 1 3
(integer) 2
Redis的三种特殊类型
1、geospatial
可以用来实现朋友的定位,附近的人,打车距离计算等
城市的经度纬度查询: http://www.jsons.cn/lngcode/
geoadd
添加地理位置
:格式:
127.0.0.1:6379> GEOADD china:city 116.40 39.90 beijing
(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 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
geopos
返回给定名称的纬度和经度
127.0.0.1:6379> GEOPOS china:city xian
1) 1) "108.96000176668167114"
2) "34.25999964418929977"
127.0.0.1:6379> GEOPOS china:city xian beijing
1) 1) "108.96000176668167114"
2) "34.25999964418929977"
2) 1) "116.39999896287918091"
2) "39.90000009167092543"
geodist
返回两个给定位置之间的距离
单位:
127.0.0.1:6379> GEODIST china:city beijing xian km
"910.0565"
127.0.0.1:6379> GEODIST china:city hangzhou xian
km "1143.6295"
geohash
返回一个11个字符的geohash字符串
127.0.0.1:6379> GEOHASH china:city xian
1) "wqj6zky6bn0"
georadius
以给定的纬度经度为中心,找到某一半径内的元素
127.0.0.1:6379> GEORADIUS china:city 110 30 1000 km
1) "chongqing"
2) "xian"
3) "shengzhen"
4) "hangzhou"
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km
1) "chongqing"
2) "xian"
127.0.0.1:6379> GEORADIUS china:city 110 30 500 km withcoord
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>
georadiusbymember
以一个成员为中心,查找指定半径范围内容的元素
127.0.0.1:6379> GEORADIUSBYMEMBER china:city xian 1000 km
1) "xian"
2) "chongqing"
3) "beijing"
geo的底层是一个zset集合
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 shanghai
(integer) 1
127.0.0.1:6379> zrange china:city 0 -1
1) "chongqing"
2) "xian"
3) "shengzhen"
4) "hangzhou"
5) "beijing"
2、hyperloglog
什么是基数?
比如数据集 {1, 3, 5, 7, 5, 7, 8},
那么这个数据集的基数集为 {1, 3, 5 ,7, 8},
基数(不重复元素)为5。 基数估计就是在误差可接受的范围内,快速计算基数。
简介
Redis hyperloglog是基数统计的算法,其在输入元素的数量或者体积很大的时候,计算基数的空间总是固定的,并且很小。(错误率:0.81%)
pfadd、pfcount、pfmerge
- pfadd key value1 value2…添加指定元素到hyperloglog中
- pfcount key key…返回给定hyperloglog的基数估算值
- pfmerge destkey soucrekey sourcekey合并多个hyperloglog
127.0.0.1:6379> pfadd myset a b c d e f f
(integer) 1
127.0.0.1:6379> pfcount myset
(integer) 6
127.0.0.1:6379> pfadd myset2 c d e f g h h
(integer) 1
127.0.0.1:6379> pfcount myset2
(integer) 6
127.0.0.1:6379> pfmerge myset3 myset1 myset2
OK
127.0.0.1:6379> pfcount myset3
(integer) 6
3、bitmaps
bitmaps是位存储的,都是二进制位来进行记录, 所以只要是只有两种状态值的场景,都可以使用bitmaps来存储。比如:登录、未登录;打卡,未打卡;活跃,不活跃等。
操作二进制位进行记录,5
setbit
在bitmaps中添加数据
:格式:
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 1
(integer) 0
127.0.0.1:6379> setbit sign 3 1
(integer) 0
127.0.0.1:6379> setbit sign 4 0
(integer) 0
getbit
查看位图中某个位置的值
:格式:
127.0.0.1:6379> getbit sign 3
(integer) 1
127.0.0.1:6379> getbit sign 1
(integer) 1
127.0.0.1:6379> getbit sign 4
(integer) 0
bitcount
统计位图中value等于1的个数
,格式:
127.0.0.1:6379> bitcount sign 0 -1
(integer) 4
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)