Redis

学习方式:

  • 上手就用
  • 基本的理论先学习,然后将知识融汇贯通

nosql讲解

为什么要用Nosql

现在都是大数据时代

大数据一般的数据库无法进行分析处理了

至少要会Springboot+SpringCloud

压力一定会越来越大,适者生存

1.单机MySQL的年代

90年代,一个基本的网站访问量一般不会太大,单个数据库完全足够,那个时候,更多的去使用静态网页,HTML,服务器根本没有太大的压力

思考一下,这种情况下:整个网站的瓶颈是什么?

1.数据量如果太大,一个机器放不下了

2.数据的索引 300万就一定要建立索引(B+Tree),一个机器内存也放不下

3.访问量(读写混合),一个服务器承受不了

只要你出现以上的三种情况之一,那么你就必须要晋级

2.Memcached(缓存)+MYSQL+垂直拆分

网站80%的情况都是在读,每次都要去查詢数据库的话就十分的麻烦!所以说我们希望减轻数据的压力,我们可以使用缓存来保证效率!

发展过程:优化数据结构和索引->文件缓存(IO)->Memcachaed(当时最热门的技术!)

3.分库分表+水平分表+MYSQL集群

技术和业务在发展的同时,对人的要求也越来越高!

本质:数据库(读,写)

早些年MYISAM:表锁,十分影响效率!高并发下就会出现严重的锁问题

转战INNODB:行锁

慢慢的就开始使用分库分表来解决写的压力!Mysql在那个年代推出了表分区!这个并没有多少公司使用!

Mysql的集群,很好的解决了那个年代的所有需求

4.如今最近的年代

技术爆炸

2010(按键手机 android1.0HTC)–2020

十年之间,世界已经发生了翻天覆地的变化(定位,也是一种数据,音乐,热榜!)

MySQL等关系型数据库就不够用了,数据量很多,变化很快!

图形数据库 JSON数据库

MYSQL有的时候使用它来存储一些比较大的文件,博客,图片!数据库表很大,效率就低了!如果有一种数据库来专门处理这种数据,mysql的压力就会变得十分小(研究如何处理这些问题!)大数据的io压力下,表几乎没法更大

目前一个基本的互联网项目

为什么要用NoSQL

用户的个人信息,社交网络,地理位置。用户自己产生的数据,用户日志等等爆发式增长!

这时候我们就需要使用NoSQL数据库的,NoSQL可以很好的处理以上的情况!

NoSQL=Not Only SQL(不仅仅是SQL)

泛指非关系型数据库,随着web2.0互联网的诞生!传统的关系型数据库很难对付web2.0时代!尤其是超大规模的高并发的社区!站长!暴露出来很多难以克服的问题,NOSQL在当今大数据环境下发展的十分迅速,Redis是发展最快的,而且是我们当下必须掌握的技术!

很多的数据类型用户的个人信息,社交网络,地理位置。这些数据类型的存储不需要一个固定的格式(行和列),不需要有多余的操作就可以横向扩展了!Map<String,Object>使用键值对来控制

NoSql特点

1.方便扩展(数据之间没有关系,很好扩展!)

2.大数据量高性能(Redis一秒可以写8万次,读取11万次,nosql的缓存记录级,是一种细粒度的缓存,性能比较高)

3.数据类型是多样型的!(不需要事先设计数据库!随取随用!如果是数据量十分大的表,很多人就无法设计了!)

4.传统RDBMS和NOSQL

传统的RDBMS

  • 结构化组织

  • SQL

  • 数据和关系都存在单独的表中

  • 操作操作,数据定义语言

  • 严格的一致性

  • 基础的事务

  • ……

NOSQL

  • 不仅仅是数据
  • 没有固定的查询语言
  • 键值对存储,列存储,文档存储,图形数据库(社交关系)
  • 最终一致性
  • CAP定理 和 BASE理论(异地多活!)初级架构师
  • 高性能,高可用,高可扩
  • ……

了解:3V+3高

大数据时代的3v:主要是描述问题的

1.海量Volume

2.多样Variety

3.实时Velocity

大数据时代的3高:主要是对程序的要求

1.高并发

2.高可拓(随时水平拆分,机器不够了,可以扩展机器)

3.高性能(保证用户体验和性能!)

真正在公司中的实践:NOsql+RDBMS一起使用才是最强的,阿里巴巴的架构演进!

技术没有高低之分,看你如何使用!(提升内功,思维的提高!)

技术急不得,越是慢慢学,才能越扎实

敏捷开发,极限编程

任何一家互联网的公司,都不可能只是简简单单让用户能用就好了

大量公司做的都是相同的业务(竞品协议)

随着这样的竞争,业务是越来越完善,然后对于开发者的要求也是越来越高!

如果你未来想当一个架构师:没有什么是加一层解决不了的

#1.商品的基本信息

名称,价格,商家信息

关系型数据库就可以解决了(王坚:阿里云的这群疯子)

淘宝内部的mysql 不是大家用的mysql

#2.商品的描述,评论(文字比较多)

文档型数据库中,mongodb

#3.图片

分布式文件系统 FastDFS

  • 淘宝自己的TFS
  • Google的 GFS
  • Hadoop HDFS
  • 阿里云的 oss

#4.商品的关键字(搜索)

  • 搜索引擎 solr elasticsearch
  • Isearch: 多隆

所有牛逼的人都有一段苦逼的岁月,但是你只要像sb一样的去坚持,终将牛逼!

#5.商品热门的波段信息

  • 内存数据库
  • redis tair memache

#6.商品的交易,外部的支付接口

  • 三方应用

要知道,一个简单的网页背后的技术不一定是大家所想的那么简单!

大型互联网应用问题

  • 数据类型太多了
  • 数据源太多了
  • 经常重构
  • 数据要改造,大面积改造麻烦

解决问题:



关系型数据库:表格,行,列(POI)

NoSql的四大分类

kv键值对:

  • 新浪:redis
  • 美团:redis+tair
  • 阿里,百度:Redis+memcache

文档型数据库(bson格式和json一样)

  • mongodb(一般必须要掌握)

    • mongodb是一个基于分布式文件存储的数据库,C++编写,主要用来处理大量的文档
    • mongodb是一个介于关系型数据库和非关系型数据库之间的产品,Mongodb是非关系型数据库中功能最丰富,最像关系型数据库的
  • conthDB

列存储数据库

  • HBase
  • 分布式文件系统

图关系型数据库

  • 它不是存图形,放的是关系,比如:朋友圈社交网络,广告推荐
  • Neo4j,InfoGrid

Redis入门

redis是什么

Redis(Remote Dictionary Server ),即远程字典服务

是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步

免费和开源,是当下最热门的nosql技术之一,也被人们称之为结构化数据库

Redis能干嘛

1.内存存储,持久化,内存中是断电即失,所以说持久化很重要(rdb,aof)

2.效率高,可以用于高速缓存

3.发布订阅系统

4.地图信息分析

5.计时器,计数器(浏览量)

6.……

特性

1.多样的数据类型

2.持久化

3.集群

4.事务

……

注意

Window在Github上下载(停更很久了)

Redis推荐都是在Linux服务器上搭建的,我们是基于Linux学习

默认端口是6379

window下使用确实简单,但是redis推荐我们使用linux去开发使用

测试性能

“redis-benchmark” 是一个压力测试工具!

官方自带的性能测试工具

redis-benchmark

#测试:100个并发连接 100000请求

redis-benchmark -h localhost -p 6379 -c 100 -n 100000

基础的知识

redis默认有16个数据库

默认使用的是第0个数据库

可以使用select进行切换数据库

select 3 //切换到第三个数据库

dbsize //查看当前的大小

set k v //插入数据

get k //查询数据

keys * //查询所有的k

flushdb //清空当前库

flushall //清空全部的数据库

exists name //判断name是否存在

move name 1 //移除在第一个数据库中的name

expire name 10 //该参数10秒后过期

ttl name //查询剩余的过期时间 -2表示没了

type name //查询当前的key的类型

append key1 “hello” //在key后面追加字符串,如果当前key不存在,就相当于setkey

strlen key1 //获取字符串长度

incr views //数据加1

decr views //数据减1

incrby views 10 //数据加10

decrby views 10 //数据减10

getrange key 0 3 //取0-3中间的字符串

getrange key 0 -1 //取全部符串和get key是一样的

setrange key 1 xx //替换指定位置的字符串

setex (set with expire) //设置过期时间

setnx (set if not expire) //不存在设置 (在分布式锁中会常常使用)如果存在就创建成功,如果不存在就创建失败

mset //批量插入

mget //批量获取

msetnx //批量不存在设置(原子性:一个错误全部错误)

#对象

set user:1 {name:zhangsan,age:3} //设置一个user:1 对象 值为json字符串来保存一个对象

mset user:1:name zhangsan user:2:name lisi

#这里的key是一个巧妙的设计: user:{id}:{filed} ,如此设计在redis中是完全ok了

getset //先get然后再set 如果不存在值,则返回nil 如果存在值,获取原来的值,并设置新的值

数据结构是相同的,jedis

string类型的使用场景:value除了是我们的字符串还可以是我们的数字

  • 计数器
  • 统计多单位数量
  • 粉丝数
  • 对象缓存存储

思考:为什么redis是6379

粉丝效应

Redis是单线程的

明白Redis是很快的,官方表示,Redis是基于内存操作,CPU不是redis性能瓶颈,redis的瓶颈是根据机器的内存和网络带宽,既然可以使用单线程来实现,就使用单线程了

Reids是c语言写的,官方提供的数据为10W+的QPS,完全不比同样是使用k-v的Memcache差

Redis为什么单线程还这么快?

1.误区1:高性能的服务器一定是多线程的

2.误区2:多线程(cpu上下文会切换!)一定比单线程效率高!

cpu>内存>硬盘的速度要有所了解!

核心:redis是所有的数据全部放在内存中的,所以说使用单线程去操作效率就是最高的,多线程(cpu上下文会切换:耗时的操作),对于内存系统来说,如果没有上下文切换效率就是最高的,多次读写都是在一个cpu上的,在内存情况下,这个就是最佳的方案!

redis

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-key

大基本数据类型

  • String(字符串)

    90%的java程序员使用redis只会使用一个String类型

  • List

    基本的数据类型,列表

    在redis里面,我们可以把list玩成,栈,队列,阻塞队列

    所有的list命令都是l开头的

    1. #############################################
    2. > lpush list one #将一个值或者多个值,插入到列表头部(左)
    3. 1
    4. > lpush list two
    5. 2
    6. > lpush list three
    7. 3
    8. > lrange list 0 -1
    9. three
    10. two
    11. one
    12. > lrange list 0 1
    13. three
    14. two
    15. > rpush list right #将一个值或者多个值,插入到列表头部(右)
    16. 4
    17. > lrange list 0 -1
    18. three
    19. two
    20. one
    21. right
    22. #############################################
    23. lpop
    24. rpop
    25. > lrange list 0 -1
    26. three
    27. two
    28. one
    29. right
    30. > lpop list #移除列表的第一个元素
    31. three
    32. > rpop list #移除列表的最后一个元素
    33. right
    34. > lrange list 0 -1
    35. two
    36. one
    37. #############################################
    38. lindex
    39. > lindex list 1 #通过下标获得list中的某一个值
    40. one
    41. > lindex list 0
    42. two
    43. #############################################
    44. llen
    45. > lpush list one
    46. 1
    47. > lpush list two
    48. 2
    49. > lpush list three
    50. 3
    51. >
    52. (error) ERR unknown command
    53. > llen list #返回列表长度
    54. 3
    55. #############################################
    56. 移除指定的值!
    57. > lrange list 0 -1
    58. three
    59. three
    60. two
    61. > lrem list 1 three #移除list集合中指定个数的value,精确匹配
    62. 1
    63. > lrange list 0 -1
    64. three
    65. two
    66. > lpush list three
    67. 3
    68. > lrem list 2 three
    69. 2
    70. > lrange list 0 -1
    71. two
    72. #############################################
    73. trim 修剪
    74. > rpush mylist "hello"
    75. 1
    76. > rpush mylist "hello1"
    77. 2
    78. > rpush mylist "hello2"
    79. 3
    80. > rpush mylist "hello3"
    81. 4
    82. > ltrim mylist 1 2 #通过下标截取指定的长度,这个list已经被改变了,只剩下截取的元素
    83. OK
    84. > lrange mylist 0 -1
    85. hello1
    86. hello2
    87. #############################################
    88. rpoplpush #移除列表最后一个元素并且移动到新的列表中
    89. > rpush mylist "hello"
    90. 1
    91. > rpush mylist "hello1"
    92. 2
    93. > rpush mylist "hello2"
    94. 3
    95. > rpoplpush mylist myotherlist #移除列表最后一个元素并且移动到新的列表中
    96. hello2
    97. > lrange mylist 0 -1 #查看原来的列表
    98. hello
    99. hello1
    100. > lrange myotherlist 0 -1 #查看目标列表中,确实存在该值
    101. hello2
    102. #############################################
    103. lset 将列表中指定下标的值替换为另外一个值,更新操作
    104. > exists list #判断这个列表是否存在
    105. 0
    106. > lset list 0 item #如果不存在列表我们去更新就会报错
    107. ERR no such key
    108. > lpush list value1
    109. 1
    110. > lrange list 0 0
    111. value1
    112. > lset list 0 item #如果存在,更新当前下标的值
    113. OK
    114. > lrange list 0 0
    115. item
    116. > lset list 1 other #如果不存在,则会报错
    117. ERR index out of range
    118. #############################################
    119. linsert #将某个具体的value插入到列表中某个元素的前面或者后面
    120. > rpush mylist hello
    121. 3
    122. > rpush mylist hello1
    123. 4
    124. > linsert mylist before hello1 other
    125. 5
    126. > lrange mylist 0 -1
    127. hello
    128. other
    129. hello1
    130. hello
    131. hello1
    132. > linsert mylist after other enw
    133. 6
    134. > lrange mylist 0 -1
    135. hello
    136. other
    137. enw
    138. hello1
    139. hello
    140. hello1

    小结

    • 它实际上是一个链表,before node after ,left ,right 都可以插入值

    • 如果key不存在,创建新的链表

    • 如果key存在,新增内容

    • 如果移除了所有的值,空链表,也代表不存在

    • 在两边插入或者改动值效率最高!中间元素,相对来说效率会低一点

      消息队列(Lpush Rpop) 栈 (Lpush Lpop)

  • Set(集合)

    set中的值是不能重复的

    1. #############################################
    2. > sadd myset hello #set集合中添加元素
    3. 1
    4. > sadd myset kuangshen
    5. 1
    6. > sadd myset lovekuangshen
    7. 1
    8. > smembers
    9. ERR wrong number of arguments for 'smembers' command
    10. > smembers myset #查看指定set的所有值
    11. lovekuangshen
    12. kuangshen
    13. hello
    14. > sismember myset hello #判断某一个值是不是在set集合中
    15. 1
    16. > sismember myset world
    17. 0
    18. #############################################
    19. > scard myset #获取set集合中的内容元素个数
    20. 3
    21. > sadd myset lovekuangshen #已经存在的添加失败
    22. 0
    23. #############################################
    24. > srem myset hello #移除set集合中的指定元素
    25. 1
    26. > scard myset
    27. 2
    28. > smembers myset
    29. lovekuangshen
    30. kuangshen
    31. #############################################
    32. set是无序不重复集合,抽随机
    33. > srandmember myset #随机抽选出一个元素
    34. kuangshen
    35. > srandmember myset
    36. lovekuangshen
    37. > srandmember myset 2 #随机抽取指定个数的元素
    38. kuangshen
    39. lovekuangshen
    40. #############################################
    41. 删除指定的key,随机删除key
    42. > smembers myset
    43. lovekuangshen
    44. kuangshen
    45. > spop myset #随机删除一些set集合中的元素
    46. lovekuangshen
    47. > spop myset
    48. kuangshen
    49. #############################################
    50. 将一个指定的值,移动到另外一个set集合中
    51. > sadd myset hello
    52. 1
    53. > sadd myset hello
    54. 0
    55. > sadd myset world
    56. 1
    57. > sadd myset kuangshen
    58. 1
    59. > sadd myset2 set2
    60. 1
    61. > smove myset myset2 kuangshen #将一个指定的值,移动到另外一个set集合
    62. 1
    63. > smembers myset
    64. world
    65. hello
    66. > smembers myset2
    67. set2
    68. kuangshen
    69. #############################################
    70. > sadd key1 a
    71. 1
    72. > sadd key1 b
    73. 1
    74. > sadd key1 c
    75. 1
    76. > sadd key2 c
    77. 1
    78. > sadd key2 d
    79. 1
    80. > sadd key2 e
    81. 1
    82. > sadd key2 e
    83. 0
    84. > sadd key2 key
    85. 1
    86. > sdiff key1 key2 #差集
    87. a
    88. b
    89. > sinter key1 key2 #交集(共同好友就可以这样实现)
    90. c
    91. > sunion key1 key2 #并集
    92. c
    93. e
    94. key
    95. d
    96. b
    97. a

    微博,a用户将所有关注的人放在一个set集合中,将它的粉丝也放在一个集合中

    共同关注,共同爱好,二度好友,推荐好友!(六度分割理论)

  • Hash(哈希)

    Map集合,key-Map集合,本质和String类型没有太大区别,还是一个简单的kv

    set myhash field kuangshen

    1. > hset myhash field1 kuangshen #set一个具体key-value
    2. 1
    3. > hget myhash field1 #获取一个字段值
    4. kuangshen
    5. > hmset myhash field1 hello field2 world #set多个key-value
    6. OK
    7. > hmget myhash field1 field2 #获取多个字段值
    8. hello
    9. world
    10. > hgetall myhash #获取全部的数据
    11. field1
    12. hello
    13. field2
    14. world
    15. #############################################
    16. > hdel myhash field1 #删除hash指定key字段,对应的value值也就消失了
    17. 1
    18. > hgetall myhash
    19. field2
    20. world
    21. #############################################
    22. hlen
    23. > hmset myhash field1 hello field2 world
    24. OK
    25. > hgetall myhash
    26. field2
    27. world
    28. field1
    29. hello
    30. > hlen myhash #获取hash表的字段数量
    31. 2
    32. #############################################
    33. > hexists myhash field #判断hash中指定字段是否存在
    34. 0
    35. > hexists myhash field1
    36. 1
    37. #############################################
    38. #只获得所有field
    39. #只获得所有value
    40. > hkeys myhash#只获得所有field
    41. field2
    42. field1
    43. > hvals myhash#只获得所有value
    44. world
    45. hello
    46. #############################################
    47. incr decr
    48. > hset myhash field3 5 #指定增量
    49. 1
    50. > hincrby myhash field3 1
    51. 6
    52. > hincrby myhash field3 -1
    53. 5
    54. > hsetnx myhash field4 hello #如果不存在则可以设置
    55. 1
    56. > hsetnx myhash field4 world #如果存在则不能设置
    57. 0
    58. #############################################
    59. > hset user:1 name qinjiang
    60. 1
    61. > hget user:1 name
    62. qinjiang

    hash变更的数据user name age 尤其是用户信息之类的,经常变动的信息!hash更适合于对象的存储,String更加适合字符串存储

  • Zset(有序集合)

    在set的基础上,增加了一个值,set k1 v1 zset k1 score1 v1

    1. > zadd myset 1 one #添加一个值
    2. 1
    3. > zadd myset 2 two 3 three #添加多个值
    4. 1
    5. > zrange myset 0 -1
    6. one
    7. two
    8. three
    9. #############################################
    10. 排序如何实现
    11. > zadd salary 2500 xiaohogn #添加三个用户
    12. 1
    13. > zadd salary 5000 zhangsan
    14. 1
    15. > zadd salary 500 kuangshen
    16. 1
    17. > zrangebyscore salary -inf +inf #显示全部的用户,从小到大排序
    18. kuangshen
    19. xiaohogn
    20. zhangsan
    21. > zrange salary 0 -1
    22. kuangshen
    23. xiaohogn
    24. zhangsan
    25. > zrangebyscore salary 0 -1 #显示全部的用户并附带成绩
    26. kuangshen
    27. 500
    28. xiaohogn
    29. 2500
    30. zhangsan
    31. 5000
    32. > zrangebyscore salary -inf 2500 withscores #显示工资小于2500员工的降序排列
    33. kuangshen
    34. 500
    35. xiaohogn
    36. 2500
    37. > zrevrange salary 0 -1 #从大到小排序
    38. zhangsan
    39. kuangshen
    40. #############################################
    41. 移除rem中的元素
    42. > zrange salary 0 -1
    43. kuangshen
    44. xiaohogn
    45. zhangsan
    46. > zrem salary xiaohogn #移除有序集合中的指定元素
    47. 1
    48. > zrange salary 0 -1
    49. kuangshen
    50. zhangsan
    51. > zcard salary # 获取有序集合中的个数
    52. 2
    53. #############################################
    54. > zadd myset 1 hello
    55. 1
    56. > zadd myset 2 world 3 kuangshen
    57. 2
    58. > zcount myset 1 3 #获取指定区间的成员数量
    59. 3
    60. > zcount myset 1 2
    61. 2

    案例思路:set排序 存储班级成绩表,工资排序

    普通消息1 重要消息2 带权重进行判断

    排行榜应用实现

三种特殊数据类型

  • geospatial 地理位置

    朋友的定位,附近的人,打车距离计算

    redis的geo在redis3.2版本就推出了!这个功能可以推算地理位置的信息,两地之间的距离,方圆几里的人

getadd http://www.jsons.cn/lngcode/

  1. #geoadd 地理位置
  2. #规则:两极无法直接添加,我们一般会直接下载城市数据,直接通过java程序一次性导入
  3. #参数key 值(纬度经度名称)
  4. > geoadd china:city 116.40 39.90 beijing
  5. 1
  6. > geoadd china:city 121.47 31.23 shanghai
  7. 1
  8. > geoadd china:city 106.50 29.53 chongqin
  9. 1
  10. > geoadd china:city 114.08 22.54 shenzhen
  11. 1
  12. > geoadd china:city 120.16 30.24 hangzhou
  13. 1
  14. > geoadd china:city 108.96 34.26 xian
  15. 1
  16. #有效的经度-180度到180度
  17. #有效的纬度-85.05112878度到85.05112878度
  18. #当坐标位置超出上述指定范围时,该命令将会返回一个错误

geopos

  1. > geopos china:city beijing #获取指定的城市的经度和纬度
  2. 116.39999896287918
  3. 39.900000091670925
  4. > geopos china:city beijing shanghai
  5. 116.39999896287918
  6. 39.900000091670925
  7. 121.47000163793564
  8. 31.229999039757836

geodist

两人之间的距离

单位如下

m表示单位为米

km表示单位为千米

mi表示单位为英里

ft表示单位为英尺

  1. > geodist china:city beijing shanghai #查看上海到北京的直线距离
  2. 1067378.7564
  3. > geodist china:city beijing shanghai km
  4. 1067.3788
  5. > geodist china:city beijing chongqin km
  6. 1464.0708

georedius 以给定的经纬度为中心

我附近的人?(获得所有附近的人的地址,定位)通过半径来查询

获得指定数量的人,200

所有的数据都应该录入:china:city才会让结果更清晰

  1. > georadius china:city 110 30 1000 km #以110 30这个经纬度为中心,寻找方圆1000km内的城市
  2. chongqin
  3. xian
  4. shenzhen
  5. hangzhou
  6. > georadius china:city 110 30 500 km
  7. chongqin
  8. xian
  9. > georadius china:city 110 30 500 km withdist #显示到中间距离的位置
  10. chongqin
  11. 341.9374
  12. xian
  13. 483.8340
  14. > georadius china:city 110 30 500 km withcoord #显示他人的定位信息
  15. chongqin
  16. 106.49999767541885
  17. 29.529999579006592
  18. xian
  19. 108.96000176668167
  20. 34.2599996441893
  21. > georadius china:city 110 30 500 km withdist withcoord count 1 #筛选出指定的用户
  22. chongqin
  23. 341.9374
  24. 106.49999767541885
  25. 29.529999579006592
  26. > georadius china:city 110 30 500 km withdist withcoord count 2
  27. chongqin
  28. 341.9374
  29. 106.49999767541885
  30. 29.529999579006592
  31. xian
  32. 483.8340
  33. 108.96000176668167
  34. 34.2599996441893

georadiusbymember

  1. #找出位于指定元素周围的其他元素
  2. > georadiusbymember china:city beijing 1000 km
  3. beijing
  4. xian
  5. > georadiusbymember china:city shanghai 400 km
  6. hangzhou
  7. shanghai

gethash 命令-返回一个或多个位置元素的geohash表示

该命令将返回11个字符的geohash字符串

  1. #将二维的经纬度转换为一维的字符串,如果两个字符串越接近,那么则距离越近
  2. > geohash china:city beijing chongqin
  3. wx4fbxxfke0
  4. wm5xzrybty0

geo 底层的实现原理其实就是Zset!我们可以使用Zset命令来操作geo

  1. > zrange china:city 0 -1 #查看地图中全部的元素
  2. chongqin
  3. xian
  4. shenzhen
  5. hangzhou
  6. shanghai
  7. beijing
  8. > zrem china:city beijing #移除指定元素
  9. 1
  • hyperloglog

    什么是基数

    A{1.3.5.7.8.9.7}

    B{1,3,5,7,8}

    基数(不重复的元素) =5 ,可以接受误差!

    简介

    reids2.8.9版本就更新了Hyperloglog 数据结构

    reids hyperloglog 基数统计的算法

    网页的uv(一个人访问一个网站多次,但是还是算作一个人)

    传统的方式,set保存用户的id,然后就可以统计set中的元素数量作为标准判断

    这个方式如果保存大量的用户id,就会比较麻烦!我们的目的是为了计数,而不是保存用户id

    优点:占用的内存是固定的,2^64不同的元素的技术,只需要废12kb内存,如果要从内存角度来比较的话,hyperloglog是首选

    0.81%错误率,统计uv任务,可以忽略不计的

    1. > pfadd mykey a b c d e f g h i j #创建第一组元素
    2. 1
    3. > pfcount mykey #统计mykey元素的基数数量
    4. 10
    5. > pfadd mykey2 i j z x c v b n m #创建第二组元素
    6. 1
    7. > pfcount mykey2
    8. 9
    9. > pfmerge mykey3 mykey mykey2 #合并两组 mykey mykey2 => mykey3 (并集)
    10. OK
    11. > pfcount mykey3 #查看并集的数量
    12. 15

    如果允许容错,那么一定可以使用hyperloglog

    如果不允许容错,就使用set或者自己的数据类型即可

  • bitmap

    位存储

    统计疫情感染人数:010101

    统计用户信息,活跃,不活跃!登录,未登录!打卡,365打卡!两个状态的,都可以使用bitmaps

    Bitmaps 位图,数据结构!都是操作二进制位来进行记录,就只有0和1两个状态!

    365天=365bit 1字节 = 8bit 46个字节左右

    测试

    使用bitmap来记录 周一到周日的打卡

    setbit sign 0 1
    0
    setbit sign 1 0
    0
    setbit sign 3 0
    0
    setbit sign 4 0
    0
    setbit sign 5 1
    0
    setbit sign 6 1
    0

    查看某一天是否有打卡

    1. #############################################
    2. > getbit sign 4
    3. 0
    4. > getbit sign 6
    5. 1

    统计打卡天数

    1. > bitcount sign #统计这周的打卡记录,就可以看到是否有全勤
    2. 3

Redis配置详解

Redis持久化

  • RDB
  • AOF

Redis事务操作 ACID

redis单条命令是保证原子性的,但是事务不保证原子性的,要么同时成功,要么同时失败,原子性!

redis事务的本质:一组命令的集合!一个事务中的所有命令都会被序列化,在事务执行的过程中,会按照顺序执行

一次性,顺序性,排他性!执行一些列的命令

  1. -----队列 set set set 执行 ----

redis事务没有隔离级别的概念!

所有的命令在事务中,并没有直接被执行!只有发起执行命令的时候才会执行!exec

redis的事务

  • 开启事务 (multi)
  • 命令入队
  • 执行事务 (exec)

锁:redis可以实现乐观锁

正常执行事务!

  1. > multi #开启事务
  2. OK
  3. #命令入队
  4. > set k1 v1
  5. QUEUED
  6. > set k2 v2
  7. QUEUED
  8. > get k2
  9. QUEUED
  10. > set k3 v3
  11. QUEUED
  12. > exec #执行事务
  13. OK
  14. OK
  15. v2
  16. OK

放弃事务

  1. multi #开启事务
  2. OK
  3. > set k1 v1
  4. QUEUED
  5. > set k2 v3
  6. QUEUED
  7. > set k4 b5
  8. QUEUED
  9. > discard #取消事务
  10. QUEUED
  11. > get k4 #事务队列中命令都不会被执行
  12. QUEUED
  13. >
  14. (error) ERR unknown command
  15. > DISCARD
  16. QUEUED

编译型异常(代码有问题!命令有错!),事务中所有的命令都不会被执行

  1. > multi
  2. OK
  3. > set k1 v1
  4. QUEUED
  5. > set k2 v2
  6. QUEUED
  7. > set k3 v3
  8. QUEUED
  9. > getset k3 #错误命令
  10. QUEUED
  11. > set k4 v4
  12. QUEUED
  13. > set k5 v5
  14. QUEUED
  15. > exec #执行事务报错
  16. EXECABORT Transaction discarded because of previous errors.
  17. > get k5 #所有的命令都不会被执行
  18. null

运行时异常(1/0),如果队列中存在一些语法型错误,那么执行命令的时候,其他命令式可以正常执行的,错误命令会抛出异常

  1. > set k1 v1
  2. OK
  3. > multi
  4. OK
  5. > incr k1 #会执行的时候失败
  6. QUEUED
  7. > set k2 v2
  8. QUEUED
  9. > set k3 v3
  10. QUEUED
  11. > get k3
  12. QUEUED
  13. > exec
  14. OK
  15. OK
  16. v3
  17. > get k2
  18. v2
  19. > get k3
  20. v3
  21. > get k1
  22. v1
  23. > incr k1
  24. ERR value is not an integer or out of range #虽然第一条命令报错了,但是依旧正常执行成功了

监控!watch(面试常问)

悲观锁

  • 很悲观,什么时候都会出问题,无论做什么都会加锁!

乐观锁

  • 很乐观,认为什么时候都不会出现问题,所以不会上锁!更新数据的时候去判断一下,在此期间是否有人修改过这个数据,version
  • 获取version
  • 更新的时候比较version

redis测监视测试

  1. 正常执行成功
  2. > set money 100
  3. OK
  4. > set out 0
  5. OK
  6. > watch money #监视money对象
  7. OK
  8. > multi #事务正常结束,数据期间没有发生变动,这个时候就正常执行成功
  9. OK
  10. > decrby money 20
  11. QUEUED
  12. > incrby out 20
  13. QUEUED
  14. > exec
  15. 80
  16. 20

测试多线程修改值,使用watch可以当做redis的乐观锁操作!

  1. > set money 100
  2. OK
  3. > set out 0
  4. OK
  5. > watch money #监视money
  6. OK
  7. > multi
  8. OK
  9. > decrby money 20
  10. QUEUED
  11. > incrby out 20
  12. QUEUED
  13. > exec #执行之前,另外一个线程,修改了我们的值,这个时候,就会导致事务执行失败
  14. null

如果修改失败,获取最新的值就好

Jedis

我们要使用java来操作redis

什么是jedis是redis官方推荐的java连接开发工具!使用java操作redis,如果你要使用java操作redis,那么一定要对jedis十分的熟悉

测试

1.导入对应的依赖

  1. <!--导入jedis的包-->
  2. <dependencies>
  3. <!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
  4. <dependency>
  5. <groupId>redis.clients</groupId>
  6. <artifactId>jedis</artifactId>
  7. <version>3.3.0</version>
  8. </dependency>
  9. <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
  10. <dependency>
  11. <groupId>com.alibaba</groupId>
  12. <artifactId>fastjson</artifactId>
  13. <version>1.2.73</version>
  14. </dependency>
  15. </dependencies>

2.编码测试:

  • 连接数据库

    1. package com.kuang;
    2. import redis.clients.jedis.Jedis;
    3. public class testPing {
    4. public static void main(String[] args) {
    5. //1.new jedis对象即可
    6. Jedis jedis = new Jedis("127.0.0.1",6379);
    7. //jedis所有的命令就是我们之前学习的所有指令~!所以之前的指令学习很重要
    8. System.out.println(jedis.ping());
    9. }
    10. }

    输出

常用的api

String

List

Set

Hash

Zset

所有的api命令,就是我们对应的上面的指令!所以之前的指令学习很重要

  • 操作命令

  • 断开连接!

SpringBoot整合

SpringBoot操作数据:spring-data jpa jdbc mongodb redis

SpringData也是和Springboot齐名的项目

说明:在springboot2.x后,原来使用的jedis被替换成为了lettuce

jedis:采用的是直连,多个线程操作的话是不安全的,如果想要避免不安全的,使用jedis pool连接池!BIO阻塞

lettuce:采用netty,实例可以在多个线程中进行共享,不存在线程不安全的情况!可以减少线程数量,更像Nio模式

#Springboot 所有的配置类,都有一个自动配置类

#自动配置类都会绑定一个properties 配置文件

源码分析

整合测试一下

1.导入依赖

2.配置连接

3.测试

Redis实现订阅发布(消息队列)

Redis主从复制

概念

主从复制,是指将一台redis服务器的数据,复制到其他redis服务器。前者称为主节点(master/leader),后者称为从节点(slave/follower);数据的复制都是单向的,只能由主节点到从节点。master以写为主,slave以读为主。

默认情况下,每台redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。

主从复制的作用主要包括:

1.数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式

2.故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复,实际上是一种服务的冗余

3.负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写redis服务时应用读取主节点,读redis服务时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高redis服务器的并发量

4.高可用基石(集群):除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是redis高可用的基础

一般来说,要将redis应用于项目工程中,只使用的一台redis服务器是万万不能的,原因如下:

1.从结构上,单个redis服务器会发生单点故障,并且一台服务器需要处理所有的请求负载,压力较大;

2.从容量上,单个redis服务器内存容量有限,就算一台redis服务器容量为256g,也不能将所有内存用作于redis存储内存,一般来说,单台redis最大使用内存不应该超过20g

电商网站上的商品,一般都是一次上传,无数次浏览的,说专业点也就是“多读少写”

主从复制,读写分离!80%的情况下都是在进行读操作!减缓服务器的压力!架构中经常使用!一主二从!

只要在公司中,主从复制就是必须要使用的

,因为在真实的项目中不可能单机使用redis

环境配置

只配置从库,不配置主库

  1. > info replication #查看当前库的信息
  2. # Replication
  3. role:master #角色 master
  4. connected_slaves:0 #没有从机
  5. master_repl_offset:0
  6. repl_backlog_active:0
  7. repl_backlog_size:1048576
  8. repl_backlog_first_byte_offset:0
  9. repl_backlog_histlen:0

复制3个配置文件,然后修改对应的信息

1.端口

2.pid名字

3.log文件名字

4.dump.rdb名字

一主二从

我们一般情况下只用配置从机就好了

一个主机两个从机

  1. slaveof 127.0.0.1 6379

真实得从主配置应该在配置文件中配置,这样的话是永久的,我们这里使用的是命令,暂时的!

细节

主机可以写,从机不能写只能读!主机中所有的信息和数据,都会自动被从机保存

主机写:

从机只能读取内容:

测试:主机断开连接,从机依旧连接到主机的,但是没有写操作,这个时候,主机如果回来了,从机依旧可以直接获取到主机写的信息!

如果是使用命令行来配置的主从,这个时候如果重启了,就会自动变回主机!只要变为从机,立马就会从主机中获取值!

复制原理

slave启动成功连接到master后会发送一个sync同步命令

Master接到命令,启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master将传送整个数据文件到slave,并完成一次完全同步

全量复制:而salve服务在接收到数据库文件数据后,将其存盘并加载到内存中

增量复制:master继续将新的所有收集到的修改命令依次传给slave,完成同步

但是只要是重新连接master,一次完全同步(全量复制)将被自动执行

我们的数据一定可以在从机中看到!

层层链路

上一个M连接下一个S!

这个时候也可以完成我们的主从复制!

如果没有老大了,这个时候能不能选择一个老大出来呢?手动!

谋权篡位

如果主机断开了连接,我们可以使用SLAVEOF no one让自己变成主机!其他的节点就可以手动连接到最新的这个主节点(手动)!如果这个时候老大修复了,那就重新连接

Redis哨兵模式(现在公司中所有的集群都用哨兵模式)

自动选举老大的模式

概述:

主从切换技术的方法是:当主服务器宕机后,需要手动把一台服务器切换为主服务器,这就需要人工干预,费时费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式。redis从2.8开始正式提供了Sentinel(哨兵模式)架构来解决这个问题

谋权篡位的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库

哨兵模式是一种特殊的模式,首先redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行,其原理是哨兵通过发送命令,等待redis服务器响应,从而监控运行的多个redis实例

这里哨兵有两个作用

  • 通过发送命令,让redis服务器返回监控其运行状态,包括主服务器和从服务器
  • 当哨兵检测到master宕机,会自动将slave切换为master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机

然而一个哨兵进程对redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控,各个哨兵之间还会进行监控,这样酒就形成了多哨兵模式

假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票结果由一个哨兵发起,进行failover[故障转移]操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线

测试

我们目前的状态是一主二从

1.配置哨兵配置文件

  1. # sentinel monitor 被监控的名称 host port 1
  2. sentinel monitor myredis 127.0.0.1 6379 1

后面的数字1,代表主机挂了,slave投票看让谁接替成为主机,票数最多的,就会成为主机!

2.启动哨兵

如果Master节点断开了,这个时候就会从从机中随机选择一个服务器(这里面有一个投票算法)

哨兵日志

如果主机此时回来了,只能归并到新的主机下,当做从机,这就是哨兵模式的规则!

哨兵模式

优点:

1.哨兵集群,基于主从复制模式,所有的主从配置的优点它全有

2.主从可以切换,故障可以转移,系统的可用性就会更好

3.哨兵模式就是主从模式的升级,手动到自动,更加健壮!

缺点:

1.redis不好啊在线扩容的,集群容量一旦到达上限,在线扩容就十分麻烦

2.实现哨兵模式的配置其实是很麻烦的,里面有很多选择

哨兵模式的全部配置

  1. # Example sentinel.conf
  2. # port <sentinel-port>
  3. port 8001
  4. # 守护进程模式
  5. daemonize yes
  6. # 指明日志文件名
  7. logfile "./sentinel1.log"
  8. # 工作路径,sentinel一般指定/tmp比较简单
  9. dir ./
  10. # 哨兵监控这个master,在至少quorum个哨兵实例都认为master down后把master标记为odown
  11. # (objective down客观down;相对应的存在sdown,subjective down,主观down)状态。
  12. # slaves是自动发现,所以你没必要明确指定slaves。
  13. sentinel monitor MyMaster 127.0.0.1 7001 1
  14. # master或slave多长时间(默认30秒)不能使用后标记为s_down状态。
  15. sentinel down-after-milliseconds MyMaster 1500
  16. # 若sentinel在该配置值内未能完成failover操作(即故障时master/slave自动切换),则认为本次failover失败。
  17. sentinel failover-timeout TestMaster 10000
  18. # 设置master和slaves验证密码
  19. sentinel auth-pass TestMaster testmaster123
  20. sentinel config-epoch TestMaster 15
  21. #除了当前哨兵, 还有哪些在监控这个master的哨兵
  22. sentinel known-sentinel TestMaster 127.0.0.1 8002 0aca3a57038e2907c8a07be2b3c0d15171e44da5
  23. sentinel known-sentinel TestMaster 127.0.0.1 8003 ac1ef015411583d4b9f3d81cee830060b2f29862

Redis缓存穿透和雪崩(面试高频,工作常用)

Redis缓存的使用,极大的提升了应用程序的性能和效率,特别是数据查询方面。但同时,它也带来了一些问题。其中,最要害的问题,就是数据的一致性问题,从严格意义上讲,这个问题无解。如果对数据的一致性要求很高,那么就不能使用缓存。

另外的一些典型问题就是,缓存穿透,缓存雪崩和缓存击穿。目前,业界也都有比较流行的解决方案

缓存穿透(查不到)

概览

缓存穿透的概念很简单,用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这个时候就相当于出现了缓存穿透。

解决方案

布隆过滤器

布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力

缓存空对象

当存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个数据将会直接从缓存中获取,保护了后端数据源;

但是这种方法会存在两个问题:

1.如果空值能够被缓存起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中可能会有很多的空值的键

2.即使对空值设置了过期时间,还是会存在缓存层的数据会有一段时间窗口的不一致,这对于需要保持一致性的业务会有影响。

缓存击穿(量太大,缓存过期!)

概述

微博服务器宕机

这里需要注意和缓存击穿的区别,缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。

当某个key在过期的瞬间,有大量的请求并发访问,这类数据一般是热点数据,由于缓存过期,会同时访问数据库来查询最新数据,并且回写缓存,会导致数据库瞬间压力过大 。

解决方案

设置热点数据永不过期

从缓存层面来看,没有设置过期时间,所以不会出现热点key过期后产生的问题

加互斥锁

分布式锁:使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务,其他线程没有获得分布式锁的权限,因此只需要等待即可。这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大

缓存雪崩

服务器的高可用问题

概念

缓存雪崩,是指在某一个时间段,缓存集中过期失效,redis宕机!

产生雪崩的原因之一,比如在写文本的时候,马上就要双十二零点,很快就会迎来一波抢购,这波商品时间比较集中的放入了缓存,假设缓存一个小时,那么到了凌晨一点钟的时候,这批商品的缓存就都过期了。而对这批商品访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。于是所有的请求都会达到存储层,存储层的调用量会暴增,造成存储层也会挂掉的情况

其实集中过期,倒不是非常致命,比较致命的缓存雪崩,是缓存服务器某个节点宕机或断网。因为自然形成的缓存雪崩,一定是在某个时间段集中创建缓存,这个时候,数据库也是考研顶住压力的。无非就是对数据库产生周期性的压力而已。而缓存服务节点的宕机,对数据库服务器造成的压力是不可预知的,很有可能瞬间就把数据库压垮。

双十一:停掉一些服务,(保证主要的服务可用!)服务降级

解决方案

redis高可用

这个思想的含义是,既然redis有可能挂掉,那我多增设几台redis,这样一台挂掉之后其他的还可以继续工作,其实就是搭建的集群(异地多活)

限流降级(在springCloud讲解过!)

这个解决方案的思想是,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

数据预热

数据加热的含义就是在正式部署之前,我线把可能的数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀

基础知识redis详解--【Foam番茄】的更多相关文章

  1. 基础拾遗------redis详解

    基础拾遗 基础拾遗------特性详解 基础拾遗------webservice详解 基础拾遗------redis详解 基础拾遗------反射详解 基础拾遗------委托详解 基础拾遗----- ...

  2. Selenium基础知识(详解IDE命令、css及xpath定位一)

    1. ide常用命令,参考 http://sariyalee.iteye.com/blog/1743350  2. ide介绍,参考 http://blog.csdn.net/oscar999/art ...

  3. python基础知识——字符串详解

    大多数人学习的第一门编程语言是C/C++,个人觉得C/C++也许是小白入门的最合适的语言,但是必须承认C/C++确实有的地方难以理解,初学者如果没有正确理解,就可能会在使用指针等变量时候变得越来越困惑 ...

  4. (cdh)hive 基础知识 名词详解及架构

    过程 启动 hive 之后出现的 CLI 是查询任务的入口,CLI 提交任务给 Driver Driver 接收到任务后调用 Compiler,Executor,Optimizer 将 SQL 语句转 ...

  5. 基础拾遗------webservice详解

    基础拾遗 基础拾遗------特性详解 基础拾遗------webservice详解 基础拾遗------redis详解 基础拾遗------反射详解 基础拾遗------委托详解 基础拾遗----- ...

  6. Redis详解(五)——主从复制

    Redis详解(五)--主从复制 面临问题 机器故障.我们部署到一台 Redis 服务器,当发生机器故障时,需要迁移到另外一台服务器并且要保证数据是同步的.而数据是最重要的,如果你不在乎,基本上也就不 ...

  7. Redis详解入门篇

    Redis详解入门篇 [本教程目录] 1.redis是什么2.redis的作者3.谁在使用redis4.学会安装redis5.学会启动redis6.使用redis客户端7.redis数据结构 – 简介 ...

  8. (转)总结之:CentOS 6.5 MySQL数据库的基础以及深入详解

    总结之:CentOS 6.5 MySQL数据库的基础以及深入详解 原文:http://tanxw.blog.51cto.com/4309543/1395539 前言 早期MySQL AB公司在2009 ...

  9. Redis详解入门篇(转载)

    Redis详解入门篇(转载) [本教程目录] 1.redis是什么2.redis的作者3.谁在使用redis4.学会安装redis5.学会启动redis6.使用redis客户端7.redis数据结构 ...

随机推荐

  1. requests 库和beautifulsoup库

    python 爬虫和解析 库的安装:pip install requests; pip install beautifulsoup4 requests 的几个常用方法: requests.reques ...

  2. 4G工业路由器的传输功率是越高越好吗?

    现在人们越来越多的利用运营商网络进行家庭的Wi-Fi上网,早已是非常普遍的事情了.而无线路由器作为设备组网的重要组成部分,与路由器相关的话题.知识总会能够引发大家的热议.这里,以众山物联网研发.生产的 ...

  3. lora技术在电力行业的应用

    智能电网的目标是建立一个高速通信网络之上的传统电网.它通过传感,分析,预测,决策和控制提供稳定,高效的电力供应.传统电网分为三个主要区域S-发电,输电和配电.先进的计量系统是使这种传统电网智能化的基础 ...

  4. 【Android Studio】安卓开发初体验3.1——UI设计之常用控件

    常用控件 首先对xml文件的编辑有三种模式 Code为纯代码 Split是一边代码,一边预览效果图 Designer就是有UI设计界面 TextView 用于在界面上显示一段文本信息 所有控件都可以在 ...

  5. Linux系统下安装配置JDK(rpm方式及tar.gz方式)

    以前都是在Windows环境进行开发的,最近因工作需要:学习在Linux系统下搭建开发环境,自此记录搭建过程,以方便查阅. 本文借鉴了 Angel挤一挤 .小五 两位的博客. 准备材料: JDK下载链 ...

  6. Pandas_VBA_数据分类比较

    Python与VBA的比较2 需求: input文件中有两列数据,第一列为Name,第二列为Score,Name列里有重复的值,要求按照name的唯一值统计 score,输出到output文件按中. ...

  7. Linux7(centOS7)安装jdk/tomcat/docker/mysql

    jdk的rpm安装.tomcat的解压缩安装.docker的yum安装.mysql的docker安装 下载地址 1.1.jdk下载地址 https://www.oracle.com/java/tech ...

  8. http 请求体数据处理2--ngx

    HTTP 处理数据包, 有的业务不需要,此时只需要将数据包文读取后丢弃, 但是ngx 为什么还要提供一个丢弃接口呢???解决了什么问题?? ------对于HTTP模块而言,放弃接收包体就是简单地不处 ...

  9. UNP——第二章,TCP状态,TIME_WAIT

    状态可以用 netstat 验证 加粗线为 数据交换. 可以看出,TCP在 建立连接和 关闭连接,耗费资源, 因为UDP只需要两次数据通信即可. 但UDP没有可靠传输,和流量控制. 上面协商的MSS为 ...

  10. ceph luminous bluestore热插拔实现

    需求描述 在某些测试场景下面,需要满足能够拔盘以后在插入的时候能够自动上线磁盘,这个需求实际在生产中是不建议使用的,原因是插入的磁盘如果本身存在问题,那么拉起的操作可能会破坏了本身集群的稳定性,所以这 ...