python入门到精通 练习题30道(初级)

Posted love9599

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python入门到精通 练习题30道(初级)相关的知识,希望对你有一定的参考价值。

主要给学习Python的新手们分享了几道简单练习题,文中给出了详细的示例代码供大家学习参考,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们来一起学习学习吧。

题目1

编程实现,让用户输入一个整数n,打印输出n以内的全部大于0的偶数(不包含n)

# 方法1==================================================
# 让用户输入一个数字
num=int(input("请输入一个整数"))
# 判断是否满足循环条件,如果满足,则进入循环
while num>0:
    if num%2 == 0:
        # 打印数字
        print(num)
    # 修改num的值,让其自减1【目的是为了将来能结束循环】    
    num -= 1
 

# 方法2================================================== 
# 让用户输入一个数字
userInput=int(input("请输入一个整数"))

# 通过range直接生成偶数
for num in range(2,userInput+1,2):
    print(num)

题目2

编程实现,让用户输入三个整数,要求打印输出最大的和最小的数字。

# 方法1:用列表的max和min方法=====================================
#定义空列表
li = []

# 通过for循环,让用户输入三个数字,并依次加入到列表中
for num in range(1,4):
    userInput = input("请输入数字: ")
    li.append(int(userInput))

# 输出列表中的所有的数
print(li)
# 输出列表中的最大的数
print(max(li))
# 输出列表中的最小的数
print(min(li))



# 方法2:用比较数字大小的方法=======================================
# 让用户输入一个数字
userInput = int(input("请输入数字:"))   

# 定义一个变量,保存最大的数
maxNum = userInput          
# 定义一个变量,保存最小的数
minNum = userInput          

for num in range(1,3):
    # 让用户输入一个数字
    userInput = int(input("请输入数字:"))    

    # 判断maxNum中保存的数字和新输入的数字谁大谁小
    if maxNum < userInput:
        # 如果新输入的数字,比如maxNum中保存的数字还大,说明maxNum中的数已经不是最大的数
        maxNum = userInput

    # 判断minNum中保存的数字和新输入的数字谁大谁小
    if minNum > userInput:
        minNum = userInput

print(maxNum,minNum)

题目3

编程实现,使用循环实现输出2-3+4-5+6-7+8-9+10 的和

sum1 = 0   # 定义变量保存2 4 6 8 10的和
sum2 = 0   # 定义变量保存3 5 7 9的和

# 计算2 4 6 8 10的和
for m in range(2,11,2):
    sum1 += m

# 计算3 5 7 9的和
for n in range(3,10,2):
    sum2 += n

# 计算2-3+4-5+6-7+8-9+10,也就是计算(2+4+6+8+10) -(3+5+7+9)
res = sum1 - sum2
print(res)

题目4

编程实现,使用循环实现输出 1,2,3,4,5, 7,8,9, 11,12

# 生成1-12的数字
for num in range(1,13):
    # 如果数字是6 或者 10,则立刻开始下一次循环
    if num==6 or num==10:
        continue

    print(num)

题目5

编程实现,使用while 循环输出100-50,从大到小,如100,99,98...,到50时再从0循环输出到50,然后结束

# 方法1:用两个独立的循环================================================
n = 100
m = 0
while n>=50:
    print(n)
    n -= 1

while m<=50:
    print(m)
    m += 1
    
    
# 方法2:用一个循环 ======================================================
# 定义变量m,用于定义输出100~50之间的数
m = 100
# 定义变量n,用于实现while的循环控制,并输出0-50之间的数
n = 0
# 开始循环
while n<=50:
    if m>=50:
        print(m)
    else:
        print(n)
        n+=1
    m -= 1  

题目6

编程实现,使用 while 循环实现输出 1-100 内的所有奇数

# 方法1:用range实现=====================================
for n in range(1,101,2):
    print(n)


# 方法2:用while=========================================
n = 1
while n<101:
    if n%2 == 1:
        print(n)
    n += 1

题目7

编程实现,让用户输入行数和高度,打印一个矩形方框如:

##########
#        #
#        #
#        #
##########
# 方法1==============================================
h = int(input("请输入高度:"))
w = int(input("请输入宽度:"))

# 打印 h 行 #,每行有w个 #

# 打印第一行
print("#"*w)

# 打印中间的行
for n in range(h-2):
    print("#",end="")
    print(" "*(w-2),end="")
    print("#")
    
# 打印最后一行
print("#"*w)

# 方法2================================================

height = int(input("请输入高度:"))
weidth = int(input("请输入宽度:"))
number = 1
while number <= height:
    if number == 1 or number ==height:
        print("#"*weidth)
    elif number > 1 and number < height:
        space = weidth - 2
        print("#",end="")
        print(" "*space,end="")
        print("#")
    number +=1

题目8、编程实现,让用户输入一个字符串

     判断用户输入的字符串有几个字符'a'

     判断用户输入的字符串有几个字符'a'

userInput = input("请输入一句话: ")

m=0
n=0

for char in userInput:
    if char == 'a':
        m += 1
    elif char == 'b':
        n += 1

print("a的个数%d  b的个数%d" %(m,n))

题目9

重复让用户输入一个单词,直到用户输入bye才退出,统计一下,用户一共输入了多少个单词?

# 方法1===================================
import sys
n = 0
while True:
    userInput = input("请输入:")
    if userInput = "bye":
        print("您一共输入了%d个单词"%(n))
        sys.exit(0)
	else:
        n+=1
        
# 方法2===================================
n = 0
while True:
    userInput = input("请输入:")
    if userInput = "bye":
        print("您一共输入了%d个单词"%(n))
        break
	else:
        n+=1

题目10  编程实现,模拟出租车计价器,具体收费标准如下

             3公里以内收费13元

             超出3公里以外,每公里基本单价2.3元/公里

             空驶费:超过15公里后每公里加收1.15元空驶费

userInput = float(input("请输入: "))
if userInput <= 3:
    feiyong = 13.0
elif userInput >3 and userInput <=15:
    feiyong = (userInput-3)*2.3 + 13
else:
    feiyong = 13+(userInput-3)*2.3+(userInput-15)*1.15

print("你需要支付%.1f"%(feiyong))

题目11

实现用户输入用户名和密码,当用户名为 seven 或 alex 且 密码为 123 时,显示登陆成功,否则登陆失败,失败时允许重复输入三次

# 方法1 ==============================================
n = 1
while True:
    # 判断用户是否已经输入了三次
    if n > 3:
        print("你已经输入了3次,再见")
        break
        
    # 如果不到三次,就让n加1
    n += 1
    
    # 让用户输入,并判断
    uName = input("用户名: ")
    uPass = input("密  码: ")
    if uName == "alex" or uName == "seven":
        if uPass == "123":
            print("登录成功")
            break
        else:
            print("登录失败")
    else:
        print("登录失败")


# 方法2 =============================================
n = 1
while n<=3:
    # 如果不到三次,就让n加1
    n += 1

    # 让用户输入,并判断
    uName = input("用户名: ")
    uPass = input("密  码: ")
    if uName == "alex" or uName == "seven":
        if uPass == "123":
            print("登录成功")
            break
        else:
            print("登录失败")
    else:
        print("登录失败")

题目12 

编程实现,输入一年份,判断该年份是否是闰年并输出结果。凡符合下面两个条件之一的年份是闰年。

能被4整除但不能被100整除

能被400整除。

# 方法1 ===============================================
year = int(input("请输入年份:"))
if (year%4 == 0 and year %100 !=0) or (year%400 ==0):
    print("闰年")
else:
    print("非闰年")

题目13

编程实现,一球从100米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在第10次落地时,共经过多少米?第10次反弹多高?

sum = 0
h = 100
for num in range(1,4):
    if num == 1:
		sum = h + sum
    else:
        sum = h*2 + sum
    h = h*0.5
print(sum)

题目14

编程计算BMI值【公式是:BMI = 体重(公斤) / 身高*身高(米)】,并根据BMI指数:

  • 低于18.5:过轻

  • 18.5-25:正常

  • 25-28:过重

  • 28-32:肥胖

  • 高于32:严重肥胖

weight=float(input("请输入你的体重:"))
height=float(input("请输入你的身高:"))
bmi = weight/height**2

if bmi <18.5:
    print("你的体重太轻了")
elif bmi >=18.5 and bmi<25:
    print("你的体重正常") 
    ...
print("体重是 %.2f,身高%.2f,bmi=%.2f"%(weight,height,bmi))

题目15

编程实现,让用户输入10个数字,要求输出这10个数字,并输出10个数字中最大的和最小的数字

# 方法1 ==================================================
# 让用户输入一个数字
num = int(input("请输入一个数字: "))
# 定义变量max和min,让两个的初始值都是num
min=max=num

# 定义变量n,用来实现循环9次【前面已经输入一个第一个数字了】
n=9
while n>=1:
    num = int(input("请输入一个数字: "))
    # min变量中保存的是最小的
    # 如果min中的数字比刚如数的数字还大,说明刚输入的数字小
    # 此时就就将刚输入的数字替换掉min中原有的数字
    if min >= num:
        min = num
    elif max <= num:
        max = num
	n-=1

print("max=%d, min=%d"%(max,min))


# 方法2 ==================================================
# 定义空列表
li = []
# 循环让用户输入,将用户输入的内容添加到列表中
for num in range(1,11):
    userInput = int(input("enter a number: "))
    li.append(userInput)
    
# 获取列表的最大和最小数
maxNum = max(li)
minNum = min(li)

print("全部数字列表:",li)
print("最大的是:",maxNum)
print("最小的是:",minNum)

题目16

编程实现,让用户输入一个季度数【1-4】,然后输出这个季度有那几个月,如果输入不是1-4的整数,提示用户您输错了,例如输入1,就提示1季度也有1月 2月 3月

userInput = int(input("请输入季度[1-4]: "))
if userInput == 1:
    print("一季度有1月2月3月")
elif userInput == 2:
    print("二季度有4月5月6月")
elif userInput == 3:
    print("三季度有7月8月9月")
elif userInput == 4:
    print("四季度有10月11月12月")
else:
    print("error.")

题目17

用程序计算100以内有多少个3的整数倍数字

# 方法1 =======================================
sum = 0
for num in range(1,101):
    if num%3 == 0:
        sum += 1
print(sum)

# 方法2 =======================================
sum = 0
n=1
while n<100:
    if n%3 == 0:
        sum +=1
    n += 1
print(sum)

题目18

编程实现,用程序打印效果

*
**
***
****
*****
****
***
**
*

n=1
m=4
while n<=5:
    print("*"*n)
    n+=1
while m>=1:
    print("*"*m)
    m-=1

题目19

打印99乘法表

# 方法1:=============================================
for m in range(1,10):
    for n in range(1,m+1):
        print("%d*%d=%d"%(n,m,m*n),end=" ")
    print("")

# 方法2 ==============================================
for n in range(1,10):
    for m in range(1,10):
        if m <= n:
            print("%d*%d=%d"%(m,n,m*n),end=" ")
        else:
            print("")
            break

题目20

用两种方法实现判断用户输入的内容中是否有c,要求最多输入三次

number = 3
while number > 0:
     userinput = input("输入内容:")
     if "c" in userinput:
         print("输出的内容有c")
         break
     else:
         number -= 1
         print("输出的内容没有c")

题目21

案例1:让用户输入数字,实现输出结果是

  • 如果用户输入了q,停止让用户输入

  • 当用户输入了q,显示输出结果::数字1+数字2+数字3....

# 定义空列表,用于存储用户每次输入的内容
li = []
while True:
    # 让用户输入输入
    str = input("请输入数字:")
    # 如果用户输入了q,停止让用户输入
    if str == "q":
        print("over")
        break

    # 将用户输入的内容作为一个元素添加到列表中
    li.append(str)

# 将列表中的元素用+拼接成一个字符串
res = "+".join(li)
# 输出拼接成的哪个最终字符串
print(res)

题目22

让用户输入n数字

  • 如果用户输入了q,停止让用户输入;如果用户没有输入q,就继续输入

  • 停止输入后,显示所有用户输入数字,和最大数以及最小数

# 定义空列表,用于存储用户每次输入的内容
li = []
while True:
    # 让用户输入输入
    str = input("请输入数字:")
    # 如果用户输入了q,停止让用户输入
    if str == "q":
        print("over")
        break

    # 将用户输入的内容保存到列表中
    li.append(int(str))

# 输出列表,也就是输出用户所输入的全部的数字
print(li)
print(max(li))
print(min(li))

题目23

让用户随意输入内容,实现用户输入的内容始终在框内,而且居中

userinput = input("输入内容:")
userinputNum = len(userinput)
space = 3
space_1 = space*2
print("+",end="")
print("-"*userinputNum+"-"*space_1,end="")
print("+")
print("|"+" "*space+userinput+" "*space+"|")
print("+",end="")
print("-"*userinputNum+"-"*space_1,end="")
print("+")

题目24

生成一个1-100的列表

# 方法1:循环生成100个数字 - for 版
li = []
for n in range(1,101):
	li.append(n)
	
# 方法2:循环生成100个数字 - while 版
li = []
n=1
while n<=100:
	li.append(n)
	n += 1

题目25

让 用户输一段话,判断一共有多少个单词?

userInput = input("请输入一段内容:")
n = 1
# userInput  abc qq test 123 hhaha hello world qq abcd
for char in userInput:
    if char == " ":
        n += 1
print(n)

题目26

逐一打印输出列表中的元素


li  = ["a","b","c","d"]
li.reverse               # 对li中的内容进行逆序排序
while True:       
    print(li.pop())      # 每次循环,用pop方法,从列表中取出一个元素,并打印输出
    num = len(li)        # 计算列表中剩余的元素数量
    if num == 0:         # 取完后,剩余的元素个数为0,此时结束循环
        break
     

题目27

将字符串abc123转换为321cba

str = "abc123"         # 定义字符串变量 
print(str)             # 输出结果

str = reversed(str)    # 将字符串逆序                            321cba
li = list(str)         # 将逆序后的字符串对象转换为列表             [3,2,1,c,b,a]
str = "".join(li)      # 通过join方法,将列表中的元素拼接成字符串    321cba
print(str)

题目28

li1 = [3,2,1,7,6,4,5] 实现正序和逆序排序

li1 = [3,2,1,7,6,4,5]

li1.sort()
print(li1)

li1.sort(reverse=True)
print(li1)

题目29:购物车

要求

  • 让用户输入账户余额

  • 自动打印商品名称和价格,

  • 判断余额

    • 如果余额不足,则提示,并退出

    • 同时计算余额是否可以购买至少一个产品,让用户输入产品编号和数量

  • 要求可以实现在买了一个产品后可以继续购买其他产品

import sys
userInput = float(input("输入账户余额: "))
price = ["", 4.8 , 3.8 , 2 , 4288]
print("*" * 30, "\\n""商品1.瓜子:4.8元""\\n""商品2.花生:3.8""\\n""商品3.矿泉水:2元""\\n""商品4.3060显卡:4288元")
print("*" * 30)
while True:
    if userInput >= price[3]:
        commodity_number = input("输入商品编号(输入q退出):")
        if commodity_number == "q" or commodity_number == "Q":
                print("欢迎下次光临")
                sys.exit()
        else:
                pass
        commodity_number1 = input("请输入商品数量:")
        if float(commodity_number) < 1 or float(commodity_number) > 4:
            print("没有该件商品")
            continue
        elif price[int(commodity_number)]*(float(commodity_number1)) > userInput:
            print("您的余额不足以购买此商品")
            continue
        else:
            print("购买成功!")
            userInput = userInput - float(commodity_number1) * price[int(commodity_number)]
            userInput_1 = input("余额还有%.2f,是否继续购买Y|N:"%(userInput))
            if userInput_1 == "y" or userInput_1 == "Y":
                continue
            if userInput_1 == "N" or userInput_1 == "n":
               print("欢迎下次光临")
               sys.exit()
    else:
        print("余额不足够购买任意商品")
        sys.exit(1)

题目30

让用户输入个人基本信息,包括 姓名、电话、住址、年龄,通过字典保存用户的数据信息,当用户输入q的时候,结束输入

结束输入后,打印显示全部的用户名,并要求选择一个名称

然后打印输出这个用户的全部信息,输出信息的格式:用户 xxx,电话是xxx,地址是xxx,年龄是xxx

user_list = []
user_dict=
while True:
    userinput_name = input("输入姓名按q退出:").strip().lower()
    if userinput_name == "q":
        break
    else:
        userinput_tel = input("输入电话:").strip()
        userinput_addr = input("输入地址:").strip()
        userinput_age = input("输入年龄:").strip()
        user_dict[userinput_name] =  "tel":userinput_tel, "addr": userinput_addr, "age": userinput_age
        user_list.append(userinput_name)
        continue
print("====================用户菜单=======================")
num = 1
for listnum in user_list:
    print("%s. %s"%(num,listnum))
    num += 1
userinput = input("选择一个用户查看:").lower().strip()
name = user_list[int(userinput)-1]
tel = user_dict[user_list[int(userinput)-1]]["tel"]
addr = user_dict[user_list[int(userinput)-1]]["addr"]
age = user_dict[user_list[int(userinput)-1]]["age"]
print("用户名是:%s 电话号是:%s 地址是:%s 年龄是:%s"%(name,tel,addr,age))

Redis从入门到精通:初级篇

原文链接:http://www.cnblogs.com/xrq730/p/8890896.html,转载请注明出处,谢谢

 

Redis从入门到精通:初级篇

平时陆陆续续看了不少Redis的文章了,工作中也一直在用Redis,感觉是时候对过往Redis的所学进行一次系统性的总结。《Redis从入门到精通》系列会分为初级、中级、高级三篇,从浅入深讲解Redis相关知识点。

在本文中,我们将看到以下内容:

  • Redis简介
  • Redis安装、启动
  • Redis登录授权
  • Redis配置文件redis.conf中参数详细的一个解读
  • Redis性能测试

这些内容无关具体用法,作为一些初级的知识,系统地先认识一下Redis。

 

Redis简介

Redis是一款开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存也可持久化的日志型、Key-Value高性能数据库。Redis与其他Key-Value缓存产品相比有以下三个特点:

  • 支持数据持久化,可以将内存中的数据保存在磁盘中,重启可再次加载使用
  • 支持简单的Key-Value类型的数据,同时还提供List、Set、Zset、Hash等数据结构的存储
  • 支持数据的备份,即Master-Slave模式的数据备份

同时,我们再看下Redis有什么优势:

  • 读速度为110000次/s,写速度为81000次/s,性能极高
  • 具有丰富的数据类型,这个上面已经提过了
  • Redis所有操作都是原子的,意思是要么成功执行要么失败完全不执行,多个操作也支持事务
  • 丰富的特性,比如Redis支持publish/subscribe、notify、key过期等

 

Redis安装、启动

这次写Redis系列的文章,LZ特意去阿里云上买了一个月的服务器,操作系统是Linux,因为Redis项目本身不正式支持Windows系统。不过微软开放技术小组开发和维护了Windows版本的Redis,下载地址为https://github.com/MicrosoftArchive/redis/releases,感兴趣的可以自己去试下,LZ在自己笔记本上安装启动过,没有问题,但就不细说了。

下面说一下在Linux系统上安装并启动Redis的步骤(我的Redis安装在/data/component/redis目录下,每一步使用的命令标红加粗):

  • 进入目录,cd /data/component/redis
  • 下载Redis,wget http://download.redis.io/releases/redis-3.2.11.tar.gz,可以看到LZ使用的Redis版本是3.2.11,在LZ写这篇文章的时候,Redis最新版本为4.0.9,地址为http://download.redis.io/releases/redis-4.0.9.tar.gz,感兴趣的朋友也可以用这个版本
  • 解压下载下来的tar包,tar -zxvf redis-3.2.11.tar.gz,解压完毕的文件夹名称为redis-3.2.11
  • 进入redis-3.2.11,cd redis-3.2.11
  • 由于我们下载下来的是源文件,因此使用make命令对源文件进行一个构建,构建完毕我们会发现src目录下多出了redis-benchmark、redis-check-aof、redis-check-rdb、redis-cli、redis-sentinel、redis-server几个可执行文件,这几个可执行文件后面会说到
  • 由于上述几个命令在/data/component/redis/redis-3.2.11/src目录下,为了更方便地使用这几个命令而不需要指定全路径,配置一下环境变量。这里我是以非root用户进行登录的,因此配置用户变量,先执行cd命令回到初始目录,再vi ./.bash_profile,在path这一行加入PATH=$PATH:$HOME/.local/bin:$HOME/bin:/data/component/redis/redis-3.2.11/src,使用:wq保存并退出
  • 使环境变量生效,执行source ./.bash_profile
  • 使用redis-server即可启动redis,redis-server /data/component/redis/redis-3.2.11/redis.conf

不过这个时候我们的启动稍微有点问题,不是后台启动的,即ctrl+c之后Redis就停了:

为了解决这个问题,我们需要修改一下redis.conf,将Redis设置为以守护进程的方式进行启动,打开redis.conf,找到daemonize,将其设置为yes即可:

这个时候先关闭一下再启动,Redis就在后台自动运行了,关闭Redis有两种方式:

  • redis-cli shutdown,这是种安全关闭redis的方式,但这种写法只适用于没有配置密码的场景,比较不安全,配置密码下一部分会讲
  • kill -9 pid,这种方式就是强制关闭,可能会造成数据未保存

重启后,我们可以使用ps -ef | grep redisnetstat -ant | grep 6379命令来验证Redis已经启动。

 

Redis登录授权

上面我们安装了Redis,但这种方式是非常不安全的,因为没有密码,这样任何连接上Redis服务器的用户都可以对Redis执行操作,所以这一部分我们来讲一下给Redis设置密码。

打开redis.conf,找到"requirepass"部分,打开原本关闭的注释,替换一下自己想要的密码即可:

重启Redis,授权登录有两种做法:

  • 连接的时候直接指定密码,redis-cli -h 127.0.0.1 -p 6379 -a 123456
  • 连接后授权,redis-cli -h 127.0.0.1 -p 6379auth 123456

在配置了密码的情况下,没有进行授权,那么对Redis发送的命令,将返回"(error) NOAUTH Authentication required."。

 

Redis配置文件redis.conf

上面两小节,设置使用守护线程启动、设置密码,都需要修改redis.conf,说明redis.conf是Redis核心的配置文件,本小节我们来看一下redis.conf中一些常用配置:

配置 作用 默认
bind

当配置了bind之后:

  • 只有bind指定的ip可以直接访问Redis,这样可以避免将Redis服务暴露于危险的网络环境中,防止一些不安全的人随随便便通过远程访问Redis
  • 如果bind选项为空或0.0.0.0的话,那会接受所有来自于可用网络接口的连接
127.0.0.1
protected-mode

protected-mode是Redis3.2之后的新特性,用于加强Redis的安全管理,当满足以下两种情况时,protected-mode起作用:

  • bind未设置,即接收所有来自网络的连接
  • 密码未设置

当满足以上两种情况且protected-mode=yes的时候,访问Redis将报错,即密码未设置的情况下,无密码访问Redis只能通过安装Redis的本机进行访问

yes
port Redis访问端口,由于Redis是单线程模型,因此单机开多个Redis进程的时候会修改端口,不然一般使用大家比较熟悉的6379端口就可以了 6379
tcp-backlog 半连接队列的大小,对半连接队列不熟的可以看我以前的文章TCP:三次握手、四次握手、backlog及其他 511
timeout 指定在一个client空闲多少秒之后就关闭它,0表示不管 0
tcp-keepalive

设置tcp协议的keepalive,从Redis的注释来看,这个参数有两个作用:

  • 发现死的连接
  • 从中间网络设备的角度看连接是否存活
300
daemonize 这个前面说过了,指定Redis是否以守护进程的方式启动 no
supervised 这个参数表示可以通过upstart和systemd管理Redis守护进程,这个具体和操作系统相关,资料也不是很多,就暂时不管了 no
pidfile 当Redis以守护进程的方式运行的时候,Redis默认会把pid写到pidfile指定的文件中 /var/run/redis_6379.pid
loglevel

指定Redis的日志级别,Redis本身的日志级别有notice、verbose、notice、warning四种,按照文档的说法,这四种日志级别的区别是:

  • debug,非常多信息,适合开发/测试
  • verbose,很多很少有用的信息(直译,读着拗口,从上下文理解应该是有用信息不多的意思),但并不像debug级别这么混乱
  • notice,适度的verbose级别的输出,很可能是生产环境中想要的
  • warning,只记录非常重要/致命的信息
notice
logfile 配置log文件地址,默认打印在命令行终端的窗口上 ""
databases 设置Redis数据库的数量,默认使用0号DB 16
 save 把Redis数据保存到磁盘上,这个是在RDB的时候用的,介绍RDB的时候专门说这个 

save 900 1

save 300 10

save 60 10000 

 stop-writes-on-bgsave-error

当启用了RDB且最后一次后台保存数据失败,Redis是否停止接收数据。

这会让用户意识到数据没有正确持久化到磁盘上,否则没有人会注意到灾难(disaster)发生了。

如果Redis重启了,那么又可以重新开始接收数据了

 yes
rdbcompression  是否在RBD的时候使用LZF压缩字符串,如果希望省点CPU,那就设为no,不过no的话数据集可能就比较大  yes 
 rdbchecksum 是否校验RDB文件,在RDB文件中有一个checksum专门用于校验 yes 
 dbfilename dump的文件位置 dump.rdb 
 dir Redis工作目录 ./ 
 slaveof 主从复制,使用slaveof让一个节点称为某个节点的副本,这个只需要在副本上配置  关闭
masterauth 如果主机使用了requirepass配置进行密码保护,使用这个配置告诉副本连接的时候需要鉴权 关闭
slave-serve-stale-data

当一个Slave与Master失去联系或者复制正在进行中,Slave可能会有两种表现:

  • 如果为yes,Slave仍然会应答客户端请求,但返回的数据可能是过时的或者数据可能是空的
  • 如果为no,在执行除了INFO、SLAVEOF两个命令之外,都会应答"SYNC with master in progres"错误
yes
 slave-read-only 配置Redis的Slave实例是否接受写操作,即Slave是否为只读Redis  yes
 slave-priority 从站优先级是可以从redis的INFO命令输出中查到的一个整数。当主站不能正常工作时,redis sentinel使用它来选择一个从站并将它提升为主站。 
低优先级的从站被认为更适合于提升,因此如果有三个从站优先级分别是10, 100, 25,sentinel会选择优先级为10的从站,因为它的优先级最低。 
然而优先级值为0的从站不能执行主站的角色,因此优先级为0的从站永远不会被redis sentinel提升。 
100 
 requirepass 设置客户端认证密码 关闭 
 rename-command

命令重命名,对于一些危险命令例如:

  • flushdb(清空数据库)
  • flushall(清空所有记录)
  • config(客户端连接后可配置服务器)
  • keys(客户端连接后可查看所有存在的键)                   

作为服务端redis-server,常常需要禁用以上命令来使得服务器更加安全,禁用的具体做法是是:

  • rename-command FLUSHALL ""

也可以保留命令但是不能轻易使用,重命名这个命令即可:

  • rename-command FLUSHALL abcdefg

这样,重启服务器后则需要使用新命令来执行操作,否则服务器会报错unknown command

关闭 
maxclients  设置同时连接的最大客户端数量,一旦达到了限制,Redis会关闭所有的新连接并发送一个"max number of clients reached"的错误 关闭,默认10000 
 maxmemory 不要使用超过指定数量的内存,一旦达到了,Redis会尝试使用驱逐策略来移除键  关闭 
 maxmemory-policy

当达到了maxmemory之后Redis如何移除数据,有以下的一些策略:

  • volatile-lru,使用LRU算法,移除范围为设置了失效时间的
  • allkeys-lru,根据LRU算法,移除范围为所有的
  • volatile-random,使用随机算法,移除范围为设置了失效时间的
  • allkeys-random,使用随机算法,移除范围为所有的
  • volatile-ttl,移除最近过期的数据
  • noeviction,不过期,当写操作的时候返回错误

注意,当写操作且Redis发现没有合适的数据可以移除的时候,将会报错

关闭,noeviction
appendonly  是否开启AOF,关于AOF后面再说   no
appendfilename AOF文件名称 appendonly.aof
appendfsync 

操作系统实际写数据到磁盘的频率,有以下几个选项:

  • always,每次有写操作都进行同步,慢,但是最安全
  • everysec,对写操作进行累积,每秒同步一次,是一种折衷方案
  • no,当操作系统flush缓存的时候同步,性能更好但是会有数据丢失的风险

当不确定是使用哪种的时候,官方推荐使用everysec,它是速度与数据安全之间的一种折衷方案

everysec 
 no-appendfsync-on-rewrite

aof持久化机制有一个致命的问题,随着时间推移,aof文件会膨胀,当server重启时严重影响数据库还原时间,因此系统需要定期重写aof文件。

重写aof的机制为bgrewriteaof(另外一种被废弃了,就不说了),即在一个子进程中重写从而不阻塞主进程对其他命令的处理,但是这依然有个问题。

bgrewriteaof和主进程写aof,都会操作磁盘,而bgrewriteaof往往涉及大量磁盘操作,这样就会让主进程写aof文件阻塞。

针对上述问题,可以使用此时可以使用no-appendfsync-on-rewrite参数做一个选择:

  • no,最安全,不丢失数据,但是需要忍受阻塞
  • yes,数据写入缓冲区,不造成阻塞,但是如果此时redis挂掉就会丢失数据,在Linux操作系统默认设置下,最坏场景下会丢失30秒数据
 no
 auto-aof-rewrite-percentage 本次aof文件超过上次aof文件该值的百分比时,才会触发rewrite  100 
 auto-aof-rewrite-min-size aof文件最小值,只有到达这个值才会触发rewrite,即rewrite由auto-aof-rewrite-percentage+auto-aof-rewrite-min-size共同保证  64mb
 aof-load-truncated

redis在以aof方式恢复数据时,对最后一条可能出问题的指令的处理方式: 

  • yes,log并继续
  • no,直接恢复失败
 yes
 slowlog-log-slower-than Redis慢查询的最低条件,单位微妙,即查询时间>这个值的会被记录   10000
 slowlog-max-len Redis存储的慢查询最大条数,超过该值之后会将最早的slowlog剔除 128 
lua-time-limit 一个lua脚本执行的最大时间,单位为ms 5000
cluster-enabled 正常来说Redis实例是无法称为集群的一部分的,只有以集群方式启动的节点才可以。为了让Redis以集群方式启动,就需要此参数。 关闭
cluster-config-file 每个集群节点应该有自己的配置文件,这个文件是不应该手动修改的,它只能被Redis节点创建且更新,每个Redis集群节点需要不同的集群配置文件 关闭,nodes-6379.conf 
 cluster-node-timeout 集群中一个节点向其他节点发送ping命令时,必须收到回执的毫秒数  关闭,15000
cluster-slave-validity-factor

如果该项设置为0,不管Slave节点和Master节点间失联多久都会一直尝试failover。

比如timeout为5,该值为10,那么Master与Slave之间失联50秒,Slave不会去failover它的Master

关闭,10 
cluster-migration-barrier

当一个Master拥有多少个好的Slave时就要割让一个Slave出来。

例如设置为2,表示当一个Master拥有2个可用的Slave时,它的一个Slave会尝试迁移

关闭,1
cluster-require-full-coverage 

有节点宕机导致16384个Slot全部被覆盖,整个集群是否停止服务,这个值一定要改为no

关闭,yes

以上把redis.conf里面几乎所有的配置都写了一遍(除了ADVANCED CONFIG部分),感觉其他博客很少有看到比我这个还全的了^_^,给大家作为参考吧。

 

Redis性能测试

之前说过Redis在make之后有一个redis-benchmark,这个就是Redis提供用于做性能测试的,它可以用来模拟N个客户端同时发出M个请求。首先看一下redis-benchmark自带的一些参数:

参数 作用 默认值
-h 服务器名称 127.0.0.1
-p 服务器端口 6379
-s 服务器Socket
-c 并行连接数 50
-n 请求书 10000
-d SET/GET值的字节大小 2
-k 1表示keep alive,0表示重连 1
-r

SET/GET/INC使用随机Key而不是常量,在形式上key样子为mykey_ran:000000012456

-r的值决定了value的最大值

-p 使用管道请求 1,即不使用管道
-q 安静模式,只显示query/sec值
--csv 使用csv格式输出
-l 循环,无限运行测试
-t 只运行使用逗号分割的命令的测试
-I 空闲模式,只打开N个空闲线程并且等待

抛开配置只谈性能的都是耍流氓,说一下我买的阿里云服务器的配置:

  • 单核CPU,CPU类型为Intel(R) Xeon(R) CPU E5-2682 v4 @ 2.50GHz
  • 内存4G
  • 带宽1M
  • 操作系统为Centos7

首先我们运行最简单的redis-benchmark -q,运行结果为:

打印了每个命令的QPS,看到基本都在读写速度基本都在100000次/s以上。

接着换一个命令进行测试,因为实际场景中我们的Key和Value一定是非常丰富的,不可能是单一的Key和单一的Value,因此接着去的测试使用-r模拟value到100000且将运行次数提高到1000000次,具体命令为redis-benchmark -q -r 100000 -n 1000000,运行结果为:

看到整个读写效率基本都在110000次/s以上,证明了读写的高效率。

简单对于Redis的性能测试就到这儿,这个测试结果看起来很美,但是实际应用却完全不是,主要体现在以下几点:

  • 网络与带宽,这是现实中最主要的影响因素,上面的测试还是太过于低级,现实使用中Redis里面存一个用户信息、订单信息,几KB的大小,100000qps根本不可能大家可以算算需要多大的带宽,粗粗算一下超过1个G吧,很多线上服务的带宽根本达不到1G/s,所以Redis的吞吐量最先会被网络带宽限制住
  • Redis由于是单线程模型,因此CPU性能非常重要,尤其是大缓存的快速CPU,我这里的CPU上面写过了,Intel(R) Xeon(R) CPU E5-2682 v4 @ 2.50GHz总体还是可以的
  • 客户端连接数,上面使用了默认的连接数50,实际上10W、20W甚至100W+呢?不过得益于epoll模型,整个下降的可以接受,下面有一张连接数和qps的关系,我也是网上找来的
  • RDB和AOF可能会对Redis造成的阻塞并未考虑进去
  • 尽可能使用大内存,避免SWAP

无论如何,总而言之,Redis整个性能是非常不错的,个人认为如果要选一款存储系统,那么Redis应当是首选。

以上是关于python入门到精通 练习题30道(初级)的主要内容,如果未能解决你的问题,请参考以下文章

C语言课程设计——25道蓝桥杯练习题

蓝桥杯DFS深度优先练习题——基础入门模板

蓝桥杯练习系统--入门训练+基础练习

蓝桥杯 基础练习 BASIC-30 阶乘计算

蓝桥杯DFS正确入门方式 | DFS + 递归与递推习题课(上) | 一节课教你爆搜!——学习笔记

蓝桥杯省赛真题25Scratch射击水果(初级) 少儿编程scratch蓝桥杯省赛真题讲解