大家好,又见面了,我是你们的朋友全栈君。
Redis
- Redis入门菜
- Redis为什么这么快?
- 五大数据类型
- Zset
Redis可以用作数据库,缓存,消息中间件
Redis入门菜
redis 默认有16个数据库 可以使用select 进行切换数据库
代码语言:javascript复制root@ubuntu:/usr/bin/redisconf# redis-cli
127.0.0.1:6379> select 3 //选择第3个数据库
OK
127.0.0.1:6379[3]> DBSIZE //查看数据库大小
(integer) 0
127.0.0.1:6379[3]> set name cc //设置键值对
OK
127.0.0.1:6379[3]> get name //获取键值对
"cc"
127.0.0.1:6379[3]> keys * //查看所有key
1) "name"
127.0.0.1:6379[3]> flushdb //删除对应数据库中所有key
OK
127.0.0.1:6379[3]> keys *
(empty list or set)
127.0.0.1:6379[3]> select 0 //选择第0号数据库
OK
127.0.0.1:6379> keys * //查看所有key
1) "key:__rand_int__"
2) "counter:__rand_int__"
3) "name"
4) "mylist"
127.0.0.1:6379> flushALL //清楚所有数据库的keys
OK
127.0.0.1:6379> select 2 //选择第二号数据库
OK
127.0.0.1:6379[2]> keys * //查看所有的key
(empty list or set)
Redis为什么这么快?
官方答案:
因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了。
现来聊一下什么是同步,异步,阻塞和非阻塞 同步和异步的概念描述的是用户线程与内核的交互方式:同步是指用户线程发起IO请求后需要等待或者轮询内核IO操作完成后才能继续执行;而异步是指用户线程发起IO请求后仍继续执行,当内核IO操作完成后会通知用户线程,或者调用用户线程注册的回调函数。
阻塞和非阻塞阻塞是指进程发起IO操作请求后需要彻底完成后才返回到用户空间;而非阻塞是指进程发起IO请求被调用后立即返回给用户一个状态值,无需等到IO操作彻底完成。
同步阻塞IO,同步非阻塞IO,多路复用IO技术
同步阻塞IO:同步阻塞IO模型是最简单的IO模型,进程在内核进行IO操作时被阻塞。 同步非阻塞IO:进程需要不断地调用read,如果有数据收到,就返回数据,如果没有数据收到,就立刻返回一个错误,让后进程再次read,直到这样是不会阻塞线程了,但是你还是要不断的轮询来读取或写入。 I/O多路复用 IO多路复用模型是建立在内核提供的多路分离函数select基础之上的,使用select函数可以避免同步非阻塞IO模型中轮询等待的问题。 线程首先将socket注册到select中,然后阻塞等待select系统调用返回,之后线程可以去做其他的事情。当数据到达时,socket被激活,select函数返回。用户线程正式发起read请求,读取数据并继续执行。使用select函数进行IO请求和同步阻塞模型没有太大的区别,甚至还多了添加监视socket,以及调用select函数的额外操作,效率更差。但是,使用select以后最大的优势是用户可以在一个线程内同时处理多个socket的IO请求。用户可以注册多个socket,然后不断地调用select读取被激活的socket,即可达到在同一个线程内同时处理多个IO请求的目的。而在同步阻塞模型中,必须通过多线程的方式才能达到这个目的。
Redis快的原因
- 完全基于内存:内存存储本来就比磁盘高
- 不存在多进程或者多线程导致的切换而消耗CPU
- 不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗
- 使用多路I/O复用模型:多路I/O复用是用一个线程同时监察多个流的I/O事件的能力,在空闲时,会把前线程阻塞掉,在有一个或者是多个流有I/O事件的时候,就会从阻塞态当中唤醒,所以,程序就会轮询一遍所有的流,并且,依次顺序的处理就绪的流,这样做的话,就可以避免很多无用操作。(注意,这里的多路它所指的是多个网络连接,这里的复用指的是复用同一个线程。)
五大数据类型
String 常用命令
代码语言:javascript复制127.0.0.1:6379[2]> keys *
1) "name"
2) "age"
127.0.0.1:6379[2]> exists name //查看是否存在key
(integer) 1
127.0.0.1:6379[2]> move name 1 //复制name到数据库1中
(integer) 0
127.0.0.1:6379[2]> expire name //设置name key的到期时间
127.0.0.1:6379[2]> ttl name //查看name的到期时间
(integer) 7
127.0.0.1:6379[2]> type age //查看类型
string
String
代码语言:javascript复制127.0.0.1:6379[2]> keys *
1) "name"
2) "key1"
127.0.0.1:6379[2]> get name
"cc"
127.0.0.1:6379[2]> APPEND name 'hello world' //追加字符,如果key不存在,则创建新的
(integer) 13
127.0.0.1:6379[2]> get name
"cchello world"
127.0.0.1:6379[2]> strlen name //长度
(integer) 13
127.0.0.1:6379> set num 1
127.0.0.1:6379> INCR num //自增’
127.0.0.1:6379> INCRBY num 10 //设置增加值
127.0.0.1:6379> decr num //自减
127.0.0.1:6379> DECRBY num 10 //设置自减值
127.0.0.1:6379> set name cc_fendouing
127.0.0.1:6379> GETRANGE name 1 3
"c_f"
127.0.0.1:6379> SETRANGE name 2 xx //replace
127.0.0.1:6379> get name
"ccxxendouing"
# setex (set with expire) //设置过期时间
# setnx (set if not exist) //不存在再设置 (分布式锁常使用)
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 //同时创建多个key value
127.0.0.1:6379> keys *
1) "k1"
2) "k2"
3) "k3"
127.0.0.1:6379> mget k1 k2 k3 //同时获得多个值
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> msetnx k1 v1 k6 v6 //是一个原子性操作,要么都成功,要么都失败
(integer) 0
# 对象
127.0.0.1:6379> mset user:1:name cc user:1:age 22 // user:{id}:{field}
127.0.0.1:6379> keys *
1) "user:1:age"
2) "user:1:name"
127.0.0.1:6379> getset name lish //先获取再赋值
List 所有的list命令都是l开头的 List实际上是一个列表
代码语言:javascript复制127.0.0.1:6379> LPUSH list one //从左边push
127.0.0.1:6379> Lpush list two
127.0.0.1:6379> LRANGE list 0 -1
1) "two"
2) "one"
127.0.0.1:6379> RPUSH list three //从右边push
127.0.0.1:6379> LRANGE list 0 -1
1) "two"
2) "one"
3) "three"
127.0.0.1:6379> LPOP list //从左边弹出
127.0.0.1:6379> LINDEX list 1 //第一个值
127.0.0.1:6379> LLEN list //长度
127.0.0.1:6379> LREM list 1 one //从左边数删除1个名字为one的值
127.0.0.1:6379> LRANGE list 0 -1
1) "two"
2) "one"
3) "three"
127.0.0.1:6379> LTRIM list 1 2 //截取
OK
127.0.0.1:6379> LRANGE list 0 -1
1) "one"
2) "three"
# rpoplpush list t_list //组合操作 把list右边的值push到t_list 左边
# lset list 0 cc //将列表中指定下标的值替换为另外一个值 指定的下表必须存在
# linsert list before 'cc' 'aa' # 在cc前面插入aa
Set Set中的值是不能重复的
代码语言:javascript复制127.0.0.1:6379> sadd myset hello //添加
(integer) 1
127.0.0.1:6379> sadd myset cc
(integer) 1
127.0.0.1:6379> sadd myset lisi
(integer) 1
127.0.0.1:6379> SMEMBERS myset //查看set
1) "lisi"
2) "cc"
3) "hello"
127.0.0.1:6379> SISMEMBER myset cc //查看是否存在
(integer) 1
127.0.0.1:6379> SCARD myset //长度
(integer) 3
127.0.0.1:6379> SRANDMEMBER myset 2 //随机抽选两个元素
1) "hello"
2) "cc"
127.0.0.1:6379> SPOP myset //随机删除
"cc"
127.0.0.1:6379> SMOVE myset t_myset lisi 将集和中的一个值移动到另外一个集和
127.0.0.1:6379> SDIFF set1 set2 //差集
127.0.0.1:6379> SInsert set1 set2 //交集
127.0.0.1:6379> SUnion set1 set2 //并集
Hash Map集和,key-map!这个value是一个map集合
代码语言:javascript复制127.0.0.1:6379> HSET myhash field1 cc //添加hash
(integer) 1
127.0.0.1:6379> hget myhash field1 //获取hash值
127.0.0.1:6379> HMset myhash field1 lisi field2 22 //批量设置
127.0.0.1:6379> HMGET myhash field1 field3 //批量获取
1) "lisi"
2) (nil)
127.0.0.1:6379> HMGET myhash field1 field3 // 获取全部key value
1) "lisi"
2) (nil)
127.0.0.1:6379> HLEN myhash //长度
(integer) 2
127.0.0.1:6379> HEXISTS myhash field1 //是否存在字段
(integer) 1
127.0.0.1:6379> HSET myhash field3 1
(integer) 1
127.0.0.1:6379> HINCRBY myhash field3 2 //hash值增加
(integer) 3
127.0.0.1:6379> HSETNX myset field4 ee //存在则创建,不存在则不创建
hash更适合对象存储
Zset
有序集合
代码语言:javascript复制127.0.0.1:6379> zadd zset 1 one //添加值
(integer) 1
127.0.0.1:6379> ZADD zset 2 tow
(integer) 1
127.0.0.1:6379> ZADD zset 3 three 4 four //添加多个值
(integer) 2
127.0.0.1:6379> ZRANGE zset 0 -1
1) "one"
2) "tow"
3) "three"
4) "four"
127.0.0.1:6379> ZADD salary 100 cc
(integer) 1
127.0.0.1:6379> ZADD salary 200 lisi
(integer) 1
127.0.0.1:6379> ZADD salary 300 zhangsan
(integer) 1
127.0.0.1:6379> ZRANGEBYSCORE salary -inf inf //排序显示
1) "cc"
2) "lisi"
3) "zhangsan"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf inf withscores //排序显示key value
1) "cc"
2) "100"
3) "lisi"
4) "200"
5) "zhangsan"
6) "300"
127.0.0.1:6379> ZREM salary cc //移除
127.0.0.1:6379> ZCARD salary //获取个数
# zrevrange salary //反转查看
# zcount count 1 3 //指定区间的成员数量
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/168802.html原文链接:https://javaforall.cn