一、什么是redis?
Redis(Remote Dictionary Server,远程字典服务) 是一个使用 C 语言编写的,开源的(BSD许可)高性能非关系型(NoSQL)数据库中的键值对数据库。与传统关系型数据库不同的是, Redis 的数据是存在内存中的,所以读写速度非常快,因此 redis 被广泛应用于缓存方向,每秒可以处理超过 10万次读写操作。它会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并在此基础上实现了master-slave(主从)同步。
Redis可以用作数据库,缓存和消息中间件MQ
二、Redis有哪些优缺点?
优点:
- 读写性能优异, Redis能读的速度是110000次/s,写的速度是81000次/s。
- 支持数据持久化,支持AOF和RDB两种持久化方式。
- 支持事务,Redis的所有操作都是原子性的,同时Redis还支持对几个操作合并后的原子性执行。
- 数据结构丰富,除了支持string类型的value外还支持hash、set、zset、list等数据结构。
- 支持主从复制,主机会自动将数据同步到从机,可以进行读写分离。
缺点:
- 数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。
- Redis 不具备自动容错和恢复功能,主机从机的宕机都会导致前端部分读写请求失败,需要等待机器重启或者手动切换前端的IP才能恢复。
- 主机宕机,宕机前有部分数据未能及时同步到从机,切换IP后还会引入数据不一致的问题,降低了系统的可用性。
- Redis 较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。为避免这一问题,运维人员在系统上线时必须确保有足够的空间,这对资源造成了很大的浪费。
redis经常会被拿来跟memcached作比较,但是他们之间最大区别就是memcached是内存中的缓存,并不能持久化,而redis可以做持久化的。
与memcached的不同:
- memcached是多线程的,redis是单线程的。
- memcached存储不持久,redis是支持持久存储。
- memcached善用多核CPU,redis不善用
- memcached可能有更少的内存分片。
- 但是二者的性能不相上下。
三、基础知识
1.切换数据库:select
Redis有16个数据库,默认使用的是第0个,可以使用select
来切换数据库。DBSIZE来查看数据库的规模
2.清除数据库数据
清空当前数据库数据:flushdb
清空所有数据库数据:FLUSHALL
3.Redis是单线程的。
既然是单线程为什么还这么快?
- redis是将所有的数据全部放在内存中的,避免了不必要的上下文切换和竞争条件,而且不存在多进程或者多线程导致的切换而消耗 CPU。对于内存系统来说,如果没有上下文切换效率就是最高的,所以使用单线程去操作效率是最高的。
- 数据结构简单,对数据操作也简单。
- 使用多路 I/O 复用模型,非阻塞 IO。这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程
4.为什么Redis是单线程的?
Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了。
四、数据类型
Redis主要有5种数据类型,包括String,List,Set,Zset,Hash
(一)String
做简单的键值对缓存。
127.0.0.1:6379> set name yang #设置key-value
OK
127.0.0.1:6379> set age 12
OK
127.0.0.1:6379> keys * #查看所有的key
1) "age"
2) "name"
127.0.0.1:6379> exists name #查看某一个key是否存在
(integer) 1
127.0.0.1:6379> exists name1
(integer) 0
127.0.0.1:6379> move name 1 #移除某个key
(integer) 1
127.0.0.1:6379> keys *
1) "age"
127.0.0.1:6379> type age #查看key的类型
string
127.0.0.1:6379> append age "foever" #给key对应的value追加字符串,如果key不存在,就相当于set key
(integer) 8
127.0.0.1:6379> get age
"12foever"
127.0.0.1:6379> strlen age #获取字符串的长度
(integer) 8
127.0.0.1:6379>
##############################################################
# i++
# 步长 i+=
127.0.0.1:6379> set views 0 #设置初始为0
OK
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incr views #自增1
(integer) 1
127.0.0.1:6379> incr views
(integer) 2
127.0.0.1:6379> decr views #自减1
(integer) 1
127.0.0.1:6379> decr views
(integer) 0
127.0.0.1:6379> incrby views 10 #设置步长,指定增量
(integer) 10
127.0.0.1:6379> get views
"10"
##############################################################
#字符串范围 range
127.0.0.1:6379> set key1 "hello,yang"
OK
127.0.0.1:6379> GETRANGE key1 0 3 #截取字符串[0.3],相当于java中的substring
"hell"
127.0.0.1:6379> GETRANGE key1 0 -1 #获取全部的字符串,相当于get key
"hello,yang"
127.0.0.1:6379> set key2 asdfwe
OK
127.0.0.1:6379> SETRANGE key2 1 ** #替换字符串,1为开始替换的下标,相当于java中的replace
(integer) 6
127.0.0.1:6379> get key2
"a**fwe"
##############################################################
# setex 设置过期时间
#setnx 如果不存在再设置 在分布式锁中经常用
127.0.0.1:6379> setex key3 30 "hello" #设置key3的值为hello,30秒后过期
OK
127.0.0.1:6379> ttl key3 #查看过期剩余时间
(integer) 24
127.0.0.1:6379> get key3
"hello"
127.0.0.1:6379> get key3 #过期
(nil)
127.0.0.1:6379> setnx mykey "nihao" #如果mykey不存在,则创建mykey
(integer) 1
127.0.0.1:6379> keys *
1) "key1"
2) "mykey"
3) "key2"
127.0.0.1:6379> get mykey
"nihao"
127.0.0.1:6379> setnx mykey "study" #如果mykey已存在,则创建失败
(integer) 0
127.0.0.1:6379> get mykey
"nihao"
##############################################################
# 批量设置批量获取
# mset
# mget
#对象,user:{id}:{filed}
127.0.0.1:6379> mset user:1:name yangg user:1:age 2
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "yangg"
2) "2"
(二)List
在redis中,list可以做栈、队列、阻塞队列,即存储一些列表型的数据结构
当从左边压入,从右边弹出时,就是消息队列(Lpush Rpop),当从左边压入,左边弹出时,就是栈(Lpush Lpop)
所有list命令都是用l或者r开头的
127.0.0.1:6379> LPUSH list one #向list中添加数据,插入列表头部(左侧)
(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 #取出list中[0 1]范围的数据,发现是后存入的两个数,这也是list队列的体现
1) "three"
2) "two"
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> RPUSH list four #从右边插入数据
(integer) 4
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "two"
3) "one"
4) "four"
####################################