一. Redis的历史
1. 什么是nosql
nosql=not only sql,不仅仅是sql,是区别于关系型数据库的一种。
关系型数据库:具有行列组成的表格样式的数据库
nosql数据库:数据的存储不需要指定类型、不需要过多的操作就可以横向扩展,
2. nosql特点:
- 方便扩展(数据之间KV存储,没有关系,很好扩展)
- 大数据量高性能(官方测试一秒钟读取11万,写8万次)
- 数据类型是多样的,随取随用,并可以设置过期
- 关系型数据库RDBMS和nosql数据库区别
传统的RDBMS:
- 结构化组织(行列组成的表关系)
- 有单独的执行操作语法
- 严格的一致性
- 事务控制
nosql数据库:
- 没有固定的查询语句
- 存储形式多样:键值对存储、列存储、文档存储、图形数据库
- 保证最终一致性
- 高性能、高可用、高扩展
- CAP定理和BASE 实现了异地多活。
3. nosql 的四大分类
①KV键值对
通过KV的形式完成存储,像Redis的KV键值对
②文档型数据库
最经典的就是MongoDB,他是一个基于分布式文件存储的数据库,主要用来处理大量的文件
他是介于关系型数据库和非关系型数据库之间,并且是非关系型数据库中最接近关系型数据库的数据库.
③列数据库
Hbase、分布式文件系统等以列进行存储的数据库
④图形数据库(关系拓扑图)
一般用来存储朋友圈社交网络、广告产品推荐等。
------图片来自网络
4. 什么是Redis、Redis能做什么?
Redis(Remote Dictionary Server ),即远程字典服务。是支持网络、可基于内存亦可持久化的日志型、Key-Value数据库。
Redis能做什么:
- 可以作为内存存储,并提供持久化功能(内存不持久化则断电即失)
- 效率高,可以用于告诉缓存
- 发布订阅系统
- 地图信息分析
- 计数器计时器控制
二.Redis安装以及基本知识
1. Linux安装Redis
①下载Redis安装包:https://redis.io/
②解压安装包至/usr/develop/redis目录中
③解压安装包,tar -zxvf redis-5.0.8.tar.gz
④安装Redis编译环境: yun install -y gcc-c++
⑤进入到Redis的路径,make执行编译后make install执行安装。
⑥安装完成后默认安装目录是在/usr/local/bin下,将安装包中的配置文件rdis.conf复制到/usr/local/bin/wconf下:
cp /usr/develop/redis/redis.conf /usr/local/bin/wconf
⑦修改配置文件:
默认是非后台启动,修改为后台启动:daemonize yes
默认是本机访问,修改为任意终端访问:bind 0.0.0.0
默认是无密码访问,添加Redis访问密码:取消第502行的注释,并修改密码为root
# use a very strong password otherwise it will be very easy to break.
# requirepass root
# Command renaming.
⑧启动Redis。指定配置文件方式启动:在/usr/local/bin路径下:./redis-server wconf/redis.conf,查询到Redis进程号即代表启动成功了。
⑨启动客户端测试ping为pong即代表服务启动成功
2. redis-benchmark压力测试工具的使用
redis-benchmark是Redis官方的压力测试工具,通过命令来进行测试。
简单测试1000个并发下请求10W个请求,每次请求100字节的压力测试命令:
redis-benchmark -h localhost -p 6379 -c 1000 -n 100000 -d 100
其他常用指令可自行百度
3. Redis的基本知识
---redis默认有16个库,在配置文件database 16 中表示
---Redis是单线程
Redis是基于内存操作。CPU不是Redis的性能瓶颈(多线程是CPU),Redis的瓶颈是根据机器的内存和网络带宽。所以使用单线程来实现。
为什么单线程还这么快呢:
①多线程不一定比单线程效率高,多线程会涉及到CPU的上下文切换,这是一个耗时的操作。Redis是完全放在内存操作的,读写都是在同一个CPU上操作的。同时也不存在并发时的加锁释放锁的问题。当访问量多时,单线程能够节省多线程CPU的上下文切换。所以说单线程是最快。
②才用多路IO复用模型,属于非阻塞IO
4. redis的常用命令
不会的命令可以查看官网
* select 6 #切换数据库
* dbsize #查看数据库大小
三. Redis的五大数据类型
1. redis-key的命令
* keys * # 查看所有key
* flushdb #清空当前库 flushall #清空所有数据库
* exists key #查询某个key是否存在,1存在/0不存在
* move key 1 #移除key值,1代表当前库
* expire key 30 #设置key值30秒过期
* ttl key #查询key的剩余过期时间 单位是S
* type key #查看key的数据类型
2. String(字符串)
字符串类型的KV数据,使用场景:value一般是字符串或者数字。可以用来做计数器、统计数量等
* set key hello #设置值
* get key #获取值
* mset k1 v1 k2 v2 # 批量设置kv值,同时set了k1、k2
* mget k1 k2 # 批量获取值,同时获取k1、k2的值
* append key "append" # 给key值后面追加字符串append,如果key值不存在,则会新创建
* strlen key #获取字符串的长度
* incr key #将key值+1,可以用来记录网站的浏览量 每次执行就会+1,操作非数字的key会报错
* incrby key 10 #将key值每次+10,即可以设置步长
* decr key #将key值-1。
* decrby key 10 #将key值每次-10
* getrange key 0 3 #截取字符串,相当于java中substring, getrange key start end ,从0开始,本例为从0截取到3---->[0,3]字符
GETRANGE key1 4 -1 #从4截取到最后,-1为最后。
* setrange key 1 xx #替换,把key中从第1个开始,替换成xx。指定位置的替换。可替换一个或多个
* setex(set with expire) #设置一个key值,并设置过期时间 : setex key 30 "hello", 设置key值为hello并30秒过去
* setnx(set if no exist) #设置一个key值,当他不存在时,如果该key值已经存在,则会设置失败,直接set如果存在则会覆盖
setnx key "hello" 如果存在返回0,set失败,如果不存在返回1,set成功。 在分布式锁中常常会被使用。
* msetnx k1 v1 k4 v4 #setnx是一个原子性操作,如果k1已经存在了,k4不存在,同样k4也不会添加成功。
技巧:通过巧妙的key值,方便工作 例如,设置ID为1的用户登录次数+1 set user:1:login 0 以后再每次给该用户+1时,可以动态的根据ID来给该value值进行操作,不用直接存储user对象解析后再+1了。
* getset key hello # 如果不存在值,返回null,并设置新值,如果存在,返回原来值,并设置新的值。可用来更新操作。
3. list(列表)
在Redis里,可以把list作为栈、队列、阻塞队列来使用。list中的值是可以重复的。
所有list命令都是用l开头的。
list的存储顺序是: lpush list one, lpush list two, lpush list three。则获取第0个位three,获取第1个位two,获取第2个为one.顺序为先进后出。倒着来的。
list 实际上是一个链表,存在node,node 有before和after, 在left和right都可以进行插入值。
在两边执行操作,效率最高,但是在中间元素操作,效率会低一点。
* lpush list one lpush list two lpush list three #将一个值或者多个值放入列表的头部,push的顺序是往左边(头部)放,存放顺序是从右至左
* lrange list 0 -1 #获取全部的list值, lrange list 0 1 ,获取0-1的值, 顺序是从左到右取值。
* rpush list four #将一个多个值放在列表的尾部。push的顺序是往右边(尾部)放,存放顺序为从左往右。
* lpop list #将list的值最左边的值移除,并返回该值。即第一个
* rpop list #将list的最右边的值移除,并返回该值。即最后一个
* lrem list 2 one #从左到右移除list中指定的两个one值,并指定移除个数
* lindex list 1 # 通过下标获取list中的某个值。从0开始
* LLEN list #获取list的长度
* ltrim list 1 2 #将list中的1-2位置上的值进行截取,list中其余的就没有了。通过下标截取指定长度。
* rpoplpush list otherList #移动操作。将list中的最后一个(rpop)移动到(lpush) otherList中去,otherlist中就是list被移除的最后一个值
* lset list 0 value #将列表中已经存在的指定下标的值更新为另一个值,如果list不存在/或者下标越界,则报错。
* linsert list before/after "hello" "other" #在list中指定的元素前/后 插入一个指定的value值。hello是list中存在的指定元素, other 是需要插入的值,此时执行结果就是 list中多了一个元素,在hello的前面