Buy
Buy

Using a 3rd Party to Install Redis

The best part about roles is they're shareable. There are a ton of third-party roles that you can download to give your playbook free stuff! I love free stuff!

Refresh the page in the "dev" environment. The page took over 2 seconds to load! Why? In DefaultController, our app is trying to use Redis:

... lines 1 - 9
class DefaultController extends Controller
{
... lines 12 - 14
public function indexAction()
{
... lines 17 - 20
// Redis cache
try {
if ($this->getRedisClient()->exists('total_video_uploads_count')) {
$totalVideoUploadsCount = $this->getRedisClient()->get('total_video_uploads_count');
} else {
$totalVideoUploadsCount = $this->countTotalVideoUploads();
$this->getRedisClient()->set('total_video_uploads_count', $totalVideoUploadsCount, 'ex', 60); // 60s
}
if ($this->getRedisClient()->exists('total_video_views_count')) {
$totalVideoViewsCount = $this->getRedisClient()->get('total_video_views_count');
} else {
$totalVideoViewsCount = $this->countTotalVideoViews();
$this->getRedisClient()->set('total_video_views_count', $totalVideoViewsCount, 'ex', 60); // 60s
}
} catch (ConnectionException $e) {
$totalVideoUploadsCount = $this->countTotalVideoUploads();
$totalVideoViewsCount = $this->countTotalVideoViews();
}
... lines 40 - 46
}
... lines 48 - 109
}

But, it's not installed! So, this fails... and just for a good example, our code rescues thing but sleeps for 2 seconds to "fake" the page being really slow:

... lines 1 - 9
class DefaultController extends Controller
{
... lines 12 - 70
/**
* @return int
*/
private function countTotalVideoUploads()
{
sleep(1); // simulating a long computation: waiting for 1s
$fakedCount = intval(date('Hms') . rand(1, 9));
return $fakedCount;
}
/**
* @return int
*/
private function countTotalVideoViews()
{
sleep(1); // simulating a long computation: waiting for 1s
$fakedCount = intval(date('Hms') . rand(1, 9)) * 111;
return $fakedCount;
}
... lines 94 - 109
}

In other words, without Redis, our site is slow. But after we install it, the page should be super quick!

Installing the Redis Role

We already have all the skills needed to install Redis. But... maybe someone already did the work for us? Google for "Redis Ansible role". Hello DavidWittman/ansible-redis! This role helps install Redis... and it looks fairly active. And check it out: it looks like our role, with templates, vars, handlers and a few other things.

So... if we could download this into our project, we could activate the role and get free stuff! The way to do that is by using a command called ansible-galaxy. Copy it! Then, find your terminal and paste!

ansible-galaxy install DavidWittman.redis

In my case, it's already installed.

By default, ansible-galaxy downloads roles to a global directory. When you tell Ansible to load a role, it looks in your local directory but also looks in that global spot to find possible roles.

You could also download the role locally in your project. Add --help to the command:

ansible-galaxy install DavidWittman.redis --help

The -p option is the key! Downloading the role locally might be even better than downloading it globally. When it's in your project, you can commit it to your repository and manage its version.

Activate & Configure the Role

With the role downloaded, all we need to do is activate it! Easy! Copy the role name. Under our roles, I'll use a longer syntax: role: DavidWittman.redis then become: true:

---
- hosts: vb
... lines 3 - 35
roles:
... line 37
- role: DavidWittman.redis
become: true
... lines 40 - 173

If you tried the role, you'd find out you need that. We didn't need it for the nginx role because we had the become: true lines internally.

Ok team, run the entire playbook in the dev environment:

ansible-playbook ansible/playbook.yml -i ansible/hosts.ini

While we're waiting for someone else to install Redis for us - thanks David - head back to the documentation. The main way to control how a role works is via variables, like redis_bind in this example:

---
- hosts: redis01.example.com
  vars:
    - redis_bind: 127.0.0.1
  roles:
    - DavidWittman.redis

It's cool how it works: internally, the role sets some variables and then uses them. We, of course, can override them. Simple, but powerful.

There is one downside to third-party roles: they can add some serious bloat to your playbook. Yea, it's running a lot of tasks. Often, a role is designed to work on multiple operating systems and versions. Some of these tasks are determining facts about the environment, like what Ubuntu version we have or what utilities are available. The role is really flexible, but takes extra time to run.

And, this first execution will take a long time: it's installing Redis!

Finally... it gets into our stuff.

Ding! Let's try it! Refresh MooTube. Then, refresh again. Yes! 29 milliseconds! Amazing! So much faster!

This works because our application is already configured to look for Redis on localhost. So as soon as it was installed, our app picked it up.

Next, let's talk more about configuration and how you might control things like the Redis host or database password.

Leave a comment!

  • 2018-07-18 Victor Bocharsky

    Hey Cesar,

    > I was reading some blogs about it and some people say that MySQL could have less performance than Redis for storing session but I think in my case, it doesn't make a considerable difference.

    Yes, that's true, Redis probably would be faster, but I think MySQL should be enough for your case. Anyway, you always can switch to Redis in the future when you start having performance issues.

    And yeah, you found the right article in docs for it 👍

    Cheers!

  • 2018-07-17 Cesar Delgado

    Thank you Victor. I also use AWS RDS because it was a security requirement in my company the decouple data from the EC2 so, it's a good idea to use it and save some money.

    I was reading some blogs about it and some people say that MySQL could have less performance than Redis for storing session but I think in my case, it doesn't make a considerable difference.

    I am going to follow this http://symfony.com/doc/3.4/... for the configuration

  • 2018-07-17 Victor Bocharsky

    Hey Cesar,

    Ah, ok, makes more sense.. but everything what I said is still relevant - you probably can save some money and launch Redis on the same EC2 instance. Well, on KnpU we keep session in DB, but we use AWS RDS to decouple data and session from the EC2 instance, that gives us some advantages, e.g. we can easily drop the EC2 instance, create another one and just link DB from it and nobody will lost their session and data. So, it's cheaper than using AWS Elasticache because you need a DB anyway. Well, if you want this feature i.e. when you can easily drop your EC2 instance and launch another one without loosing session, then you can consider storing session into AWS RDS or in AWS Elasticache. If you're not sure you need this feature - not a big deal, you can just do not overwrite path to session in config, i.e. use default PHP session storage that is somewhere internal in the Linux and in this case you won't lose session on every deploy anyway, but you will lose it on drop/launch EC2 instance. Btw, we're talking about it here: https://knpuniversity.com/s... - I recommend you to re-watch this video again. So the question is do you often to drop/launch instances on AWS? :) Probably your EC2 instance may work for years. So, here's some outcomes, but the choice is yours ;)

    Cheers!

  • 2018-07-16 Cesar Delgado

    Sorry Victor, I didn't explain you the reasons. I want to use redis because I need to take out the session of my code because:

    - Everytime I deploy another version of my code, using Ansistrano, all my users are kicked out and they need lo login again. I was thinking to put the session in the shared folder but I was not sure of that.
    - Thinking in long term, I will want to deploy my code in more than one server (autoscaling) and, as Ryan explain here https://knpuniversity.com/s..., I need to put the session out. I know my app won't have a lot of users but I want to ensure its availability.

    What would be your recommendation for my case? I hope you can help me.

  • 2018-07-16 Victor Bocharsky

    Hey Cesar,

    Hm, 150 users per day probably sounds ok even without Redis ;) Why do you want to use Redis in your application? What is the reason behind? I think you should not have any performance problems with your current load, so I suppose you just want to practice, right? Anyway, I think you can install Redis on the same ec2 instance where you run your project, it will cost you less, because it's easier to configure and you don't have to pay for AWS Elasticache. And in any case, you can move to AWS Elasticache later when you do not have enough resources on your ec2 server (not upgrade your EC2 instance to a new price plan).

    Cheers!

  • 2018-07-13 Cesar Delgado

    Hey guys,

    I went back to chapter 25 because I want to use redis in my app to take it out the session. Do you recommend to install redis in the ec2 server or do I need to create another server in AWS Elasticache for example? My app have 150 users per day but not simultaneously. I would appreciate any advice.

    Cheers!

  • 2018-04-10 Victor Bocharsky

    Hey Nia,

    Thanks for sharing it! So, you changed the default Redis port and that's why you saw the error, right?

    Cheers!

  • 2018-04-07 Nia Kathoni

    I did got an error with restating above and https://github.com/DavidWit... helped me to get rid of it.

  • 2017-05-24 Victor Bocharsky

    Hey Chea,

    Looks like you have a typo in your "Install low-level utilities" task, probably some indentation problems. As you can see, the "Install low-level utilities" task name isn't shown in your output. Could you show the code of it?

    Cheers!

  • 2017-05-24 sokphea chea

    Following the tutorial and I got the message below, and it's like the play book stop at the "Install low-level utilities" task. Is it from apt not update? Thanks :


    TASK [Install cow say's - it's probably important] ******************************************************************************************
    ok: [192.168.33.10]

    TASK [{{ item }}] ***************************************************************************************************************************
    failed: [192.168.33.10] (item=zip) => {"failed": true, "item": "zip", "msg": "one of the following is required: package,upgrade,update_cache,deb,autoremove"}
    failed: [192.168.33.10] (item=unzip) => {"failed": true, "item": "unzip", "msg": "one of the following is required: package,upgrade,update_cache,deb,autoremove"}
    to retry, use: --limit @/home/sokphea/Documents/knpUniversity/Ansible/start/ansible/playbook.retry

    PLAY RECAP **********************************************************************************************************************************
    192.168.33.10 : ok=30 changed=2 unreachable=0 failed=1