NoSQL(NoSQL = Not Only SQL ),意即“不仅仅是SQL”,泛指非关系型的数据库,NoSQL 不依赖业务逻辑方式存储。
用不着sql的和用了sql也不行的情况,请考虑用NoSql
Redis是一个开源的 key-value 存储系统
它支持存储的value类型相对更多,包括 string、list、set、zset(sorted set --有序集合)和 hash
这些数据类型都支持 push/pop、add/remove 及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。
在此基础上,Redis支持各种不同方式的排序
为了保证效率,数据都是缓存在内存中
Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件
并且在此基础上实现了master-slave(主从)同步
docker pull redis # 安装最新版本的redis
# 在 data/redis/redis.conf 配置文件中写配置内容: appendonly yes
# 配置文件挂载,/data/redis目录下有redis.conf配置文件,主机中的 /data/redis 目录对应容器中的 /usr/local/etc/redis # 持久化数据挂载 # 后台运行 起别名 # 端口映射 # 启动容器中的redis docker run -v /data/redis:/usr/local/etc/redis \ -v /data/redis/data:/data \ -d --name myredis \ -p 6379:6379 \ redis:latest redis-server /usr/local/etc/redis/redis.conf
docker exec -it CONTAINER redis-cli
ping
select <dbid>
来切换数据库。如: select 8
Redis 是单线程+多路IO复用技术
多路复用是指使用一个线程来检查多个文件描述符(Socket)的就绪状态,比如调用select和poll函数,传入多个文件描述符,如果有一个文件描述符就绪,则返回,否则阻塞直到超时。得到就绪状态后进行真正的操作可以在同一个线程里执行,也可以启动线程执行(比如使用线程池)
Redis有5种常用数据类型,它们是key-value中的value,对于key来说有一些通用命令:
set k1 v1 # 存入键值对 keys * # 查看当前库所有key exists key # 判断某个key是否存在 type key # 查看你的key是什么类型 del key # 删除指定的key数据 unlink key # 根据value选择非阻塞删除,仅将keys从keyspace元数据中删除,真正的删除会在后续异步操作。 expire key 10 # 设置key10秒后过期,过期后自动删除 ttl key # 查看还有多少秒过期,-1表示永不过期,-2表示已过期 select # 命令切换数据库 dbsize # 查看当前数据库的key的数量 flushdb # 清空当前库 flushall # 通杀全部库
String是Redis最基本的类型,key都是字符串类型,其他几种数据结构都是在String基础上构建的。String的值实际可以是字符串(简单字符串、复杂字符串如Json、XML)、数字(整数、浮点数),甚至是二进制(图片、音视频),最大不能超过512M
SET key value [EX seconds|PX milliseconds|EXAT timestamp|PXAT milliseconds-timestamp|KEEPTTL] [NX|XX] [GET] # EX seconds:设置key的秒级过期时间 # PX milliseconds:设置key的毫秒级过期时间,与EX互斥 # NX:key必须不存在才能设置成功,用于添加 # XX:key必须存在才能设置成功,用于更新 # return value:set执行正确返回OK,指定了NX/XX但没有正确执行,返回(nil) SETNX key value # 相当于 SET key value NX SETEX key seconds value # 相当于 SET key value EX seconds
MSET key value [key value ...] # 原子操作
GET key # return value:key存在返回对应的value,不存在返回(nil)
MGET key [key ...]
INCR key # value为String类型的数字时才能自增1,是原子操作 INCRBY key increment # value自增increment
DECR key DECRBY key increment
APPEND key value # return value:返回value的长度
STRLEN key
GETSET key value # return value:返回旧值
SETRANGE key offset value # 用value覆盖从offset开始的字符串,返回新字符串的长度
GETRANGE key start end # 左闭右闭
String 的内部编码有3种:
String 的数据结构为简单动态字符串(Simple Dynamic String,缩写SDS)。是可以修改的字符串,内部结构实现上类似于 Java 的 ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配。
当字符串长度小于 1M 时,扩容都是加倍现有的空间,如果超过 1M,扩容时一次只会多扩 1M 的空间。需要注意的是字符串最大长度为 512M
List 是插入有序的字符串列表。底层是双向链表,可以添加一个元素到列表的头部或者尾部,能充当栈和队列。一个列表可以存储 231 - 1 个元素。
RPUSH key element [element ...] # return value:返回列表中元素的个数
LPUSH key element [element ...]
LINSERT key BEFORE|AFTER pivot element
LRANGE key start stop # 左闭右闭 # 索引下标从左到右是 0 到 n-1,从右到左是 -1 到 -n # lrange mylist 0 -1 表示查询所有
LINDEX key index
LLEN key
RPOP key
LPOP key
LREM key count element # count > 0,从左到右,删除最多count个元素 # count < 0,从右到左,删除最多-count个元素 # count == 0,删除所有value为element的元素
LTRIM key start stop # 左闭右闭
LSET key index element
BRPOP key [key ...] timeout BLPOP key [key ...] timeout # key对应的列表为空,客户端等待timeout后返回,返回值为(nil)和阻塞时间timeout,若timeout==0,客户端一直等待下去 # 列表不为空,客户端会立即返回,返回值是弹出元素的key和弹出的元素
List 的内部编码如下:
快速列表(quicklist)
列表的节点是ziplist,双指针将ziplist串起来组成quicklist
lpush + lpop = stack
lpush + rpop = queue
lpush + ltrim = capped collection(有限集合)
lpush + brpop = message queue(消息队列)
Set 是无序去重的,底层是 value 为 null 的 Hash 表
SADD key member [member ...] # 重复元素不添加,自动去重 # return value:返回集合中添加成功的元素个数
SMEMBERS key
SRANDMEMBER key [count] # count不写默认为1
SCARD key
SISMEMBER key member # 在返回1,不在返回0
SREM key member [member ...] # return value:返回成功删除的元素个数
SPOP key [count]
SMOVE source destination member # 将一个元素从source移动到destination
SINTER key [key ...] SINTERSTORE destinationkey key [key ...] # 将多个集合交集保存到destinationkey集合中
SUNION key [key ...] SUNIONSTORE destinationkey key [key ...]
SDIFF key [key ...] SDIFFSTORE destinationkey key [key ...]
Set 的内部编码有2种:
set-max-intset-entries
配置(默认512个)时,使用intsetHash 是键值对(field-value)集合,类似于 Java 中的 Map,field不能重复
HSET key field value [field value ...] # field去重 # return value:返回Hash中添加成功的元素个数,若为覆盖操作则返回0 HSETNX key field value # 当且仅当field不存在时生效
HGET key field
HMGET key field [field ...]
HKEYS key
HVALS key
HLEN key
HEXISTS key field
HDEL key field [field ...] # return value:返回成功删除的field个数
HGETALL key
HINCRBY key field increment
HSTRLEN key field
Hash 的内部编码有2种:
ziplist
当 Hash 类型的元素个数小于hash-max-ziplist-entries
(默认512个),且所有值的空间大小小于hash-max-ziplist-value
(默认64字节)时,使用ziplist
hashtable
无法满足上述条件时,使用hashtable
用户信息的存储:hset user:1 name dxx age 25 city lanzhou
Sorted Set 是有序去重的,它给每个元素设置一个分数(score),并以此为依据进行排序(分数升序)。
ZADD key [NX|XX] [GT|LT] [CH] [INCR] score member [score member ...] # 重复元素不添加,自动去重 # return value:返回集合中添加成功的元素个数,若为更改则返回0;可通过CH参数将返回值改变为 添加和更改的元素个数
ZRANGE key start stop [WITHSCORES] # 分数从低到高排名 ZREVRANGE key start stop [WITHSCORES] # 分数从高到低排名
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count] # min和max反着写一下 # [LIMIT offset count] 限制输出的起始位置和输出个数 # (min (max 表示左开右开,不写括号表示左闭右闭 # -inf 表示无穷小,+inf 表示无穷大
ZCARD key
ZCOUNT key min max
ZSCORE key member
ZRANK key member ZREVRANK key member
ZINCRBY key increment member
ZREM key member [member ...] # return value:返回成功删除的元素个数
ZREMRANGEBYRANK key start stop
ZREMRANGEBYSCORE key min max
ZINTER numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX] [WITHSCORES] # numkeys:需要做交集计算键的个数 # [WEIGHTS weight]:每个key的权重,计算时每个key中的每个member会将自己的score乘以权重,默认是1 # [AGGREGATE SUM|MIN|MAX]:计算交集后,分数可以按照sum、min、max做汇总,默认是sum ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX] # destination:交集计算的结果保存到这个key
ZUNION numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX] [WITHSCORES] ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]
Sorted Set 内部编码有2种:
ziplist
当有序集合的元素个数小于zset-max-ziplist-entries
(默认128个),且每个元素所占空间大小小于zset-max-ziplist-value
(默认64字节)时,使用ziplist
skiplist
上述条件不满足时,会使用跳跃表
跳跃表是一种基于有序链表的扩展,简称跳表。
分层建立多级索引,使得比较次数减少,时间复杂度降低到
O(logn)
,属于空间换时间。
排行榜系统
Bitmaps 本身不是一种数据类型,实际上它就是字符串,但是它可以对字符串的位进行操作。可以把 Bitmaps 想象成一个以位为单位的数组,数组的每个单元只能存储0和1,数组的下标在 Bitmaps 中叫做偏移量。
SETBIT key offset value
GETBIT key offset
BITCOUNT key [start end] # start end 表示起始和结束的字节数,1 byte = 8 bit
BITPOS key bit [start] [end]
BITOP operation destkey key [key ...] # operation 包括 and、or、not、xor # 将运算结果存放到destKey中
记录用户是否访问过网站时,每个用户只占用 1bit 的空间。具体操作如下:首先将所有用户都存储起来,用0表示没访问过,1表示访问过。若活跃用户很多时,使用 Bitmaps 可以节省空间。
用户id会以一个较大的数字开始(比如10000),若直接将用户id与偏移量对应必然会造成空间浪费,通常做法是将用户id减去这个数字。
HyperLogLog 本身不是一种数据类型,实际上它是字符串类型,是用来做基数统计的算法,它可以利用极小的内存空间完成独立总数的统计(近似值)。
PFADD key element [element ...]
PFCOUNT key [key ...] # 简单来说就是统计不重复的元素
PFMERGE destkey sourcekey [sourcekey ...]
只需要统计总数,不需要获取具体的单条数据,且可以容忍一定的误差。
GEO(Geographic),就是元素的二维坐标,在地图上就是经纬度。
GEOADD key [NX|XX] [CH] longitude latitude member [longitude latitude member ...] # longitude latitude member 分别是经度、纬度、所属城市
GEOPOS key member [member ...]
GEODIST key member1 member2 [m|km|ft|mi]
GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count [ANY]] [ASC|DESC] [STORE key] [STOREDIST key] GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count [ANY]] [ASC|DESC] [STORE key] [STOREDIST key]
GEOHASH key member [member ...]
ZREM key member [member ...] # redis没有提供删除命令,但是GEO底层是zset,所以可以使用zrem删除
地理位置信息