Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。
redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave主从同步
NoSQL,泛指非关系型的数据库。
NoSQL有如下优点:易扩展,NoSQL数据库种类繁多,但是一个共同的特点都是去掉关系数据库的关系型特性。数据之间无关系,这样就非常容易扩展。无形之间也在架构的层面上带来了可扩展的能力。大数据量,高性能,NoSQL数据库都具有非常高的读写性能,尤其在大数据量下,同样表现优秀。这得益于它的无关系性,数据库的结构简单。
KV键值对
文档数据类型:bson格式
列存储
图关系数据库
使用docker安装
docker pull redis:latest
docker run -itd --name redis-test -p 6379:6379 redis
docker exec -it redis-test /bin/bash
进入容器内部查看安装了什么程序
docker 默认配置的redis没有配置文件,需要从容器外部进行映射
docker run -p 6378:6379 --name redis01 -v /root/redis/redis01/conf/redis.conf:/etc/redis/redis.conf -v /root/redis/redis01/data:/data -d redis redis-server /etc/redis/redis.conf --appendonly yes
-p 6378:6379 容器redis 端口6379 映射 宿主机未6378
–name redis01 容器 名字 为 redis01
-v /root/redis/redis01/conf/redis.conf:/etc/redis/redis.conf 容器 /etc/redis/redis.conf 配置文件 映射宿主机 /root/redis/redis01/conf/redis.conf。 会将宿主机的配置文件复制到docker中。
重要: 配置文件映射,docker镜像redis 默认无配置文件。
-v /root/redis/redis01/data:/data 容器 /data 映射到宿主机 /root/redis/redis01/data
-d redis 后台模式启动 redis
redis-server /etc/redis/redis.conf redis 将以 /etc/redis/redis.conf 为配置文件启动
–appendonly yes 开启redis 持久化
redis-benchmark– 压力测试工具
root@848185349f6b:/data# redis-benchmark -c 100 -n 100000
# 模拟测试100个并发 每个并发10w次请求
默认使用第0个
可以使用select进行切换
#切换到第四个数据库
127.0.0.1:6379> select 4
OK
#查看数据库的大小
127.0.0.1:6379[4]> DBSIZE
(integer) 0
#清除当前数据库 FLUSHDB
127.0.0.1:6379[5]> DBSIZE
(integer) 1
127.0.0.1:6379[5]> FLUSHDB
OK
127.0.0.1:6379[5]> DBSIZE
(integer) 0
#清除所有数据库 FLUSHALL
#EXISTS KEY 判断这个key是否存在 返回一个整型数据
#MOVE KEY 库序号 移动一个key到另一个库
#EXPIRE KEY SECONDS 设置key过期时间
#TTL KEY 查看key过期时间
#TYPE KEY 查看key的数据类型
redis6支持多线程,redis基于内存操作,cpu不是redis性能瓶颈,redis瓶颈在于机器的内存和网络的带宽
redis为什么单线程还那么快?
redis将所有的数据全部放在内存中,使用单线程去操作效率就是最高的,多线程(CPU上下文会切换),对于内存系统来说,如果没有上下文切换效率就是最高的。多次读写都是在一个cpu上
127.0.0.1:6379> set key1 v1
OK
127.0.0.1:6379> keys *
1) "key1"
127.0.0.1:6379> get key1
"v1"
127.0.0.1:6379> exists KEY1
(integer) 0
127.0.0.1:6379> exists key1
(integer) 1
127.0.0.1:6379> APPEND key1 hello #在字符串后面增加值,返回字符串的长度,如果key不存在 相当于新建了key
(integer) 7
127.0.0.1:6379> STRLEN key1 #获取字符串的长度
(integer) 7
127.0.0.1:6379> set views 0
OK
127.0.0.1:6379> type views
string
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incr views #key对应的值++
(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 vies #key对应的值-- 若没有对应的key 则新建一个key
(integer) -1
127.0.0.1:6379> decr views
(integer) 1
127.0.0.1:6379> INCRBY views 10 #key对应的值以步长的方式增加
(integer) 11
127.0.0.1:6379> INCRBY views 10
(integer) 21
127.0.0.1:6379> DECRBY views 10 #key对应的值以步长的方式减小
127.0.0.1:6379> set key1 "hellp"
OK
127.0.0.1:6379> get key1
"hellp"
127.0.0.1:6379> GETRANGE key1 0 1 #截取字符串
"he"
127.0.0.1:6379> get key1
"hellp"
127.0.0.1:6379> GETRANGE key1 0 -1 #截取全部的字符串
"hellp"
127.0.0.1:6379> set key2 abcdefgg
OK
127.0.0.1:6379> get key2
"abcdefgg"
127.0.0.1:6379> setrange key2 1 xx #替换字符串 从第一个位置开始替换 返回替换后的长度
(integer) 8
127.0.0.1:6379> get key2
"axxdefgg"
#setex (set with expire) #设置过期时间
#setnx (set if not exist) #不存在再设置
127.0.0.1:6379> mset key1 v1 key2 v2 key3 v3 #批量设置值
OK
127.0.0.1:6379> keys *
1) "key3"
2) "key2"
3) "key1"
127.0.0.1:6379> mget key1 key2 key3 #批量获取值
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> msetnx key1 v1 key4 v4 #因为key1存在,key4也创建失败了,原子性操作
(integer) 0
127.0.0.1:6379> set user:1 {name:lyc,age:3} #设置一个对象
OK
127.0.0.1:6379> keys *
1) "key3"
2) "key2"
3) "user:1"
4) "key1"
127.0.0.1:6379> get user:1
"{name:lyc,age:3}"
127.0.0.1:6379>
#getset 先获取值再设置新的值
#如果不存在值 就返回nil
#可用于更新的操作
127.0.0.1:6379> getset dh 1
(nil)
127.0.0.1:6379> getset dh 2
"1"
127.0.0.1:6379> getset dh 3
"2"
#同理setget 先设置值再获取值? 其实并没有
string使用场景
类似Map集合
类似于key-
#设置一个值
# hset key field value
127.0.0.1:6379> hset hash1 lyc handsome
(integer) 1
#获取一个值
# hget key field
127.0.0.1:6379> hget hash1 lyc
"handsome"
#hmset 同时设置多个值
#hgetall 将hash里面的值全部取出来
#hdel key field 删除某个key的字段
#hlen key 获取hash有多少个键值对
#hexists key field 判断hash指定字段是否存在
#只获得所有的field
hkeys keys
#只获得所有的values
#以指定步长增加
#Hincrby key field 步长
适用于存放对象
列表
可以当作队列,栈,循环队列
所有的list命令以l开头
127.0.0.1:6379> lpush av x [23m23,2323,2323] #推入一系列值进入队列
(integer) 2
127.0.0.1:6379> keys *
1) "av"
127.0.0.1:6379> lpop av #弹出顶端
"[23m23,2323,2323]"
127.0.0.1:6379> lpop av
"x"
127.0.0.1:6379> lpush a b1 c1 d1 2 3 4
(integer) 6
127.0.0.1:6379> lrange a 0 -1 #获取列表中全部的值
1) "4"
2) "3"
3) "2"
4) "d1"
5) "c1"
6) "b1"
# lpush 和 Rpush的区别 一个左侧推入 一个右侧推入 类似于双向列表
127.0.0.1:6379> lpush a 1 2 3 4 5 6
(integer) 6
127.0.0.1:6379> rpush b 1 2 3 4 5 6
(integer) 6
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379> lrange a 0 -1
1) "6"
2) "5"
3) "4"
4) "3"
5) "2"
6) "1"
127.0.0.1:6379> lrange b 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
#lindex 通过下标获得list中的某一个值
127.0.0.1:6379> lrange a 0 -1
1) "4"
2) "3"
3) "2"
127.0.0.1:6379> lindex a 1
"3"
127.0.0.1:6379> lindex a 2
"2"
#Llen 获取list的长度
127.0.0.1:6379> lpush a 1 2 3 4 5 6
(integer) 6
127.0.0.1:6379> llen a
(integer) 6
#lrem 删除指定个数指定值,优先删除刚加入的元素
127.0.0.1:6379> llen a
(integer) 6
127.0.0.1:6379> lrange a 0 -1
1) "6"
2) "5"
3) "4"
4) "3"
5) "2"
6) "1"
127.0.0.1:6379> lrem a 1 1
(integer) 1
127.0.0.1:6379> lrange a 0 -1
1) "6"
2) "5"
3) "4"
4) "3"
5) "2"
#ltrim 通过下表截取指定的长度,原list被改变
#rpoplpush 右边弹出左边插入到新表
#lset list index elements 指定下标改变值 但表没有的时候会报错
#linsert list before/aftert word value 在word前后插入值
127.0.0.1:6379> linsert a before 9 value
(integer) 2
127.0.0.1:6379> lrange a 0 -1
1) "value"
2) "9"
127.0.0.1:6379> linsert a after 9 value
(integer) 3
实际上是个双向链表
在两边插入,改值效率最高
中间元素效率偏低
set的值不能重复
127.0.0.1:6379> sadd myset a #往set集合放值
(integer) 0
127.0.0.1:6379> sadd myset v
(integer) 1
127.0.0.1:6379> smembers myset #查看set里面的成员
1) "a"
2) "v"
#scard set 获取set多少个成员
#srem set value 删除指定元素
127.0.0.1:6379> srem myset v
(integer) 1
#srandmember 随机抽取几个成员
#srandmember set value 随机抽取出指定个数的元素
127.0.0.1:6379> srandmember myset 1
1) "v"
127.0.0.1:6379> srandmember myset 1
1) "v"
127.0.0.1:6379> srandmember myset 1
1) "v"
127.0.0.1:6379> srandmember myset 1
1) "a"
#随机删除key,spop
127.0.0.1:6379> spop myset
"a"
127.0.0.1:6379> spop myset
"v"
#将一个指定的值,移动到另一个集合中
127.0.0.1:6379> sadd a 1 2 3 4 5
(integer) 5
127.0.0.1:6379> sadd b 1 2 3 4 5
(integer) 5
127.0.0.1:6379> smove a b 3
(integer) 1
127.0.0.1:6379> smembers b
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
127.0.0.1:6379> smembers a
1) "1"
2) "2"
3) "4"
4) "5"
# 移出移入操作
#交并补集
127.0.0.1:6379> sadd key 1 a b c
(integer) 4
127.0.0.1:6379> sadd key2 c
(integer) 1
127.0.0.1:6379> sadd key2 d e
(integer) 2
127.0.0.1:6379> smembers key
1) "c"
2) "1"
3) "a"
4) "b"
127.0.0.1:6379> smembers key2
1) "e"
2) "d"
3) "c"
# 差集 sdiff
127.0.0.1:6379> sdiff key key2
1) "1"
2) "a"
3) "b"
#交集 sinter
127.0.0.1:6379> sinter key key2
1) "c"
#并集 sunion
127.0.0.1:6379> sunion key key2
1) "b"
2) "d"
3) "e"
4) "c"
5) "1"
6) "a"
在set基础上加了个排序
mset k1 v1
zset k1 1 v1
用中间的值排序
#ZrangerByscore key -inf +inf
#遍历出所有的key
#ZrangerByscore key -inf +inf withscores
#遍历出所有的key 和value
#移除所有元素
zrem key member
#获取集合中的个数
zcard key
#获取区间内的成员个数
zcount myset min max
位存储
统计用户信息
两个状态的01数据都可以用bitmaps
位图,二进制位进行记录
#设置位图的值
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
#GETBIT key 1
#获取当天的值
#统计1的个数
#BITcount key start end
基数(cardinal number)在数学上,是集合论中刻画任意集合大小的一个概念。两个能够建立元素间一一对应的集合称为互相对等集合。例如3个人的集合和3匹马的集合可以建立一一对应,是两个对等的集合。
A{1,3,5,7,8,9,7}
B{1,3,5,7,8,9}
不重复的元素(基数) =5 相对于一个集合来说
可以用来保存需要去重的数据
#添加进hyperloglogs中
127.0.0.1:6379> PFADD myset a v vf dd d dw e esd ds
(integer) 1
#返回基数个数
127.0.0.1:6379> PFCOUNT myset
(integer) 9
#合并两个hyperloglogs
PFMERGE newkey key1 key2
redis 的geo
#添加经纬度
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
#GEOPOS Key1 key 获取指定key的经纬度
#获得当前定位的位置
#获取两个key之间的距离
#GEODITS KEY1 KEY KEY KM
redis> GEODIST Sicily Palermo Catania
"166274.1516"
#以给定的经纬度为中心,找出某一半径的元素
#GEOREDIS KEY 经度 纬度 半径
redis> GEORADIUS Sicily 15 37 100 km
1) "Catania"
redis> GEORADIUS Sicily 15 37 200 km
1) "Palermo"
2) "Catania"
#找出位于元素周围的元素
#GEORADIUSBYMEMEBER
#GEOHASH 返回经纬度的hash值,将二维经纬度转换为一维字符串
底层实现:Zset
tial 地理位置
redis 的geo
#添加经纬度
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
#GEOPOS Key1 key 获取指定key的经纬度
#获得当前定位的位置
#获取两个key之间的距离
#GEODITS KEY1 KEY KEY KM
redis> GEODIST Sicily Palermo Catania
"166274.1516"
#以给定的经纬度为中心,找出某一半径的元素
#GEOREDIS KEY 经度 纬度 半径
redis> GEORADIUS Sicily 15 37 100 km
1) "Catania"
redis> GEORADIUS Sicily 15 37 200 km
1) "Palermo"
2) "Catania"
#找出位于元素周围的元素
#GEORADIUSBYMEMEBER
#GEOHASH 返回经纬度的hash值,将二维经纬度转换为一维字符串
底层实现:Zset