Redis
单机MySQL的演进
1.单机MYSQL的年代
APP—>DAL—>MySql
2.Memcached(缓存) + MySql + 垂直拆分(读写分离)
网站百分之八十的情况都在读,每次都要查询数据库的话十分麻烦。所以我们希望减轻数据库的压力,可以通过缓存来提高效率!
分库分表 + 水平拆分 + MySQL集群
NoSql
NpSql
NoSql = Not Only Sql (不仅仅是Sql)
关系型数据库:表格,行,列
很多用户的个人信息、社交网络、地理位置,这些类型的存储不需要一个固定的格式。
传统RDBMS和NoSql
传统的RDBMS
- 结构化组织
- SQL
- 数据和关系都存在单独的表中
- 严格的一致性
NoSql
、- 不仅仅是数据
- 没有固定的查询语言
- 键值对存储 列存储 文档存储 图形数据库(社交关系)
- 最终一致性
- CAP原理和BASE
- 高可用 高性能 高可扩
NoSql的四大分类
-
KV键值对:redis
-
文档型数据库(bson格式和json一样):MongoDB
MongoDB:一个基于分布式文件存储的数据库,主要用于处理大量的文档。是一个介于关系型数据库和非关系型数据中中间的产品。
-
列存储数据库:HBase、分布式文件系统
-
图关系数据库:Neo4j,InfoGrid 不是存图形,而是放关系 如朋友圈社交网络、广告推荐
Redis
Redis是什么?
Redis(Remote Dictionary Server),即远程字典服务。redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并实现了master-slave(主从)同步。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能干嘛?
-
内容存储、持久化,内存中的数据是断电即失,所以持久化很重要(rdb、aof)
-
效率高,可用于高速缓存
-
发布订阅系统(消息队列)
-
地图信息分析
-
计时器、计数器(浏览量)
-
。。。。
特性
- 多样的数据类型
- 持久化
- 集群
- 事务
- …
Redis推荐搭建在Linux服务器上
中文官方网站:http://www.redis.cn/
Redis不区分大小写命令
基本知识
Redis有16个数据库 默认使用的是第0个,可以使用select进行切换
基础语法:
select index --切换数据库
dbsize --数据库大小
set key value --存储键值对
get key --获得key所对应的value
keys * --查看所有的key
flushdb --清空当前数据库
flushall --清空所有数据库
EXISTS key --判断某个key是否存在 返回1则代表存在
move key --移出某个值
EXPIRE key seconds --设置某个key的过期时间
ttl key --查看还有多久过期
type key --查看key的类型
shutdown --停止运行
Redis是单线程的
Redis速度很快。Redis基于内存操作,CPU不是Redis的性能瓶颈,而是机器的内存和网络带宽。
Redis为什么单线程还这么快?
1:高性能的服务器不一定是多线程的
2:多线程(CPU会上下文切换)的效率不一定比单线程高
核心:redis是将所有的数据全部放在内存中的,所以使用单线程操作效率就是最高的,多线程(CPU会上下文切换,耗时的操作),对弈内存系统来说,如果没有上下文切换那么效率就是最高的。多次读写在一个CPU上,这个就是最佳的方案!
五大数据类型
String
适用场景:更适合字符串存储
命令:
APPEND key value --在key对应的值上附加值 若append的值不存在,则新建一个值
STRLEN key --查看key的长度
incr key --key值加1
decr key --key值减1
INCRBY key count --key值增长count
DECRBY key count --key值减少count
GETRANGE key start end --获得某个范围的字符串(类似于subString)
GETRANGE key 0 -1 --查看全部的字符串
SETRANGE key offset value --替换指定位置开始的字符串
setex key seconds value --设置key的过期时间
setnx --不存在则设置 在分布式锁中常使用
mset k1 v1 k2 v2 --批量设置值
mget k1 k2 --批量获取值
msetnx k1 v1 k2 v2 --原子操作 只要有一个存在 就不会创建成功
set user:1{name:zhangsan,age:3} --设置一个user:1对象 值为json字符串来保存一个对象
另一种存储对象的方式:
mset user:1 name zhangsan user:1:age 2
getset key value --先get 再set
String类似的使用场景:value除了字符串,还可以是数字(可以应用于计数器)
List
在redis里面,我们可以把List设计成栈、队列、阻塞队列!
所有的List命令都是以l开头的
基本命令
LPUSH list value --向list中添加一个值 添加到列表头部(左)
RPUSH list value --添加到列表尾部
LRANGE list 0 -1 --查看list中的所有值
LRANGE list start end --查看指定位置的元素值
LPOP list --移出list最左边的元素
RPOP list --移出list最右边的元素
LINDEX list index --获取指定位置的元素
Llen list --返回l;ist的长度
Lrm list count value --移出count个value元素
Ltrim list start end --截取操作 只会保留范围内的数据
rpoplpush list1 list2 --移出列表最后一个元素 并将该元素添加到另一个列表的头部
lset list index value --指定位置更新值(注意:此位置必须存在值才可以进行设置)
LINSERT list after(before) sourcevalue aimvalue --在原位置后(前)插入数据
小结
- 实际是一个链表 (left Node right)
- 如果key不存在,创建新的链表。如果key存在,新增内容
- 如果移除了所有值,空链表,也代表不存在
- 在两边插入或改动值,效率最高。中间元素,效率较低
- 消息排队,消息队列(Lpush Rpop) 栈(Lpush Lpop)
Set
无序 不重复 集合
所有的命令以s开头
基本命令
sadd set mermber #set集合中添加一个元素
smembers set #查看set集合中的所有元素
sismember set member #查看set集合中是否存在某个元素
scard set #查看set集合中所有元素的个数
srem set mermer #移除某个元素
srandmember set #随机抽选出一个元素
srandmember set 2 #随机抽选出两个元素
spop set #随机删除一个元素
smove source destination member #将某个集合的指定元素移动到另一个集合中
数学集合类
sdiff set1 set2 #差集 找出set1中有而set2中没有的元素
sinter set1 set2 #交集 共同好友的实现
sunion set1 set2 #并集
Hash
存储结构:key->Map
适用场景:存储变更数据,尤其是用户信息之类的 更适合对象的存储
基本命令:
hset hash field value #添加一个entry(field->value)
hget hash field #获取指定hash的字段值
hmset hash field1 value1 field2 value2 #批量添加值
hget hash field1 field2 #批量获取值
hgetall hash #获取当前hash的所有值
hdel hash field #删除hash指定的entry
hlen hash #当前hash中entry的个数
hexists hash field #判断hash中指定字段是否存在
hkeys hash #获取hash中所有entry的key
hvals hash #获取hash中所有entry的value
hincrby hash field 1 #指定字段值自增1
hdecrby hash field 1 #指定字段值自减1
hsetnx hash field value #field不存在时创建
hset user:1 name zhangsan #存储一个对象
Zset
在set的基础上增加一个score字段 用于排序
基本命令
zadd set score member #增加一个值
zadd set score1 member1 score2 member2 #增加多个值
zrange set 0 -1 #查看set中的所有值
ZRANGEBYSCORE set set min max #按照score进行排序 升序
ZRANGEBYSCORE set -inf +inf withscores #按照score进行排序 并带出score值
ZREVRANGE set 0 -1 #降序排序
ZREM set member #移出某个元素
ZCARD set #集合中的元素个数
zcount set start end #获取指定区间的元素个数
三种特殊数据类型
geospatial(地理位置)
适用场景:定位、附近的人、打车距离、方圆几里的人
GEOADD
当坐标位置超出指定范围时,该命令将会返回一个错误。
GEOADD key 纬度 经度 member #添加一个地理空间位置 两级是无法直接添加的 我们一般会下载城市数据 通过java一次性导入
GEOPOS
GEOPOS key member1 member2 #获取指定位置的经度和纬度
GEODIST
返回两个给定位置之间的距离。
如果两个位置之间的其中一个不存在, 那么命令返回空值。
指定单位的参数 unit 必须是以下单位的其中一个:
- m 表示单位为米。
- km 表示单位为千米。
- mi 表示单位为英里。
- ft 表示单位为英尺。
GEODIST key member1 member2 unit #返回两个位置之间的距离
GEORADIUS
以给定的经纬度为中心,找出某一半径内的元素(元素必须在集合中)
适用场景:附近的人
GEORIDUS key 经度 纬度 radius unit
GEORADIUSBYMEMBER
找出位于指定位置内的元素,中心点是由给定的位置元素决定
GEORIDUSBYMEMBER key member radius unit
GEOHASH
返回一个或多个位置的GEOHASH表示
该命令将返回11个字符的Geohash字符串(将二维的经纬度转化为一维的字符串,如果两个字符串越接近,则距离越近)
GEO底层的实现原理是Zset,我们可以使用Zset命令来操作GEO
hyperloglog(基数统计的算法)
基数:不重复的元素
优点:占用内存小
0.81%的错误率
适用场景:网页的浏览量(一个人浏览网页多次,还是算作一个人)
传统方式,set来保存用户id,然后就可以统计set中的元素数量作为标准判断
基础知识
PFadd key element1 element2 element3 #添加元素
PFcount key #统计key的元素
PFmerge destkey sourcekey #合并key
bitmap
操作二进制位来进行记录的 ,就只有0和1两个状态
适用场景:统计用户信息(如活跃、不活跃;365天打卡;两个状态的都适用)
基本命令
setbit key offset value #设置值
get key offset #获取指定位置的值
bit count key #获取状态为1的个数
使用bitmap来记录周一到周日的打卡情况
统计打卡的天数
事务
Redis单条命令是保证原子性的,但是事务不保证原子性!
Redis事务本质:一组命令的集合!一个事务中的所有命令都会被序列化,在事务执行的过程中,会按照顺序执行。
特性:一次性、顺序性、排他性(事务运行中不允许被打断)
------队列 set set set 执行 -----
Redis事务没有隔离级别的概念
所有的命令在事务中,并没有直接执行!只有发起执行命令的时候才会执行!