redis五种常用的数据结构为string (字符串)、list (列表)、set (集合)、hash (哈希) 和 zset (有序集合)。小白易读,建议收藏。

目录

  • 万丈高楼平地起
  • string (字符串)
    • 常用指令
      • 设置获取值
      • 设置过期时间
      • 保证不覆盖value
      • 批量设置获取值
      • 计数
      • 追加值
      • 字符串长度
      • 设置并返回原先值
      • 设置指定位置的字符
      • 获取部分字符串
      • 总结
    • 内部编码
    • 使用场景
  • list (列表)
    • 栈与队列
      • 队列
    • 常用命令
      • 向队列任意位置加入元素
      • 查找元素
      • 删除数据
      • 修改
      • 阻塞操作
      • 总结
    • 内部编码
    • 使用场景
  • hash (哈希)
    • 常用命令
      • 设置值
      • 获取值
      • 删除field
      • 计算field个数
      • 批量设置获取值
      • 判断filed是否存在
      • 获取所有filed或者value
      • 获取所有filed和value
      • 自增
      • 计算值的长度
      • 总结
    • 内部编码
    • 使用场景
  • set (集合)
    • 常用命令
      • 增加元素
      • 删除元素
      • 计算元素个数
      • 判断元素是否在集合中
      • 随机返回一定数量的元素
      • 随机弹出一个元素
      • 获取所有元素
      • 计算并查集
      • 总结
    • 内部编码
    • 使用场景
  • zset(有序集合)
    • 常用命令
      • 总结
    • 内部编码
    • 使用场景

万丈高楼平地起

reids是键值对结构的NoSql数据库,key都是字符串,常说的数据类型不同,说的都是value

redis所有的数据都会有一个dicEntry,众多dicEntry组成一个链表。上方那个sds就是key,可以看出是一个字符串。下方那个绿色的redisObject就是value。可以看出图中给的例子就是string类型。redisObject会指向真实的数据(比如图中的字符串“world”)。后面我们说的数据类型特指value部分。

string (字符串)

Redis 的字符串是动态字符串,是可以修改的字符串。当字符串长度小于 1M 时,扩容都是加倍现有的空间,如果超过 1M,扩容时一次只会多扩 1M 的空间。一个字符串最大可以承受512M。

常用指令

设置获取值

127.0.0.1:6379> set name pjjlt
OK
127.0.0.1:6379> get name
"pjjlt"
127.0.0.1:6379> exists name
(integer) 1

设置使用set,获取使用get,查看某key是否存在用exists

设置过期时间

127.0.0.1:6379> setex company 10  gongsi
OK
127.0.0.1:6379> get company
"gongsi"
127.0.0.1:6379> get company
(nil)

可以在设置值的时候直接指定,keycompany可以存活10秒。此外,也可以将设置值设置过期时间分开,使用expire

127.0.0.1:6379> set company gongsi
OK
127.0.0.1:6379> expire company 10
(integer) 1
127.0.0.1:6379> get company
"gongsi"
127.0.0.1:6379> get company
(nil)

保证不覆盖value

redis还提供了命令,在设置值的时候,如果发现key已存在,此次设置失败,保证原始value不被覆盖。使用setnx命令。

127.0.0.1:6379> setnx company gongsi
(integer) 1
# 可以看到第二次设置失败,返回值为 0.
127.0.0.1:6379> setnx company haha
(integer) 0
127.0.0.1:6379> get company
"gongsi"

批量设置获取值

127.0.0.1:6379> mset name pjjlt age 26 company gongsi
OK
127.0.0.1:6379> mget name age company
1) "pjjlt"
2) "26"
3) "gongsi"

批量设置使用mset,批量获取使用mget。批量设置获取,减少IO,提高性能,你值得拥有。

计数

redis还可以通过自增的方式计数。

127.0.0.1:6379> set key 10
OK
127.0.0.1:6379> incr key
(integer) 11
127.0.0.1:6379> incr key
(integer) 12
# 字符串报错
127.0.0.1:6379> set key2 haha
OK
127.0.0.1:6379> incr key2
(error) ERR value is not an integer or out of range
# 超出long的范围
127.0.0.1:6379> set key3 9223372036854775807
OK
127.0.0.1:6379> incr key3
(error) ERR increment or decrement would overflow
# key4不存在
127.0.0.1:6379> incr key4
(integer) 1
127.0.0.1:6379> incr key4
(integer) 2

可以通过incr关键字自增,可以看出key自增了两次。不能给字符串自增,那样会报错,例如key2。不能超过long的范围,那样也会报错,例如key3。如果初始key不存在,则增从0开始,例如key4。

追加值

127.0.0.1:6379> set name pj
OK
127.0.0.1:6379> append name jlt
(integer) 5
127.0.0.1:6379> get name
"pjjlt"

字符串长度

127.0.0.1:6379> get name
"pjjlt"
127.0.0.1:6379> strlen name
(integer) 5

设置并返回原先值

127.0.0.1:6379> get name
"pjjlt"
127.0.0.1:6379> getset name mj
"pjjlt"
127.0.0.1:6379> get name
"mj"

设置指定位置的字符

127.0.0.1:6379> get name
"mj"
127.0.0.1:6379> setrange name 0 p
(integer) 2
127.0.0.1:6379> get name
"pj"

获取部分字符串

127.0.0.1:6379> set name pjjlt
OK
127.0.0.1:6379> getrange name 0 2
"pjj"

总结

命令 解释
set 设置值
get 获取值
setex 设置值并添加过期时间
setnx 保证不覆盖value
mset 批量设置值
mget 批量获取值
incr 计数
append 追加值
strlen 字符串长度
getset 设置并返回原先值
setrange 设置指定位置的字符
getrange 获取部分字符串

内部编码

虽然某种数据类型的value名称是一致的,比如都是string,但是根据数据量的大小,会采用不同的内部编码,这样可以更高效的利用空间嘛。内部编码类型也储存在redisObject中。利用object encoding key可查看内部编码类型。

int:长整型,超越长整型或者是字符串会升级。

embstr:小于等于44个字节的字符串。笔者用的是redis5.0.9,有人说这个字节范围是39,亲测是44。查了一下,源码确实改了,现在是44.

raw:大于44个字节的字符串。

127.0.0.1:6379> set name 1234567890
OK
127.0.0.1:6379> object encoding name
"int"
# 这里设置44个字符
127.0.0.1:6379> set name qwertyuiopqwertyuiopqwertyuiopqwertyuiopqwer
OK
127.0.0.1:6379> object encoding name
"embstr"
# 这里设置45个字符
127.0.0.1:6379> set name qwertyuiopqwertyuiopqwertyuiopqwertyuiopqwert
OK
127.0.0.1:6379> object encoding name
"raw"

使用场景

可以用于计数,比如网站访问量。
可以共享Session,比如分布式系统,多个实例验证用户是否登录。
可以限速,比如控制一个ip或者一个用户一定时间内访问次数。

list (列表)

Redis 的列表相当于 Java 语言里面的 LinkedList,注意它是链表而不是数组。这意味着list 的插入和删除操作非常快,时间复杂度为 O(1),但是索引定位很慢,时间复杂度为O(n)。list的两端都可以弹入弹出数据,所以可以做队列

栈与队列

栈如同一个死胡同,只有一个出口,后进来的先出,先进来的后出。

127.0.0.1:6379> rpush books python java golong
(integer) 3
127.0.0.1:6379> rpop books
"golong"
127.0.0.1:6379> rpop books
"java"
127.0.0.1:6379> rpop books
"python"
127.0.0.1:6379> rpop books
(nil)

数据从右边进(rpush),右边出(rpop),先进去的最后出来。

队列

队列如同排队打饭的同学们,先进先出。

127.0.0.1:6379> rpush books python java golong
(integer) 3
127.0.0.1:6379> lpop books
"python"
127.0.0.1:6379> lpop books
"java"
127.0.0.1:6379> lpop books
"golong"
127.0.0.1:6379> lpop books
(nil)

数据从右边进(rpush),左边出(lpop),先进先出。

常用命令

向队列任意位置加入元素

刚才演示的rpushlpush都是从两头加入元素,这两个命令不再演示。还可以使用linsert在某指定元素前或后插入新的元素。

127.0.0.1:6379> rpush books python java golong
(integer) 3
# 在java前面插入 ruby
127.0.0.1:6379> linsert books before java ruby
(integer) 4
# 在java后面插入 c#
127.0.0.1:6379> linsert books after java c#
(integer) 5
# 查看所有元素
127.0.0.1:6379> lrange books 0 -1
1) "python"
2) "ruby"
3) "java"
4) "c#"
5) "golong"

根据上面在java前后插入了rubyc#

查找元素

127.0.0.1:6379> lrange books 0 -1
1) "python"
2) "ruby"
3) "java"
4) "c#"
5) "golong"
127.0.0.1:6379> lindex books 2
"java"
127.0.0.1:6379> llen books
(integer) 5

指令简单,索性写一块吧。
lrange可以遍历列表,参数为startend。这里0 -1,是指从第一个到最后一个,即遍历列表。
lindex查找指定位置的元素,参数是下标值。这个命令是慢查询,需要遍历链表。
llen可以查看列表元素个数。

删除数据

刚才演示的rpoplpop可以弹出一个元素,不再演示。

可以使用lrem 删除多个同一元素
count > 0:从左到右,删除最多 count 个元素。
count < 0:从右到左,删除最多 count 绝对值 个元素。
count = 0,删除所有。

# 从左删除a元素,删除了3个
127.0.0.1:6379> rpush char a a b b a a c
(integer) 7
127.0.0.1:6379> lrem chae 3 a
(integer) 0
127.0.0.1:6379> lrem char 3 a
(integer) 3
127.0.0.1:6379> lrange char 0 -1
1) "b"
2) "b"
3) "a"
4) "c"
# 从右删除 3 个a元素
127.0.0.1:6379> rpush char1 a a b b a a c
(integer) 7
127.0.0.1:6379> lrem char1 -3 a
(integer) 3
127.0.0.1:6379> lrange char1 0 -1
1) "a"
2) "b"
3) "b"
4) "c"
# 删除所有 a 元素
127.0.0.1:6379> rpush char2 a a b b a a c
(integer) 7
127.0.0.1:6379> lrem char2 0 a
(integer) 4
127.0.0.1:6379> lrange char2 0 -1
1) "b"
2) "b"
3) "c"

还可以使用ltrim截取一部分数据,删除其余数据

127.0.0.1:6379> rpush char3 a b c d e f g
(integer) 7
127.0.0.1:6379> ltrim char3 1 3
OK
127.0.0.1:6379> lrange char3 0 -1
1) "b"
2) "c"
3) "d"

修改

127.0.0.1:6379> lrange books 0 -1
1) "python"
2) "ruby"
3) "java"
4) "c#"
5) "golong"
127.0.0.1:6379> lset books 2 javaScript
OK
127.0.0.1:6379> lrange books 0 -1
1) "python"
2) "ruby"
3) "javaScript"
4) "c#"
5) "golong"

可以用lset更改某个位置上的元素,这也是个慢查询,时间复杂度为O(n)。

阻塞操作

blpopbrpoplpoprpop基础上增加了阻塞时间,如果直接获取,发现列表中没有数据,那么会阻塞等待一段时间,如果该段时间内还是无法得到数据,就返回等待时长。若设置的时间是0的话,即为无限等待。这里需要两个终端做配合。

# 终端1
127.0.0.1:6379> lpop books
(nil)
127.0.0.1:6379> blpop books 5
(nil)
(5.06s)
# 这里需要在终端1 执行blpop后插入一条数据
127.0.0.1:6379> blpop books 20
1) "books"
2) "java"
(4.61s)
# 这里需要在终端1 执行blpop后插入一条数据
127.0.0.1:6379> blpop books 0
1) "books"
2) "python"
(9.66s)
# 除此之外,还可以同时阻塞多个队列,先有数据的那个弹出
127.0.0.1:6379> blpop books schools 0
1) "schools"
2) "hzsy"
(26.75s)

总结

命令 解释
rpush lpush 弹入数据
rpop lpop 弹出数据
brpop blpop 阻塞弹出数据
linsert 向队列任意位置加入元素
lrange 遍历列表
lindex 查找指定位置上元素
llen 列表长度
lrem 删除多个同一元素
ltrim 截取指定列表
lset 修改列表指定位置元素

内部编码

ziplist:当列表的元素个数小于list-max-ziplist-entries配置(默认 512 个),同时列表中每个元素的值都小于list-max-ziplist-value配置时(默认 64 字节),Redis 会选用ziplist来作为 列表 的内部实现来减少内存的使用。
linkedlist:当列表类型无法满足ziplist的条件时,Redis会使用linkedlist作为列表的内部实现。

使用场景

可以做或者队列
还可以利用阻塞功能做消息队列

hash (哈希)

Redis 的字典相当于Java语言里面的HashMap,它是无序字典。内部实现结构上同Java的HashMap也是一致的,同样的数组 + 链表二维结构。扩容rehash的时候,采用渐进式。在rehash时,保留两个新旧hash结构,查询的时候都查,再根据定时任务,一点点将旧hash上的数据迁移到新的hash上,迁移完毕,旧hash被删除,并收回内存。我们默认key为hashKey,filed为小key

常用命令

设置值

127.0.0.1:6379> hset user name pjjlt
(integer) 1
127.0.0.1:6379> hset user age 26
(integer) 1
127.0.0.1:6379> hset user company gongsi
(integer) 1

获取值

127.0.0.1:6379> hget user name
"pjjlt"

删除field

127.0.0.1:6379> hdel user company
(integer) 1

计算field个数

127.0.0.1:6379> hlen user
(integer) 2

批量设置获取值

127.0.0.1:6379> hmset user name pjjlt age 26 city shijiazhuang
OK
127.0.0.1:6379> hmget user name age
1) "pjjlt"
2) "26"

判断filed是否存在

127.0.0.1:6379> hexists user name
(integer) 1

获取所有filed或者value

127.0.0.1:6379> hkeys user
1) "name"
2) "age"
3) "city"
127.0.0.1:6379> hvals user
1) "pjjlt"
2) "26"

获取所有filed和value

127.0.0.1:6379> hgetall user
1) "name"
2) "pjjlt"
3) "age"
4) "26"
5) "city"
6) "shijiazhuang"

自增

127.0.0.1:6379> hincrby user age -8
(integer) 18
127.0.0.1:6379> hset user scroe 99.6
(integer) 1
127.0.0.1:6379> hincrbyfloat user scroe 0.4
"100"

hincrbyhincrbyfloat分别增加或者减少整型浮点型

计算值的长度

127.0.0.1:6379> hget user name
"pjjlt"
127.0.0.1:6379> hstrlen user name
(integer) 5

总结

命令 解释
hset 设置值
hget 获取值
hdel 删除值
hlen 计算field个数
hmset 批量设置值
hmget 批量获取值
hexists 判断field是否存在
hkeys 获取所有field
hvals 获取所有value
hgetall 获取所有filed和value
hincrby 增加整型数值
hincrbyfloat 增加浮点型数值
hstrlen 计算值的长度

内部编码

ziplist:当列表的元素个数小于list-max-ziplist-entries配置(默认 512 个),同时列表中每个元素的值都小于list-max-ziplist-value配置时(默认 64 字节),Redis 会选用ziplist来作为 列表 的内部实现来减少内存的使用。

hashtable:当哈希类型无法满足ziplist的条件时,Redis会使用hashtable作为哈希的内部实现,因为此时ziplist的读写效率会下降,而hashtable的读写时间复杂度为O(1)。

使用场景

hash很适合缓存对象,比如商城系统可以存放商品,hashkey为商品id,field为各种属性,value为数据。当然string也可以存放商品,只不过它的value,时json串,还需要解析,从代码角度和网络代价来讲都不如hash

set (集合)

set相当于Java语言里面的 HashSet,它内部的键值对是无序的唯一的。它的内部实现相当于一个特殊的字典,字典中所有的value都是一个值NULL。

常用命令

增加元素

127.0.0.1:6379> sadd books java python python ruby java
(integer) 3

sadd可以添加一个或者多个元素,并且去重。

删除元素

127.0.0.1:6379> srem books python ruby
(integer) 2

srem可以删除一个或者多个元素。

计算元素个数

127.0.0.1:6379> sadd books python ruby c#
(integer) 3
127.0.0.1:6379> scard books
(integer) 4

判断元素是否在集合中

127.0.0.1:6379> sismember books java
(integer) 1
127.0.0.1:6379> sismember books c
(integer) 0

随机返回一定数量的元素

127.0.0.1:6379> srandmember books 2
1) "java"
2) "ruby"
127.0.0.1:6379> srandmember books 2
1) "c#"
2) "ruby"

随机弹出一个元素

127.0.0.1:6379> spop books
"ruby"
127.0.0.1:6379> scard books
(integer) 3

获取所有元素

127.0.0.1:6379> smembers books
1) "c#"
2) "java"
3) "python"

计算并查集

127.0.0.1:6379> sadd set1 a b c d e
(integer) 5
127.0.0.1:6379> sadd set2 d e f g
(integer) 4
# 计算两个集合交集
127.0.0.1:6379> sinter set1 set2
1) "e"
2) "d"
# 计算两个集合并集
127.0.0.1:6379> sunion set1 set2
1) "g"
2) "a"
3) "d"
4) "e"
5) "c"
6) "f"
7) "b"
# 计算两个集合差集
127.0.0.1:6379> sdiff set1 set2
1) "c"
2) "b"
3) "a"

总结

命令 解释
sadd 增加元素
srem 删除元素
scard 计算元素个数
sismember 判断元素是否在集合中
srandmember 随机返回一定数量的元素
spop 随机弹出一个元素
smembers 获取所有元素
sinter 计算两个集合交集
sunion 计算两个集合并集
sdiff 计算两个集合差集

内部编码

intset:当集合中的元素都是整数且元素个数小于set-max-intset-entries配置(默认 512 个)时,Redis会选用intset来作为集合的内部实现,从而减少内存的使用。

hashtable:当集合类型无法满足intset的条件时,Redis会使用hashtable作为集合的内部实现。

使用场景

利用并查集可以用于查找用户共同爱好。

利用不可重复性,可以用于抽奖,保证每个用户只能中一次奖。

zset(有序集合)

zset可能是Redis提供的最为特色的数据结构。它类似于Java的SortedSet和HashMap的结合体,一方面它是一个set,保证了内部value的唯一性,另一方面它可以给每个value赋予一个score,代表这个value的排序权重。

常用命令

# 设置值
127.0.0.1:6379> zadd books 9 java
(integer) 1
127.0.0.1:6379> zadd books 8 python
(integer) 1
127.0.0.1:6379> zadd books 7 golang
(integer) 1
# 查看一定范围内的值
127.0.0.1:6379> zrange books 0 -1
1) "golang"
2) "python"
3) "java"
# 删除某个值
127.0.0.1:6379> zrem books golang
(integer) 1
# 根据score 正序排
127.0.0.1:6379> zrange books 0 -1
1) "python"
2) "java"
# 根据score 倒叙排
127.0.0.1:6379> zrevrange books 0 -1
1) "java"
2) "python"
# 查看元素个数
127.0.0.1:6379> zcard books
(integer) 2
# 查看某元素分值
127.0.0.1:6379> zscore books java
"9"
# 正序排名,从0开始
127.0.0.1:6379> zrank books  python
(integer) 0
127.0.0.1:6379> zrank books java
(integer) 1
# 一定范围内scor内的元素
127.0.0.1:6379> zrangebyscore books 0 8.8
1) "python"

总结

命令 解释
zadd 设置值
zrange 查看一定范围内的值
zrem 删除某个值
zrange 根据score正序排
zrevrange 根据score倒叙排
zcard 查看元素个数
zscore 查看某元素分值
zrank 正序排名,从0开始
zrangebyscore 一定范围内scor内的元素

内部编码

zset内部的排序功能是通过「跳跃列表」数据结构来实现的,它的结构非常特殊,也比较复杂。举个例子吧,就好像一个公司,有9个员工,分为3各小组,每个小组算一个小组长(注意小组长还具备员工角色,只不过多了小组长角色)小组长再选出一个技术总监(技术总监同时具备员工、小组长、技术总监角色)

使用场景

适合排名性质的场景,比如微博热搜,某技术网站热门博客等等。

总结不易,小伙伴给个赞再走吧。

【那些年我们用过的Redis】还记得大明湖畔那些Redis数据吗?相关推荐

  1. 那些年的java游戏_那些年我们曾经玩过的游戏,你还记得几个

    标题:那些年我们曾经玩过的游戏,你还记得几个 随着时间长河的推进,我们已经长大了.你还记得我们那些年一起玩过的游戏么? 弹弓 一般用树枝做弓架,也可以用旱伞的伞骨做弹弓架.要买弹力很大的像皮筋,就和那 ...

  2. 一个时代的印记:还记得那些年我们逃课去的网吧

    一一哥Sun 2020-03-06 11:52:16 对于大多数80后,90后来说,有一个地方应该是你青春回忆里很重要的一个所在,那就是网吧! 相信看我这篇文章的小伙伴们,可能90%以上都去过网吧,曾 ...

  3. 70、80后、90后,小时候开学的场景!你还记得吗?

    转眼又是一年开学季 角色转变,现在是目送孩子们去上学 还记得那些年, 我们开学的日子吗? 那时候的农村的学校 水泥地面很少 任何地方都适合杂草生长 一个暑假过完 教室前后.操场.... 全部被杂草占领 ...

  4. 星梦缘陈彦妃_还记得《星梦缘》的女主吗,她现在变成这样了

    如今<为了你我愿意热爱整个世界>.<扶摇>等偶像剧凭借男女主演的人气,每每有新看点出现都能上热搜,成为年轻一代谈论的话题.自始至终偶像剧都是一个很卖座的题材,但你还记得曾经经典 ...

  5. 你还记得当初为什么进入IT行业吗?

    2019独角兽企业重金招聘Python工程师标准>>> 说到这个问题,小编相信不少童鞋开始忆往昔峥嵘岁月,那个少年为了心中的改变世界的理想,进入了这个行业,但是呢,有一群人画风就不一 ...

  6. 如果你还记得我[转载]

    这是我在[飞雪连天]博客中看到的一篇文章,文章不错,借用一下. 最后一次见到方强是在他家搬离村庄的那天早上. 那天早上,我和母亲从菜地拔菜回来,还在路上,我就听见村子里的人跟母亲说,庆文嫂家要搬到市里 ...

  7. 哨兵机器人钢力士_还记得秒杀X战警的哨兵机器人吗?在漫威原著里,X战警更憋屈...

    还记得<X战警:逆转未来>中的哨兵机器人吗?他们出现在这部电影的开场部分,哨兵机器人对X战警造成了非常大的困扰. 在漫威漫画原著里呢,哨兵机器人的历史也颇为复杂,他们的程序设定就是&quo ...

  8. 有了这篇你还说你不会redis性能优化、内存分析及优化

    点击上方 好好学java ,选择 星标 公众号重磅资讯,干货,第一时间送达 今日推荐:推荐19个github超牛逼项目!个人原创100W +访问量博客:点击前往,查看更多 来源: https://bl ...

  9. 还记得当年你是如何接触Python的吗?

    @图片自制byunsplash 阅读文本大概需要 3 分钟. 绘画:琪琪  |  作者:xiaoyu 要说目前什么语言最受欢迎,我想Python肯定是其中之一了吧.Python语言以其简单的操作.强大 ...

  10. 你还记得20年前的语文课本吗?

    让你的孩子,变成科学达人! 记得当时年纪小,你爱谈天我爱笑. 有一天并肩坐在桃树下, 风在林梢鸟儿在叫. 不知怎么睡着了, 梦里花落知多少. 还记得小时候的课本吗? 我给你们翻出来啦! 每个句子.每个 ...

最新文章

  1. J2EE面试题集锦(附答案)
  2. linux 中断机制的处理过程
  3. linux常用命令:wget 命令
  4. C++ hamming distance汉明距离算法(附完整源码)
  5. 基于密度的异常值检测方法整理
  6. mysql备份表恢复数据库_mysql备份恢复数据库据/表
  7. 捕获标志位_如何通过捕获标志挑战来提高网络安全技能-PicoCTF演练
  8. c语言指针选择排序1,求助利用指针进行选择排序
  9. php单字母函数(快捷方法)使用总结转载
  10. GJB150.5A-2009军用装备实验室温度冲击环境试验
  11. 四种Java跨域配置
  12. FlashFXP连接虚拟机ubuntu 16.04
  13. 如何禁止Chrome浏览器版本自动更新的方法
  14. sd卡数据损坏怎么回事,sd卡数据损坏怎么恢复
  15. 你打开的那些网页,大概率是被监控了
  16. IT66021FN 寄存器配置
  17. 在3dmax中导入的动画摄像机巡游与主摄像机之间的切换
  18. 辨别 利用AAC转成无损格式音乐 的假无损
  19. js中类似`${xx,xxxy}`的语句
  20. 英语基础太差,能学好编程吗?

热门文章

  1. Picgo 水印制作教程
  2. Android短信验证码控件,Android中实现短信验证码自动填入
  3. hbase snappy 安装_【hbase-部署】配置snappy压缩
  4. 前端失业 3个月,尝试接私单的感触
  5. MySQL事务之幻读问题
  6. android wifi热点默认名称,Android 修改WiFi热点的默认SSID和密码
  7. 麦吉尔大学统计与计算机科学,麦吉尔大学统计学和计算机科学本科.pdf
  8. 打开本地html加载网页慢,浏览器打开网页很慢怎么回事_浏览器打开网页很慢如何解决...
  9. 如何简单快速去掉电脑桌面图标上的小箭头
  10. 遇到U盘无法打开,属性显示0字节这样的问题?数据该如何导出?